2013-04-09 5 views
5

Utworzono ciąg znaków base64 ze zdjęcia na karcie SD za pomocą tego (poniższego) kodu i działa, ale kiedy próbuję go zdekodować (jeszcze dalej poniżej), otrzymuję numer java.lang.outOfMemoryException, prawdopodobnie dlatego, że nie dzielę łańcucha na rozsądny rozmiar, zanim go zdekoduję, tak jak ja, zanim go zakoduję.Dekodowanie dużego łańcucha base64

byte fileContent[] = new byte[3000]; 
StringBuilder b = new StringBuilder(); 
try{ 
    FileInputStream fin = new FileInputStream(sel); 
    while(fin.read(fileContent) >= 0) { 
    b.append(Base64.encodeToString(fileContent, Base64.DEFAULT)); 
    } 
}catch(IOException e){ 

} 

Powyższy kod działa dobrze, ale problem pojawia się, gdy próbuję zdekodować obraz za pomocą następującego kodu;

byte[] imageAsBytes = Base64.decode(img.getBytes(), Base64.DEFAULT); 
ImageView image = (ImageView)this.findViewById(R.id.ImageView); 
image.setImageBitmap(
    BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length) 
); 

Próbowałem w ten sposób zbyt

byte[] b = Base64.decode(img, Base64.DEFAULT); 
Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length); 
image.setImageBitmap(bitmap); 

Teraz zakładam, że muszę podzielić ciąg na sekcje, jak mojego kodu kodowania obrazu, ale nie mam pojęcia, jak go o to robi .

Odpowiedz

13

Potrzebny jest dekodowanie obrazu w wątku tła, takim jak AsyncTask lub potrzebujesz zmniejszyć jakość obrazu za pomocą BitmapFactory. Przykład:

BitmapFactory.Options options = new BitmapFactory.Options(); 

      options.inSampleSize = 2; 
      options.inPurgeable=true; 
     Bitmap bm = BitmapFactory.decodeFile("Your image exact loaction",options); 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     bm.compress(Bitmap.CompressFormat.JPEG, 100, baos); //bm is the bitmap object 

     byte[] b = baos.toByteArray(); 
     String encodedImage = Base64.encodeToString(b, Base64.DEFAULT); 
+0

To niesamowite rozwiązanie! Działa doskonale – jcw

1

masz dwie problemu

  • kodowanie base64 wymaga znacznie więcej przestrzeni. 3 bajty konwertować do 4 znaków (współczynnik 8/3)
  • przeczytać cały plik na raz

w taki sam sposób Twoja pierwsza podejście rozwiązuje te problemy. Więc po prostu użyć tej wersji

tą drogą, dlaczego używasz decodeByteArray i nie decodeFile

+0

Używam tablicy bajtów dekodowania, ponieważ po zakodowaniu obrazu, nie umieszczam go w pliku, przechowuję go w zmiennej statycznej, a następnie dostęp z następnego pliku aktywacji – jcw

+0

Czy plik dekodowania jest bardziej wydajny? – jcw

+0

W pewien sposób zależy od konkretnej implementacji. decodeFile nie potrzebuje (ogromnej) tablicy bajtów, jest prawdopodobne, że natywna (C++?) implementacja jest znacznie wydajniejsza w pamięci –

1

Można spróbować zdekodować do pliku tymczasowego i utworzyć obraz z tego pliku.

Co do base64, to 6 bitów na znak, lub 6x4 = 24 bity = 3 bajty na 4 znaki. Więc jeśli weźmiesz 4 znaki base64, nie złamiesz odpowiednich 3 bajtów. Oznacza to, że możesz dzielić dane zakodowane w base64 na indeksy znaków, które są wielokrotnością 4.

+0

Tworzenie pliku tymczasowego brzmi tak, jakby to mogło zadziałać, dam mu szansę – jcw