保持宽高比并适应宽度和高度的缩放位图

3

我想按比例缩放位图,但要适应所需的尺寸。 这个答案 缩放位图并保持纵横比,但除非图像是完美的正方形,否则会留下一些空白区域。我需要填充宽度和高度,就像 ImageViewFIT_XY ScaleType 属性一样。

3个回答

6

基于波士顿街道的答案,我编写了这个方法,它可以将任何位图按所需的宽度和高度进行缩放并适配两个维度(没有空白空间!)。它会自动适应更多水平或更多垂直的图像。

public Bitmap resizeBitmapFitXY(int width, int height, Bitmap bitmap){
    Bitmap background = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    float originalWidth = bitmap.getWidth(), originalHeight = bitmap.getHeight();
    Canvas canvas = new Canvas(background);
    float scale, xTranslation = 0.0f, yTranslation = 0.0f;
    if (originalWidth > originalHeight) {
        scale = height/originalHeight;
        xTranslation = (width - originalWidth * scale)/2.0f;
    }
    else {
        scale = width / originalWidth;
        yTranslation = (height - originalHeight * scale)/2.0f;
    }
    Matrix transformation = new Matrix();
    transformation.postTranslate(xTranslation, yTranslation);
    transformation.preScale(scale, scale);
    Paint paint = new Paint();
    paint.setFilterBitmap(true);
    canvas.drawBitmap(bitmap, transformation, paint);
    return background;
}

1
想象一下,这段代码会将图像从左右两侧裁剪。 - Lovekush Vishwakarma
@LovekushVishwakarma 这段代码的目的是将任何位图适应任何尺寸而不会失真,这意味着有时它会在水平或垂直方向裁剪以保持纵横比。 - Pablo Quemé
不过我想展示实际的图像,但是用你的代码会从左右两侧进行太多裁剪。我的需求只是调整大小而不是裁剪左右两侧,我想要的是调整高度和宽度后的实际图像。 - Lovekush Vishwakarma
1
我猜这段代码对你来说不太合适,Lovekush。 - Pablo Quemé
此答案包含代码,可将图像按给定比例缩放并保持其比例,不进行裁剪。https://dev59.com/6GUp5IYBdhLWcg3wNFar#32810187 - CrackerKSR
如果你将条件改为:float widthRatio = width / originalWidth; float heightRatio = heigh / originHeight; if (widthRatio > heightRatio) {它应该会得到期望的结果。 - Lambage

0
这将使图像按比例缩放以适应正方形,而没有任何实心颜色填充在其余区域,并且不会进行裁剪。如果图像不是正方形,则会出现透明区域,图像的宽高比将与原始图像相同。我已经使用肖像和风景图片测试过了。
import android.graphics.*;

 public static Bitmap scalePreserveRatio(Bitmap imageToScale, int destinationWidth,
        int destinationHeight) {
        if (destinationHeight > 0 && destinationWidth > 0 && imageToScale != null) {
            int width = imageToScale.getWidth();
            int height = imageToScale.getHeight();

            //Calculate the max changing amount and decide which dimension to use
            float widthRatio = (float) destinationWidth / (float) width;
            float heightRatio = (float) destinationHeight / (float) height;

            //Use the ratio that will fit the image into the desired sizes
            int finalWidth = (int)Math.floor(width * widthRatio);
            int finalHeight = (int)Math.floor(height * widthRatio);
            if (finalWidth > destinationWidth || finalHeight > destinationHeight) {
                finalWidth = (int)Math.floor(width * heightRatio);
                finalHeight = (int)Math.floor(height * heightRatio);
            }

            //Scale given bitmap to fit into the desired area
            imageToScale = Bitmap.createScaledBitmap(imageToScale, finalWidth, finalHeight, true);

            //Created a bitmap with desired sizes
            Bitmap scaledImage = Bitmap.createBitmap(destinationWidth, destinationHeight, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(scaledImage);

            //Draw background color
            Paint paint = new Paint();
            paint.setColor(Color.TRANSPARENT);
            paint.setStyle(Paint.Style.FILL);
            canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);

            //Calculate the ratios and decide which part will have empty areas (width or height)
            float ratioBitmap = (float)finalWidth / (float)finalHeight;
            float destinationRatio = (float) destinationWidth / (float) destinationHeight;
            float left = ratioBitmap >= destinationRatio ? 0 : (float)(destinationWidth - finalWidth) / 2;
            float top = ratioBitmap < destinationRatio ? 0: (float)(destinationHeight - finalHeight) / 2;
            canvas.drawBitmap(imageToScale, left, top, null);

            return scaledImage;
        } else {
            return imageToScale;
        }
    }

来自https://dev59.com/6GUp5IYBdhLWcg3wNFar#32810187


0

答案基于Pablo的回答并解决了被裁剪的问题:

        myBitmap?.let {
        val originalWidth = it.width.toFloat()
        val originalHeight = it.height.toFloat()
        var scale = 0.0f
        var xTranslation = 0.0f
        var yTranslation = 0.0f
        val widthRatio = viewWidth / originalWidth
        val heightRatio = viewHeight / originalHeight

        if (widthRatio > heightRatio) {
            scale = viewHeight / originalHeight
            xTranslation = (viewWidth - originalWidth * scale) / 2.0f
        } else {
            scale = viewWidth / originalWidth
            yTranslation = (viewHeight - originalHeight * scale) / 2.0f
        }

        val matrix = Matrix()
        matrix.postTranslate(xTranslation, yTranslation)
        matrix.preScale(scale, scale)
        canvas.drawBitmap(it, matrix, myBitmapPainter)
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接