2010-11-05 4 views
2

В моем приложении, я создаю растровое изображение из его цвета кода, как это:CreateBitmap вызывает OutOfMemory ошибку

int width=getImageWidth(); 
int height=getImageHeight(); 
int[] array=getbitmap(); 
int[] colorsAsIntegers = new int[width*height]; 
int i = 0; 
int j = 0; 

while (i<width*height*4) { 
colorsAsIntegers[j] = Color.argb(array[i], array[i+1], array[i+2], 
array[i+3]); 
i += 4; 
j++; 
} 

myBitmap=Bitmap.createBitmap(colorsAsIntegers, 
width, 
height, 
Bitmap.Config.ARGB_8888); 

И часто я получаю OutOfMemoryError :( Так как я могу использовать BitmapFactory оптимизации, чтобы избежать эта проблема? , потому что у меня нет входного потока или файла, у меня есть только массив, содержащий моих пикселей

Спасибо

+0

Сколько у вас большое изображение? На каком устройстве возникают проблемы? – I82Much

+0

Он не создает растровое изображение все время, когда мы получаем эту ошибку. http://stackoverflow.com/a/18625792/2403532 – Narasimha

ответ

1

Попробуйте субдискретизацию изображения, как показано here

3

Пара вещей ....

Android имеет очень серьезные проблемы с растровыми изображениями. Они выделяются в памяти, не содержащей мусора. Это хорошо. Они получают сборку мусора, когда собирает собственный битмап. То, что они не делают, - это перемещение, в то время как куча уплотняется. Это может привести к преждевременным ошибкам вне памяти из-за фрагментации кучи. Решение: вызовите Bitmap.recycle, как только закончите с растровым изображением. Это освобождает память не-gc и уменьшает проблемы фрагментации.

Вы также можете уменьшить давление памяти, создав пустое растровое изображение, а затем скопировав пиксели в строке за строкой из одного небольшого буфера. Java gc не особенно любит огромные массивы (хотя большие массивы могут быть перемещены во время gc). Снижение производительности незначительно и незначительно по сравнению с ударом производительности, вызванным преждевременным сбором мусора. Это уменьшит использование памяти на 49,99 процента.

1

пожалуйста расшифровать файл первым, для этого использовать этот код:

public static Bitmap new_decode(File f) { 

     // decode image size 

     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 
     o.inDither = false; // Disable Dithering mode 

     o.inPurgeable = true; // Tell to gc that whether it needs free memory, 
           // the Bitmap can be cleared 

     o.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 
     try { 
      BitmapFactory.decodeStream(new FileInputStream(f), null, o); 
     } catch (FileNotFoundException e1) { 
      // TODO Auto-generated catch block 
      e1.printStackTrace(); 
     } 

     // Find the correct scale value. It should be the power of 2. 
     final int REQUIRED_SIZE = 300; 
     int width_tmp = o.outWidth, height_tmp = o.outHeight; 
     int scale = 1; 
     while (true) { 
      if (width_tmp/1.5 < REQUIRED_SIZE && height_tmp/1.5 < REQUIRED_SIZE) 
       break; 
      width_tmp /= 1.5; 
      height_tmp /= 1.5; 
      scale *= 1.5; 
     } 

     // decode with inSampleSize 
     BitmapFactory.Options o2 = new BitmapFactory.Options(); 
     // o2.inSampleSize=scale; 
     o.inDither = false; // Disable Dithering mode 

     o.inPurgeable = true; // Tell to gc that whether it needs free memory, 
           // the Bitmap can be cleared 

     o.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 
     // return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); 
     try { 

//   return BitmapFactory.decodeStream(new FileInputStream(f), null, 
//     null); 
      Bitmap bitmap= BitmapFactory.decodeStream(new FileInputStream(f), null, null); 
      System.out.println(" IW " + width_tmp); 
      System.out.println("IHH " + height_tmp);   
       int iW = width_tmp; 
       int iH = height_tmp; 

       return Bitmap.createScaledBitmap(bitmap, iW, iH, true); 

     } catch (OutOfMemoryError e) { 
      // TODO: handle exception 
      e.printStackTrace(); 
      // clearCache(); 

      // System.out.println("bitmap creating success"); 
      System.gc(); 
      return null; 
      // System.runFinalization(); 
      // Runtime.getRuntime().gc(); 
      // System.gc(); 
      // decodeFile(f); 
     } catch (FileNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
      return null; 
     } 

    } 

Вы можете использовать android:largeHeap="true" запросить больший размер кучи упоминает об этом в файл манифеста, чтобы использовать большую кучу.

+0

Отметьте это как ответ, если он healps @sharktiger – Hamad