Подтвердить что ты не робот

Загрузка больших изображений с помощью Picasso и настраиваемого объекта Transform

Я получаю исключение Out Of Memory, используя Picasso при загрузке больших изображений ( > 1.5MB) из Android Gallery (с использованием startActivityForResult).

Я использую настраиваемый объект Target, потому что мне нужно предварительно обработать битмап, когда он будет готов, а также я использую настраиваемый объект Transform для масштабирования растрового изображения.

Проблема заключается в том, что метод public Bitmap transform(Bitmap source) на моем объекте Transform никогда не вызывается из-за исключения из памяти, поэтому я не получаю возможности для повторной настройки изображения.

Но, если я использую метод .resize(maxWidth, maxHeight), он загружает изображение OK. Я предположил, что объект Transform тоже был для этой цели, но кажется, что метод преобразования вызывается после изменения размера, и, если я не вызываю изменение размера, тогда он закончится с нехваткой памяти.

Проблема в том, что при изменении размера мне нужно указать ширину и высоту, но мне нужно масштабировать и сохранять соотношение сторон.

Учтите, что изображения будут выбраны из пользовательской галереи, поэтому они могут быть больше или меньше, портретные, квадратные или ландшафтные и т.д., поэтому мне нужен собственный объект Transformation для выполнения логики, требующей моего приложения.

4b9b3361

Ответ 1

Я нашел решение..

В моем объекте Transform мне понадобилось масштабировать изображение (поддерживая соотношение сторон) до макс. 1024 x 768.

Объект Transform никогда не вызывался, если я не позвоню .resize(width, height), чтобы выполнить повторный выбор изображения.

Для сохранения соотношения сторон и изменения размера я вызываю .centerInside(). Таким образом, изображение будет масштабироваться по мере увеличения ширины, высоты).

Значение, которое я выдаю .resize(ширина, высота), 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;
    }

}

Ответ 2

Там очень хорошая статья на веб-сайте разработчика Android, которая очень помогла мне, когда у меня была такая же проблема с загрузкой больших изображений.

В этой статье подробно объясняется, что вызывает ошибку и как ее решить. Существуют также другие статьи (см. Меню), например, изображения кеша.