android encode image with max size limit - android

I need to encode an image to be JPEG and maximum file zise to be 300 K and send it as byte array. I make encoding :
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
image = baos.toByteArray();
do you know how to limit the file size to 300K? maybe the solution is to make image quality lower, but sometimes(when the image is smaller) I may not need this. Thanks

By repeatedly compressing with descending 'quality' values until the resulting byte[] length <= 300KB. There is no shortcut through this (AFAIK) but you can choose the quality values carefully and limit yourself to, say, a maximum of 4 compressions.

Quick answer is to use a trial and test solution to find a compression value which gives you a value close to less than 300k.
File sizes for JPEG are highly dependent on the detail of the image so unless you're pictures are going to be of the same detail (no all black images etc) then the best compression rating will be different.
Maybe use a binary search style algorithm to find a good solution? Start at 50, then if too big, go down to 25 otherwise go up to 75. Then whenever you're within say 270-300 just stop?

Related

Bitmap.compress doesn't decrease the Byte count

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.

Decreasing File Size of Image From ImageView

I use the following code to obtain a bitmap from an ImageView. This image is not saved anywhere else on my device. I want to upload this image into an online mysqli database. However, to do so I need to decrease the size of the file first. I found a lot of links about this, however they all require the file to be saved on the device and then use FileOutputStream. I am looking for a way to reduce the file size so that it can be comfortably transferred using the Volley API ( i am currently receiving either run out of memory exceptions or broken pipe errors). Hence I am looking for a way to modify this code to be able to significantly decrease the file size, whilst still maintaining a quality which can be comfortably shown on a mobile device. The original image is taken straight from the camera hence the size is quite large. Here is my code:
ImageView pic_holder = (ImageView) findViewById(R.id.picturedisplay);
Bitmap bitmap = ((BitmapDrawable)pic_holder.getDrawable()).getBitmap();
ByteArrayOutputStream stream=new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
byte[] image=stream.toByteArray();
String img_str = Base64.encodeToString(image, 0);
I would like to decrease the size of the img_str which is passed to my Volley method.

Android Image Compression Without Res Change

I am looking for a solution that I found here for IOS for an android application. I have developed IOS applications and was just wondering if anyone had some insight on how to achieve this similar goal in android.
I am trying to just compress the image before uploading it to the server. I do not need the resolution to go down, and 200 kb or up to 400 kb should be fine and keep things looking alright for a phone. If anyone can take a look as at least give me a direction. I figured I would ask this before diving into some more complicated ways to do it that I have read into. If there was something as easy as it was in IOS then that would be better.
Thank you.
try
Bitmap original = BitmapFactory.decodeStream(getAssets().open("1024x768.jpg"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
original.compress(Bitmap.CompressFormat.PNG, 100, out);
Bitmap decoded = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));
from How to make Bitmap compress without change the bitmap size?
Use Bitmap.compress(Bitmap.CompressFormat format, int quality, OutputStream stream) using Bitmap.CompressFormat.JPEG and set the quality to something less than 100. Play around with different quality values until you get the right balance between size and quality.

Android read image from sdcard. Wrong size

I am creating an android app and want to read a file from sdcard and send it to a rest webservice. Everything works fine but when I read the file from sdcard its filesize is much bigger than its originalsize. A 10 KB file is getting 260 KB.
I am doing the following...
File f = new File(uri);
Log.d("ORIGINAL FILESIZE:"+f.length());
Filesize 10752 Bytes on SDCARD.
This is exactly the same size the image has on the phone.
Bitmap bmp = BitmapFactory.decodeFile(uri);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, bao);
Log.d("FILESIZE AFTER:"+bao.size());
Filesize 260904 Bytes after decode / compress.
This is the filesize the server receives and writes to disk.
It's the same Image and Quality but about 20 times bigger.
Does anyone know what I am doing wrong?
If your original file is a jpeg with high compression rate, it's normal that the decoded bitmap is much larger, especially if you use a quality of 100 in the compress() method (which means high quality).
Did you try using compress() with a lower quality value (cf documentation) ?
It is not wrong. Or at least it could be. The bytes rapresentation of a bitmap in memory, requires (a 32-bit image) height * widht * 4 bytes. And of course it differs from the file size becaouse of the compression.

Android image file size limit and how to handle large images?

If we work with large images (bitmaps) we will hit a wall eventually in the size the image is allowed to be (in order to be displayed). I wondered if anyone knows where this limit is? There is many factors in this, the maximum heap size of the phone etc.
Also is there any workaround to handling large images if you want to display them and make them interact-able?
If you already have decoded image data, you can store them in file on storage
and then mmap this buffer.
Then you can create sub-images (tiles) over this buffer via createBitmap function
MMapped memory areas do not count agains heap, are not subject for garbage collection
and are handled by paging subsystem bypassing usual file operations.
To compress large image size you can use
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
If you want to display whole image fullscreen then delegate it to build-in application:
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(uri, "image/jpeg");
startActivity(i);
When you want to display it as a thumbnail etc then read this doc.
This article talks about working with large bitmaps and dealing with memory constraints. It also talks about a few factors that cause the OutOfMemoryErrors such as heap size, other bitmaps loaded into memory and memory fragmentation. Finally, it provides an algorithm to dynamically load the largest possible image file into memory and perform transforms.
http://bricolsoftconsulting.com/handling-large-images-on-android/

Categories

Resources