Android из-за нехватки памяти с растровыми изображениями

1

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

Сначала я получаю ширину и высоту изображения и вычисляю размер выборки:

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(backgroundPath, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, getWidth(), getHeight());

Здесь, как я получаю размер выборки (хотя это не очень важно):

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {

    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    // NOTE: we could use Math.floor here for potential better image quality
    // however, this also results in more out of memory issues
    if (height > reqHeight || width > reqWidth) {
        if (width > height) {
            inSampleSize = Math.round((float)height / (float)reqHeight);
        } else {
            inSampleSize = Math.round((float)width / (float)reqWidth);
        }
    }

    return inSampleSize;
}

Теперь, когда у меня есть размер выборки, я загружаю изображение с диска на приблизительный размер (размер выборки):

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    options.inPurgeable = true;
    Bitmap bmp = BitmapFactory.decodeFile(backgroundPath, options);

Теперь я масштабирую это растровое изображение, которое я создал, до нужного мне размера и очистки:

    // scale the bitmap to the exact size we need
    Bitmap editedBmp = Bitmap.createScaledBitmap(bmp, (int) (width * scaleFactor), (int) (height * scaleFactor), true); 

    // clean up first bitmap
    bmp.recycle();
    bmp = null;
    System.gc();    // I know you shouldnt do this, but I'm desperate 

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

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

Какие-либо предложения?

Спасибо, Ник

  • 0
    Перед созданием editedBmp , editedBmp его ширину и высоту, а также scaleFactor, чтобы убедиться, что ваши параметры верны.
  • 0
    вместо createScaledBitmap вы можете сделать то, что здесь делается? developer.android.com/training/displaying-bitmaps/… просто изменить decodeResources на decodeFile и передать параметры размера?
Показать ещё 9 комментариев
Теги:
memory
memory-management
out-of-memory
bitmap

2 ответа

2
Лучший ответ

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

drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)

drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)
0

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

private Bitmap decodeFile(File f){
    try {
        //Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f),null,o);

        //The new size we want to scale to
        final int REQUIRED_SIZE=250;

        //Find the correct scale value. It should be the power of 2.
        int scale=1;
        while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
            scale*=2;

        //Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize=scale;
        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
    } catch (FileNotFoundException e) {}

    return null;
} 
  • 0
    При этом используется размер выборки, аналогичный тому, что я делаю на первом этапе моего вопроса. Это не дает вам точный размер необходимого размера.
  • 0
    Я думаю, что вызов Bitmap.createScaledBitmap (), который вы используете, переносит полный битовый образ в память. Я использую описанный выше метод для создания масштабированного растрового изображения, а затем я использую Bitmap.createScaledBitmap () в возвращенном растровом изображении, чтобы изменить его размер до нужного мне размера. Извините, я не помог вам.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню