Bitmap size after using BitmapFactory.decodeStream - android

I am using BitmapFactory.decodeStream(inputStream) to create a bitmap. But the size of the bitmap returned by bitmap.getByteCount() is coming out be very huge compared to the actual image size. The actual image size when I download(on disk) is around 36kb, but the bitmap generated has a size of around 800kb. Since it is the same image, how come there is such a huge difference ? I am using the following piece of code.
Bitmap.Config.RGB_565 is helping me to reduce the size of the image
public Bitmap downloadImage(String imageUrl) {
Bitmap bitmap = null;
InputStream inputStream = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
inputStream = (new URL(imageUrl)).openStream();
bitmap = BitmapFactory.decodeStream(inputStream, null, options);
Log.d("downloadImage","size of downloaded image " + bitmap.getByteCount()/1024);
return bitmap;
} catch (Exception e) {
}
finally {
try {
if(inputStream != null) {
inputStream.close();
}
} catch(Exception e) {
}
}
return bitmap;
}

Related

How does a bitmap cache work?

Can someone explain the difference between a method like this and a bitmap cache? Don't they both just load it into memory? Which one is more efficient?
public static Bitmap loadBitmap(String filename, boolean transparency) {
InputStream inputStream = null;
try {
inputStream = GameMainActivity.assets.open(filename);
} catch (IOException e) {
e.printStackTrace();
}
Options options = new Options();
if (transparency) {
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
} else {
options.inPreferredConfig = Bitmap.Config.RGB_565;
}
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null,
options);
return bitmap;
}
A cache (in this case a bitmap cache) is used to avoid to create again again the bitmap, so you can speedup things. It's really needed when you need to create the bitmap on-the-fly for example using the Canvas methods.

How to examine the potential filesize/bitmap size before decoding the bitmap from file path in android?

After using the device camera I get a 52MB bitmap and I decode it this way:
try {
bitmapLarge = BitmapFactory.decodeFile(pathName, bitmapOptions);
} catch (OutOfMemoryError ex) {
ex.printStackTrace();
try {
bitmapOptions.inSampleSize = 2;
bitmapOptions.inJustDecodeBounds = false;
bitmapLarge = BitmapFactory.decodeFile(pathName, bitmapOptions);
bitmapOptions.inSampleSize = 1;
} catch (OutOfMemoryError ex2) {
ex2.printStackTrace();
try {
bitmapOptions.inSampleSize = 4;
bitmapOptions.inJustDecodeBounds = false;
bitmapLarge = BitmapFactory.decodeFile(pathName, bitmapOptions);
} catch (OutOfMemoryError ex3) {
ex3.printStackTrace();
bitmapOptions.inSampleSize = 8;
bitmapOptions.inJustDecodeBounds = false;
bitmapLarge = BitmapFactory.decodeFile(pathName, bitmapOptions);
bitmapOptions.inSampleSize = 1;
}
bitmapOptions.inSampleSize = 1;
}
} catch (Exception ex) {
ex.printStackTrace();
Log.e("resizing bitmap", "#### NULL");
bitmapLarge = null;
return null;
}
I get a huge OutOfMemoryError at the first attempt to decodeFile:
12-15 18:24:24.393: E/dalvikvm-heap(12890): Out of memory on a 51916816-byte allocation.
How do I know what the size of the bitmap would be BEFORE trying to do anything with it?
And even if this is possible, how do I decode it downsampled somehow?
Instead of doing bitmapOptions.inJustDecodeBounds = false; change that to true and you will get back the bounds of the image
you should probably read this too http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
with inJustDecodeBounds = true. You will get back a null bitmap, but the bitmapOptions object will be filled with Bitmap's width and height. Then it is just Mathematic.. You need width * height * 4 bytes to keep your bitmap in memory

Prevent bitmap being written to disk being scaled

