【问题标题】:Create ArrayList of Bitmap thumbnails创建位图缩略图的 ArrayList
【发布时间】:2014-10-22 01:55:10
【问题描述】:

我正在尝试创建一个显示多个壁纸的应用程序,这些壁纸可以在按下按钮时进行设置。 Threrfore 我创建了一个包含 10 个不同片段的 ViewPager。每个片段应全屏显示壁纸的一部分。问题是,壁纸的清晰度非常高 (3000*2500),这会导致 OutOfMemoryException。这就是为什么我首先想生成一个充满屏幕大小位图的 ArrayList,而不是这种高分辨率。尽管如此,我还是得到了 OutOfMemoryException。这是我尝试实现此目的的代码:

public ArrayList<Bitmap> createThumbnails() {
    ArrayList<Bitmap> result = new ArrayList<Bitmap>();
    for(int i = 0; i < NUM_PAGES; i++) {

        //Bitmaps will be loaded here by resource, they're called w_0, w_1, w_2...

        Bitmap b0 = BitmapFactory.decodeResource(getResources(), getResources().getIdentifier("w_" + i, "drawable", getPackageName()));

        //Here the thumbnail gets created with new Dimensions (screenWidth and screenHeight)

        Bitmap b1 = Bitmap.createBitmap(b0, 0, 0, screenWidth, screenHeight);

        //The full-sized Bitmap gets recycled to gain some memory back

        b0.recycle();

        //The resized Bitmap 'b1' gets added to the ArrayList and the loop repeats

        result.add(b1);
    }
    return result;
}

我的问题有更好的解决方案吗?我有几张不同侧面比例的壁纸。我只想从这张壁纸中截取屏幕的尺寸并全屏显示。我怎样才能做到这一点?

提前致谢

【问题讨论】:

标签: java android android-fragments bitmap


【解决方案1】:

您尝试在缩略图中加载的图像通常需要大约 7MB,这反过来可能会导致内存不足。您需要先将图片缩小到更小的尺寸,然后才能在缩略图中显示。

Android 培训中心有这个主题handling bitmaps efficiently 将帮助您解决您的问题。

【讨论】:

  • 如果我缩小刚刚生成的图像,如何将其拉伸到全屏?我已将我的 ImageView 属性都设置为“match_parent”,拉伸是否自动完成?感谢您的建议!
  • @user2410644 您可以使用视图的setScaleType 来确定您希望壁纸的显示方式,这很可能是一种裁剪形式。你甚至可能需要使用setAdjustViewBounds(true)
【解决方案2】:

如果您尝试提供向他们显示小缩略图的片段,那么您应该以适当的大小加载小缩略图。不要以全尺寸加载图像。如果您可以控制资源,那么我会在那里加载 300 x 250 的小缩略图。当他们选择适当的缩略图时,然后将其用作与它对应的完整图像的映射并加载它。

最好确保它适合内存。在 Google 提供的 loading of bitmaps efficiently 链接之后,有几种方法可以做到这一点。不过

private Bitmap getImage(String path)
{
    try
    {
        final int sizeFactors[] = { 1, 2, 4, 8, 16, 32 };

        if (new File(path).exists())
        {
            BitmapFactory.Options options = new BitmapFactory.Options();
            for (int i = 0; i < sizeFactors.length; ++i)
            {
                try
                {
                     options.inSampleSize = sizeFactors[i];
                     Bitmap bmp = BitmapFactory.decodeFile(path, options);

                     if(bmp.getHeight() > MyImageView.MAXIMUM_BITMAP_HEIGHT ||
                        bmp.getWidth() > MyImageView.MAXIMUM_BITMAP_WIDTH)
                     {
                        continue;
                     }

                        /*
                         * @category Check against EXIF data if the image needs to be rotated or not for viewing.
                         */
                        Matrix matrix = new Matrix ();
                        ExifInterface exif = new ExifInterface(path); 
                        int orientation = exif.getAttributeInt (ExifInterface.TAG_ORIENTATION, 1); 
                        switch(orientation) 
                        { 
                            case ExifInterface.ORIENTATION_NORMAL:
                                break; 
                            case ExifInterface.ORIENTATION_ROTATE_90: 
                                matrix.postRotate (90); 
                                break; 
                            case ExifInterface.ORIENTATION_ROTATE_180: 
                                matrix.postRotate (180);
                                break; 
                            case ExifInterface.ORIENTATION_ROTATE_270:
                                matrix.postRotate (270); 
                                break; 
                            default: 
                        } 

                        bmp = Bitmap.createBitmap (bmp, 0, 0, bmp.getWidth (), bmp.getHeight (), matrix, true);

                        return bmp;
                    } catch (OutOfMemoryError outOfMemory)
                    {
                        Log.d("MyLog", "Resampling to fit the image on the screen.");
                    }
                }
                throw new Exception("Not enough memory for loading image");
            }
        } catch (Exception e)
        {
            Log.w("MyLog", "Exception.");
        }
        return null;
    }

【讨论】:

    【解决方案3】:

    在显示之前尝试调整位图的大小。

    如果这不是你想要的, 然后这样做

    在您的清单文件中,设置 机器人:LargeHeap =“真”

    如果这仍然不能满足您,那么您必须将位图保存在 java 之外---->。 https://github.com/AndroidDeveloperLB/AndroidJniBitmapOperations

    【讨论】:

    • 这是我的想法。我首先使用我发布的这段代码 sn-p 创建 ArrayList,并尝试绘制这些真实图像的“缩略图”。
    • 位图数组列表对内存来说非常沉重。也许您应该尝试位图 url 或文件路径的数组列表。
    • 所有位图都显示在 ViewPager 中,所以我猜它们都是同时显示的,如果它们是通过 ArrayList 绘制或通过它们的 URL 加载(同时)有区别吗?
    • 将位图保存在一个数组中就像同时邀请您学校的所有朋友进入您的房间。您应该只在需要时创建位图,并在完成后立即发布它们
    • 所以它是否显示在 ViewPager 中并不重要。分配给位图的内存仍然很重要。所以是的,它有所作为。
    猜你喜欢
    • 2011-02-18
    • 2012-03-19
    • 2012-02-04
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 2013-05-31
    • 2018-10-31
    • 2014-11-25
    相关资源
    最近更新 更多