Bitmap fragment reuse open source library for any operation:Github.com/Dawish/Bitm…

The true face of Lushan

A Bitmap is not an image. People who are new to Android probably think that Bitmap is just an image, like me, hahaha, that’s what I thought when I first came to Android.

In a word:

Bitmap is a final class that implements the Parcelable interface. The new keyword cannot be used to create a Bitmap. Java function methods in Bitmap are basically implemented by calling native.

The word Bitmap is a bit and a map, just like our Java HashMap, which is just a special data store class.

The Bitmap class in Android is the data storage class for Android interface drawing. Our Canvas saves the drawn things in Bitmap and then hands them to the bottom layer for rendering. Since Bitmap needs to be passed in memory, this is also the reason for the implementation of Parcelable interface.

Second, Bitmap reuse

2.1 Storage Version Differences:

In Android 2.3.3 and earlier versions, bitmap pixel data is stored in Native memory, while bitmap objects are stored in Dalvik heap. Starting from Android 3.0, Pixel data is stored in the Dalvik Heap along with bitmap objects.

A few days ago, I saw that the latest Android O put Bitmap pixel data in Native memory again. You can refer to the article: www.cnblogs.com/xiaji5572/p…

2.2 Differences of reuse between different versions:

The inBitmap setting was introduced in Android 3.0. By setting this parameter, you can use a previously created Bitmap when loading images, but the size should be the same to save memory and avoid creating a new Bitmap. In Android4.4, inBitmap has been added to allow inBitmap to set the size of the image to be different from the image that needs to be loaded, as long as the inBitmap image is larger than the image that needs to be loaded.

2.3 Points for Reusing Bitmap

Bitmap multiplexing is preferred by requiring its mIsMutable property to be true, which means mutable

Controls whether the setPixel method of a Bitmap can be used, that is, whether the outside world can modify the pixels of a Bitmap. The mIsMutable property is true to modify the pixel data in a Bitmap, which makes it possible to reuse Bitmap objects.

How is this mIsMutable property assigned to true when creating a Bitmap?

1. Create a new Bitmap by using the createBitmap method mIsMutable property default to true

