在不改变原始纵横比的情况下将位图大小调整为 512x512

Posted

技术标签:

【中文标题】在不改变原始纵横比的情况下将位图大小调整为 512x512【英文标题】:Resize Bitmap to 512x512 Without changing original aspect ratio 【发布时间】:2019-05-14 02:40:38 【问题描述】:

我有一个创建的位图。尺寸不具体。有时是 120x60、129x800、851x784。它没有特定的值...我想让这些位图始终调整为 512x512,但不改变原始图像的纵横比。并且无需裁剪。新图像必须具有 512x512 的画布,并且原始图像必须居中且没有任何裁剪。

我正在使用此功能调整位图的大小,但它使图像非常糟糕,因为图像适合 X 和 Y 。我不希望图像同时适合 x 和 y 适合其中一个并保持其纵横比。

 public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) 
        int width = bm.getWidth();
        int height = bm.getHeight();
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // CREATE A MATRIX FOR THE MANIPULATION
        Matrix matrix = new Matrix();
        // RESIZE THE BIT MAP
        matrix.postScale(scaleWidth, scaleHeight);

        // "RECREATE" THE NEW BITMAP
        Bitmap resizedBitmap = Bitmap.createBitmap(
                bm, 0, 0, width, height, matrix, false);
        bm.recycle();
        return resizedBitmap;
    

我有什么;

我想要什么;

【问题讨论】:

所以你想添加一个填充。在您的示例中,左右填充。当原始图像的宽度大于高度时,您需要添加顶部和底部填充。 @J.A.P 显然 Mahir 是在谈论像素纵横比,而不是图像纵横比。 我想将我的原始图像以 512x512 空位图为中心,并且没有任何裁剪,您可以从我添加到问题的图像中理解。再次感谢。 不,这在技术上是不可能的。中心 1 像素线 :) 您需要的是填充。 scaleWidth 和 scaleHeight 的最小值是您的拉伸因子并计算剩余的空间并将其用于填充以将您的位图居中到另一个。见这里adilatwork.blogspot.com/2012/10/… 【参考方案1】:

好的,所以你真的很接近。我现在不能测试这个,但基本上需要改变的是

1) 您需要对 X 和 Y 应用相同的比例,因此您需要选择较小的比例(如果不起作用,请尝试较大的比例)。

matrix.postScale(Math.min(scaleWidth, scaleHeight), Math.min(scaleWidth, scaleHeight));

2) 结果将是一个位图,其中至少一侧是 512px 大,另一侧会更小。因此,您需要添加填充以使该边适合 512 像素(左右相等/上下居中)。为此,您需要创建所需大小的新位图:

Bitmap outputimage = Bitmap.createBitmap(512,512, Bitmap.Config.ARGB_8888);

3) 最后取决于resizedBitmap 的哪一侧是512px,您需要将resizedBitmap 绘制到outputImage 中的正确位置

Canvas can = new Canvas(outputimage);
can.drawBitmap(resizedBitmap, (512 - resizedBitmap.getWidth()) / 2, (512 - resizedBitmap.getHeight()) / 2, null);

请注意,512 - resizedBitmap.getWidth() 的结果是 0,因此在正确大小的一侧没有填充。

4) 现在返回outputImage

【讨论】:

你是国王。那解决了...我真的很感激。这是新的和最终的输出:) prntscr.com/lu8gz9 你真的是最好的。我花了超过 12 个小时来修复它。 不客气,感谢您将我的答案标记为解决方案。 @user8652379 能否分享最终代码或使用最终代码 user8652379 编辑此答案【参考方案2】:

这是 Kotlin 中的一个简化,它使用矩阵进行缩放和平移,跳过中间位图。

请注意,它还将新像素的背景颜色设置为白色,这是我的图像管道所需要的。如果您不需要它,请随意删除它。

fun resizedBitmapWithPadding(bitmap: Bitmap, newWidth: Int, newHeight: Int) : Bitmap 
    val scale = min(newWidth.toFloat() / bitmap.width, newHeight.toFloat() / bitmap.height)
    val scaledWidth = scale * bitmap.width
    val scaledHeight = scale * bitmap.height

    val matrix = Matrix()
    matrix.postScale(scale, scale)
    matrix.postTranslate(
        (newWidth - scaledWidth) / 2f,
        (newHeight - scaledHeight) / 2f
    )

    val outputBitmap = Bitmap.createBitmap(newWidth, newHeight, bitmap.config)
    outputBitmap.eraseColor(Color.WHITE)
    
    Canvas(outputBitmap).drawBitmap(
        bitmap,
        matrix,
        null
    )

    return outputBitmap

【讨论】:

以上是关于在不改变原始纵横比的情况下将位图大小调整为 512x512的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python - 如何在不超过原始图像大小的情况下调整裁剪图像的大小以满足纵横比

如何在不扭曲纵横比的情况下将 1000x1000 图像调整为 200x300 图像[重复]

在不丢失纵横比的情况下将图像放入特定大小的盒子中?

使图像适应容器大小保持纵横比

如何在调整窗口大小时锁定纵横比?

在不保持纵横比的情况下使用 mogrify 调整图像大小