I'm trying to read in a .jpg using BitmapFactory. I want to get a RGB888 formatted bitmap, but I keep seeming to get RGB565. Is there anyway to change this?
BitmapFactory methods let you pass a BitmapFactory.Options instance. You can use BitmapFactory.Options to specifcy the inPreferredConfig, which defines the format of the Bitmap returned after decoding, just set it to Bitmap.Config.ARGB_8888.
Related
I need to compress an image to send it to my server. I am trying to do it this way:
private Bitmap compressImage(Bitmap bitmapImg){
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmapImg.compress(Bitmap.CompressFormat.JPEG, 50, out);
Bitmap compressed = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));
return compressed;
}
But when I compare the Byte count of the original Bitmap object and the compressed one, I get the same number:
Log.e("UNCOMPRESSED", Integer.toString(mBitmapImg.getByteCount()));
E/UNCOMPRESSED: 23970816
Log.e("COMPRESSED", Integer.toString(compressedBitmapImg.getByteCount()));
E/COMPRESSED: 23970816
How can I fix this to have a smaller file?
But when I compare the Byte count of the original Bitmap object and the compressed one, I get the same number:
The size of a Bitmap in memory is based only on its resolution (width and height in pixels) and bit depth (the number of bytes per pixel, for controlling how many colors can be used per pixel).
How can I fix this to have a smaller file?
You do not have a file. You have a Bitmap object in memory. An image file is usually stored in a compressed form. In particular, this is true for JPEG, PNG, WebP, and GIF, the four major image formats used in Android. So, for example, out.toByteArray() will be smaller than 23,970,816 bytes.
Moreover, you are not sending a Bitmap to the server. You are sending an image to the server. You need to read the documentation for the server, or talk to the server developers, to determine what image format(s) they support and how to send the image to the server (ideally, something efficient like an HTTP PUT).
If you want to reduce the in-memory size of the Bitmap, scale it to a lower-resolution image (e.g., via createScaledBitmap()).
You can change your bitmap format to RGB_565 from ARGB_8888. That'll reduce your bitmap's memory footprint to half, but, would lead to loss of quality as well. Unfortunately, that's the most you can do with Bitmap.
Having said that, the compression method that you're using should work fine for most situations. It's also the advocated method for a number of platforms. An example for Firebase is this.
I am working with a customizable database with pictures. Right now I am taking pictures as it is from the sdcard and encoding it in base64 String and then putting it in the database. but whenever I am trying decoding it and showing it in my view, I am getting Out of memory error. Can any one one tell me what is the best procedure to do it? Shall I change the size of the pictures before encoding it?
I want to re-size all of the pictures into 512*512.
Image to Base64 is very heavy operation in android. Consider saving the images on the external/internal memory and save the file path in the sqlite database.
You can convert your image to byte array then store values in sql by using BLOB type and vice versa.
As you mentioned you want to resize the images to 512*512, you can scale the image using below code,
Create bitmap from captured image and then use below line
Bitmap resizedBitmap = Bitmap.createScaledBitmap(myBitmap, 512, 512, false);
It will give you a smaller image, you can also consider compressing the image to reduce in size,
OutputStream imagefile = new FileOutputStream("/your/file/name.jpg");
// Write 'bitmap' to file using JPEG and 50% quality hint for JPEG:
bitmap.compress(CompressFormat.JPEG, 50, imagefile);
Now, you have two options,
Save the scaled and compressed image into a file and save the path of that file in db. (Better way)
Convert the scaled and compressed image to base64 string and save in db.
Althought base64 is , as many answers said, a heavy operation for android, if done properly, it should not be a problem.
There are many reasons a bitmap could be required to be saved to a DB , (photo of a invoice ticket, for example?), and this is the way i do it.
first, create a new , smaller bitmap like #Swapnil commented.
and second, correctly use the bitmap transformation methods, i've been using these (look below) two so far and haven't had any memory issue on many different devices.
link to my BitmapUtils transformation methods
I try to load jpeg resource image to Bitmap of ARGB_8888 format:
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap b = BitmapFactory.decodeResource(resources, resId, opts);
Log.d("test", b.getConfig().toString());
Here resId is the id of a jpeg image resource.
And the output is "RGB_565".
Tried this in emulators of android 2.2 and 2.3.
Docs of 'inPreferredConfig' say:
If this is non-null, the decoder will try to decode into this internal
configuration. If it is null, or the request cannot be met, the
decoder will try to pick the best matching config based on the
system's screen depth, and characteristics of the original image such
as if it has per-pixel alpha (requiring a config that also does).
Image are loaded with the ARGB_8888 config by default.
So am I hitting the case of "the request cannot be met"? :)
But I honestly can't see how it is very difficult to decode RGB_565 into an ARGB_8888.
So I thought maybe I am doing wrong or this is a bug in Android...
When loading jpeg you must set alpha channel to true:
bitmap.setHasAlpha(true);
After looking through the source I can only tell that the decision to follow the defined inPreferredConfig is done in native code. ref: source
I would assume because a jpg cannot have an alpha channel that it is decoding it RGB_565 because it is the most efficient config for a non-alpha image. If you really want it to be decoded to ARGB_8888 convert the image into a png.
I'm making several calls to BitmapFactory.decodeFile() and BitmapFactory.decodeResource(), and I'd like to specify the format the bitmaps are decoded to, such as RGB_565 or RGBA_8888.
Currently, the decoded bitmap format seems to depend on the incoming image. Alternatively, is there a way to convert an existing bitmap to a specific format?
The reason this is important is that when I try to decode the image using jnigraphics, some images return an AndroidBitmapFormat of type ANDROID_BITMAP_FORMAT_NONE, which I assume is useless. Does anyone have more insight into why the format would be none of the known values? When this happens, the built-in image picker correctly displays images that are decoded this way, so I assume there has to be a way to deal with them.
Thanks for your input!
This might be what you are looking for:
BitmapFactory.Options op = new BitmapFactory.Options();
op.inPreferredConfig = Bitmap.Config.ARGB_8888;
bitmap = BitmapFactory.decodeFile(path, op);
When you have bitmap you can call copy method on it specifying BitmapConfig which is basically what you want.
http://developer.android.com/reference/android/graphics/Bitmap.html#copy(android.graphics.Bitmap.Config,boolean)
I used the BitmapFactory.decodeFile method to decode an image file in Android.
About the output bitmap, what is the property of the Bitmap.Config ?
(ALPHA_8 , ARGB_4444, ARGB_8888 or RGB_565 ?)
Thanks
If you're asking for more information on these values you must read this blog entry: http://www.curious-creature.org/2010/12/08/bitmap-quality-banding-and-dithering/
edit: You're asking what the value of Bitmap.Config will be after using the Bitmap.decodeFile():Bitmap method.
According to API you can use either decodeFile with param pathName:String or with params pathName:String and opts:Bitmap.Options. That second method accepts options for decoding. One of these is a Bitmap.Config param with this information (again from API):
public Bitmap.Config inPreferredConfig If this is non-null, the decoder will try to decode into this internal configuration.