Android processes large images

Source: Internet
Author: User

Projects often encounter problems that require processing large images. Because android imposes Resource Allocation restrictions on applications, OOM is easy to cause if corresponding processing is not performed.

Android's method for processing large charts:

For a large image, obtain the width and height of the image, calculate the inSampleSize of the Image Based on the width and height of the view, compress the image, and generate the corresponding image.

Two important parameters are:

/**111         * If set to true, the decoder will return null (no bitmap), but112         * the out... fields will still be set, allowing the caller to query113         * the bitmap without having to allocate the memory for its pixels.114         */115        public boolean inJustDecodeBounds;116117        /**118         * If set to a value > 1, requests the decoder to subsample the original119         * image, returning a smaller image to save memory. The sample size is120         * the number of pixels in either dimension that correspond to a single121         * pixel in the decoded bitmap. For example, inSampleSize == 4 returns122         * an image that is 1/4 the width/height of the original, and 1/16 the123         * number of pixels. Any value <= 1 is treated the same as 1. Note: the124         * decoder uses a final value based on powers of 2, any other value will125         * be rounded down to the nearest power of 2.126         */127        public int inSampleSize;

InJustDecodeBounds can obtain the image size without allocating resources to the image.


InSampleSize: Calculate the image compression ratio


Open-source projects such as xutils, Universal-Image-Loader, and Foursquare perform similar operations on big charts.


The code for Foursquare to process a large image is as follows:

public class ImageUtils {        private ImageUtils() {    }    public static void resampleImageAndSaveToNewLocation(String pathInput, String pathOutput)         throws Exception     {        Bitmap bmp = resampleImage(pathInput, 640);                OutputStream out = new FileOutputStream(pathOutput);        bmp.compress(Bitmap.CompressFormat.JPEG, 90, out);     }        public static Bitmap resampleImage(String path, int maxDim)         throws Exception {                BitmapFactory.Options bfo = new BitmapFactory.Options();         bfo.inJustDecodeBounds = true;         BitmapFactory.decodeFile(path, bfo);             BitmapFactory.Options optsDownSample = new BitmapFactory.Options();        optsDownSample.inSampleSize = getClosestResampleSize(bfo.outWidth, bfo.outHeight, maxDim);            Bitmap bmpt = BitmapFactory.decodeFile(path, optsDownSample);            Matrix m = new Matrix();                 if (bmpt.getWidth() > maxDim || bmpt.getHeight() > maxDim) {            BitmapFactory.Options optsScale = getResampling(bmpt.getWidth(), bmpt.getHeight(), maxDim);            m.postScale((float)optsScale.outWidth  / (float)bmpt.getWidth(),                         (float)optsScale.outHeight / (float)bmpt.getHeight());         }                 int sdk = new Integer(Build.VERSION.SDK).intValue();         if (sdk > 4) {            int rotation = ExifUtils.getExifRotation(path);            if (rotation != 0) {                 m.postRotate(rotation);             }        }                return Bitmap.createBitmap(bmpt, 0, 0, bmpt.getWidth(), bmpt.getHeight(), m, true);     }        private static BitmapFactory.Options getResampling(int cx, int cy, int max) {        float scaleVal = 1.0f;        BitmapFactory.Options bfo = new BitmapFactory.Options();        if (cx > cy) {            scaleVal = (float)max / (float)cx;        }        else if (cy > cx) {            scaleVal = (float)max / (float)cy;        }        else {            scaleVal = (float)max / (float)cx;        }        bfo.outWidth  = (int)(cx * scaleVal + 0.5f);        bfo.outHeight = (int)(cy * scaleVal + 0.5f);        return bfo;    }        private static int getClosestResampleSize(int cx, int cy, int maxDim) {        int max = Math.max(cx, cy);                int resample = 1;        for (resample = 1; resample < Integer.MAX_VALUE; resample++) {            if (resample * maxDim > max) {                resample--;                break;            }        }                if (resample > 0) {            return resample;        }        return 1;    }        public static BitmapFactory.Options getBitmapDims(String path) throws Exception {        BitmapFactory.Options bfo = new BitmapFactory.Options();         bfo.inJustDecodeBounds = true;         BitmapFactory.decodeFile(path, bfo);         return bfo;    }}

There is another problem to be corrected:
I read several articles about processing large charts and said that BitmapFactory should not be called. the decodeResource function, because after the decode function is completed, it is completed through the createBitmap at the java layer and requires more memory.
I saw the source code of BitmapFactory and found that the above analysis was incorrect. decodeResource eventually called Jni to get the image. See the sequence diagram below.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.