Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reduce the size of a bitmap to a specified size in Android

I want to reduce the size of a bitmap to 200kb exactly. I get an image from the sdcard, compress it and save it to the sdcard again with a different name into a different directory. Compression works fine (3 mb like image is compressed to around 100 kb). I wrote the following lines of codes for this:

String imagefile ="/sdcard/DCIM/100ANDRO/DSC_0530.jpg"; Bitmap bm = ShrinkBitmap(imagefile, 300, 300);  //this method compresses the image and saves into a location in sdcard     Bitmap ShrinkBitmap(String file, int width, int height){           BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();             bmpFactoryOptions.inJustDecodeBounds = true;             Bitmap bitmap = BitmapFactory.decodeFile(file, bmpFactoryOptions);              int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);             int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);              if (heightRatio > 1 || widthRatio > 1)             {              if (heightRatio > widthRatio)              {               bmpFactoryOptions.inSampleSize = heightRatio;              } else {               bmpFactoryOptions.inSampleSize = widthRatio;               }             }              bmpFactoryOptions.inJustDecodeBounds = false;             bitmap = BitmapFactory.decodeFile(file, bmpFactoryOptions);              ByteArrayOutputStream stream = new ByteArrayOutputStream();                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);                byte[] imageInByte = stream.toByteArray();              //this gives the size of the compressed image in kb             long lengthbmp = imageInByte.length / 1024;               try {                 bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream("/sdcard/mediaAppPhotos/compressed_new.jpg"));             } catch (FileNotFoundException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }            return bitmap;         } 
like image 216
TharakaNirmana Avatar asked Jun 06 '13 05:06

TharakaNirmana


People also ask

How do you handle bitmaps in Android as it takes too much memory?

Choose the most appropriate decode method based on your image data source. These methods attempt to allocate memory for the constructed bitmap and therefore can easily result in an OutOfMemory exception. Each type of decode method has additional signatures that let you specify decoding options via the BitmapFactory.

What is bit map in android?

A bitmap is simply a rectangle of pixels. Each pixel can be set to a given color but exactly what color depends on the type of the pixel. The first two parameters give the width and the height in pixels. The third parameter specifies the type of pixel you want to use.

What is bitmap width?

A bitmap is rectangular and has a spatial dimension, which is the width and height of the image in pixels. For example, this grid could represent a very small bitmap that is 9 pixels wide and 6 pixels high or, more concisely, 9 by 6: By convention, the shorthand dimension of a bitmap is given with the width first.


2 Answers

I found an answer that works perfectly for me:

/**  * reduces the size of the image  * @param image  * @param maxSize  * @return  */ public Bitmap getResizedBitmap(Bitmap image, int maxSize) {     int width = image.getWidth();     int height = image.getHeight();      float bitmapRatio = (float)width / (float) height;     if (bitmapRatio > 1) {         width = maxSize;         height = (int) (width / bitmapRatio);     } else {         height = maxSize;         width = (int) (height * bitmapRatio);     }     return Bitmap.createScaledBitmap(image, width, height, true); } 

calling the method:

Bitmap converetdImage = getResizedBitmap(photo, 500); 

Where photo is your bitmap

like image 85
TharakaNirmana Avatar answered Sep 19 '22 05:09

TharakaNirmana


Here is the solution that limits image quality without changing width and height. The main idea of this approach is to compress bitmap inside the loop while output size is bigger than maxSizeBytesCount. Credits to this question for the answer. This code block shows only the logic of reducing image quality:

        ByteArrayOutputStream stream = new ByteArrayOutputStream();         int currSize;         int currQuality = 100;          do {             bitmap.compress(Bitmap.CompressFormat.JPEG, currQuality, stream);             currSize = stream.toByteArray().length;             // limit quality by 5 percent every time             currQuality -= 5;          } while (currSize >= maxSizeBytes); 

Here is the full method:

public class ImageUtils {      public byte[] compressBitmap(             String file,              int width,              int height,             int maxSizeBytes     ) {         BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();         bmpFactoryOptions.inJustDecodeBounds = true;         Bitmap bitmap;          int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);         int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);          if (heightRatio > 1 || widthRatio > 1)         {             if (heightRatio > widthRatio)             {                 bmpFactoryOptions.inSampleSize = heightRatio;             } else {                 bmpFactoryOptions.inSampleSize = widthRatio;             }         }          bmpFactoryOptions.inJustDecodeBounds = false;         bitmap = BitmapFactory.decodeFile(file, bmpFactoryOptions);          ByteArrayOutputStream stream = new ByteArrayOutputStream();         int currSize;         int currQuality = 100;          do {             bitmap.compress(Bitmap.CompressFormat.JPEG, currQuality, stream);             currSize = stream.toByteArray().length;             // limit quality by 5 percent every time             currQuality -= 5;          } while (currSize >= maxSizeBytes);          return stream.toByteArray();     } } 
like image 32
Alex Misiulia Avatar answered Sep 19 '22 05:09

Alex Misiulia