You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 20:39:03