简体   繁体   English

Android Bitmap 的裁剪中心

[英]Android Crop Center of Bitmap

I have bitmaps which are squares or rectangles.我有正方形或矩形的位图。 I take the shortest side and do something like this:我走最短的一边,做这样的事情:

int value = 0;
if (bitmap.getHeight() <= bitmap.getWidth()) {
    value = bitmap.getHeight();
} else {
    value = bitmap.getWidth();
}

Bitmap finalBitmap = null;
finalBitmap = Bitmap.createBitmap(bitmap, 0, 0, value, value);

Then I scale it to a 144 x 144 Bitmap using this:然后我使用这个将它缩放到 144 x 144 Bitmap:

Bitmap lastBitmap = null;
lastBitmap = Bitmap.createScaledBitmap(finalBitmap, 144, 144, true);

Problem is that it crops the top left corner of the original bitmap, Anyone has the code to crop the center of the bitmap?问题是它裁剪了原始 bitmap 的左上角,任何人都有裁剪 bitmap 中心的代码吗?

在此输入图像描述

This can be achieved with: Bitmap.createBitmap(source, x, y, width, height) 这可以通过以下方法实现: Bitmap.createBitmap(source,x,y,width,height)

if (srcBmp.getWidth() >= srcBmp.getHeight()){

  dstBmp = Bitmap.createBitmap(
     srcBmp, 
     srcBmp.getWidth()/2 - srcBmp.getHeight()/2,
     0,
     srcBmp.getHeight(), 
     srcBmp.getHeight()
     );

}else{

  dstBmp = Bitmap.createBitmap(
     srcBmp,
     0, 
     srcBmp.getHeight()/2 - srcBmp.getWidth()/2,
     srcBmp.getWidth(),
     srcBmp.getWidth() 
     );
}

While most of the above answers provide a way to do this, there is already a built-in way to accomplish this and it's 1 line of code ( ThumbnailUtils.extractThumbnail() ) 虽然上面的大多数答案提供了一种方法来实现这一点,但已经有一种内置的方法来实现这一点,它是一行代码( ThumbnailUtils.extractThumbnail()

int dimension = getSquareCropDimensionForBitmap(bitmap);
bitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension);

...

//I added this method because people keep asking how 
//to calculate the dimensions of the bitmap...see comments below
public int getSquareCropDimensionForBitmap(Bitmap bitmap)
{
    //use the smallest dimension of the image to crop to
    return Math.min(bitmap.getWidth(), bitmap.getHeight());
}

If you want the bitmap object to be recycled, you can pass options that make it so: 如果您希望回收位图对象,可以传递使其成为的选项:

bitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);

From: ThumbnailUtils Documentation 来自: ThumbnailUtils文档

public static Bitmap extractThumbnail (Bitmap source, int width, int height) public static Bitmap extractThumbnail(Bitmap source,int width,int height)

Added in API level 8 Creates a centered bitmap of the desired size. 在API级别8中添加创建所需大小的居中位图。

Parameters source original bitmap source width targeted width height targeted height 参数source原始位图源宽度目标宽度高度目标高度

I was getting out of memory errors sometimes when using the accepted answer, and using ThumbnailUtils resolved those issues for me. 在使用接受的答案时,我有时会出现内存错误,并且使用ThumbnailUtils为我解决了这些问题。 Plus, this is much cleaner and more reusable. 此外,这更清洁,更可重复使用。

Have you considered doing this from the layout.xml ? 您是否考虑过使用layout.xml进行此layout.xml You could set for your ImageView the ScaleType to android:scaleType="centerCrop" and set the dimensions of the image in the ImageView inside the layout.xml . 您可以将ImageViewScaleType设置为android:scaleType="centerCrop"并在layout.xml内的ImageView设置图像的尺寸。

Here a more complete snippet that crops out the center of an [bitmap] of arbitrary dimensions and scales the result to your desired [IMAGE_SIZE] . 这是一个更完整的片段,用于裁剪任意尺寸的[位图]的中心,并将结果缩放到所需的[IMAGE_SIZE] So you will always get a [croppedBitmap] scaled square of the image center with a fixed size. 因此,您将始终获得具有固定大小的图像中心的[croppedBitmap]缩放平方。 ideal for thumbnailing and such. 缩略图等的理想选择。

Its a more complete combination of the other solutions. 它是其他解决方案更完整的组合。

final int IMAGE_SIZE = 255;
boolean landscape = bitmap.getWidth() > bitmap.getHeight();

float scale_factor;
if (landscape) scale_factor = (float)IMAGE_SIZE / bitmap.getHeight();
else scale_factor = (float)IMAGE_SIZE / bitmap.getWidth();
Matrix matrix = new Matrix();
matrix.postScale(scale_factor, scale_factor);

