- In Android development, Bitmap is a big Memory eater, and a little bit of improper operation will be OOM. Although now the third party picture loading library has been many, very perfect, but as a androider still need to know how to do the operation to load the large map.
- Why loading pictures will easily cause OOM, mainly from the picture loaded into memory, if the resolution of a picture is 1000*20000, then this picture load of memory in the approximate size of 1000*20000*4 = 80000000 bytes, then the memory is about , so that it is easy to cause OOM.
- In order to not OOM, Android provides bitmapfactory.options injustdecodebounds and insimplesize, reasonable use of these variables can easily load pictures
Injustdecodebounds
- By setting the variable to True, you can get the resolution of the image without loading the picture. At this point, the Bitmap returned by the Decoderesource method is null
- Code
BitmapFactory.Options options = new Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(getResources(), R.drawable.bigpicture, options); int outHeight = options.outHeight; int outWidth = options.outWidth;
Insimplesize
- Through the injustdecodebounds to get the resolution of the picture, then through the ImageView width and height and the width of the picture to compare, only when the width of the picture and height of any one is smaller than the width and height of the picture, the calculation is over. The size of the insimplesize, the default value is 1, and then increase by 2, if Insimplesize is 2, then the width and height of the picture in accordance with 1/2 scaling, so loaded into memory reduced by 4 times times.
- Code
BitmapFactory.Options options = new Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(getResources(), R.drawable.bigpicture, options); int outHeight = options.outHeight; int outWidth = options.outWidth; int inSampleSize = 1; int height = view.getMeasuredHeight(); int width = view.getMeasuredWidth(); if (outHeight > height || outWidth > width) { int halfHeight = outHeight / 2; int halfWidth = outWidth / 2; while ((halfHeight / inSampleSize) >= height || (halfWidth / inSampleSize) >= width) { inSampleSize *= 2; } }
Load large image
private void LoadImage (ImageView view) {bitmapfactory.options options = new options (); Options.injustdecodebounds = true; Bitmapfactory.decoderesource (Getresources (), r.drawable.bigpicture, options); int outheight = Options.outheight; int outwidth = Options.outwidth; int insamplesize = 1; int height = view.getmeasuredheight (); int width = view.getmeasuredwidth (); if (Outheight > Height | | outwidth > width) {int halfheight = OUTHEIGHT/2; int halfwidth = OUTWIDTH/2; while ((halfheight/insamplesize) >= Height | | (halfwidth/insamplesize) >= width) {insamplesize *= 2; }} options.insamplesize = Insamplesize; Options.injustdecodebounds = false; Bitmap Bitmap = Bitmapfactory.decoderesource (Getresources (), r.drawable.bigpicture, options); View.setimagebitmap (bitmap); }
Show Macro Map Local
- Load the macro map, for the above way, you can not see clearly. such as Qingming River map, this time need to use to another class Bitmapregiondecoder, through the class can show the bounding rectangle area, so you can more clearly see the local.
- Code
InputStream inputStream = getResources().getAssets().open("bigpicture.jpg"); BitmapRegionDecoder regionDecoder = BitmapRegionDecoder.newInstance(inputStream, false); int measuredHeight = view.getMeasuredHeight(); int measuredWidth = view.getMeasuredWidth(); Rect rect = new Rect(0, 0, measuredWidth, measuredHeight); Bitmap bitmap = regionDecoder.decodeRegion(rect, new Options()); view.setImageBitmap(bitmap);
The above can be displayed in the ImageView of the image of the local.
Slide to show a giant image
- The above feature implements the partial display of the macro, but to scroll through the other areas of the macro, you need to customize the View, override the Ontouchevent () method, and recalculate the area of the Rect based on the distance the finger slides, to enable loading of the large map layout.
- Several points:
- Gets the measured size in onmeasure, set to Rect
- in the Ontouchevent () method, calculates the sliding distance, and then sets the new display area to rect
- after the call Invali The date () method, which requests drawing, is called by the OnDraw () method
- in the OnDraw () method based on Rect to get the local Bitmap that need to be displayed, drawn back through the Canvas.
public class Bigimageview extends View {private int slidex = 0; private int slidey = 0; Private Bitmapregiondecoder Bitmapregiondecoder; private paint paint; private int mimagewidth; private int mimageheight; private options options; Private Rect Mrect; Public Bigimageview (Context context) {This (context, NULL); } public Bigimageview (context context, @Nullable AttributeSet attrs) {This (context, attrs, 0); } public Bigimageview (context context, @Nullable attributeset attrs, int defstyleattr) {Super (context, Attrs, defst YLEATTR); Init (); } private void Init () {mrect = new Rect (); Paint = new paint (); try {inputstream InputStream = getresources (). Getassets (). Open ("bigpicture.jpg"); options = new options (); Options.injustdecodebounds = true; Bitmapfactory.decodestream (InputStream, NULL, options); Mimagewidth = Options.outwidth; Mimageheight = Options.outheight; Options.injuStdecodebounds = false; Options.inpreferredconfig = config.rgb_565; Bitmapregiondecoder = Bitmapregiondecoder.newinstance (InputStream, false); } catch (IOException e) {e.printstacktrace (); }} float Downx = 0; float DownY = 0; @Override public boolean ontouchevent (Motionevent event) {switch (event.getaction ()) {case Motionevent.ac Tion_down:downx = Event.getrawx (); DownY = Event.getrawy (); Break Case MotionEvent.ACTION_MOVE:float MoveX = event.getrawx (); float Movey = Event.getrawy (); Slidex = (int) (MOVEX-DOWNX); Slidey = (int) (MOVEY-DOWNY); if (Mimagewidth > GetWidth ()) {Mrect.offset (-slidex, 0); if (Mrect.right > Mimagewidth) {mrect.right = Mimagewidth; Mrect.left = Mrect.right-getwidth (); } if (Mrect.left < 0) {mrect.left = 0; Mrect.right = GetWidth (); } invalidate (); } if (Mimageheight > GetHeight ()) {mrect.offset (0,-slidey); if (Mrect.bottom > Mimageheight) {mrect.bottom = Mimageheight; Mrect.top = Mrect.bottom-getheight (); } if (Mrect.top < 0) {mrect.top = 0; Mrect.bottom = GetHeight (); } invalidate (); } downx = MoveX; DownY = Movey; Break Default:break; } return true; } @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespe c, Heightmeasurespec); Mrect.left = 0; Mrect.right = getmeasuredwidth () + Mrect.leHtu mrect.top = 0; Mrect.bottom = getmeasuredheight () + mrect.top; } @Override protected void OnDraw (canvas canvas) {super.ondraw (canvas); Bitmap Bitmap = bitmapregiondecoder.decoderegion (mrect, Options); Canvas.drawbitmap (bitmap, 0, 0, paint); }}
Android load larger image