introduce

There is no way around bitmaps in Android development. Most of the time, we just use the image frame to load images, and the details of Bitmap memory use are encapsulated by the image frame. But there is something we need to know about Btimap’s impact on memory.

Memory footprint

The first thing to remember is that the Bitmap file size is definitely not the actual memory load size. Because files are just stored information, they need to be transformed when loaded into memory for display.

Get runtime memory usage: Bitmap classes for Bitmap objects, the Graphics package in the Android system framework. The bitmap.getBytecount () method returns the memory size in bytes. In essence, the bitmap memory footprint is very simple:

Basic formula: Total memory = width × height × color space

But in practice, it is not so simple, and each parameter of the formula will be affected by different factors.

Three factors that affect memory size

We’re not going to start with the code, we’re not going to get to the point. Based on the previous formula. Three factors that affect memory size 1. Picture width and height. 2. Color space 3. Zoom ratio explained one by one below

High image width

We open the picture in AS to see the file information



One of the1000 x 447It’s the picture width, or the original width.

Function: The product of width and height describes the total number of pixels in an image, i.e. how many pixels the image is made of.

It is generally not the image width and height that we eventually load into memory, but can be considered the base variable.

Color space

The bitmap.config enumeration:

Function: Color space describes information about each pixel

ARGB_8888:

A total of 32 bits (4 bytes), each corresponding to four values, the unit of the value is 8 bits =1byte, respectively describing the transparency (1) +RGB channels (3). Each byte ranges from 0 to 255. As the default value for Bitmap configuration color space. BitmapFactory is loaded by default. public Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888

RGB_565:

A total of 16 bytes (2 bytes), each corresponding to three values. Five (red), six (green), and five (blue) digits describe RGB channels respectively. Public static final DecodeFormat DEFAULT = PREFER_RGB_565

As you can see, RGB_565 requires only half the size of ARGB_8888, at the expense of having no transparency description.

The zoom ratio

What it does: Identifies the original width and height of the image as the zoom ratio.

First of all, we need to point out that the scale ratio has a power effect on memory, the effect value = scale ratio × scale ratio. This is because the scaling ratio is applied to the width and height separately and is used twice. The scaling ratio can be affected by many factors.

Active setting:

When parsing a Bitmap, there is an optional Options object where the inSampleSize parameter affects the result of the scale ratio. The value must be greater than 1 and a multiple of 2. For example, when inSampleSize=2, the scaling ratio is reduced by two times (this function can only be scaled down), that is, scaling ratio = original scaling ratio x (1/2). The effect on the memory result is 4 times smaller because the width/height is 2 times smaller. This value does not take effect by default. You need to manually set it.

Passive set

In the system, it is mainly determined by the dPI level of the device running and the DPI level of the drawable file stored in the image file. First, the concept of screen density is introduced. This is the concept and unit that Android comes up with to deal with many different screen resolutions and colors.

  • Dpi hierarchy of drawable files: Bitmap files saved in the drawable series. According to the Android development specification, it is meaningful to name decorators in Drawable’s series of files after them, declaring the Dpi (screen density) level to which the file belongs. The large number of files also corresponds to the large screen density of Android devices.
  • Dpi level of equipment: refer to material. IO /devices/ for details.

Calculation of dPI scaling ratio of device and drawable file: for example, bitmap under drawable xhdpi (320=2*160=2* MDpi) is loaded into Pixel-XL of xxxhdpi (640=4*160=4* MDpi). Dpi scaling ratio = device DPI /drawable DPI, so above, DPI scaling ratio =640/320=2. The practical meaning is that on high resolution XXxHDPI devices, drawable- xhdPI files need to be enlarged by 2 times, i.e., 2 times in width and 2 times in height, to accommodate high density devices. (Assuming no scaling will make the small control larger). Note that if the Bitmap file is stored in a file with drawable without a suffix, the dPI of drawable will be 160 by default.

Note that this scaling ratio only works if the Bitmap file is in a dPI hierarchy such as drawable. If the Bitmap is located in an external file such as an Assets package, the scaling ratio (default: 1) does not affect the memory results. This is easy to understand, but when you read the file and you don’t get any more information you don’t need to process it. Glide, interestingly enough, also has the concept of scale ratio. It’s just easy

Glide scale ratio =View View value/original image value, the value here is not fixed, because there is only one scale ratio, but the ratio of View width and height to original image width and height can be different, you need to weigh out the scale ratio that can be applied to both width and height.

Final scaling ratio

Final scaling ratio result:

Scaling ratio = Active scaling ratio * Passive scaling ratio

Active scaling ratio: when not set, defaults to 1, that is, does not affect additional values. Passive scaling ratio: This depends on whether you can get the relationship between the device and the drawable (or any other relationship), or 1 if not.

The final formula

Based on the above understanding and the enrichment of the basic formula above, the final calculation Bitmap memory formula can be obtained

Final formula: Total memory =(original width x scaling ratio) x (original height x scaling ratio) x color space

validation

Original image: 1000 width X447 height, in drawable-xxhdpi (480dpi=3*160dpi) file package, device pixel-xl (560dpi=3.5*160dpi). Actively set inSampleSize=2. Use the default bitmap.config =ARGB_8888

  • Scaling ratio = Active setting × Passive setting =1/2 x (560/480)=0.5×1.166=0.5833
  • Color space =ARGB_8888=32bit=4byte
  • Original size =1000×447

Memory usage =(original width x scaling ratio) x (original height x scaling ratio) x color space =1000 x 0.5833 x 447 x 0.5833 x 4 =583 x 260 x 4 =606320byte ≈0.578MB

Finally, the above figure verifies:

The result of the calculation matches the result of the execution perfectly. The result of the calculation matches the result of the execution perfectly. The result of the calculation matches the result of the execution perfectly.

revelation

Understanding Bitmap final memory footprint calculation principle and memory footprint parameters, we have specific goals for Bitmap processing. For example, the common optimization of Bitmap loading process is actually to modify the parameter Settings of various variables during Bitmap loading. Common Bitmap optimizations:

  • Modify the zoom ratio: The goal is to modify the width and height of the final image to optimize the memory footprint. Specific is to set the inSampleSize value, such as in the appropriate View zoom display suitable bitmap, realize the efficient loading of bitmap (Glide picture framework is such, let display component View width and height involved in scaling ratio calculation).
  • Modify color space: In cases where transparency is definitely not required, use RGB_565 instead of ARGB_8888 to directly reduce memory size by half. The disadvantage is that there are constraints. (ARGB_4444 is not recommended because of the poor quality of the image)