Bitmap croppedBitmap;
if (landscape){
    int start = (tempBitmap.getWidth() - tempBitmap.getHeight()) / 2;
    croppedBitmap = Bitmap.createBitmap(tempBitmap, start, 0, tempBitmap.getHeight(), tempBitmap.getHeight(), matrix, true);
} else {
    int start = (tempBitmap.getHeight() - tempBitmap.getWidth()) / 2;
    croppedBitmap = Bitmap.createBitmap(tempBitmap, 0, start, tempBitmap.getWidth(), tempBitmap.getWidth(), matrix, true);
}

You can used following code that can solve your problem. 您可以使用以下代码来解决您的问题。

Matrix matrix = new Matrix();
matrix.postScale(0.5f, 0.5f);
Bitmap croppedBitmap = Bitmap.createBitmap(bitmapOriginal, 100, 100,100, 100, matrix, true);

Above method do postScalling of image before cropping, so you can get best result with cropped image without getting OOM error. 上面的方法在裁剪之前做postScalling图像,这样你可以获得裁剪图像的最佳效果而不会出现OOM错误。

For more detail you can refer this blog 有关更多详细信息,请参阅此博客

Probably the easiest solution so far: 到目前为止可能是最简单的解决方案:

public static Bitmap cropCenter(Bitmap bmp) {
    int dimension = Math.min(bmp.getWidth(), bmp.getHeight());
    return ThumbnailUtils.extractThumbnail(bmp, dimension, dimension);
}

imports: 进口:

import android.media.ThumbnailUtils;
import java.lang.Math;
import android.graphics.Bitmap;

To correct @willsteel solution: 要纠正@willsteel解决方案:

if (landscape){
                int start = (tempBitmap.getWidth() - tempBitmap.getHeight()) / 2;
                croppedBitmap = Bitmap.createBitmap(tempBitmap, start, 0, tempBitmap.getHeight(), tempBitmap.getHeight(), matrix, true);
            } else {
                int start = (tempBitmap.getHeight() - tempBitmap.getWidth()) / 2;
                croppedBitmap = Bitmap.createBitmap(tempBitmap, 0, start, tempBitmap.getWidth(), tempBitmap.getWidth(), matrix, true);
            }
public static Bitmap resizeAndCropCenter(Bitmap bitmap, int size, boolean recycle) {
    int w = bitmap.getWidth();
    int h = bitmap.getHeight();
    if (w == size && h == size) return bitmap;
    // scale the image so that the shorter side equals to the target;
    // the longer side will be center-cropped.
    float scale = (float) size / Math.min(w,  h);
    Bitmap target = Bitmap.createBitmap(size, size, getConfig(bitmap));
    int width = Math.round(scale * bitmap.getWidth());
    int height = Math.round(scale * bitmap.getHeight());
    Canvas canvas = new Canvas(target);
    canvas.translate((size - width) / 2f, (size - height) / 2f);
    canvas.scale(scale, scale);
    Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
    canvas.drawBitmap(bitmap, 0, 0, paint);
    if (recycle) bitmap.recycle();
    return target;
}

private static Bitmap.Config getConfig(Bitmap bitmap) {
    Bitmap.Config config = bitmap.getConfig();
    if (config == null) {
        config = Bitmap.Config.ARGB_8888;
    }
    return config;
}
public Bitmap getResizedBitmap(Bitmap bm) {
    int width = bm.getWidth();
    int height = bm.getHeight();

    int narrowSize = Math.min(width, height);
    int differ = (int)Math.abs((bm.getHeight() - bm.getWidth())/2.0f);
    width  = (width  == narrowSize) ? 0 : differ;
    height = (width == 0) ? differ : 0;

    Bitmap resizedBitmap = Bitmap.createBitmap(bm, width, height, narrowSize, narrowSize);
    bm.recycle();
    return resizedBitmap;
}
    val sourceWidth = source.width
    val sourceHeight = source.height
    val xScale = newWidth.toFloat() / sourceWidth
    val yScale = newHeight.toFloat() / sourceHeight
    val scale = xScale.coerceAtLeast(yScale)

    val scaledWidth = scale * sourceWidth
    val scaledHeight = scale * sourceHeight
    val left = (newWidth - scaledWidth) / 2
    val top = (newHeight - scaledHeight) / 2
    val targetRect = RectF(
        left, top, left + scaledWidth, top
                + scaledHeight
    )
    val dest = Bitmap.createBitmap(
        newWidth, newHeight,
        source.config
    )
    val mutableDest = dest.copy(source.config, true)
    val canvas = Canvas(mutableDest)
    canvas.drawBitmap(source, null, targetRect, null)
    binding.imgView.setImageBitmap(mutableDest)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM