Decreasing File Size of Image From ImageView - android

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.

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.

Android - Reduce image file size before upload to server with Base64

I'm trying to reduce the file size from gallery before upload to the server with base64. I've tried ALL the suggestions from stackoverflow & elsewhere I've found on the internet without success.
For images > 2MB, they seem to be reduced in size once written on the server (down to ~500KB). However, for images < 500KB they seem to be bigger than original file size once decoded and written on the server (again ~500KB). It seems like there's threshold that base64 can't get lower beyond). Is it true? Any other way I can reduce the image file size and upload to server programmatically?
private String string(Bitmap bitmap){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 50, stream);
return Base64.encodeToString(stream.toByteArray(), Base64.DEFAULT);
}
Pass bitmap into string method, to convert into String. compressFormat is in PNG which automatically lower the size and quality.

Out of memory on a byte allocation (Bitmap as String to webservice using soap)

Am having a bitmap , so I want to upload a webserivceas string and want to retrive the string.
For converting bitmap to string am using:
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
strBase64 = Base64.encodeToString(byteArray, Base64.URL_SAFE);
this above String is using as property to in soapobject to upload.
But am getting Out of memory on a 11674900-byte allocation, while print and uploading.
And if i debugged the issue, without printing am getting
com.sun.jdi.InvocationException occurred invoking method.
on soaprequest.
How to resolve this issue and to upload image to webservice as string ?
You are creating 3 copies of an 11MB image(bitmap, stream, strBase64). So reduce the memory usage by calling
bitmap.recycle();
below this line:
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
Also close the stream when you are done with it(below stream.toByteArray();):
stream.close();
stream = null;
Remember that there is no guarantee that memory will be cleaned immediately after these calls. Proper way to handle this type of situation is to transfer large files chunk by chunk.
An 11 Million byte allocation much larger than most phones' heap can handle. you definitely don't want to be holding a byte array of that size in memory.
Try using insample size with
BitmapFactory.decodeStream(InputStream is, Rect outPadding, BitmapFactory.Options opts)
and settings options to use insample size to return a reasonably sized image.
A simple fix for some might be to add android:configChanges="orientation|screenSize" to your manifest. In my case, the Nexus_S emulator was crashing without this line, while the actual Nexus 7 device I was testing on wasn't crashing on rotation.
Adding this appears to be an easy fix for apps that have a couple large "match_parent" bitmaps to rotate and resize.
Careful if you are building for APIs before 13!

The image is too small when I try to upload it using Facebook Graph API and Android

Simply put I need to capture image using camera and upload it to facebook via my android application. And I successfully did that. The problem is when the photo posted in facebook, it's just too small and in low resolution while the image I took is in high resolution.
I understand that: in order to upload to facebook, i need to convert the captured image which is in bitmap format into byte array. So i have method for that:
public static byte[] convertBitmapToByteArray(Bitmap bm){
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm.compress(CompressFormat.PNG, 100, bos);
byte[] bitmapdata = bos.toByteArray();
return bitmapdata;
}
Then to upload the image to facebook, i have code below where byteData is byte array I converted from bitmap image using the method above.
parameters.putString("message", "Test");
parameters.putByteArray("source", byteData);
String facebookResponse = facebookInstance.request(albumId+"/photos",parameters,"POST");
return facebookResponse;
I am pretty sure the problem is my convertBitmapToByteArray method since the method is to compress the bitmap image and turn it into byte array, and this made my image into low resolution image. However I can't seem to find the way to upload the image without converting it into byte array first. Any solution for me?
Alright even this thread is old, i found out the answer. It's not the problem of CompressFormant.JPEG or CompressFormat.JPG. Simply put, intent in android isn't designed to carry big data like image from activity through activity. I need to save the image from intent to sd card first before able to pull it out from there. It's my solution.

android encode image with max size limit

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?

Categories

Resources