2011-07-14 70 views
1

的很多人我有很大的圖片也有問題。 好的,在這裏我的代碼。我發現在stackoverflow如何解決這個使用BitmapFactory.Options。但在我的情況下,我得到的圖像不是來自文件。誰能告訴我如何與已經在內存中創建位圖來做到這一點(我得到這個圖片從相機手機)問題的大圖(java.lang.OutOfMemoryError:位圖大小超過VM預算)

public void getImageAndSend() 
    { 

    Bitmap newbmp ; 
     newbmp= Bitmap.createBitmap(oBmp.getWidth(), oBmp.getHeight(),oBmp.getConfig());////<----------error here 
     log("widt oBmp = "+oBmp.getWidth());/// width = 2048 
     log(" height oBmp = "+oBmp.getHeight());///height 1538 
     //BitmapFactory.Options options = new BitmapFactory.Options(); // <----- it's possible to do it without `BitmapFactory.decodeFile(pathToFile,options) ?? 
     //options.inTempStorage = new byte[16*1024]; 
      Canvas canvas = new Canvas(newbmp); 
      //code 
    System.gc();/// can't right understand but this line fixed this problem on emulator but not on real device 

}

請告訴我如何解決我的問題呢? :。( 在模擬器我不是有這樣的錯誤,但在真正的設備,我看到這個錯誤(位圖大小超過VM預算) 問候,彼得

回答

0

,因爲你是從攝像機獲取圖像,獲取圖像的URI你在onActivityResult)捕獲(方法如下

Uri selectedImageUri=intent.getData(); 
String actualPath=getRealPathFromURI(selectedImageUri); 
File file=new File(actualPath); 
Bitmap bitmap=decodeFile(file); //this is new bitmap which you can use for your purpose 

public String getRealPathFromURI(Uri contentUri) { 
     String[] proj = { MediaStore.Images.Media.DATA }; 
     Cursor cursor = managedQuery(contentUri, proj, null, null, null); 
     int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); 
     cursor.moveToFirst(); 
     return cursor.getString(column_index); 
    } 


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=70; 

      //Find the correct scale value. It should be the power of 2. 
      int width_tmp=o.outWidth, height_tmp=o.outHeight; 
      int scale=1; 
      while(true){ 
       if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE) 
        break; 
       width_tmp/=2; 
       height_tmp/=2; 
       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; 
    } 

希望這helps.This是很熟悉的問題當u處理來自phone.check this拍攝出高品質的圖像太

+0

oBmp - 我的位圖,我從byteArray中獲取,而不是從意圖。 BMP位= BitmapFactory.decodeByteArray(字節,0,bytes.length);我可以在這裏使用選項嗎? – Peter

+0

ü說,ü[R獲得的圖像從相機phone.aren't你?如果ü可以elobrate在笏ü[R從那裏幹什麼呢?那麼爲什麼ü需要從字節數組怎麼做呢? – androidGuy

+0

公共無效onPictureTaken(字節[] paramArrayOfByte,相機paramCamera) \t {} – Peter

0

這裏是我BitmpaHelper類如果證明的OutOfMemoryError :-)

import java.io.File; 
import java.io.FileInputStream; 

import android.graphics.Bitmap; 
import android.graphics.Bitmap.Config; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Matrix; 
import android.graphics.drawable.BitmapDrawable; 
import android.graphics.drawable.Drawable; 

public class BitmapHelper 
{ 

