Оптимальное использование BitmapFactory.Options.inSampleSize для скорости - PullRequest
22 голосов
/ 28 января 2011

Спасибо Schermvlieger за этот вопрос по anddev.org ,

Я просто копируюего вопрос к SO, так как никто не ответил на другом сайте, и я тоже столкнулся с той же проблемой.

Мне было интересно, как оптимально использовать BitmapFactory.Options.inSampleSize в отношении скорости отображения изображения.
В документации упоминается использование значений, которые являются степенью 2, поэтому я работаю с 2, 4, 8, 16 и т. Д.

Что мне интересно, так это:

  1. Должен ли я выполнить повторную выборку до наименьшего размера, который все еще превышает разрешение экрана, или следует выполнить выборку до размера, достаточного, чтобы избежать OutOfMemoryError?
  2. Как рассчитать максимальный размеризображение, которое все еще может отображаться без исчерпания памяти?Играет ли роль глубина цвета изображения и глубина дисплея?
  3. Эффективно ли отображать изображения с помощью двух механизмов (BitmapFactory для больших файлов, setImageURI() для меньших) Кстати, я использую ImageSwitcher.
  4. Поможет ли это создать Bitmap, BitmapFactory.Options и inTempStorage в начале приложения или создавать их только на лету, когда это необходимо??

Ответы [ 3 ]

11 голосов
/ 18 февраля 2011

Всегда старайтесь загружать и предварительно масштабировать изображения так, чтобы они были как можно ближе к их окончательному отображаемому размеру.Масштабирование изображений во время рисования чрезвычайно дорого, и его следует избегать любой ценой.

Учитывая стоимость памяти изображения, да, цветовая глубина играет очень важную роль.Изображения в формате ALPHA_8 используют 1 байт на пиксель, изображения в RGB_565 или ARGB_4444 используют 2 байта на пиксель, а изображения в ARGB_8888 используют 4 байта на пиксель.Глубина дисплея не имеет значения вообще.Вы всегда должны использовать ARGB_8888 для получения наилучшего возможного качества, но 565 может быть достаточно хорошим, если ваше изображение непрозрачное.

4 голосов
/ 09 февраля 2013

Вы задали хорошие вопросы, но все зависит от ваших потребностей и объема используемой памяти.Я рекомендую проверить эту ссылку для многих советов, касающихся растровых изображений: http://developer.android.com/training/displaying-bitmaps/index.html.

Короче говоря, вам следует подумать о кэшировании, понижающей дискретизации и использовании достаточно хорошего растрового формата, когда это возможно.

Вот мои ответы на ваши вопросы:

  1. Почему не оба?если вы считаете, что это может быть OOM, попробуйте перезапустить старые, неиспользуемые растровые изображения, а затем проверьте снова.

  2. вы можете рассчитать (приблизительный) размер растрового изображения:

    ширина * высота * bytesPerPixel

    где bytesPerPixel обычно равен 4 или 2 (в зависимости от формата растрового изображения).

  3. Никогда не использовал setImageURI, поэтому я не могу помочь вам стот.Я предлагаю загрузить изображения в фоновом потоке (использование asyncTask - один из способов сделать это) и показать их, когда они будут готовы.

  4. Если есть только несколько из них, которые, как вы знаете, не будутзанять много памяти, я думаю, это нормально.Я все еще думаю, что кэширование могло бы быть лучше.

3 голосов
/ 06 марта 2012

Здесь вы можете вызвать пользовательский метод shrinkmehtod, который фактически отправляет путь к строковому файлу, а также высоту и ширину, чтобы уменьшить изображение до метода.

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


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

Это пользовательский метод, позволяющий программно уменьшить размер изображения.

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;

    }

Надеюсь, это поможет вам уменьшить размер.

...