2012-07-02 52 views
2

如何使用給定的URI從SD卡獲取縮略圖? 我已經嘗試使用bitmapfactory,但性能不好或OutOfMemoryError 我打算把縮略圖放到有很多數據的列表視圖中 我應該使用縮略圖還是使用任何建議? 如果要使用縮略圖,那麼該怎麼做......?使用URI從SD卡獲取縮略圖

在此先感謝您的幫助

+0

你有沒有試過這種 http://stackoverflow.com/questions/1069095/how-do-you-create-a-thumbnail-image-out-of-a-jpeg在爪哇 – UdayaLakmal

回答

0

下面的方法可以用來獲取圖像的縮略圖:

private Bitmap getBitmap(String path) { 

    Uri uri = getImageUri(path); 
    InputStream in = null; 
    try { 
     final int IMAGE_MAX_SIZE = 1200000; // 1.2MP 
     in = mContentResolver.openInputStream(uri); 

     // Decode image size 
     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 
     BitmapFactory.decodeStream(in, null, o); 
     in.close(); 



     int scale = 1; 
     while ((o.outWidth * o.outHeight) * (1/Math.pow(scale, 2)) > IMAGE_MAX_SIZE) { 
      scale++; 
     } 
     Log.d(TAG, "scale = " + scale + ", orig-width: " + o.outWidth  + ", orig-height: " + o.outHeight); 

     Bitmap b = null; 
     in = mContentResolver.openInputStream(uri); 
     if (scale > 1) { 
      scale--; 
      // scale to max possible inSampleSize that still yields an image 
      // larger than target 
      o = new BitmapFactory.Options(); 
      o.inSampleSize = scale; 
      b = BitmapFactory.decodeStream(in, null, o); 

      // resize to desired dimensions 
      int height = b.getHeight(); 
      int width = b.getWidth(); 
      Log.d(TAG, "1th scale operation dimenions - width: " + width + ", height: " + height); 

      double y = Math.sqrt(IMAGE_MAX_SIZE 
        /(((double) width)/height)); 
      double x = (y/height) * width; 

      Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x,  (int) y, true); 
      b.recycle(); 
      b = scaledBitmap; 

      System.gc(); 
     } else { 
      b = BitmapFactory.decodeStream(in); 
     } 
     in.close(); 

     Log.d(TAG, "bitmap size - width: " +b.getWidth() + ", height: " + b.getHeight()); 
     return b; 
    } catch (IOException e) { 
     Log.e(TAG, e.getMessage(),e); 
     return null; 
    } 
} 

而且總是使用位圖後調用bitmap.recycle()方法。它會清除內存中的位圖。還要避免代碼中的內存泄漏。這將解決你的OOME。

+0

的編碼工作,但滾動並不那麼順利,即使有我的列表視圖上的10個項目。我已將IMAGE MAX SIZE設置爲100,但仍未解決性能問題。哦,我在我的自定義適配器上使用回收,並得到了'運行時異常:試圖使用回收位圖的畫布' – Sieryuu

+0

在回收它之前檢查(位圖!= null)。你使用哪個Android版本?如果它的3.0及以上版本在xml中爲listView提供hardwareAccelerated = true – Shrikant

0
// Parameters 
int w,h;  

// First only decode image size 
BitmapFactory.Options opt = new BitmapFactory.Options(); 
opt.inJustDecodeBounds = true; 
Bitmap bmp = BitmapFactory.decodeFile(file, opt); 

// Decode small enough image 
int heightRatio = (int)opt.outHeight/h; 
int widthRatio = (int)opt.outWidth/w; 
if (heightRatio > 1 || widthRatio > 1) 
{ 
     if (heightRatio > widthRatio) 
      opt.inSampleSize = heightRatio; 
     else 
      opt.inSampleSize = widthRatio; 
} 

opt.inJustDecodeBounds = false; 
bmp = BitmapFactory.decodeFile(file, opt); 
+0

感謝您的回答, 順便說一句我已經嘗試過你的編碼負載比我以前的代碼更快,但滾動的列表視圖不光滑。 – Sieryuu

0

使用ThumbnailUtils類來獲取圖像/視頻的拇指。

+0

好的,我會嘗試使用那個類。 – Sieryuu

0

試一試這段代碼,它修復了內存不足錯誤。改變你的高度和寬度。這裏intent_data2是文件路徑。

public Bitmap custom_SizedImage(String intent_data2) { 
     int targetHeight = 534, targetWidth = 534; 
     Options options = new Options(); 
     options.inJustDecodeBounds = true; 
     BitmapFactory.decodeFile(intent_data2, options); 
     double sampleSize = 0; 
     Boolean scaleByHeight = Math.abs(options.outHeight - targetHeight) >= Math 
       .abs(options.outWidth - targetWidth); 

     if (options.outHeight * options.outWidth * 2 >= 1638) { 
      sampleSize = scaleByHeight ? options.outHeight/targetHeight 
        : options.outWidth/targetWidth; 
      sampleSize = (int) Math.pow(2d, 
        Math.floor(Math.log(sampleSize)/Math.log(2d))); 
     } 
     options.inJustDecodeBounds = false; 
     options.inTempStorage = new byte[128]; 
     while (true) { 
      try { 
       options.inSampleSize = (int) sampleSize; 
       mBitmap = BitmapFactory.decodeFile(intent_data2, options); 
       Display display = getWindowManager().getDefaultDisplay(); 
       int width = display.getWidth(); 
       int height = display.getHeight(); 
       int screenDiff = height - width; 
       int screenRatio = screenDiff/3; 
       float scaleFactor = mBitmap.getWidth()/width; 
       float y_Pos = scaleFactor * screenRatio; 
       Matrix matrix = new Matrix(); 
       matrix.postScale(0.5f, 0.5f); 
       croppedBitmap = Bitmap.createBitmap(mBitmap, 0, (int) y_Pos, 
         mBitmap.getWidth(), mBitmap.getWidth(), matrix, true); 

       scaledBitmap = Bitmap.createBitmap(targetWidth, targetHeight, 
         Config.RGB_565); 

       float ratioX = targetWidth/(float) croppedBitmap.getWidth(); 
       float ratioY = targetHeight/(float) croppedBitmap.getHeight(); 
       float middleX = targetWidth/2.0f; 
       float middleY = targetHeight/2.0f; 

       Matrix scaleMatrix = new Matrix(); 
       scaleMatrix.setScale(ratioX, ratioY, middleX, middleY); 

       Canvas canvas = new Canvas(scaledBitmap); 
       canvas.setMatrix(scaleMatrix); 
       canvas.drawBitmap(croppedBitmap, 
         middleX - croppedBitmap.getWidth()/2, middleY 
           - croppedBitmap.getHeight()/2, new Paint(
           Paint.FILTER_BITMAP_FLAG)); 
       //saveImage(scaledBitmap); 

       break; 
      } catch (Exception ex) { 
       try { 
        sampleSize = sampleSize * 2; 
       } catch (Exception ex1) { 

       } 
      } 
     } 
     return scaledBitmap; 

}

+0

什麼是saveimage()方法? – Sieryuu

+0

如果你想保存圖像意味着使用該方法,否則評論它。 – Aerrow