0

I am using BitmapFun from the training materials to display my images in a GridView. But the code is returning very blurry images. I tracked one of the culprits to line 184 of class ImageResizer in the method decodeSampledBitmapFromDescriptor.

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

Here is the actual method

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) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while (halfHeight / inSampleSize > reqHeight && halfWidth / inSampleSize > reqWidth) {
                inSampleSize *= 2;
            }

            // This offers some additional logic in case the image has a strange
            // aspect ratio. For example, a panorama may have a much larger
            // width than height. In these cases the total pixels might still
            // end up being too large to fit comfortably in memory, so we should
            // be more aggressive with sample down the image (=larger inSampleSize).

            long totalPixels = width * height / inSampleSize;

            // Anything more than 2x the requested pixels we'll sample down further
            final long totalReqPixelsCap = reqWidth * reqHeight * 2;

            while (totalPixels > totalReqPixelsCap) {
                inSampleSize *= 2;
                totalPixels /= 2;
            }
        }
        return inSampleSize;
    }

So what I want is to not be so aggressive in sampling down. But then that leads to some questions: Since this is the official recommendation for loading bitmaps, what are some problems of changing the sampling to be less aggressive? Has anyone had to change this code to get better quality pictures? Is my investigation even correct? i.e. is this piece of code the cause of my blurry images? This is not an exhaustive list of questions/doubts, but this should give the reader a sense for my concerns. And last: how do I resolve this issue without interference with the purpose of BitmapFun? Clearly there is a reason I went to BitmapFun: my app wasn't working properly and was crashing constantly. Now it does not crash, but the images are too blurry.

learner
  • 11,490
  • 26
  • 97
  • 169
  • "what are some problems of changing the sampling to be less aggressive" -- You're very likely going to frequently experience OutOfMemoryErrors, especially on lower-memory devices. Don't be fooled, though, as you can still run into that error using inSampleSize, it's just far less likely because you're using lower-quality versions of the image. If you're seeing "aggressive" downsampling, you're probably using small source images and/or have incorrect values for the required Width/Height parameters. – Cruceo Mar 19 '14 at 19:31
  • You can try out my way of downsampling : http://stackoverflow.com/questions/16408505/how-to-downsample-images-correctly – android developer May 08 '14 at 15:06

1 Answers1

0

I had to change this code to get better quality pictures.

The change was simply to remove the "additional logic". That last while loop makes the images look really blurry.

--EDIT---

I think there is a bug in that "additional logic" causing the blurriness.

The totalPixels should be calculated by the square of inSampleSize because the image is sampled in both x and y dimensions. So simply change this line:

long totalPixels = width * height / (inSampleSize * inSampleSize);

Here's some more details about my case:

reqWidth = 357 reqHeight = 357

options.outWidth = 4128 options.outHeight = 3096

By the time it reaches the "additional logic", inSampleSize is 8

So, totalPixels = 1597536 and totalReqPixelsCap = 254898 (which is way off)