android - 使用 Picasso 和自定义 Transform 对象加载大图像

标签 android picasso

我在使用 Picasso 从 Android 图库(使用 startActivityForResult)加载“大”图像 (> 1.5MB) 时遇到内存不足异常。

我正在使用自定义 Target 对象,因为我需要在 Bitmap 准备好时对其进行预处理,并且我正在使用自定义 Transform 对象来缩放 Bitmap。

问题是我的 Transform 对象上的方法 public Bitmap transform(Bitmap source) 因为内存不足异常而从未被调用,所以我没有机会重新采样图像。

但是,如果我使用 .resize(maxWidth, maxHeight) 方法,那么它可以正常加载图像。我猜Transform对象也是为了这个目的,但是似乎在resize之后调用了transform方法,如果我不调用resize,那么它将以Out of Memory结束..

问题是调整大小时我需要指定宽度和高度,但我需要缩放并保持纵横比。

考虑到图像将从用户图库中选择,因此它们可以更大或更小、纵向、正方形或横向等,因此我需要自己的 Transformation 对象来执行需要我的应用程序的逻辑。

最佳答案

我找到了解决办法..

在我的 Transform 对象中,我需要将图像(保持纵横比)缩放到最大 1024 x 768。

除非我调用 .resize(width, height) 来重新采样图像,否则从未调用过变换对象。

为了保持纵横比和使用调整大小,我调用 .centerInside()。这样图像将被缩放重新采样以适应宽度、高度)。

我给 .resize(width, height) 的值是 Math.ceil(Math.sqrt(1024 * 768))。 这样我就可以确保我的自定义 Transform 对象的图像足够高,并且还可以避免 Out Of Memory 异常

更新:完整示例

按照此示例,您将获得适合 MAX_WIDTH 和 MAX_HEIGHT 范围内的图像(保持纵横比)

private static final int MAX_WIDTH = 1024;
private static final int MAX_HEIGHT = 768;

int size = (int) Math.ceil(Math.sqrt(MAX_WIDTH * MAX_HEIGHT));

// Loads given image
Picasso.with(imageView.getContext())
    .load(imagePath)
    .transform(new BitmapTransform(MAX_WIDTH, MAX_HEIGHT))
    .skipMemoryCache()
    .resize(size, size)
    .centerInside()
    .into(imageView);

这是我的自定义 BitmapTransform 类:

import android.graphics.Bitmap;
import com.squareup.picasso.Transformation;

/**
 * Transformate the loaded image to avoid OutOfMemoryException
 */
public class BitmapTransform implements Transformation {

    private final int maxWidth;
    private final int maxHeight;

    public BitmapTransform(int maxWidth, int maxHeight) {
        this.maxWidth = maxWidth;
        this.maxHeight = maxHeight;
    }

    @Override
    public Bitmap transform(Bitmap source) {
        int targetWidth, targetHeight;
        double aspectRatio;

        if (source.getWidth() > source.getHeight()) {
            targetWidth = maxWidth;
            aspectRatio = (double) source.getHeight() / (double) source.getWidth();
            targetHeight = (int) (targetWidth * aspectRatio);
        } else {
            targetHeight = maxHeight;
            aspectRatio = (double) source.getWidth() / (double) source.getHeight();
            targetWidth = (int) (targetHeight * aspectRatio);
        }

        Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
        if (result != source) {
            source.recycle();
        }
        return result;
    }

    @Override
    public String key() {
        return maxWidth + "x" + maxHeight;
    }

}

关于android - 使用 Picasso 和自定义 Transform 对象加载大图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23740307/

相关文章:

android - picasso 没有在 android 中从 Web 加载更新的图像

android - 如何使用 kotlin 协程处理回调

android - 拆分关于 Jsoup 的结果

android - PowerApps-将麦克风音频保存为可播放格式

android - Picasso Android 不加载类型 "content://"的 Uri

android - 在 picasso 中使用回调获取图像?

javascript - 如何检测Android浏览器隐藏软键盘事件?

java - 组织.json.JSONException : Unterminated object at character 14

Android picasso 缓存数据

android - RecyclerView 的图像遮挡了 UI