Android Image Caching Bitmap detailed (i) _android

Source: Internet
Author: User
Tags save file cpu usage

Objective:
Recently prepared to study the image caching framework, based on the idea that you should first learn about the image caching basics, today focus on the bitmap, bitmapfactory these two classes.  

Bitmap:
Bitmap is one of the most important types of image processing in the Android system. It can be used to get image file information, to cut, rotate, zoom and so on, and to save image files in the specified format.
Important Functions
public void Recycle ()//Reclaim the memory space occupied by the bitmap, marking the bitmap as dead
Public Final Boolean isrecycled ()//Determine if bitmap memory has been released
Public final int getwidth ()//Get the width of the bitmap
Public final int getheight ()//Get the height of the bitmap
Public Final Boolean ismutable ()//whether the picture can be modified
public int getscaledwidth (Canvas Canvas)//Gets the width of the specified density converted Image
public int getscaledheight (Canvas Canvas)//Gets the height of the specified density converted Image
public boolean compress (compressformat format, int quality, OutputStream stream)//Converts the picture to an output stream by the specified picture format and image quality.
Format:Bitmap.CompressFormat.PNG or Bitmap.CompressFormat.JPEG
Quality: Quality, 0-100.0 represents the lowest quality compression, 100 to the highest quality compression. This setting is ignored for images in lossless format such as PNG.
public static Bitmap CreateBitmap (Bitmap src)//src for the original image to create not to become new images
public static Bitmap Createscaledbitmap (Bitmap src, int dstwidth, int dstheight, Boolean filter)//(SRC) to create a new image, Specifies the width of the new image and whether it is variable.
public static Bitmap createbitmap (int width, int height, config config)--Creates a bitmap of the specified format and size
public static Bitmap CreateBitmap (Bitmap source, int x, int y, int width, int height) with source as the original, create a new picture, specify the starting coordinates and the height of the new image.

Bitmapfactory Factory class:
Option parameter class:
public boolean injustdecodebounds//if set to True, no picture is acquired, memory is not allocated, but the height width information of the picture is returned.
public int insamplesize//A multiple of picture scaling
public int outwidth//Gets the width value of the picture
public int outheight//Gets the height value of the picture
public int indensity//pixel compression ratio for bitmaps
public int intargetdensity//The pixel compression ratio for the destination bitmap (bitmap to be generated)
public byte[] Intempstorage//create temporary files, store pictures
public boolean inscaled//image compression When set to true, from indensity to Intargetdensity
public boolean Indither//If true, decoder attempts dither decoding
public Bitmap.config inpreferredconfig//Set Decoder
public String Outmimetype//Set decoding image
public Boolean inpurgeable//whether the storage pixel memory space can be reclaimed when the system is low on memory
public boolean ininputshareable//inpurgeable is true to take effect, can you share a InputStream
public Boolean inpreferqualityoverspeed//True gives priority to bitmap quality followed by decoding speed
public boolean inmutable//configuration bitmap can be changed, such as: Add a line segment to a few pixels on bitmap
public int inscreendensity//pixel density of current screen

  Factory methods:
  public static Bitmap DecodeFile (String pathName, Options opts //Read picture from file  
  public static Bitmap DecodeFile (String pathName)
  public static Bitmap Decodestream (InputStream is)/read the picture from the input stream
  public static Bitmap Decodestream (InputStream is, Rect outpadding, Options opts)
  public static Bitmap Decoderesource (resources res, int ID)/Read picture from resource file
  public static B Itmap Decoderesource (resources res, int ID, Options opts)  
  public static Bitmap Decodebytearray (byte[) da TA, int offset, int length)//Read picture from array
  public static Bitmap Decodebytearray (byte[] data, int offset, int length, Options opts)
  public static Bitmap Decodefiledescriptor (FileDescriptor FD)//Read files from file Unlike DecodeFile, this direct call to the JNI function is more efficient for reading
  public static Bitmap Decodefiledescriptor (FileDescriptor fd, Rect Outpadding, Options opts)  

Bitmap.config Inpreferredconfig:
enumeration variables (the higher the number of bitmap digits represents the more color information it can store, the more realistic the image, the greater the memory footprint)
public static final Bitmap.config Alpha_8//represents 8-bit ALPHA bitmap 1byte memory per pixel
public static final Bitmap.config argb_4444//represents 16-bit ARGB bitmap consumes 2byte of memory per pixel
public static final Bitmap.config argb_8888//Represents 32-bit ARGB bitmap consumes 4byte of memory per pixel
public static final Bitmap.config rgb_565//represents 8-bit RGB bitmap 2byte memory per pixel

The memory consumed by a picture in Android (BITMAP) is mainly related to the following factors: length of picture, width of picture, number of bytes per pixel.

Memory occupied by one picture (BitMap) = picture length * Picture width * Number of bytes occupied by unit pixels

Picture Reading instance:
1.) read from the file way one

 /**
  * Get scaled local picture * *
  @param filePath file path
  * @param width width
  * @param height
  * @return
  */
   
    public static Bitmap Readbitmapfromfile (String filePath, int width, int height) {
  bitmapfactory.options Options = new Bitmapfactory.options ();
  Options.injustdecodebounds = true;
  Bitmapfactory.decodefile (FilePath, options);
  float srcwidth = options.outwidth;
  float srcheight = options.outheight;
  int insamplesize = 1;

  if (Srcheight > Height | | srcwidth > width) {
   if (Srcwidth > Srcheight) {
    insamplesize = Math.Round (src height/height);
   } else {
    insamplesize = Math.Round (srcwidth/width);
   }
  }

  Options.injustdecodebounds = false;
  Options.insamplesize = insamplesize;

  Return Bitmapfactory.decodefile (FilePath, Options);
 }


   

