First, Introduction
Mobile devices continue to evolve today, some people think that the memory is large enough, no need to control what memory optimization, Java is a virtual machine can help me maintain memory. In fact, memory space resources are still very valuable, no matter how big the phone memory, the system allocated to a single application of memory space is still very limited roughly 16m,64m,128m, etc. Loading large images in Android consumes system resources very much, and 16M images can store 3 images of 1024x1536 quality of argb_8888, which do not contain any other object's resources. The software runs on the system, the environment is very complex, it is possible to test a limited number of test times did not find a memory leak problem, but in thousands of users in the process, there will always be a variety of memory leak problems.
the calculation rules of the memory space occupied by the picture
Large graph loading first to understand the quality of the picture and the calculation rules of the occupied memory: Bitmap.config
Bitmap.config |
Introduction (the composition of each pixel point) |
Space occupied by 1pix 1byte = 8 bit |
1024*1024 picture size Resolution |
Alpha_8 |
Only the transparency, no color, then one pixel occupies 8 bits. |
1byte |
1M |
R G B _565 |
That is r=5,g=6,b=5, there is no transparency, then one pixel occupies the 5+6+5=16 bit. |
2byte |
2M |
ARGB_8888 |
Consists of 4 8-bit, that is, a=8,r=8,g=8,b=8, then one pixel occupies 8+8+8+8=32 bit. |
4byte |
4M |
ARGB_4444 |
Consists of 4 4-bit, that is, a=4,r=4,g=4,b=4, then one pixel occupies 4+4+4+4=16 bit. |
2byte |
2M |
Iii. Common strategies for loading and displaying1. Load directly and display: direct image decoding and display loading on the control, the common Setimageresource method is to directly load the image to the top of ImageView display, this method is the way to load the original; 2. Load into memory to do scaling: decode to memory or bitmap, determine whether the size of the bitmap need two times, zoom to the specified size and then display; 3. Reduce mass loading:
Decoding the time set Bitmap.inpreferredconfig, try to load different quality bitmap to memory;
4. Pre-load mode:
is to get the size of the image that will be loaded, the estimated memory consumption and whether we need such a resolution picture.
loading optimization of large graphs
With bitmapfactory loading picture, it provides Decoderesource and decodefile two ways to decode the resource directory and the local SDcard directory under the image, Provides a powerful bitmapfactory.options that gives me the configuration in the process of decoding pictures.
1. Load the picture below drawable using the Decoderesource method
The image resolution is: 8176 x 2368 The color model is: ARGB_8888, The resources required to fully load into memory are: around 73.6M, meaning that a large majority of Android phones will instantly leak memory.
When loading a picture, get the size of the picture and the format of the picture: set Injustdecodebounds to True, do not decode the image to memory, read only the basic information of the picture.
Bitmapfactory.options Options = new Bitmapfactory.options (); options.injustdecodebounds = true; Bitmapfactory.decoderesource (Getresources (), r.id.myimage, options); int imageheight = Options.outheight;int ImageWidth = Options.outwidth; String imageType = Options.outmimetype;
At this point, you can get the size and format of the picture, and then calculate the size of the occupied memory space according to the model you want to load:
/** * A helper function to return the byte usage per pixel of A bitmap based in its configuration. */public static int getbytesperpixel (Bitmap.config config) { if (config = = Bitmap.Config.ARGB_8888) { return 4;< c2/>} else if (config = = Bitmap.Config.RGB_565) { return 2; } else if (config = = Bitmap.Config.ARGB_4444) { re Turn 2; } else if (config = = Bitmap.Config.ALPHA_8) { return 1; } return 1;}
Get The picture size according to the width and height of the picture:
/** * Get the image size in the RAM * * @param imagew * @param imageh * @return */public static long getbitmapsizeinmemory (int imagew, int imageh) { return Imageh * Imagew * getbytesperpixel (Bitmap.Config.ARGB_8888);}
At this point, you can add some strategies, such as loading only the control size of the picture, or to determine the current memory usage, as appropriate load the picture: This time to set the Injustdecodebounds to False, Here we demonstrate how to load a picture at a specified resolution:
/** * Load Bitmap from Resources * * @param res resource * @param drawableid resource Image ID * @param imgh Destination Image Height * @param imgw destination Image width * @return */public static Bitmap LOADHUGEBITMAPFROMDR Awable (resources resources, int drawableid, int imgh, int imgw) {log.d (TAG, "IMGH:" + imgh + "IMGW:" + IMGW); Bitmapfactory.options Options = new Bitmapfactory.options (); Preload set Injustdecodebounds True, this would load bitmap into memory Options.injustdecodebounds = true; Options.inpreferredconfig = Bitmap.config.argb_8888;//default is Bitmap.Config.ARGB_8888 Bitmapfactory.decoderesource (Resources, Drawableid, options); Get the image information Include:height and width int height = options.outheight; int width = options.outwidth; String mimeType = Options.outmimetype; LOG.D (TAG, "width:" + width + "Height:" + height + "MimeType:" + mimeType); Get sample size int samplesize = GetscaleinsamplEsize (width, height, IMGW, IMGH); Options.insamplesize = samplesize; Decode bitmap with insamplesize set options.injustdecodebounds = false; LOG.D (TAG, "Memory size:" + getbitmapsizeinmemory (width/samplesize, height/samplesize)); Bitmap Bitmap = bitmapfactory.decoderesource (resources, Drawableid, options); LOG.D (TAG, "w=" + bitmap.getwidth () + "h=" + bitmap.getheight () + "Bitmap size:" + bitmap.getrowbytes () * Bitmap.getheig HT ()); return bitmap;}
2. Load the picture below SDcard using the DecodeFile method Picture information Ibid.
/** * Load the bitmap from SDcard with the IMGW and IMGH * * @param imgpath Resource path * @param imgh result image Height * @param IMGW result image width * @return result bitmap */public static bitmap Loadhugebitmapfromsdcard (String Imgpath, int imgh, int imgw) {log.d (TAG, "IMGH:" + imgh + "IMGW:" + IMGW); Bitmapfactory.options Options = new Bitmapfactory.options (); Preload set Injustdecodebounds True, this would load bitmap into memory Options.injustdecodebounds = true; Options.inpreferredconfig = Bitmap.config.argb_8888;//default is Bitmap.Config.ARGB_8888 bitmapfactory.decodefile (Imgpath, options); Get the image information Include:height and width int height = options.outheight; int width = options.outwidth; String mimeType = Options.outmimetype; LOG.D (TAG, "width:" + width + "Height:" + height + "MimeType:" + mimeType); Get sample size int samplesize = getscaleinsamplesize (width, height, IMGW, IMGH); Options.insamplEsize = samplesize; Decode bitmap with insamplesize set options.injustdecodebounds = false; LOG.D (TAG, "Memory size:" + getbitmapsizeinmemory (width/samplesize, height/samplesize)); Bitmap Bitmap = Bitmapfactory.decodefile (Imgpath, Options); LOG.D (TAG, "w=" + bitmap.getwidth () + "h=" + bitmap.getheight () + "Bitmap size:" + bitmap.getrowbytes () * Bitmap.getheig HT ()); return bitmap;}
The principle of the two approaches is exactly the same.
3. The method of calculation and the point of attention of Insamplesize
According to the official documentation we can see that the insamplesize must be 2 of the number of times, if not 2 of the number of times will automatically transpose the number of the 2 index times, below I provide a calculation method:
/** * Get the scale sample size * * @param resW resource Width * @param resh Resource Height * @param DESW result width * @param desh Result height * @return * /public static int getscaleinsamplesize (int res W, int resh, int desw, int desh) { int scalew = RESW/DESW; int Scaleh = Resh/desh; int largescale = Scaleh > Scalew? Scaleh:scalew; int samplesize = 1; while (SampleSize < largescale) { samplesize *= 2; } LOG.D (TAG, "samplesize:" + samplesize); return samplesize; }
Next, I will continue to explain: Picture loading image caching and asynchronous loading technology.
finally I enclose the project's GitHub address:https://github.com/CJstar/HugeLocalImageLoad.git
Reference: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Android big picture load Memory optimizer (how to prevent outofmemory)