2011-01-28 16 views
20

Dzięki Schermvlieger pytasz this pytanie na anddev.org,Optymalne wykorzystanie BitmapFactory.Options.inSampleSize dla prędkości

Ja tylko kopiowanie jego pytanie SO jak nikt nie odpowiedział na drugą i mam też ten sam problem.

Zastanawiam się, jaki byłby optymalny użytek z BitmapFactory.Options.inSampleSize w odniesieniu do prędkości wyświetlania obrazu.
Dokumentacja wspomina używając wartości, które są potęgą liczby 2, więc pracuję z 2, 4, 8, 16 itd.

Rzeczy Zastanawiam się o to:

  1. Mam resample dół do najmniejszego rozmiaru, który jest nadal większy niż rozdzielczość ekranu, czy też powinienem pobierać próbki do rozmiaru wystarczającego, aby ominąć OutOfMemoryError?
  2. Jak można obliczyć maksymalny rozmiar obrazu, który może być nadal wyświetlany bez wyczerpania pamięci? Czy głębia kolorów obrazu również odgrywa rolę i głębokość wyświetlania?
  3. Czy jest wydajne wyświetlanie obrazów za pomocą dwóch mechanizmów (BitmapFactory dla dużych plików, setImageURI() dla mniejszych) Używam przy okazji ImageSwitcher.
  4. Czy to pomoże utworzyć Bitmap, BitmapFactory.Options i inTempStorage na początku aplikacji lub utworzyć je tylko w locie, w razie potrzeby?

Odpowiedz

11

Zawsze należy starać się załadować i wstępnie skalować obrazy tak, aby były jak najbliżej ich ostatecznego wyświetlanego rozmiaru. Skalowanie obrazów w czasie rysowania jest niezwykle kosztowne i należy go unikać za wszelką cenę.

Biorąc pod uwagę koszt pamięci obrazu, tak, zagęszczenie kolorów odgrywa bardzo ważną rolę. Obrazy w formacie ALPHA_8 używają 1 bajta na piksel, obrazy w RGB_565 lub ARGB_4444 używają 2 bajty na piksel, a obrazy w ARGB_8888 używają 4 bajtów na piksel. Głębokość wyświetlacza nie ma znaczenia. Zawsze powinieneś próbować używać ARGB_8888, aby uzyskać najlepszą możliwą jakość, ale 565 może być wystarczająco dobre, jeśli obraz jest nieprzejrzysty.

+0

Kiedy mówisz, że "skalowanie obrazów w czasie rysowania jest niezwykle kosztowne" czy to obejmuje również opcje options.inSampleSize? – kape123

+0

inSampleSize służy do skalowania obrazów w czasie ładowania, a nie w czasie pobierania. To bardzo dobry sposób na podskalowanie obrazów. –

+1

Używamy ARGB_8888, który produkuje bardzo zamglony obraz na Samsung Galaxy Note 2, ale działało dobrze na innym urządzeniu, przynieś go na ARGB_4444 rozkłada aplikację na Samsung Galaxy Note 2 i Pad 3110, z powodu outOfMemoryError. Czy możesz nam pomóc w rozwiązaniu tego problemu? –

3

Tutaj można wywołać zdefiniowaną przez użytkownika metodę shrinkmehtod, która faktycznie wysyła ścieżkę pliku tekstowego oraz wysokość i szerokość, które mają zostać zredukowane do metody.

Bitmap bit=shrinkmethod(arrpath1[position], 100, 100); 


      //iv.setImageURI(Uri.parse(arrpath1[position])); 
      iv.setImageBitmap(bit); 

Jest to zdefiniowana przez użytkownika metoda programowego zmniejszania rozmiaru obrazu.

Bitmap shrinkmethod(String file,int width,int height){ 
     BitmapFactory.Options bitopt=new BitmapFactory.Options(); 
     bitopt.inJustDecodeBounds=true; 
     Bitmap bit=BitmapFactory.decodeFile(file, bitopt); 

     int h=(int) Math.ceil(bitopt.outHeight/(float)height); 
     int w=(int) Math.ceil(bitopt.outWidth/(float)width); 

     if(h>1 || w>1){ 
      if(h>w){ 
       bitopt.inSampleSize=h; 

      }else{ 
       bitopt.inSampleSize=w; 
      } 
     } 
     bitopt.inJustDecodeBounds=false; 
     bit=BitmapFactory.decodeFile(file, bitopt); 



     return bit; 

    } 

Mam nadzieję, że pomoże to w zmniejszeniu rozmiaru.

+2

Na podstawie tego artykułu http://madhusudhanrc.blogspot.fr/2012/09/reduce-bitmap-size-using.html – Snicolas

4

Zadałeś dobre pytania, ale wszystko zależy od Twoich potrzeb i ilości wykorzystywanej pamięci. Polecam sprawdzenie tego linku w celu uzyskania wielu wskazówek dotyczących bitmap: http://developer.android.com/training/displaying-bitmaps/index.html.

Krótko mówiąc, należy wziąć pod uwagę buforowanie, próbkowanie w dół i używanie wystarczająco dobrego formatu bitmapy, kiedy tylko jest to możliwe.

Oto moje odpowiedzi na pytania:

  1. Dlaczego nie jedno i drugie? jeśli uważasz, że może być OOM, spróbuj odtworzyć stare, nieużywane bitmapy, a następnie sprawdź ponownie.

  2. można obliczyć (szacowany) wielkość bitmapy:

    szerokość * wysokość * bytesPerPixel

    gdzie bytesPerPixel jest zazwyczaj 4 lub 2 (w zależności od formatu bitmapy).

  3. Nigdy nie użyłem setImageURI, więc nie mogę ci w tym pomóc. Sugeruję pobieranie obrazów w wątku w tle (używając asyncTask to jeden sposób, aby to zrobić) i pokazywanie ich, gdy będzie gotowy.

  4. Jeśli istnieje tylko kilka, które wiesz, że nie zajmie dużo pamięci, myślę, że jest OK. Nadal uważam, że buforowanie może być lepsze.

Powiązane problemy