2. From file read mode Two efficiency above mode one

/** * Get scaled local picture * * @param filePath file path * @param width * @param height * @retu RN/public static Bitmap Readbitmapfromfiledescriptor (String filePath, int width, int height) {try {fileinputs
   Tream fis = new FileInputStream (FilePath);
   Bitmapfactory.options Options = new Bitmapfactory.options ();
   Options.injustdecodebounds = true;
   Bitmapfactory.decodefiledescriptor (FIS.GETFD (), null, options);
   float srcwidth = options.outwidth;
   float srcheight = options.outheight;

   int insamplesize = 1; if (Srcheight > Height | | srcwidth > width) {if (Srcwidth > Srcheight) {insamplesize = Math.Round (SrcH
    Eight/height);
    else {insamplesize = Math.Round (srcwidth/width);
   } options.injustdecodebounds = false;

   Options.insamplesize = insamplesize;
  Return Bitmapfactory.decodefiledescriptor (FIS.GETFD (), null, options);
 The catch (Exception ex) {} return null; }

Test also generates 10 pictures two ways to compare CPU usage and memory footprint The second is a little more efficient. Therefore, it is recommended that the second approach be preferred.

  Start = System.currenttimemillis ();
  for (int i = 0; i < Testmaxcount i++) {
   bitmaputils.readbitmapfromfile (FilePath,)
  End = System.currenttimemillis ();
  LOG.E (TAG, "Bitmapfactory decodefile--time-->" + (End-start));

  Start = System.currenttimemillis ();
  for (int i = 0; i < Testmaxcount i++) {
   bitmaputils.readbitmapfromfiledescriptor (FilePath,)
  End = System.currenttimemillis ();
  LOG.E (TAG, "Bitmapfactory decodefiledescriptor--time-->" + (End-start));

3.) Read the file from the input stream

 /**
  * Get scaled local picture * *
  @param ins input stream
  * @param width
  * @param height
  * @return/
 Publi C Static Bitmap Readbitmapfrominputstream (inputstream ins, int width, int height) {
  bitmapfactory.options Options = NE W bitmapfactory.options ();
  Options.injustdecodebounds = true;
  Bitmapfactory.decodestream (INS, null, options);
  float srcwidth = options.outwidth;
  float srcheight = options.outheight;
  int insamplesize = 1;

  if (Srcheight > Height | | srcwidth > width) {
   if (Srcwidth > Srcheight) {
    insamplesize = Math.Round (src height/height);
   } else {
    insamplesize = Math.Round (srcwidth/width);
   }
  }

  Options.injustdecodebounds = false;
  Options.insamplesize = insamplesize;

  Return bitmapfactory.decodestream (INS, null, options);
 }

4.) Read the file from the resource file

 public static Bitmap Readbitmapfromresource (resources, int resourcesid, int width, int height) {
  bitmapfact Ory. Options options = new Bitmapfactory.options ();
  Options.injustdecodebounds = true;
  Bitmapfactory.decoderesource (Resources, resourcesid, options);
  float srcwidth = options.outwidth;
  float srcheight = options.outheight;
  int insamplesize = 1;

  if (Srcheight > Height | | srcwidth > width) {
   if (Srcwidth > Srcheight) {
    insamplesize = Math.Round (srche ight/height);
   } else {
    insamplesize = Math.Round (srcwidth/width);
   }
  }

  Options.injustdecodebounds = false;
  Options.insamplesize = insamplesize;

  Return Bitmapfactory.decoderesource (Resources, resourcesid, options);
 

This approach is quite a memory-intensive recommendation to replace Decoderesource with Decodestream instead of the following form

 public static Bitmap Readbitmapfromresource (resources, int resourcesid, int width, int height) {
  Inputstrea M ins = Resources.openrawresource (RESOURCESID);
  Bitmapfactory.options Options = new Bitmapfactory.options ();
  Options.injustdecodebounds = true;
  Bitmapfactory.decodestream (INS, null, options);
  float srcwidth = options.outwidth;
  float srcheight = options.outheight;
  int insamplesize = 1;

  if (Srcheight > Height | | srcwidth > width) {
   if (Srcwidth > Srcheight) {
    insamplesize = Math.Round (SrcH eight/height);
   } else {
    insamplesize = Math.Round (srcwidth/width);
   }
  }

  Options.injustdecodebounds = false;
  Options.insamplesize = insamplesize;

  Return bitmapfactory.decodestream (INS, null, options);
 }

Decodestream, Decoderesource occupy memory contrast:

 start = System.currenttimemillis (); for (int i = 0; i < Testmaxcount i++) {Bitmaputils.readbitmapfromresource (Getresources (), R.mipmap.ic_app_center_b
   Anner, 400, 400);
  LOG.E (TAG, "bitmapfactory decoderesource--num-->" + i);
  End = System.currenttimemillis ();

  LOG.E (TAG, "Bitmapfactory decoderesource--time-->" + (End-start));
  Start = System.currenttimemillis (); for (int i = 0; i < Testmaxcount i++) {Bitmaputils.readbitmapfromresource1 (Getresources (), R.mipmap.ic_app_center_
   Banner, 400, 400);
  LOG.E (TAG, "bitmapfactory decodestream--num-->" + i);
  End = System.currenttimemillis ();

LOG.E (TAG, "Bitmapfactory decodestream--time-->" + (End-start)); 

Bitmapfactory.decoderesource loaded pictures may be scaled, which is currently done in the Java layer, is less efficient, and consumes the Java layer of memory. Therefore, if you use this interface heavily to load pictures, it can easily lead to oom errors.
Bitmapfactory.decodestream does not scale the loaded picture, which consumes less memory and is more efficient.
These two interfaces are useful, and you should use Decodestream if you have higher performance requirements, and you can use Decoderesource if you don't have high performance requirements and you need the Adaptive Zoom feature of Android's own pictures.

5.) reading pictures from binary data

public static Bitmap Readbitmapfrombytearray (byte[] data, int width, int height) {
  bitmapfactory.options Options = new Bitmapfactory.options ();
  Options.injustdecodebounds = true;
  Bitmapfactory.decodebytearray (data, 0, data.length, options);
  float srcwidth = options.outwidth;
  float srcheight = options.outheight;
  int insamplesize = 1;

  if (Srcheight > Height | | srcwidth > width) {
   if (Srcwidth > Srcheight) {
    insamplesize = Math.Round (srche ight/height);
   } else {
    insamplesize = Math.Round (srcwidth/width);
   }
  }

  Options.injustdecodebounds = false;
  Options.insamplesize = insamplesize;

  return Bitmapfactory.decodebytearray (data, 0, data.length, options);
 

6.) Read pictures from assets file

 /**
  * Get scaled local picture * *
  @param filePath file path
  * @return/public
 static Bitmap Readbitmapfromassetsfile (context context, String FilePath) {
  Bitmap image = null;
  Assetmanager am = context.getresources (). Getassets ();
  try {
   InputStream is = Am.open (FilePath);
   Image = Bitmapfactory.decodestream (is);
   Is.close ();
  } catch (IOException e) {
   e.printstacktrace ();
  }
  return image;
 }

Picture Save file:

 public static void Writebitmaptofile (String filePath, Bitmap b, int quality) {
  try {
   file Desfile = new File (fil Epath);
   FileOutputStream fos = new FileOutputStream (desfile);
   Bufferedoutputstream BOS = new Bufferedoutputstream (FOS);
   B.compress (Bitmap.CompressFormat.JPEG, quality, BOS);
   Bos.flush ();
   Bos.close ();
  } catch (IOException e) {
   e.printstacktrace ();
  }
 }

Picture compression:

 private static Bitmap Compressimage (Bitmap image) {
  if (image = = null) {return
   null;
  }
  Bytearrayoutputstream BAOs = null;
  try {
   BAOs = new Bytearrayoutputstream ();
   Image.compress (Bitmap.CompressFormat.JPEG, BAOs);
   byte[] bytes = Baos.tobytearray ();
   Bytearrayinputstream ISBM = new Bytearrayinputstream (bytes);
   Bitmap Bitmap = Bitmapfactory.decodestream (ISBM);
   return bitmap;
  } catch (OutOfMemoryError e) {
  } finally {
   try {
    if (BAOs!= null) {
     baos.close ();
    }
   catch ( IOException e) {
   }
  } return
  null;
 }

Picture scaling:

 /**
  * Generate a picture based on scale
  *
  * @param bitmap
  * @param scale Scaling Value
  * @return
 /public static Bitmap Bitmapscale (Bitmap Bitmap, float scale) {
  matrix matrix = new Matrix ();
  Matrix.postscale (scale, scale); The proportions of the long and wide magnification
  Bitmap resizebmp = Bitmap.createbitmap (Bitmap, 0, 0, bitmap.getwidth (), Bitmap.getheight (), Matrix, true);
  return resizebmp;
 }



Get picture rotation angle:

 /**
  * Read the rotation angle in the photo EXIF information
  * *
  @param path photo paths
  * @return Angle * * *
 private static int Readpicturedegree (String path) {
  if (textutils.isempty (path)) {return
   0;
  }
  int degree = 0;
  try {
   Exifinterface exifinterface = new Exifinterface (path);
   int orientation = Exifinterface.getattributeint (exifinterface.tag_orientation, exifinterface.orientation_normal);
   Switch (orientation) {case
    exifinterface.orientation_rotate_90:
     degree =;
     break;
    Case exifinterface.orientation_rotate_180:
     degree = 180;
     break;
    Case exifinterface.orientation_rotate_270:
     degree = 270;
     break;
   }
  } catch (Exception e) {
  } return
  degree;
 }


Picture rotation angle:

  private static Bitmap Rotatebitmap (Bitmap B, float rotatedegree) {
    if (b = = null) {return
      null;
    }
    Matrix matrix = new Matrix ();
    Matrix.postrotate (rotatedegree);
    Bitmap Rotabitmap = bitmap.createbitmap (b, 0, 0, b.getwidth (), B.getheight (), Matrix, true);
    return rotabitmap;
  }

Picture to binary:

Public byte[] Bitmap2bytes (Bitmap BM) {
    Bytearrayoutputstream BAOs = new Bytearrayoutputstream ();
    Bm.compress (Bitmap.CompressFormat.PNG, BAOs);
    return Baos.tobytearray ();
  } 

Bitmap Turn drawable

public static drawable bitmaptodrawable (resources, Bitmap BM) {
    drawable drawable = new Bitmapdrawable (res Ources, BM);
    return drawable;
  } 

drawable turn Bitmap

 public static Bitmap Drawabletobitmap (drawable drawable) {
    Bitmap Bitmap = Bitmap.createbitmap ( Drawable.getintrinsicwidth (), Drawable.getintrinsicheight (), drawable.getopacity ()!= pixelformat.opaque? Bitmap.Config.ARGB_8888:Bitmap.Config.RGB_565);
    Canvas Canvas = new Canvas (bitmap);
    Drawable.setbounds (0, 0, drawable.getintrinsicwidth (), Drawable.getintrinsicheight ());
    Drawable.draw (canvas);
    return bitmap;
  }

Discussion on drawable and bitmap occupied memory
previously used afinal and xutils familiar with both frameworks know that the two are from the same person, Xutils is an upgraded version of Afina, afinal in the picture memory cache using the bitmap And then why xutils the memory cache object to the drawable? Let's find out.
Write a test program:

 list<bitmap> bitmaps = new arraylist<> ();
    Start = System.currenttimemillis ();
    for (int i = 0; i < Testmaxcount i++) {
      Bitmap Bitmap = Bitmaputils.readbitmap (This, r.mipmap.ic_app_center_banner );
      Bitmaps.add (bitmap);
      LOG.E (TAG, "bitmapfactory bitmap--num-->" + i);
    }
    End = System.currenttimemillis ();
    LOG.E (TAG, "Bitmapfactory bitmap--time-->" + (End-start));

    list<drawable> drawables = new arraylist<> ();
    
    Start = System.currenttimemillis ();
    for (int i = 0; i < Testmaxcount i++) {
      drawable drawable = Getresources (). Getdrawable (R.mipmap.ic_app_center_ban NER);
      Drawables.add (drawable);
      LOG.E (TAG, "bitmapfactory drawable--num-->" + i);
    }
    End = System.currenttimemillis ();
    LOG.E (TAG, "Bitmapfactory drawable--time-->" + (End-start));

Test data 1000 the same picture

The test shows that drawable relative bitmap has a large memory footprint advantage. This is why the current mainstream picture cache frame memory cache that layer uses drawable as the reason for caching objects.
Summary: the picture processing temporarily learns here, later does the supplement.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

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.