位图作物中心

我有一些正方形或长方形的位图,我选择最短的一面,然后这样做:

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);

然后我用这个把它缩放到144 x 144位图:

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

问题是它裁剪原始位图的左上角,有人有裁剪位图中心的代码吗?

116744 次浏览

你有没有考虑过从 layout.xml开始做这件事?你可以为你的 ImageView设置 ScaleTypeandroid:scaleType="centerCrop",并设置 layout.xml内的 ImageView图像的尺寸。

enter image description here

这可以通过: CreateBitmap (源、 x、 y、宽度、高度)来实现

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()
);
}

您可以使用以下代码来解决您的问题。

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

上述方法在裁剪前对图像进行 postScall,可以在不产生 OOM 误差的情况下获得最佳裁剪效果。

有关详细信息,请参阅 这个博客

这里有一个更完整的片段,它裁剪出任意维度的 [位图]的中心,并将结果缩放到所需的 [图片大小]。所以你总是会得到一个 [ CroppedBitmap ]比例尺的图像中心的一个固定大小的正方形。非常适合做缩略图之类的。

它是其他解决方案的更完整的组合。

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);
}

更正@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);
}

虽然上述大多数答案提供了一种方法来实现这一点,但是已经有一种内置的方法来实现这一点,这就是一行代码(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());
}

如果您希望位图对象被回收,您可以传递这样的选项:

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

发信人: 缩略图实用程序文档

公共静态位图提取缩略图(位图源,整型宽度,整型 身高)

在 API 级别8中添加创建所需大小的居中位图。

参数源原始位图源宽度目标宽度 目标高度目标高度

当使用已接受的答案时,我有时会出现内存错误,而使用 ThumbnailUtils 为我解决了这些问题。而且,这样更干净,更可重复使用。

也许是目前为止最简单的解决办法:

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

进口:

import android.media.ThumbnailUtils;
import java.lang.Math;
import android.graphics.Bitmap;
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)