Resize image before sending to server - android

I have a very large image on my device (not taken with device camera) I need to resize the image before sending it to server. So say it is 14mb originally and I want to reduce it to 2mb. I want to resize the image without losing quality at all. What I mean is that the server will allow for zooming into the photo. So I am thinking inDensity is important. Except I don’t understand how inDensity works in this regard. Will someone please explain how I can resize the photo to 2mb but keep such a high density that the image can be zoomed with high quality? Or is that not possible.
I already know how to resize images:
public static Bitmap resizeImage(String file, int reqHeight, int reqWidth) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file, options);
options.inSampleSize = calculateInSampleSize(options, reqHeight, reqWidth);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(file, options);
}

Try this in your code:
Bitmap bmp = BitmapFactory.decodeFile(myImage)
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(CompressFormat.JPEG, 70, bos);
InputStream in = new ByteArrayInputStream(bos.toByteArray());
ContentBody image = new InputStreamBody(in, "image/jpeg", "filename");
It worked for me!

Related

size of byte array before and after writing to file is different why

public void onPictureTaken(byte[] data, Camera camera) {
Uri imageFileUri = null;
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
Bitmap mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, bmpFactoryOptions);
Log.d("SIZE", "mBitmap size :" + data.length);
bmpFactoryOptions.inJustDecodeBounds = false;
mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, bmpFactoryOptions);
imageFileUri = getApplicationContext().getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
OutputStream imageFileOS = getContentResolver().openOutputStream(imageFileUri);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageFileOS);
imageFileOS.flush();
imageFileOS.close();
ByteArrayOutputStream stream1 = new ByteArrayOutputStream();
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream1);
byte[] imageInByte1 = stream1.toByteArray();
long lengthbmp1 = imageInByte1.length;
Log.d("SIZE", "ByteArrayOutputStream1 size :" + lengthbmp1);
output of the Log is like below :
D/SIZE (23100): mBitmap size :4858755
D/SIZE (23100): ByteArrayOutputStream1 size :8931843
Can anybody help me why this difference.
I need to compress the image based on the size, but without compressing the size getting different..
You appear to be loading the image and then recompressing to bitmap
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream1);
Then you're wondering why the image size isn't the same? The answer is you've re-encoded it. Is 100 the compression ratio? If you load a bitmap compressed at 80% and then resave it to 100% in any image editor the size will grow.
The first question is why you reencode the bitmap when you already have the bytes. The size difference you observe comes from the different compression. The camera app will typically compress the image with a quality lower than 100 but you recompress it with 100. It is clear that your image representation will need more space.
If recompression is really necessary (for example if you altered the image in some way), try lower quality factors for better compression. Depending on your image something between 90 and 100 may work well.

Android - Formatting Bitmap to match instagram size

Here's what I'm trying to do:
Myapp calls the camera app, takes a picture, sends the pic path back to Myapp to be displayed in an ImageView and to then be shared to Instagram. I want the displayed bitmap to be of the same dimensions as what Instagram uses so no unexpected cropping will happen when going from Myapp to Instagram.
Here's what I've tried so far when returning from the camera:
(note: INSTAGRAM_FORMAT_W == INSTAGRAM_FORMAT_H == 1080)
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.outHeight = INSTAGRAM_FORMAT_H;
bmOptions.outWidth = INSTAGRAM_FORMAT_W;
bmOptions.inMutable = true;
Bitmap photo = (Bitmap) BitmapFactory.decodeFile(path, bmOptions);
photo = Bitmap.createScaledBitmap(photo, INSTAGRAM_FORMAT_H, INSTAGRAM_FORMAT_W, false);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
This distorts the image to fit the square format; not optimal
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.outHeight = INSTAGRAM_FORMAT_H;
bmOptions.outWidth = INSTAGRAM_FORMAT_W;
bmOptions.inMutable = true;
Bitmap photo = (Bitmap) BitmapFactory.decodeFile(path, bmOptions);
int baseX = (photo.getWidth() - INSTAGRAM_FORMAT_W)/2;
int baseY = (photo.getHeight() - INSTAGRAM_FORMAT_H)/2;
Bitmap photoResized = Bitmap.createBitmap(photo,baseX,baseY,INSTAGRAM_FORMAT_W,INSTAGRAM_FORMAT_H);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
photoResized.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
This crops too much off what the user sees thru the camera app, it is also bigger than the Instagram size which results in additional cropping when going to Instagram; not optimal
I was digging thru BitmapFactory.Options and possible parameters for Bitmap.createBitmap but I'm pretty lost in terms of what best practice is for when/where the formatting occurs, how to deal with variable pixel density of the screen (if needed) and variable camera definition (if applicable).
I could use a helping hand folks. Thanks

