BitmapFactory downsamples unexpectedly image
Asked Answered
C

1

11

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.
Callant answered 2/8, 2018 at 10:39 Comment(12)
Opening an image without BitmapFactory.Options does not downsample it. If you are fitting image into ImageView you should check out scaling type. I open 4k images and set as resource to zoomable ImageView and they don't get downsampled.Balmacaan
You can also use Glide, Picasso or any other image library to open image. You can get the full size image without any effort. I used to use Picasso, now using Glide to open images and set it to ImageViewBalmacaan
@Balmacaan Thanks, but I just tried without the Options parameters and had the same result. I don't reproduce with all my images so maybe there is something special about these downsampled imagesCallant
It's quite odd. Have you tried opening those images with any other image or gallery apps?Balmacaan
@Balmacaan Sure, they open fine in Gimp which gives the expected size in pixels.Callant
@Callant Just find if your images got downsampled from your server-end?Schoenberg
try saving your image directly to your physical storage first and check the properties of the downloaded image.Mutualize
How do you know the degradation is happening in your app and not your serverside? Just like Google Drive and Google Photo (as an example), it will reduce the image size/quality after user uploaded.Carcinomatosis
And, probably this situation is happening due to other code, it is helpful if you post full code hereCarcinomatosis
If you confirm that the image is not degraded on the server side, make sure you are correctly using the different options given to the BitmapFactory. Refer to this comment https://mcmap.net/q/186959/-most-memory-efficient-way-to-resize-bitmaps-on-android (Magic Combination) by Colt McAnlis to fully understand what the options do.Weasner
Can you provide an example of your problematic 3840x2160 image?Altarpiece
Have you tried setting outWidth and outHeight to your desired dimensions?Candidate
C
0

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.

Callant answered 15/8, 2018 at 15:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.