I'm having an issue whereby when I write a bitmap to disk, it gets written to disk, however it gets written as a miniscule image (3kb or less in filesize).
I have checked that the source image is indeed the correct dimensions, however the output image seems shrunk despite configuring the bitmap options to not scale.
#Override
protected Void doInBackground(PPImage... params) {
String filename = "pp_" + position + ".jpg";
File externalStorageDirectory = Environment.getExternalStorageDirectory();
final File destination = new File(externalStorageDirectory, filename);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 16;
opts.inPurgeable = true;
opts.inScaled = false;
decode(opts, Uri.parse(params[0].getUri()), getActivity(), new OnBitmapDecodedListener() {
#Override
public void onDecoded(Bitmap bitmap) {
try {
FileOutputStream out = new FileOutputStream(destination, false);
writeImageToFileTask.this.holder.pathToImage = destination.getAbsolutePath();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
MediaStore.Images.Media.insertImage(getActivity().getContentResolver(), destination.getAbsolutePath(), destination.getName(), destination.getName());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
});
return null;
}
private void decode(BitmapFactory.Options options, Uri mUri, Context mContext, OnBitmapDecodedListener listener) {
try {
InputStream inputStream;
if (mUri.getScheme().startsWith("http") || mUri.getScheme().startsWith("https")) {
inputStream = new URL(mUri.toString()).openStream();
} else {
inputStream = mContext.getContentResolver().openInputStream(mUri);
}
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
listener.onDecoded(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
}
How do I ensure that the image being written to file is the same dimensions as the original source image?
You have specified sample size in your code, which will result in resizing:
opts.inSampleSize = 16;
Just remove this line, and the dimension of the output image should be the same.
About the usage of inSampleSize, according to official doc:
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.

Android 4.0 ImageView setImageBitmap does not work

I develop a App with ffmpeg to decode a media frame. I filled a Bitmap object with the decode result and use ImageView.setImageBitmap to display the bitmap.
In Android 2.3 it works well, but in Android 4.0 or up it doesn't work.
The code is simply :
imgVedio.setImageBitmap(bitmapCache);//FIXME:in 4.0 it displays nothing
Then I tried write the Bitmap to a file and reload the file to display.
String fileName = "/mnt/sdcard/myImage/video.jpg";
FileOutputStream b = null;
try
{
b = new FileOutputStream(fileName);
bitmapCache.compress(Bitmap.CompressFormat.JPEG, 100, b);// write data to file
}
catch (FileNotFoundException e)
{
e.printStackTrace();
} finally
{
try
{
if(b != null)
{
b.flush();
b.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
Bitmap bitmap = BitmapFactory.decodeFile(fileName);
imgVedio.setImageBitmap(bitmap);
It works, but the performance is too poor.
So can someone help me resolve the problem?
I think it's an out of memory problem, you can fix it using this method :
private Bitmap loadImage(String imgPath) {
BitmapFactory.Options options;
try {
options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeFile(imgPath, options);
return bitmap;
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
The "inSampleSize" option will return a smaller image and save memory. You can just call this in the ImageView.setImageBitmap :
imgVedio.setImageBitmap(loadImage(IMAGE_PATH));

How to create a bitmap with RGB_565?

actually i'm opening png files from assets folder with this code:
public static Bitmap loadImage( String imageName ){
if( imageName.charAt(0) == '/' ) {
imageName = imageName.substring(1);
}
imageName = imageName + ".png";
Bitmap image = BitmapFactory.decodeStream(getResourceAsStream(imageName));
return image;
}
public static InputStream getResourceAsStream( String resourceName ) {
if( resourceName.charAt(0) == '/' ) {
resourceName = resourceName.substring(1);
}
InputStream is = null;
try {
is = context.getAssets().open( resourceName );
} catch (IOException e) {e.printStackTrace();}
return is;
}
This code opens the bitmaps with full cuality and it takes a lot of time to open it. I will try to use RGB_565 to speed up the opening of the bitmap.
What should i change into my code to open the bitmap with RGB_565? As you can see, i dont know the width and the height of the image.
Also any sugerences to speed up the opening of the bitmap will be welcome
Thanks
Add BitmapFactory.Options to to decodeStream() call:
BitmapFactory.Options bitmapLoadingOptions = new BitmapFactory.Options();
bitmapLoadingOptions.inPreferredConfig = Bitmap.Config.RGB_565;
BitmapFactory.decodeStream(instream,null,bitmapLoadingOptions);
As for how to speed up loading the image? Not sure what else you can do except maybe reduce the size of the image if that's possible.
This code worked for me
AssetManager assetManager = getAssets();
InputStream istr = null;
try {
istr = assetManager.open(strName);
} catch (IOException e) {
e.printStackTrace();
}
BitmapFactory.Options bitmapLoadingOptions = new BitmapFactory.Options();
bitmapLoadingOptions.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeStream(istr,null,bitmapLoadingOptions);
return bitmap;

Categories

Resources