【问题标题】:center Crop Image In proper size to set on ImageView在 ImageView 上设置适当大小的中心裁剪图像
【发布时间】:2014-02-02 03:19:29
【问题描述】:

我正在使用相机 API 拍照,我必须根据我的图像视图大小打开不同大小的相机。我正在关注我们在 Android sdk/sample/adroid-18 中名为“ApiDemo”的示例项目,我更改的内容不是在 setcontentview 上设置相机。我已将相机设置为帧布局。起初我的相机预览是固定的,所以我得到了相机 OptimalPreviewSize 并将 FrameLayout 参数宽度和高度设置为 wrap-content。现在相机预览比 ImageView 小(我想要的尺寸)。如果我将 FrameLayout 参数的大小设置为匹配父级,则相机视图是拉伸的。如何解决此问题。

查找此链接以获取更多规范。 Android camera preview look strange

更新

我的相机预览尺寸很好,现在我使用 on Layout 方法,我的想法是我的布局比我的 ImageView 更大,现在相机预览看起来不错。 现在我面临的问题是为此设置适当大小的图像我必须像我的 ImageView 一样以相同的大小居中裁剪和缩放。我通过 TakePicture 方法获得并保存在 sdcard 中的这个图像。

为此我正在使用这种方法:-

    public Bitmap scaleCenterCrop(Bitmap source, int newHeight, int newWidth) {
    int sourceWidth = source.getWidth();
    int sourceHeight = source.getHeight();

    // Compute the scaling factors to fit the new height and width, respectively.
    // To cover the final image, the final scaling will be the bigger 
    // of these two.
    float xScale = (float) newWidth / sourceWidth;
    float yScale = (float) newHeight / sourceHeight;
    float scale = Math.max(xScale, yScale);

    // Now get the size of the source bitmap when scaled
    float scaledWidth = scale * sourceWidth;
    float scaledHeight = scale * sourceHeight;

    // Let's find out the upper left coordinates if the scaled bitmap
    // should be centered in the new size give by the parameters
    float left = (newWidth - scaledWidth) / 2;
    float top = (newHeight - scaledHeight) / 2;

        // The target rectangle for the new, scaled version of the source bitmap will now
        // be
        RectF targetRect = new RectF(left+50, top, left + scaledWidth, top + scaledHeight+50);
//      RectF targetRect = new RectF(0, 0, newWidth, newHeight/2);
        // Finally, we create a new bitmap of the specified size and draw our new,
        // scaled bitmap onto it.
        Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, source.getConfig());
        Canvas canvas = new Canvas(dest);
        canvas.drawBitmap(source, null, targetRect, null);

        return dest;
}

但是结果图像质量不好。高度角从顶部和底部切割,结果图像质量不好。像素被拉伸。

不要告诉我使用 scaleType=Center_crop 我不能在我的情况下使用它,也不想向用户显示裁剪框,这所有过程都不应该显示在 UI 上。

更新

我使用打击方法从中心裁剪图像并根据我的 imageView 大小进行缩放

Bitmap dstBmp = ThumbnailUtils.extractThumbnail(source, newWidth, newHeight);

但我得到的位图与 FrameLayout 上显示的相机预览不同。因为相机预览很大。我认为这些代码裁剪了大面积。 我试图减小宽度并改变高度,但没有得到我想要的相同比例的裁剪图像。

在图片裁剪后,我还有一个想法是在 FrameLayout 上自动设置最后一个图像帧。我们可以从 Frame Layout 中获取该设置的框架吗?这怎么可能?

这是How to retrieve the visible part of a SurfaceView in Android这样的问题,有人有解决方案吗?

我想通过这一行 ThumbnailUtils.extractThumbnail(source, newWidth, newHeight); 来实现这一点,并且通过这一行,我得到了类似于图中描述的图像的 src。

这行到底要改什么????

【问题讨论】:

标签: android camera center crop android-framelayout


【解决方案1】:

居中裁剪图像可能会对您有所帮助。

