在 Android 中裁剪以适应图像

Posted

技术标签:

【中文标题】在 Android 中裁剪以适应图像【英文标题】:Crop-to-fit image in Android 【发布时间】:2011-03-08 00:16:09 【问题描述】:

我已经尝试了一段时间,我想从Bitmap 创建一个壁纸。假设所需的壁纸尺寸为 320x480,源图像尺寸为 2048x2048。

我不确定裁剪以适应是否是正确的术语,但我想要实现的是让图片的大部分部分与所需的壁纸尺寸 (320x480) 具有相同的比例。

所以在这种情况下,我想从源 Bitmap 获取 2048x1365 或(准确地说是 1365.333...),并将其缩小到 320x480。

我尝试过的技术是:

1) 先将位图裁剪为 2048x1365

bm = Bitmap.createBitmap(bm, xOffset, yOffset, 2048, 1365);

2) 将其缩小到 320x480

bm = Bitmap.createScaledBitmap(bm, 320, 480, false);

产生 OutOfMemory 错误。

有什么办法可以做到吗?

问候,

德祖尔

【问题讨论】:

我认为将您的标题描述为“缩放以适应,保持相同的纵横比”会更好 谢谢,这可能和标题一样合适,但实际上,我想要实现的是“缩放”和“裁剪”图像的某些区域以适应 如果您解决了,请分享您的解决方案。 【参考方案1】:

感谢开源,我在第 230 行的 android Gallery 源代码here 中找到了答案:-D

croppedImage = Bitmap.createBitmap(mOutputX, mOutputY, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(croppedImage);

Rect srcRect = mCrop.getCropRect();
Rect dstRect = new Rect(0, 0, mOutputX, mOutputY);

int dx = (srcRect.width() - dstRect.width()) / 2;
int dy = (srcRect.height() - dstRect.height()) / 2;

// If the srcRect is too big, use the center part of it.
srcRect.inset(Math.max(0, dx), Math.max(0, dy));

// If the dstRect is too big, use the center part of it.
dstRect.inset(Math.max(0, -dx), Math.max(0, -dy));

// Draw the cropped bitmap in the center
canvas.drawBitmap(mBitmap, srcRect, dstRect, null);

【讨论】:

我有同样的问题。您能解释一下什么是 mOutputX、mCrop... 或者更好,您能否编写示例函数而不是接收位图并返回裁剪和缩放的位图?非常感谢。 这些是输出的宽度和高度。这个确切的主题已添加到 Android 开发者网站 developer.android.com/training/displaying-bitmaps/… 基本:1、设置srcRect为位图的大小(0、0、bitmapWidth、bitmapHeight)。 2. 将 dstRect 设置为显示区域的大小。 3. 从“int dx”行执行。 您可以使用我的 JNI 解决方案进行裁剪,从而避免同时拥有 2 个位图:github.com/AndroidDeveloperLB/AndroidJniBitmapOperations。我还想问是否有办法通过使用自定义可绘制对象来避免这一切,该可绘制对象仅绘制您想要绘制的位图的一部分。 链接已失效!尝试发布内容而不是链接【参考方案2】:

我知道这是一个非常晚的回复,但可能是这样的:

public static Bitmap scaleCropToFit(Bitmap original, int targetWidth, int targetHeight)
    //Need to scale the image, keeping the aspect ration first
    int width = original.getWidth();
    int height = original.getHeight();

    float widthScale = (float) targetWidth / (float) width;
    float heightScale = (float) targetHeight / (float) height;
    float scaledWidth;
    float scaledHeight;

    int startY = 0;
    int startX = 0;

    if (widthScale > heightScale) 
        scaledWidth = targetWidth;
        scaledHeight = height * widthScale;
        //crop height by...
        startY = (int) ((scaledHeight - targetHeight) / 2);
     else 
        scaledHeight = targetHeight;
        scaledWidth = width * heightScale;
        //crop width by..
        startX = (int) ((scaledWidth - targetWidth) / 2);
    

    Bitmap scaledBitmap = Bitmap.createScaledBitmap(original, (int) scaledWidth, (int) scaledHeight, true);

    Bitmap resizedBitmap = Bitmap.createBitmap(scaledBitmap, startX, startY, targetWidth, targetHeight);
    return resizedBitmap;

【讨论】:

【参考方案3】:

这里有一个答案,可以帮助您了解大部分情况: How to crop an image in android?

【讨论】:

谢谢,但不是我正在寻找的解决方案。查看我自己的答案,只需使用 Rect 来缩放它。而且它不会产生 OOM :-)

以上是关于在 Android 中裁剪以适应图像的主要内容,如果未能解决你的问题,请参考以下文章

缩放图像以在android中裁剪

如何在android中以圆形裁剪图像?

intent.putExtra 的所有属性以在 android 中裁剪图像

在android中以不规则形状裁剪图像无法正常工作

在Android中以给定的正方形大小裁剪图像?

我如何在android中裁剪像scanmaster.apk这样的图像