    //decodes image and scales it to reduce memory consumption 
    public static Bitmap decodeFile(File bitmapFile, int requiredWidth, int requiredHeight, boolean quickAndDirty) 
    { 
     try 
     { 
      //Decode image size 
      BitmapFactory.Options bitmapSizeOptions = new BitmapFactory.Options(); 
      bitmapSizeOptions.inJustDecodeBounds = true; 
      BitmapFactory.decodeStream(new FileInputStream(bitmapFile), null, bitmapSizeOptions); 

      // load image using inSampleSize adapted to required image size 
      BitmapFactory.Options bitmapDecodeOptions = new BitmapFactory.Options(); 
      bitmapDecodeOptions.inTempStorage = new byte[16 * 1024]; 
      bitmapDecodeOptions.inSampleSize = computeInSampleSize(bitmapSizeOptions, requiredWidth, requiredHeight, false); 
      bitmapDecodeOptions.inPurgeable = true; 
      bitmapDecodeOptions.inDither = !quickAndDirty; 
      bitmapDecodeOptions.inPreferredConfig = quickAndDirty ? Bitmap.Config.RGB_565 : Bitmap.Config.ARGB_8888; 

      Bitmap decodedBitmap = BitmapFactory.decodeStream(new FileInputStream(bitmapFile), null, bitmapDecodeOptions); 

      // scale bitmap to mathc required size (and keep aspect ratio) 

      float srcWidth = (float) bitmapDecodeOptions.outWidth; 
      float srcHeight = (float) bitmapDecodeOptions.outHeight; 

      float dstWidth = (float) requiredWidth; 
      float dstHeight = (float) requiredHeight; 

      float srcAspectRatio = srcWidth/srcHeight; 
      float dstAspectRatio = dstWidth/dstHeight; 

      // recycleDecodedBitmap is used to know if we must recycle intermediary 'decodedBitmap' 
      // (DO NOT recycle it right away: wait for end of bitmap manipulation process to avoid 
      // java.lang.RuntimeException: Canvas: trying to use a recycled bitmap [email protected] 
      // I do not excatly understand why, but this way it's OK 

      boolean recycleDecodedBitmap = false; 

      Bitmap scaledBitmap = decodedBitmap; 
      if (srcAspectRatio < dstAspectRatio) 
      { 
       scaledBitmap = getScaledBitmap(decodedBitmap, (int) dstWidth, (int) (srcHeight * (dstWidth/srcWidth))); 
       // will recycle recycleDecodedBitmap 
       recycleDecodedBitmap = true; 
      } 
      else if (srcAspectRatio > dstAspectRatio) 
      { 
       scaledBitmap = getScaledBitmap(decodedBitmap, (int) (srcWidth * (dstHeight/srcHeight)), (int) dstHeight); 
       recycleDecodedBitmap = true; 
      } 

      // crop image to match required image size 

      int scaledBitmapWidth = scaledBitmap.getWidth(); 
      int scaledBitmapHeight = scaledBitmap.getHeight(); 

      Bitmap croppedBitmap = scaledBitmap; 

      if (scaledBitmapWidth > requiredWidth) 
      { 
       int xOffset = (scaledBitmapWidth - requiredWidth)/2; 
       croppedBitmap = Bitmap.createBitmap(scaledBitmap, xOffset, 0, requiredWidth, requiredHeight); 
       scaledBitmap.recycle(); 
      } 
      else if (scaledBitmapHeight > requiredHeight) 
      { 
       int yOffset = (scaledBitmapHeight - requiredHeight)/2; 
       croppedBitmap = Bitmap.createBitmap(scaledBitmap, 0, yOffset, requiredWidth, requiredHeight); 
       scaledBitmap.recycle(); 
      } 

      if (recycleDecodedBitmap) 
      { 
       decodedBitmap.recycle(); 
      } 
      decodedBitmap = null; 

      scaledBitmap = null; 
      return croppedBitmap; 
     } 
     catch (Exception ex) 
     { 
      ex.printStackTrace(); 
     } 
     return null; 
    } 

    /** 
    * compute powerOf2 or exact scale to be used as {@link BitmapFactory.Options#inSampleSize} value (for subSampling) 
    * 
    * @param requiredWidth 
    * @param requiredHeight 
    * @param powerOf2 
    *   weither we want a power of 2 sclae or not 
    * @return 
    */ 
    public static int computeInSampleSize(BitmapFactory.Options options, int dstWidth, int dstHeight, boolean powerOf2) 
    { 
     int inSampleSize = 1; 

     // Raw height and width of image 
     final int srcHeight = options.outHeight; 
     final int srcWidth = options.outWidth; 

     if (powerOf2) 
     { 
      //Find the correct scale value. It should be the power of 2. 

      int tmpWidth = srcWidth, tmpHeight = srcHeight; 
      while (true) 
      { 
       if (tmpWidth/2 < dstWidth || tmpHeight/2 < dstHeight) 
        break; 
       tmpWidth /= 2; 
       tmpHeight /= 2; 
       inSampleSize *= 2; 
      } 
     } 
     else 
     { 
      // Calculate ratios of height and width to requested height and width 
      final int heightRatio = Math.round((float) srcHeight/(float) dstHeight); 
      final int widthRatio = Math.round((float) srcWidth/(float) dstWidth); 

      // Choose the smallest ratio as inSampleSize value, this will guarantee 
      // a final image with both dimensions larger than or equal to the 
      // requested height and width. 
      inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 
     } 

     return inSampleSize; 
    } 

    public static Bitmap drawableToBitmap(Drawable drawable) 
    { 
     if (drawable instanceof BitmapDrawable) 
     { 
      return ((BitmapDrawable) drawable).getBitmap(); 
     } 

     Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888); 
     Canvas canvas = new Canvas(bitmap); 
     drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 
     drawable.draw(canvas); 

     return bitmap; 
    } 

    public static Bitmap getScaledBitmap(Bitmap bitmap, int newWidth, int newHeight) 
    { 
     int width = bitmap.getWidth(); 
     int height = bitmap.getHeight(); 
     float scaleWidth = ((float) newWidth)/width; 
     float scaleHeight = ((float) newHeight)/height; 

     // CREATE A MATRIX FOR THE MANIPULATION 
     Matrix matrix = new Matrix(); 
     // RESIZE THE BIT MAP 
     matrix.postScale(scaleWidth, scaleHeight); 

     // RECREATE THE NEW BITMAP 
     Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false); 
     return resizedBitmap; 
    } 

} 
0

我在我的Android應用程序相同的問題。當你從一個大尺寸的圖像解碼一個位圖並設置爲imageBitmap到一個圖像視圖時,你的應用程序可能會變慢,經過幾次嘗試,你會得到一個「內存不足的例外」

你可以使用通用圖像加載程序。 https://github.com/nostra13/Android-Universal-Image-Loader

String url = "file://" + your_file_path_on_sd_card; 
com.nostra13.universalimageloader.core.ImageLoader.getInstance().displayImage(url, ivPicture, options); 
相關問題