public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height, @NonNull Config config, boolean hasAlpha, @NonNull ColorSpace colorSpace) { ...... Nullptr color Spaces have a particular meaning in native and are interpreted as sRGB // unnecessary extra work of the else branch) if (config ! = Config. ARGB_8888 | | the colorSpace = = the colorSpace. Get (the colorSpace. Named. SRGB)) {/ * * * * * * * * * * eighth direct assignment mutable attribute to true * * * * * * * * * * /  bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true, null, null); } else { if (! (colorSpace instanceof ColorSpace.Rgb)) { throw new IllegalArgumentException("colorSpace must be an RGB color space"); } ColorSpace.Rgb rgb = (ColorSpace.Rgb) colorSpace; ColorSpace.Rgb.TransferParameters parameters = rgb.getTransferParameters(); if (parameters == null) { throw new IllegalArgumentException("colorSpace must use an ICC " + "parametric transfer function"); } ColorSpace.Rgb d50 = (ColorSpace.Rgb) ColorSpace.adapt(rgb, ColorSpace.ILLUMINANT_D50); **********/ bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true, d50.getTransform(), parameters); }... Slightly}Copy the code

2. Use BitmapFactory and Options to decode a Bitmap by setting the Options decoding property to true

1 final BitmapFactory.Options options = new BitmapFactory.Options(); 2 //size must be 1; otherwise, an exception will be reported if the inBitmap attribute is used. 4 // this attribute must be used in SRC Bitmap decode, otherwise you can use which inBitmap attribute to decode the c++ level will raise an exception 5 //BitmapFactory: Unable to reuse an immutable bitmap as an image decoder target. 6 options.inMutable = true; InBitmap2 7 inBitmap2 = bitmapFactory.decodefile (path1,options); // Use the object inBitmap2 8 iv.setImageBitmap(inBitmap2); Options. inBitmap = inBitmap2; 10 long start=System.currentTimeMillis(); 11 iv2.setImageBitmap(BitmapFactory.decodeFile(path2,options)); 12 iv3.setImageBitmap(BitmapFactory.decodeFile(path3,options)); 13 iv4.setImageBitmap(BitmapFactory.decodeFile(path4,options));Copy the code

This reuse is written in comments.

2.4 Bitmap Reuse:

As you can see in the above code, retrieving a reusable bitmap from the cache assigns options.inBitmap to this bitmap when using the BitmapFactory to decode. This reuses the bitmap.

2. When an empty bitmap is needed, it can be obtained from the cache. The used bitmap can be placed in the LruCache cache. This allows us to retrieve a reusable bitmap setting from the LruCache cache to the Canvas

There is already an open source bitmap reuse project on Github github.com/amitshekhar… It is very simple to use.

The GlideBitmapPool open source project is used as follows:

Using Glide Bitmap Pool in your application

Add this in your build.gradle

The compile 'com. Amitshekhar. Android: glide - bitmap - the pool: first 0.0.1'Copy the code

Then initialize it in onCreate() Method of application class, :

GlideBitmapPool.initialize(10 * 1024 * 1024); // 10mb max memory size
Copy the code

Decoding the bitmap from file path

Bitmap bitmap = GlideBitmapFactory.decodeFile(filePath);
Copy the code

Decoding the bitmap from resources

Bitmap bitmap = GlideBitmapFactory.decodeResource(getResources(), R.drawable.testImage);
Copy the code

Decoding the down sample bitmap

Bitmap Bitmap = GlideBitmapFactory. DecodeFile (filePath, 100100);Copy the code

Making the bitmap available for recycle or reuse

GlideBitmapPool.putBitmap(bitmap);
Copy the code

Getting the empty bitmap from the pool

Bitmap bitmap = GlideBitmapPool.getBitmap(width, height, config);
Copy the code

Clearing or Trimming Memory

GlideBitmapPool.clearMemory();
GlideBitmapPool.trimMemory(level);
Copy the code

3. Arbitrary clipping in the case of reuse of Bitmap fragments

Fragmentation multiplexing refers to the creation and discarding of a large number of bitmaps during image clipping. If these bitmaps are not multiplexed, redundant memory will be wasted, resulting in memory jitter.

3.1 The remaining part of Bitmap clipping is reserved:

instructions Comparison of effects before and after
Cut the lower part and take half the height TIM picture 20180228220755. PNG After the cut: Screenshot_2018-02-28-21-59-16-052_BitmapKit.png

Clipping code:

@param srcBitmap * @param needHeight * @param recycleSrc Whether to recycle the original map * @return */ @debuglog public static Bitmap cropBitmapBottom(Bitmap srcBitmap, int needHeight, boolean recycleSrc) { Log.d("danxx", "cropBitmapBottom before h : "+srcBitmap.getHeight()); /** needY = srcbitmap.getheight () -needheight; / * * * cut key steps/Bitmap cropBitmap = Bitmap. CreateBitmap (srcBitmap, 0, needY, srcBitmap getWidth (), needHeight); Log.d("danxx", "cropBitmapBottom after h : "+cropBitmap.getHeight()); RecycleSrc &&srcbitmap; = null && ! srcBitmap.equals(cropBitmap) && ! srcBitmap.isRecycled()) { GlideBitmapPool.putBitmap(srcBitmap); } return cropBitmap; }Copy the code

3.2 Bitmap clipping retains the left part:

instructions Comparison of effects before and after
Trim the left part and take half the width TIM picture 20180228220755. PNG After the cut: Screenshot_2018-02-28-21-59-34-089_BitmapKit.png

Clipping code:

@param srcBitmap @param needWidth @return */ @debuglog public static Bitmap cropBitmapLeft(Bitmap  srcBitmap, int needWidth, boolean recycleSrc) { Log.d("danxx", "cropBitmapLeft before w : "+srcBitmap.getWidth()); /** cropBitmap = bitmap.createBitMap (srcBitmap, 0, 0, needWidth, srcbitmap.getheight ()); Log.d("danxx", "cropBitmapLeft after w : "+cropBitmap.getWidth()); RecycleSrc &&srcbitmap; = null && ! srcBitmap.equals(cropBitmap) && ! srcBitmap.isRecycled()) { GlideBitmapPool.putBitmap(srcBitmap); } return cropBitmap; }Copy the code

3.3 Retain the right part of Bitmap clipping:

instructions Comparison of effects before and after
Crop the right part and take half the width TIM picture 20180228220755. PNG After the cut: Screenshot_2018-02-28-22-00-03-095_BitmapKit.png

Clipping code:

@param srcBitmap @param needWidth @return */ @debuglog public static Bitmap cropBitmapRight(Bitmap srcBitmap, int needWidth, boolean recycleSrc) { Log.d("danxx", "cropBitmapRight before w : "+srcBitmap.getWidth()); int needX = srcBitmap.getWidth() - needWidth; /** cropBitmap = bitmap.createBitMap (srcBitmap, needX, 0, needWidth, srcbitmap.getheight ()); Log.d("danxx", "cropBitmapRight after w : "+cropBitmap.getWidth()); RecycleSrc &&srcbitmap; = null && ! srcBitmap.equals(cropBitmap) && ! srcBitmap.isRecycled()) { GlideBitmapPool.putBitmap(srcBitmap); } return cropBitmap; }Copy the code

3.4 Retain the upper part of Bitmap clipping:

instructions Comparison of effects before and after
Cut the top part and take half the height TIM picture 20180228220755. PNG After the cut: Screenshot_2018-02-28-21-59-49-769_BitmapKit.png

Clipping code:

@param srcBitmap * @param needHeight * @param recycleSrc Whether to recycle the original map * @return */ @debuglog public static Bitmap cropBitmapTop(Bitmap srcBitmap, int needHeight, boolean recycleSrc) { Log.d("danxx", "cropBitmapBottom before h : "+srcBitmap.getHeight()); /** Cut the Y coordinates of the first pixel of the remaining upper part */ int needY = 0; / * * * cut key steps/Bitmap cropBitmap = Bitmap. CreateBitmap (srcBitmap, 0, needY, srcBitmap getWidth (), needHeight); Log.d("danxx", "cropBitmapBottom after h : "+cropBitmap.getHeight()); RecycleSrc &&srcbitmap; = null && ! srcBitmap.equals(cropBitmap) && ! srcBitmap.isRecycled()) { GlideBitmapPool.putBitmap(srcBitmap); } return cropBitmap; }Copy the code

3.5 Arbitrary clipping of specified parameters:

instructions Comparison of effects before and after
Specify arbitrary clipping of parameters TIM picture 20180228220755. PNG After the cut: Screenshot_2018-02-28-22-00-13-606_BitmapKit.png

Clipping code:

/** * custom clipping, Trim * @param srcBitmap * @Param firstPixelX * @Param firstPixelY * @Param needWidth * @param needWidth * @param needHeight * @param recycleSrc * @return */ @DebugLog public static Bitmap cropBitmapCustom(Bitmap srcBitmap, int firstPixelX, int firstPixelY, int needWidth, int needHeight, boolean recycleSrc) { Log.d("danxx", "cropBitmapRight before w : "+srcBitmap.getWidth()); Log.d("danxx", "cropBitmapRight before h : "+srcBitmap.getHeight()); if(firstPixelX + needWidth > srcBitmap.getWidth()){ needWidth = srcBitmap.getWidth() - firstPixelX; } if(firstPixelY + needHeight > srcBitmap.getHeight()){ needHeight = srcBitmap.getHeight() - firstPixelY; } /** * cropBitmap = bitmap.createBitmap (srcBitmap, firstPixelX, firstPixelY, needWidth, needHeight); Log.d("danxx", "cropBitmapRight after w : "+cropBitmap.getWidth()); Log.d("danxx", "cropBitmapRight after h : "+cropBitmap.getHeight()); RecycleSrc &&srcbitmap; = null && ! srcBitmap.equals(cropBitmap) && ! srcBitmap.isRecycled()) { GlideBitmapPool.putBitmap(srcBitmap); } return cropBitmap; }Copy the code

Bitmap fragment reuse open source library for any operation:Github.com/Dawish/Bitm…