2013-05-05 67 views
4

我正在製作媒體播放器應用程序,並希望加載專輯圖像以在ListView中顯示。現在它可以很好地處理我從last.fm自動下載的圖像,這些圖像在500x500 png以下。不過,我最近添加了另一個面板到我的應用程序,允許查看全屏幕作品,所以我已經用一些大的(1024x1024)PNG取代了我的一些作品。以縮略圖加載許多大型位圖圖像 - Android

現在,當我滾動多個具有高分辨率圖形的相冊時,我的BitmapFactory上出現java.lang.OutOfMemoryError。

static public Bitmap getAlbumArtFromCache(String artist, String album, Context c) 
    { 
    Bitmap artwork = null; 
    File dirfile = new File(SourceListOperations.getAlbumArtPath(c)); 
    dirfile.mkdirs(); 
    String artfilepath = SourceListOperations.getAlbumArtPath(c) + File.separator + SourceListOperations.makeFilename(artist) + "_" + SourceListOperations.makeFilename(album) + ".png"; 
    File infile = new File(artfilepath); 
    try 
    { 
     artwork = BitmapFactory.decodeFile(infile.getAbsolutePath()); 
    }catch(Exception e){} 
    if(artwork == null) 
    { 
     try 
     { 
      artwork = BitmapFactory.decodeResource(c.getResources(), R.drawable.icon); 
     }catch(Exception ex){} 
    } 
    return artwork; 
    } 

有什麼我可以添加到限制所產生的位圖對象的大小來說,256x256?這就是縮略圖需要做的更大的工作,我可以製作一個重複的函數或參數來獲取全尺寸圖形以顯示全屏。

另外,我正在將這些位圖顯示在小圖像上,大約150x150到200x200。較小的圖像比較大的圖像比較好。是否有任何方法可以應用縮小過濾器來平滑圖像(也許是抗鋸齒)?如果我不需要,我不想緩存一堆其他縮略圖文件,因爲這會使管理圖片圖像變得更加困難(目前您只需在目錄中轉儲新的縮略圖文件,並且它們將在下次自動使用他們得到加載)。

完整的代碼位於src/com/calcprogrammer1/calctunes/AlbumArtManager.java中的http://github.org/CalcProgrammer1/CalcTunes,儘管其他函數沒有多少區別(如果圖像丟失,可以返回檢查last.fm)。

+0

使用懶惰列表或通用圖像加載程序。隨着這個http://developer.android.com/training/improving-layouts/smooth-scrolling.html。 Lazy List和UIL加載縮小版的位圖。 http://stackoverflow.com/questions/15621936/whats-lazylist – Raghunandan 2013-05-05 09:56:24

回答

2

我用這個私有函數設置我想要的大小爲我的縮略圖:

//decodes image and scales it to reduce memory consumption 
public static Bitmap getScaledBitmap(String path, int newSize) { 
    File image = new File(path); 

    BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    options.inInputShareable = true; 
    options.inPurgeable = true; 

    BitmapFactory.decodeFile(image.getPath(), options); 
    if ((options.outWidth == -1) || (options.outHeight == -1)) 
     return null; 

    int originalSize = (options.outHeight > options.outWidth) ? options.outHeight 
      : options.outWidth; 

    BitmapFactory.Options opts = new BitmapFactory.Options(); 
    opts.inSampleSize = originalSize/newSize; 

    Bitmap scaledBitmap = BitmapFactory.decodeFile(image.getPath(), opts); 

    return scaledBitmap;  
} 
+0

我發現一個解決方案非常類似於這個,你看起來更緊湊,所以我可以切換到它。謝謝! – CalcProgrammer1 2013-05-05 06:16:51

0
public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) 
{ 
    // First decode with inJustDecodeBounds=true to check dimensions 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeFile(path, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeFile(path, options); 
} 

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; 

    if (height > reqHeight || width > reqWidth) { 

     // Calculate ratios of height and width to requested height and width 
     final int heightRatio = Math.round((float) height/(float) reqHeight); 
     final int widthRatio = Math.round((float) width/(float) reqWidth); 

     // 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; 
} 

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html改編,但使用的負載從文件而不是資源。我添加了一個縮略圖選項,例如:

//Checks cache for album art, if it is not found return default icon 
static public Bitmap getAlbumArtFromCache(String artist, String album, Context c, boolean thumb) 
{ 
    Bitmap artwork = null; 
    File dirfile = new File(SourceListOperations.getAlbumArtPath(c)); 
    dirfile.mkdirs(); 
    String artfilepath = SourceListOperations.getAlbumArtPath(c) + File.separator + SourceListOperations.makeFilename(artist) + "_" + SourceListOperations.makeFilename(album) + ".png"; 
    File infile = new File(artfilepath); 
    try 
    { 
     if(thumb) 
     { 
      artwork = decodeSampledBitmapFromFile(infile.getAbsolutePath(), 256, 256); 
     } 
     else 
     { 
      artwork = BitmapFactory.decodeFile(infile.getAbsolutePath()); 
     } 

約恩的答案看起來非常相似,是一個比較凝聚,可能會使用該解決方案代替,但頁面獲得了BitmapFactory它的一些好的信息。

0

一種方法是AQuery library

這是一個庫,允許您從本地存儲或網址延遲加載圖像。支持諸如緩存和縮小等。

例懶負載的資源而不縮小:

AQuery aq = new AQuery(mContext); 
aq.id(yourImageView).image(R.drawable.myimage); 

實例來延遲加載在縮小文件對象的圖像:

InputStream ins = getResources().openRawResource(R.drawable.myImage); 
    BufferedReader br = new BufferedReader(new InputStreamReader(ins)); 
    StringBuffer sb; 
    String line; 
    while((line = br.readLine()) != null){ 
     sb.append(line); 
     } 

    File f = new File(sb.toString()); 

    AQuery aq = new AQuery(mContext); 
    aq.id(yourImageView).image(f,350); //Where 350 is the width to downscale to 

例如何從本地存儲的URL下載緩存,本地存儲緩存和調整大小。

AQuery aq = new AQuery(mContext); 
aq.id(yourImageView).image(myImageUrl, true, true, 250, 0, null); 

這將在myImageUrl開始圖像的異步下載,它的大小調整爲250寬度和緩存在內存中,並storage.Then它會顯示在你的yourImageView圖像。每當myImageUrl的圖像被下載並緩存之前,這行代碼就會加載緩存在內存或存儲器中的代碼。

通常這些方法將在列表適配器的getView方法中調用。

有關AQuery圖像加載功能的完整文檔,可以查看the documentation

0

這是很容易與droidQuery完成:

final ImageView image = (ImageView) findViewById(R.id.myImage); 
$.ajax(new AjaxOptions(url).type("GET") 
          .dataType("image") 
          .imageHeight(256)//set the output height 
          .imageWidth(256)//set the output width 
          .context(this) 
          .success(new Function() { 
           @Override 
           public void invoke($ droidQuery, Object... params) { 
            $.with(image).val((Bitmap) params[0]); 
           } 
          }) 
          .error(new Function() { 
           @Override 
           public void invoke($ droidQuery, Object... params) { 
            droidQuery.toast("could not set image", Toast.LENGTH_SHORT); 
           } 
          })); 

您也可以使用緩存的cachecacheTimeout方法的響應。