Android如何缩小Bitmap并保持宽高比,已有Bitmap实例该如何操作
问题根源
你当前使用的缩放方法没有统一宽高缩放系数,分别对宽高应用独立的缩放比例,直接导致图片拉伸变形。比如你测试用的348x96图片,宽度缩放比约为0.92,高度缩放比约为1.67,两个系数不一致就会出现纵向拉伸的问题。
方案1:保持宽高比,输出严格等于目标尺寸,内容居中留白
这种方案会先按最小的缩放系数等比缩小图片,让图片完整展示在目标尺寸范围内,剩下的区域填充透明背景,最终输出的Bitmap宽高严格等于你传入的目标宽高,完全满足你提到的300x600转240x120的需求:
public static Bitmap scaleCenterFit(Bitmap src, int targetWidth, int targetHeight) { // 计算统一的等比缩放系数 float scale = Math.min((float) targetWidth / src.getWidth(), (float) targetHeight / src.getHeight()); int scaledWidth = (int) (src.getWidth() * scale); int scaledHeight = (int) (src.getHeight() * scale); // 创建目标尺寸的空Bitmap作为画布 Bitmap output = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); // 计算居中绘制的偏移量 float left = (targetWidth - scaledWidth) / 2f; float top = (targetHeight - scaledHeight) / 2f; // 抗锯齿、优化缩放画质的绘制配置 Matrix matrix = new Matrix(); matrix.postScale(scale, scale); matrix.postTranslate(left, top); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); canvas.drawBitmap(src, matrix, paint); // 可选:如果原Bitmap不需要再使用,可以在这里回收节省内存 // src.recycle(); return output; }
该方法处理300x600转240x120的场景时,会先把原图等比缩放到60x120,再居中绘制在240x120的透明画布上,最终输出就是240x120的标准尺寸Bitmap。
方案2:保持宽高比,铺满目标尺寸,裁剪超出部分
如果你不需要留白,要求图片完全铺满目标尺寸,超出边界的部分直接裁剪,可以用这个实现:
public static Bitmap scaleCenterCrop(Bitmap src, int targetWidth, int targetHeight) { // 取最大的缩放系数保证铺满目标尺寸 float scale = Math.max((float) targetWidth / src.getWidth(), (float) targetHeight / src.getHeight()); int scaledWidth = (int) (src.getWidth() * scale); int scaledHeight = (int) (src.getHeight() * scale); Bitmap output = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); // 居中偏移,裁剪超出边界的部分 float left = (targetWidth - scaledWidth) / 2f; float top = (targetHeight - scaledHeight) / 2f; Matrix matrix = new Matrix(); matrix.postScale(scale, scale); matrix.postTranslate(left, top); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); canvas.drawBitmap(src, matrix, paint); // src.recycle(); return output; }
大Bitmap缩放优化
如果你拿到的原始Bitmap尺寸非常大,直接用Matrix缩放容易占用过高内存,可以参考官方的采样逻辑先粗缩放再细缩放,大幅降低内存开销:
public static Bitmap sampledScale(Bitmap src, int targetWidth, int targetHeight) { int srcWidth = src.getWidth(); int srcHeight = src.getHeight(); // 计算粗缩放的采样系数 int inSampleSize = 1; while (srcWidth / (2 * inSampleSize) >= targetWidth && srcHeight / (2 * inSampleSize) >= targetHeight) { inSampleSize *= 2; } // 先做粗缩放降低内存占用 BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = inSampleSize; ByteArrayOutputStream baos = new ByteArrayOutputStream(); src.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] data = baos.toByteArray(); Bitmap sampledBmp = BitmapFactory.decodeByteArray(data, 0, data.length, options); // 再做精准细缩放 Bitmap result = scaleCenterFit(sampledBmp, targetWidth, targetHeight); sampledBmp.recycle(); // src.recycle(); return result; }
内容的提问来源于stack exchange,提问作者lannyf
相关产品推荐
相关产品推荐

