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

Размер растрового изображения, возвращаемого камерой с помощью намерения?

Как получить растровое изображение с определенным (с учетом памяти) размером с камерой?

Я начинаю с камеры:

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

Я обрабатываю результат здесь:

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

Bitmap photo = getBitmap(photoUri);

Теперь, если я использую прокомментированную строку - сразу получаю растровое изображение, всегда получаю растровое изображение размером 160 х 120, и это слишком мало. Если я загружу его из URI, используя некоторые стандартные материалы, которые я нашел (метод getBitmap), он загружает растровое изображение 2560 x 1920 (!) И потребляет почти 20 МБ памяти.

Как я могу загрузить 480 х 800 (тот же самый размер, который показывает мне предварительный просмотр камеры)?

Без необходимости загружать 2560 x 1920 в память и уменьшать масштаб.

4b9b3361

Ответ 1

Вот что я придумал на основе метода getBitmap() из библиотеки уроков, который был удален из старой версии Android. Я сделал некоторые изменения:

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

Что это такое - загрузить растровое изображение, используя BitmapFactory.Options() + некоторый размер выборки - таким образом исходное изображение не загружается в память. Проблема в том, что размер выборки просто работает поэтапно. Я получаю "минимальный" размер выборки для своего изображения, используя некоторые математические данные, которые я скопировал, и вычитаю 1, чтобы получить размер выборки, который приведет к минимуму. растровое изображение больше, чем размер, который мне нужен.

А затем, чтобы получить растровое изображение с точно запрошенным размером, выполните нормальное масштабирование с помощью Bitmap.createScaledBitmap(b, width, height, false);. И сразу же после этого перерабатывает большее растровое изображение. Это важно, потому что, например, в моем случае, чтобы получить растровое изображение 480 x 800, большее растровое изображение было 1280 x 960 и занимает память 4.6 МБ.

Более дружественным для памяти способом было бы не настраивать scale, поэтому меньшая растровая карта будет масштабироваться, чтобы соответствовать требуемому размеру. Но это уменьшит качество изображения.