2012-07-29 11 views
13

Jak uzyskać mapę bitową o określonym rozmiarze (z zapisem w pamięci) od aparatu?Rozmiar mapy bitowej zwracanej przez kamerę za pomocą intencji?

Zaczynam intencję kamery z:

Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
cameraIntent.putExtra("return-data", true); 

photoUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "mytmpimg.jpg")); 
cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoUri);   

startActivityForResult(cameraIntent, REQUEST_CODE_CAMERA); 

obsłużyć wynik tutaj:

// Bitmap photo = (Bitmap) intent.getExtras().get("data"); 

Bitmap photo = getBitmap(photoUri); 

Teraz, jeśli mogę użyć komentowanej linii - uzyskać bitmapy bezpośrednio, mam zawsze 160 x 120 bitmapa, a to za mało. Jeśli załaduję go z identyfikatora URI za pomocą pewnych standardowych rzeczy znalezionych (metoda getBitmap), to ładuje mapę bitową 2560 x 1920 (!), Która zużywa prawie 20 MB pamięci.

Jak mogę załadować, powiedzmy 480 x 800 (taki sam rozmiar, jaki pokazuje podgląd kamery)?

Bez konieczności ładowania pamięci 2560 x 1920 i skalowania w dół.

+0

Czy to pomaga? http://stackoverflow.com/questions/3331527/android-resize-a-large-bitmap-file-to-scaled-output-file –

+0

Prawdopodobnie, ale nie ma sposobu, aby uzyskać to, co widzę na ekranie podczas robienia zdjęcia ...? Nie potrzebuję niczego więcej. – Ixx

+0

Link do Ben Rujil wskazuje na najlepszą odpowiedź, jaką znam. Twój wybór to w zasadzie zamiar wykonania miniatury lub natywne zdjęcie w pliku. Jeśli nie masz aplikacji aparatu, aby zapisać zdjęcie w niższej rozdzielczości, to jest twój wybór. – Sparky

Odpowiedz

2

Oto, co wymyśliłem, na podstawie metody o nazwie getBitmap() z biblioteki upraw, która została usunięta ze starej wersji Androida. Zrobiłem pewne modyfikacje:

private Bitmap getBitmap(Uri uri, int width, int height) { 
    InputStream in = null; 
    try { 
     int IMAGE_MAX_SIZE = Math.max(width, height); 
     in = getContentResolver().openInputStream(uri); 

     //Decode image size 
     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 

     BitmapFactory.decodeStream(in, null, o); 
     in.close(); 

     int scale = 1; 
     if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) { 
      scale = (int)Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE/(double) Math.max(o.outHeight, o.outWidth))/Math.log(0.5))); 
     } 

     //adjust sample size such that the image is bigger than the result 
     scale -= 1; 

     BitmapFactory.Options o2 = new BitmapFactory.Options(); 
     o2.inSampleSize = scale; 
     in = getContentResolver().openInputStream(uri); 
     Bitmap b = BitmapFactory.decodeStream(in, null, o2); 
     in.close(); 

     //scale bitmap to desired size 
     Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, width, height, false); 

     //free memory 
     b.recycle(); 

     return scaledBitmap; 

    } catch (FileNotFoundException e) { 
    } catch (IOException e) { 
    } 
    return null; 
} 

Co to robi to załadować bitmapę korzystając BitmapFactory.Options() + trochę wielkość próby - w ten sposób oryginalny obraz nie jest załadowany do pamięci. Problem polega na tym, że rozmiar próbki działa tylko w krokach. Dostaję "minimalny" rozmiar próbki dla mojego obrazu, używając trochę matematyki, którą skopiowałem - i odejmuję 1, aby uzyskać wielkość próbki, która wytworzy min. bitmapa większa niż rozmiar, którego potrzebuję.

A następnie, aby uzyskać bitmapę o dokładnie takim rozmiarze, należy wykonać normalne skalowanie za pomocą Bitmap.createScaledBitmap(b, width, height, false);. I natychmiast po przetworzeniu większej bitmapy. Jest to ważne, ponieważ, na przykład, w moim przypadku, aby uzyskać mapę bitową 480 x 800, większa bitmapa miała 1280 x 960 i zajmowała pamięć 4,6 MB.

Bardziej przyjazny dla pamięci sposób polegałby na nie dostosowaniu scale, więc mniejsza bitmapa zostanie przeskalowana w celu dopasowania do wymaganego rozmiaru. Ale to obniży jakość obrazu.

Powiązane problemy