2014-05-19 8 views
20

Otrzymuję wyjątek braku pamięci przy użyciu Picasso podczas ładowania "dużych" obrazów (> 1,5 MB) z galerii Android (przy użyciu startActivityForResult).Załaduj duże obrazy za pomocą Picassa i niestandardowego obiektu transformacji

Używam niestandardowego obiektu docelowego, ponieważ muszę go wstępnie przetworzyć, kiedy jest gotowy, a także używam niestandardowego obiektu transformacji do skalowania bitmapy.

Problem polega na tym, że metoda public Bitmap transform(Bitmap source) w moim obiekcie transformacji nigdy nie jest wywoływana z powodu wyjątku braku pamięci, więc nie mam możliwości ponownego próbkowania obrazu.

Ale jeśli użyję metody .resize(maxWidth, maxHeight), to ładuje obraz OK. Przekonałem się, że obiekt Transform jest również do tego celu, ale wydaje się, że metoda transformacji jest wywoływana po zmianie rozmiaru, a jeśli nie wywoła zmiany rozmiaru, to zakończy się brakiem pamięci.

Problem polega na tym, że przy zmianie rozmiaru muszę podać zarówno szerokość, jak i wysokość, ale muszę skalować i zachować proporcje.

Należy wziąć pod uwagę, że obrazy zostaną wybrane z galerii użytkownika, aby mogły być większe lub mniejsze, portret, kwadrat lub krajobraz itd., Więc potrzebuję własnego obiektu transformacji, aby wykonać logikę wymagającą zastosowania.

Odpowiedz

55

mogę znaleźć rozwiązanie ..

moim obiekt Transform że potrzebne skalowanie obrazu (przy zachowaniu proporcji) do 1024 x 768 max.

Obiekt transformacji nigdy nie został wywołany, chyba że zadzwonię pod numer .resize(width, height), aby zmienić rozmiar obrazu.

Aby zachować proporcje i zmienić rozmiar, należy zadzwonić pod numer .centerInside(). W ten sposób obraz zostanie przeskalowany, aby dopasować szerokość, wysokość).

Wartość, którą daję .resize (szerokość, wysokość) to Math.ceil(Math.sqrt(1024 * 768)). ten sposób jestem pewny, że obraz wyższej wystarcza moim zwyczajem Transform obiektu, a także uniknąć Out Of wyjątkiem pamięci

Update: Pełny przykład

Po tym przykładzie można uzyskać obraz, który pasuje wewnątrz MAX_WIDTH i MAX_HEIGHT granicach (przy zachowaniu proporcji),

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); 

a to moja klasa zwyczaj 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; 
    } 

} 
+0

Math.ceil (Math.sqrt (1024 * 768)) dla szerokości i wysokości? – DayDayHappy

+0

Tak, @DayDayHappy. Podaję przykład. Mam nadzieję, że to pomoże – edrian

+0

dobrze zrobione i wznowione – DayDayHappy

2

Istnieje bardzo dobry artykuł na stronie dla programistów Androida, który bardzo mi pomógł, gdy miałem ten sam problem z ładowaniem dużych obrazów.

This Artykuł wyjaśnia bardzo dobrze, co powoduje błąd i jak go rozwiązać. Istnieją również inne artykuły (patrz menu), na przykład obrazy w pamięci podręcznej.

+1

Czy możesz podać link do artykułu, do którego się odwołujesz? –