How to handle OutOfMemory Exception while creating a Bitmap from image fetched from SQLite DB?

I have primarily a question,Can I set a byte[] as image in ImageView without converting back to Bitmap?
The OOM error is thrown when I decode the byte[] to bitmap and I am seeing this happening for images of 300 KB even. I have opted to use BitmapFactory.options (inSampleSize) to scale the image to avoid the exception.
But this alters the dimension (width especially) of my image which looks so bad in my application. Is there anyway to fetch the original image from DB without scaling or altering the image (of course without the risk of OOM error)??
Any help is appreciated..!!
Thanks in Advance.
Code that troubles:
ByteArrayInputStream imageStream = new ByteArrayInputStream(imageByteArray);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap ImageBmp = BitmapFactory.decodeStream(imageStream, null, options);
options.inJustDecodeBounds = false;
//checking if the image is too large we can resize it small in order to avoid Out of Memory error from the decodeStream method.
if(showfullImage(options.outWidth) && !isExternal)
{
options.inSampleSize = 2;
}
imageStream.close();
imageStream = new ByteArrayInputStream(imageByteArray);
ImageBmp = BitmapFactory.decodeStream(imageStream, null, options);
return ImageBmp;

Avoid OutOfMemoryError for Bitmap.createScaledBitmap in Android

I am using following code to enlarge a image.
bmp=new BitmapFactory().decodeFile(util.getPathFromUri(tempFile));
Bitmap scaledBitmap=Bitmap.createScaledBitmap(bmp, newWidth, newHeight, true); //Line 2
ByteArrayOutputStream bos=new ByteArrayOutputStream();
scaledBitmap.compress(CompressFormat.JPEG, 100, bos);
bmp.recycle();
bmp=null;
OutputStream out;
out = new FileOutputStream(util.getTempFileName());
bos.writeTo(out);
bos.flush();
But sometimes OutOfMemoryError occurs at line 2 and app crashes, I tried enclosing this code within try-catch but still my app crashes as only exceptions are caught by try-catch, also createScaledBitmap() functions only throws IllegalArgumentException.
Since, I don't want to display image therefore I don't need ot scale it down(as I saw in other Questions in SOF).
So, How can I pre-detect that OutOfMemoryError will occur if I use that (newWidth, newHeight). Is there any way to calculate bytes required by Bitmap of (newWidth, newHeight) in memory and max available memory that can be allocated to bitmap?
Please help!
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Config.RGB_565;
options.inPurgeable = true;
options.inSampleSize = 1;
options.inScaled = false;
options.inDensity = DisplayMetrics.DENSITY_DEFAULT;
options.inTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
options.inScreenDensity = DisplayMetrics.DENSITY_DEFAULT;
new BitmapFactory().decodeFile(util.getPathFromUri(tempFile),options);
To avoid java.lang.OutOfMemory exceptions, check the dimensions of a bitmap before decoding it, unless you absolutely trust the source to provide you with predictably sized image data that comfortably fits within the available memory. For more details see this
Try this method to resize your bitmap:
Bitmap bitmpResizeResult = ThumbnailUtils.extractThumbnail(bitmapWantToResize, width, height);

How to efficiently decode JPEG from Base64?

In my android app I capture an image from the camera, compress it to jpeg, send it to the server and save it on hdd. There it takes 48,9kb (e.g.). I send it back in a Base64-String and decode it on the Android side like this:
byte[] img;
img = Base64.decode(base64, Base64.DEFAULT);
ByteArrayInputStream in = new ByteArrayInputStream(img);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 3;
Bitmap bmp = BitmapFactory.decodeStream(in, null, options);
return bmp;
Values bigger than 3 for
options.inSampleSize
will make the image look ugly. But if i now look at the size of
bmp
it is 156kb. Why does the size increase? How can I decode it, so that it keeps its original size and doesnt look ugly (too hard downsampling)?

Categories

Resources