2013-05-05 45 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方法的响应。