🖼️

【Android】Picassoの「Canvas: trying to draw too large bitmap」への対処法

2022/07/06に公開約2,300字

Picassoでサイズが大きい画像を扱うと、Canvas: trying to draw too large(121114048bytes) bitmapというエラーが発生することがありますが、そんなときは画像をリサイズします。

resize(width, height)

まずは、resizeを使う方法です。

resizeに指定したwidth / heightのピクセルサイズで、画像をリサイズします。

RequestCreator.java

// Resize the image to the specified size in pixels.
public RequestCreator resize(int targetWidth, int targetHeight) {
    data.resize(targetWidth, targetHeight);
    return this;
}

How to use

Picasso.get()
    .load(url)
    .resize(width, height)
    .into(imageView)

resize(width, height)に、onlyScaleDown()を付けると、読み込む画像のサイズがresizeに指定したwidth / heightを「超えた場合にのみ」リサイズされます。

RequestCreator.java

// Only resize an image if the original image size is bigger than the target size specified by resize(int, int).
public RequestCreator onlyScaleDown() {
    data.onlyScaleDown();
    return this;
}

How to use

Picasso.get()
    .load(url)
    .resize(width, height)
    .onlyScaleDown()
    .into(imageView)

fit()

もう一つは、fit()を使う方法です。

fit()は、画像をセットするImageViewのサイズに合わせて、画像をリサイズしてくれます。

内部でImageViewのサイズを取得するためにViewTreeObserverを使用しているので、ImageViewがレイアウトされるまでリクエストが遅延するようになっています。

RequestCreator.java

// Attempt to resize the image to fit exactly into the target ImageView's bounds. 
// This will result in delayed execution of the request until the ImageView has been laid out.
// Note: This method works only when your target is an ImageView.
public RequestCreator fit() {
    deferred = true;
    return this;
}

public void into(ImageView target, Callback callback) {
    ...
    if (deferred) {
      if (data.hasSize()) {
        throw new IllegalStateException("Fit cannot be used with resize.");
      }
      int width = target.getWidth();
      int height = target.getHeight();
      if (width == 0 || height == 0) {
        if (setPlaceholder) {
          setPlaceholder(target, getPlaceholderDrawable());
        }
	// ImageViewのサイズが確定していない場合、DeferredRequest内で
	// view.getViewTreeObserver()を呼び出し、画像サイズを確定させてから
	// 再度into(ImageView, Callback)を呼び出している
        picasso.defer(target, new DeferredRequestCreator(this, target, callback));
        return;
      }
      // ImageViewのサイズにリサイズ
      data.resize(width, height);
    }

How to use

Picasso.get()
    .load(url)
    .fit()
    .into(imageView)

Discussion

ログインするとコメントできます