public Bitmap scaleCenterCrop(Bitmap source, int newHeight, int newWidth) {
    int sourceWidth = source.getWidth();
    int sourceHeight = source.getHeight();

    // Compute the scaling factors to fit the new height and width, respectively.
    // To cover the final image, the final scaling will be the bigger
    // of these two.
    float xScale = (float) newWidth / sourceWidth;
    float yScale = (float) newHeight / sourceHeight;
    float scale = Math.max(xScale, yScale);

    // Now get the size of the source bitmap when scaled
    float scaledWidth = scale * sourceWidth;
    float scaledHeight = scale * sourceHeight;

    // Let's find out the upper left coordinates if the scaled bitmap
    // should be centered in the new size give by the parameters
    float left = (newWidth - scaledWidth) / 2;
    float top = (newHeight - scaledHeight) / 2;

    // The target rectangle for the new, scaled version of the source bitmap will now
    // be
    RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight);

    // Finally, we create a new bitmap of the specified size and draw our new,
    // scaled bitmap onto it.
    Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, source.getConfig());
    Canvas canvas = new Canvas(dest);
    canvas.drawBitmap(source, null, targetRect, null);

    return dest;
}

【讨论】:

【解决方案2】:

@Akanksha 请使用下面的代码,你只需要传递保存图像的路径,以及我们的图像视图的高度和宽度。这段代码非常适合我。


    import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class ImageHandler {
    /**
     * Decode and sample down a bitmap from a file to the requested width and
     * height.
     * 
     * @param filename
     *            The full path of the file to decode
     * @param reqWidth
     *            The requested width of the resulting bitmap
     * @param reqHeight
     *            The requested height of the resulting bitmap
     * @return A bitmap sampled down from the original with the same aspect
     *         ratio and dimensions that are equal to or greater than the
     *         requested width and height
     */


public static Bitmap decodeSampledBitmapFromFile(String filename,
            int reqWidth, int reqHeight) {

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filename, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth,
                reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filename, options);
    }



public static int calculateInSampleSize(BitmapFactory.Options options,
            int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            if (width > height) {
                inSampleSize = Math.round((float) height / (float) reqHeight);
            } else {
                inSampleSize = Math.round((float) width / (float) reqWidth);
            }

            // This offers some additional logic in case the image has a
            // strange
            // aspect ratio. For example, a panorama may have a much larger
            // width than height. In these cases the total pixels might
            // still
            // end up being too large to fit comfortably in memory, so we
            // should
            // be more aggressive with sample down the image (=larger
            // inSampleSize).

            final float totalPixels = width * height;

            // Anything more than 2x the requested pixels we'll sample down
            // further.
            final float totalReqPixelsCap = reqWidth * reqHeight * 2;

            while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
                inSampleSize++;
            }
        }
        return inSampleSize;
    }
}

我在异步任务中调用这个方法,因为它可能需要太多的 UImemory 和时间 我是这样称呼它的。


class Asyncing extends AsyncTask {

        private int reqWidth;
        private int reqHeight;
        private ImageView iv;
        private String fileName;
        private ProgressDialog pd;

        public Asyncing(int reqWidth, int reqHeight, ImageView iv,
                String fileName) {
            super();
            this.reqWidth = reqWidth;
            this.reqHeight = reqHeight;
            this.fileName = fileName;
            this.iv = iv;
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            return ImageHandler.decodeSampledBitmapFromFile(params[0],
                    reqWidth, reqHeight);

        }

        @Override
        protected void onPostExecute(Bitmap result) {
            iv.setImageBitmap(result);
            if (pd.isShowing()) {
                pd.setMessage(getString(R.string.completed));
                pd.dismiss();
            }

            super.onPostExecute(result);
        }

        @Override
        protected void onProgressUpdate(Void... values) {

            super.onProgressUpdate(values);
        }

        @Override
        protected void onPreExecute() {
            pd = ProgressDialog.show(CustomerDetailsActivity.this, "",
                    getString(R.string.processing_signature));
            super.onPreExecute();
        }

    }

这就是你需要调用异步任务的方式


signedImagePath = data.getExtras().getString("imagePath");

            new Asyncing(signature_img.getWidth(), signature_img.getHeight(),
                    signature_img, "spenTest.png").execute(signedImagePath);

以上代码是根据我的要求写的,你根据你的修改。

【讨论】:

  • 这里signedImagePath是你的图片文件的路径,spendest.png是图片文件的名字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-08
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
相关资源
最近更新 更多