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

OutofMemoryError: размер растрового изображения превышает бюджет VM (Android)

Получение исключения в BitmapFactory. Не уверен, в чем проблема. (Ну, я могу догадаться, но не знаю, почему это происходит)

ERROR/AndroidRuntime(7906): java.lang.OutOfMemoryError: bitmap size exceeds VM budget

ERROR/AndroidRuntime(7906):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:295)

Мой код довольно прост. Я определил формат XML с изображением по умолчанию. Я пытаюсь загрузить bm на SDCard (если присутствует - это). Если нет, отображается изображение по умолчанию. В любом случае.. Вот код:

public class showpicture extends Activity {
  public void onCreate(Bundle savedInstanceState) {

         /** Remove menu/status bar **/
         requestWindowFeature(Window.FEATURE_NO_TITLE);
         final Window win = getWindow();   
         win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

            Bitmap bm;
         super.onCreate(savedInstanceState);
         setContentView(R.layout.showpicture);
            try {
         ImageView mImageButton = (ImageView)findViewById(R.id.displayPicture);
         bm = Bitmap.createScaledBitmap(BitmapFactory.decodeFile("/sdcard/dcim/Camera/20091018203339743.jpg"),100, 100, true);
         parkImageButton.setImageBitmap(bm);
         }
         catch (IllegalArgumentException ex) {
          Log.d("MYAPP",ex.getMessage());
         } 
            catch (IllegalStateException ex) {

Неужели на bm=Bitmap.createScaledBitmap нет никаких мыслей? Я провел некоторое исследование на форумах, и он указал на этот пост Я просто не знаю, почему он не работает. Любая помощь будет замечательной! Спасибо,

Крис.

4b9b3361

Ответ 2

inSampleSize - хороший намек. Но фиксированное значение часто не работает нормально, поскольку большие растровые изображения из файлов обычно являются пользовательскими файлами, которые могут варьироваться от маленьких миниатюр до 12-мегапиксельных изображений из digicam.

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

public static Bitmap loadResizedBitmap( String filename, int width, int height, boolean exact ) {
    Bitmap bitmap = null;
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile( filename, options );
    if ( options.outHeight > 0 && options.outWidth > 0 ) {
        options.inJustDecodeBounds = false;
        options.inSampleSize = 2;
        while (    options.outWidth  / options.inSampleSize > width
                && options.outHeight / options.inSampleSize > height ) {
            options.inSampleSize++;
        }
        options.inSampleSize--;

        bitmap = BitmapFactory.decodeFile( filename, options );
        if ( bitmap != null && exact ) {
            bitmap = Bitmap.createScaledBitmap( bitmap, width, height, false );
        }
    }
    return bitmap;
}

Btw, в новых API-интерфейсах также есть много BitmapFactory.Option для подгонки изображения к экранам DPI, но я не уверен, действительно ли они упрощают что-либо. Использование android.util.DisplayMetrics.density или просто фиксированный размер для меньшего потребления памяти, похоже, лучше работает imho.

Ответ 3

Что касается ссылки , обратите внимание, что ошибка outOfMemory может быть решена следующим образом:

public Bitmap decodeFile(String filePath) {

Bitmap bitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inPurgeable = true;

try {
BitmapFactory.Options.class.getField("inNativeAlloc").setBoolean(options,true);

} catch (IllegalArgumentException e) {
    e.printStackTrace();
} catch (SecurityException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (NoSuchFieldException e) {
    e.printStackTrace();
}

if(filePath != null)
{
    bitmap = BitmapFactory.decodeFile(filePath, options);               
}

return bitmap;
}

Ответ 4

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

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap = BitmapFactory.decodeFile(mPathName, options);

Ответ 5

Обязательно защитите свое растровое изображение от ошибок из памяти! На большинстве платформ у Android не так много памяти, и он быстро заканчивается с растровыми изображениями. Кроме того, убедитесь, что вы как можно больше вручную переработали растровые изображения, я заметил, что сборка мусора может быть довольно медленной.

try{            
  Bitmap myFragileBitmap = Bitmap.createBitmap(500, 500, Bitmap.Config.ARGB_8888);
}
catch(IllegalArgumentException e){
  Log.e(TAG,"Illegal argument exception.");
}
catch(OutOfMemoryError e){
  Log.e(TAG,"Out of memory error :(");
}

Ответ 6

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

Ответ 7

используйте эти параметры в файле decode. Надеюсь, что u может объединить растровое изображение, превысив бюджетную проблему vm.

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

bfOptions.inDither=false;          //Disable Dithering mode
bfOptions.inPurgeable=true;       //Tell to gc that whether it needs free memory, the Bitmap can be cleared
bfOptions.inInputShareable=true;  //Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future
bfOptions.inTempStorage=new byte[32 * 1024]; 

Ответ 8

Вы проверили DDMS? С тем, с чем я сталкивался, это, вероятно, не размер изображений, потому что Android, похоже, отлично справляется с большими изображениями. Если вы отслеживаете кучу с помощью DDMS, вы обнаружите, что у вас много свободной памяти. Вы можете "развернуть" свою кучу, добавив эту

static { @SuppressWarnings("unused")
byte dummy[] = new byte[ 8*1024*1024 ]; }    

к вашему коду, чтобы заставить кучу расшириться. Это может сделать его немного реже. К сожалению, за исключением того, что он утверждает, что он не может выделить некоторое количество байтов. Скажем 1M. Если вы посмотрите на "свободную" линию, вы увидите, что самый большой блок → > 1M. Там что-то странное, что я не могу понять. Это не связано даже со скоростью прокручивания изображений. Я видел в каком-то потоке, что вы можете назвать "переработать" или так для растровых изображений. Я все еще не понимаю, почему это должно помочь, если размер кучи выше установленного размера.

Ответ 9

У меня возникла эта ошибка, когда я начал изменять размер изображения с 320x240 до примерно 64x240 (вниз), а затем импортировал в свой проект (так как я хотел улучшить скорость рендеринга, и до этого момента он содержал множество бесполезных альфа-областей).

теперь последний ответ имеет смысл:

Вы можете "развернуть" свою кучу, добавив этот статический {@SuppressWarnings ( "неиспользуемый" ) байтовый макет [] = новый байт [8 * 1024 * 1024]; } к вашему коду, чтобы заставить кучу расшириться. Это может сделать это немного меньше часто.

Я думаю, что это случилось со мной. Android автоматически расшифровывает чертежи в растровые изображения (а затем хранится в куче, все время компиляции?)

Я начал видеть ошибку, когда я использовал меньшую версию моего изображения во время выполнения (я масштабирую их во время выполнения, так как я программирую VGA-игру с ретро-графикой, используя BitmapFactory.decodeResource и Bitmap.createScaledBitmap).

это должно быть похоже на то, как Марве сказал: "Куча" недостаточно велика в моем случае после сокращения моего рисунка/изображения и импорта его в мой проект.

Мне удалось избавиться от моего OutOfMemoryException при изменении размера изображения до более крупного размера (320x240), который проверяет проблему, о которой я думаю?