user2410644
user2410644

Reputation: 3891

Create ArrayList of Bitmap thumbnails

I am trying to create an application that shows multiple wallpapers which can be set at a button press. Threrfore I created a ViewPager with 10 different Fragments. Each fragment should show a section of the wallpaper in full screen. The problem is, that the wallpapers are very high definition (3000*2500) which causes in an OutOfMemoryException. This is why I first wanted to generate an ArrayList full of Bitmaps of the screen size instead of this high resolution. Still, I get an OutOfMemoryException. Here's my code how I tried to achieve this:

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

Is there a better solution for my problem? I've got several wallpapers with different side-ratios. I just want to get the dimension of the screen cut out of this wallpaper and show it in full-screen. How can I achieve this?

Thanks in advance

Upvotes: 0

Views: 553

Answers (3)

Jay Snayder
Jay Snayder

Reputation: 4338

If you are trying to provide a segment that shows them small thumbnails, then you should load in small thumbnails at an appropriate size. Don't load the images at full size. If you have control over the resources, then I would just load in like 300 x 250 small thumbnails there. When they select the appropriate thumbnail, then use that as a map to your full-blown image that it corresponds to and load that.

It would also be best to make sure that it will fit in memory. There are several ways to do that following the loading of bitmaps efficiently link provided by Google. However

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

Upvotes: 1

BDRSuite
BDRSuite

Reputation: 1612

The image you are trying to load in your thumbnail typically requires about 7MB which in turn could produce out of memory. You need to scale down your image to a smaller size before displaying it in your thumbnail.

Android training center has this topic handling bitmaps efficiently will help you to address your issue.

Upvotes: 1

kc ochibili
kc ochibili

Reputation: 3131

Try resizing the bitmap before displaying.

If that's not what you want, Then do this

In your manifest file, set android: LargeHeap = "true"

If that still doesn't satisfy you, then you'd have to hold the bitmap outside java---->. https://github.com/AndroidDeveloperLB/AndroidJniBitmapOperations

Upvotes: 0

Related Questions