Search code examples
androidandroid-bitmapbitmapfactory

BitmapFactory downsamples unexpectedly image


In my android application, I upload and download JPEG images. For some images BitmapFactory downsamples the downloaded image and I don't understand why and how to stop it from doing so. I log the Bitmap object size when I upload and download the images:

Uploading image with size 3840x2160 Opening received image of size 2601584B degradation 0 decoded 384x216

So here my image width and height are divided by 10 after decoding by BitmapFactory. For another image I go from 3480x4640 to 217x290, so a division by 16. I first thought it could be caused by image dpi metadata, so I tried to force it when opening the image with the following code:

BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 1 << degradation;
opts.inScaled = false;
opts.inDensity = 1;
opts.inTargetDensity = 1;
opts.inScreenDensity = 1;
final Bitmap original = BitmapFactory.decodeByteArray(data, 0, data.length, opts);
Log.d(Tags.IMAGES, "Opening received image of size " + data.length + " degradation " + degradation + " decoded " + original.getWidth() + "x" + original.getHeight());

As you can see the number of bytes (2MB) I give the BitmapFactory is consistent with a large image not with a 300x200px image. So my uploading code and downloading code are correct I have the right data before decoding.

I forced all the densities to avoid scaling and also disabled scaling and my sample size is 1 since my degradation is 0 so I don't force any subsampling. I still end with a very small image. And BitmapFactory.decodeByteArray quickly calls native code so I can't really debug that.

I tried:

  • settings all the density in the BitmapFactory.Options object to 0 but this didn't change a thing.
  • setting up the density of the bitmap before uploading, no effect (originally these two subsampled images had a density of 420).
  • reading the size of the bitmap before decoding it fully (via justDecodeBounds), and the size returned this way is also too small.
  • not pass any options to the decodeByteArray method, still the image is too small.

Solution

  • Ok after more investigation I found the issue and it was due to another part of the code. Due to a race condition in the application I was writing to the same file the image and a miniature of it concurrently. So I ended up with a large image file but its beginning was overridden with a small image, and this is why BitmapFactory creates this small image. Sorry the issue was not in this part of the code so you couldn't find it.