BitmapFactory.decodeFile always return null on Xiaomi
Asked Answered
L

2

0

Hello I have this piece of code:

EDIT:

imageName = data.getData();

try{
    InputStream stream = getContentResolver().openInputStream(imageName);

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    bitmap = BitmapFactory.decodeStream(stream,null,options);

    final int REQUIRED_WIDTH=(int)screenWidth;
    final int REQUIRED_HIGHT=(int)screenHeight;

    int scale=1;
    while(options.outWidth/scale/2>=REQUIRED_WIDTH && options.outHeight/scale/2>=REQUIRED_HIGHT)
        scale*=2;

    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize=scale;
    bitmap = BitmapFactory.decodeStream(stream, null, o2);

    if ( bitmap != null ){
        ok=true;
    }
}catch(Exception e){
    Toast.makeText(getBaseContext(),"error", Toast.LENGTH_SHORT).show();
}

But the bitmap is still null

Can Anyone tell me why ? or better... How to fix it ?

Luetic answered 2/10, 2014 at 18:57 Comment(6)
What is getPathFromURI()? If it is what I think it is, get rid of it, as a Uri is not necessarily a File.Chiba
I don't understand. I will add the method hereBoots
Delete that method. Read the blog post that I linked to. Use openInputStream() on a ContentResolver to read in the data at the Uri.Chiba
please check my updatesBoots
At this point, I have no idea what you are doing. If your objective is to get a Bitmap object on the data represented by the Uri, just pass stream to decodeStream() and get rid of tmp, the ByteArrayOutputStream, and the ByteArrayInputStream. Bear in mind that the image may be too big for your heap space.Chiba
Ok, so If I'll do it like it's now in edited post, how can I "resize" the image to get rid of outOfMemory Exception ?Boots
C
0

Ok, so If I'll do it like it's now in edited post, how can I "resize" the image to get rid of outOfMemory Exception ?

Aha! Now we are getting somewhere.

What you had, in a prior edit of your question, was:

  1. read the entire bitmap into a byte array
  2. write the entire bitmap into another byte array as a low-quality JPEG
  3. read the entire bitmap into a Bitmap, backed by yet a third byte array

This will result in your consuming ~2.1x the heap space of your current implementation, which is already giving you OutOfMemoryError messages. The byte arrays from #1 and #3 above will be the same size, equal to:

width x height x 4

where the width and height are expressed in pixels.

To reduce your memory consumption, you need to do to things:

  1. Read in the bitmap once, as your current code does.

  2. Use BitmapFactory.Options to control the decoding of the bitmap. In particular, use inSampleSize to reduce the number of pixels in the resulting Bitmap. Quoting the JavaDocs for inSampleSize:

If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory. The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16 the number of pixels. Any value <= 1 is treated the same as 1. Note: the decoder uses a final value based on powers of 2, any other value will be rounded down to the nearest power of 2.

This sample project demonstrates the use of inSampleSize for various hardcoded values. The actual Bitmap loading comes from:

private Bitmap load(String path, int inSampleSize) throws IOException {
  BitmapFactory.Options opts=new BitmapFactory.Options();

  opts.inSampleSize=inSampleSize;

  return(BitmapFactory.decodeStream(assets().open(path), null, opts));
}
Chiba answered 2/10, 2014 at 19:47 Comment(0)
C
0

Your getPathFromUri method is failing. It should be returning something like /storage/emulated/0/DCIM/camera/bla bla.jpg. The file:// is the authority and isn't part of the path. BitmapFactory is looking for an actual file location path.

You can strip that manually or use Uri class with something like this:

Uri imgUri = Uri.parse(imgPath);
String filePath = imgUri.getPath();
Carltoncarly answered 2/10, 2014 at 19:10 Comment(1)
Stil not working... now the file:/// is gone but still getting nullBoots
C
0

Ok, so If I'll do it like it's now in edited post, how can I "resize" the image to get rid of outOfMemory Exception ?

Aha! Now we are getting somewhere.

What you had, in a prior edit of your question, was:

  1. read the entire bitmap into a byte array
  2. write the entire bitmap into another byte array as a low-quality JPEG
  3. read the entire bitmap into a Bitmap, backed by yet a third byte array

This will result in your consuming ~2.1x the heap space of your current implementation, which is already giving you OutOfMemoryError messages. The byte arrays from #1 and #3 above will be the same size, equal to:

width x height x 4

where the width and height are expressed in pixels.

To reduce your memory consumption, you need to do to things:

  1. Read in the bitmap once, as your current code does.

  2. Use BitmapFactory.Options to control the decoding of the bitmap. In particular, use inSampleSize to reduce the number of pixels in the resulting Bitmap. Quoting the JavaDocs for inSampleSize:

If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory. The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16 the number of pixels. Any value <= 1 is treated the same as 1. Note: the decoder uses a final value based on powers of 2, any other value will be rounded down to the nearest power of 2.

This sample project demonstrates the use of inSampleSize for various hardcoded values. The actual Bitmap loading comes from:

private Bitmap load(String path, int inSampleSize) throws IOException {
  BitmapFactory.Options opts=new BitmapFactory.Options();

  opts.inSampleSize=inSampleSize;

  return(BitmapFactory.decodeStream(assets().open(path), null, opts));
}
Chiba answered 2/10, 2014 at 19:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.