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
- Picture width and height.
- Color space
- The scaling ratios are explained one by one
High image width
We open the picture in AS to see the file information
1000 x 447
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.
- Equipment dpi level: reference https://material.io/devices/ can understand.
Calculation of dPI scaling ratio of device and drawable file: for example, bitmap under drawable xhdpi (320=2160= 2MDpi) is loaded into Pixel-XL of xxxhdpi (640=4160= 4MDpi). 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. Note that if the Bitmap file is stored in a file with drawable without a suffix, the dPI of drawable is 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 or a URL network address, 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, also has a scaling ratio concept, but it has nothing to do with DPI, it has to do with View.
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 is two, need to weigh out the scale ratio that can be applied to the width and height at the same time.
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 some other relationship, such as Glide’s view picture ratio) 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, located in drawable-xxhdpi (480dpi=3160dpi) file package, device pixel-xl (560dpi=3.5160dpi). Actively set inSampleSize=2. Use the default bitmap.config =ARGB_8888
- Zoom ratio = active set by passive set hierarchy (dpi) = 1/2 * (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 active zoom ratio: The goal is to modify the width and height of the final image to optimize 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 passive scaling ratio: understand the calculation of passive scaling ratio, device DPI level and image DPI level relationship. The best case scenario is that the same image has an appropriate size in each dPI-level package of the drawable file (so that the passive zoom ratio is 1 for each device running). Otherwise, if the device does not have a drawable file that directly corresponds to the DPI, the passive scaling ratio will be affected, and most of the time the image will be enlarged, and the memory will be increased quadratic. If you move the image from drawable-xxhdpi(480dpi) to the drawable package (160 by default), the same loading code will end up enlarging memory by 9 times.
- 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)