catalogue

  • 01. How to calculate the memory occupied by Bitmap
    • 1.1 How to Calculate memory Usage
    • 1.2 Is the above method correct in calculating memory
    • 1.3 How much memory a pixel takes up
  • 02. There are four common color formats for bitmaps
    • 2.1 What is a Bitmap
    • 2.2 Android is usually the kind
    • 2.3 This section describes four common color formats
    • 2.4 How many color formats do Bitmaps have
  • 03.Bitmap compression technology
    • 3.1 Quality compression
    • 3.2 Sampling rate compression
    • 3.3 Compression by scaling
  • 04.Bitmap recycling problem
    • 4.1 recycle () method
    • 4.2 Cache Principles
    • 4.3 Reuse of Bitmap
  • 05. Common operations of Bitmap
    • 5.1 Compression mode of Bitmap
    • 5.2 How to Reuse Bitmap
    • 5.3 Bitmap Uses apis to obtain memory
    • 5.4 The blog corresponds to the test project address

Good news

  • Summary of blog notes [March 2016 to present], including Java basic and in-depth knowledge points, Android technology blog, Python learning notes, etc., including the summary of bugs encountered in daily development, of course, I also collected a lot of interview questions in my spare time, updated, maintained and corrected for a long time, and continued to improve… Open source files are in Markdown format! Also open source life blog, since 2012, accumulated a total of 50 articles [nearly 300,000 words], reprint please indicate the source, thank you!
  • Link address:Github.com/yangchong21…
  • If you feel good, you can star, thank you! Of course, also welcome to put forward suggestions, everything starts from small, quantitative change causes qualitative change!
  • Multicast map package library: github.com/yangchong21…
  • Lightweight version update popup: github.com/yangchong21…
  • Notification package library: github.com/yangchong21…

01. How to calculate the memory occupied by Bitmap

  • Welcome to see the demo compression effect directly, github.com/yangchong21…

1.1 How to Calculate memory Usage

  • If the image is to be displayed on the Android device, the ImageView will eventually load the Bitmap object, so we need to consider the memory footprint of a single Bitmap object. How to calculate the memory footprint of an image? This is the total memory footprint of all pixels:
  • Bitmap Memory size = Image length x image width x Bytes per pixel
  • Bitmap’ is usually encoded in two different ways: ARGB_8888 and RGB_565. ARGB_8888 has 4 bytes per pixel, and RGB_565 has 2 bytes. ARGB_8888 is usually used. The typical 1080 x 1920 image memory footprint is 1920 x 1080 x 4 = 7.9m

1.2 Is the above method correct in calculating memory

  • I see a lot of blogs doing this, but is it right? Have any of you tried this method correctly? I think reading blogs is to be skeptical of the bloggers and to prove whether what others have written is correct. More details can be found on my GitHub:Github.com/yangchong21…
    • The above statement is also true, but not entirely true. It does not describe the scene, and also ignores an influence term: Density. Next, look at the source code.
    • InDensity defaults to the density of the folder where the image is located. InTargetDensity is the current system density.
    • Width * height * nTargetDensity/inDensity * nTargetDensity/inDensity * one pixel of memory.
    @Nullable
    public static Bitmap decodeResourceStream(@Nullable Resources res, @Nullable TypedValue value,
            @Nullable InputStream is, @Nullable Rect pad, @Nullable Options opts) {
        validate(opts);
        if (opts == null) {
            opts = new Options();
        }
    
        if(opts.inDensity == 0 && value ! = null) { final int density = value.density;if (density == TypedValue.DENSITY_DEFAULT) {
                opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
            } else if (density != TypedValue.DENSITY_NONE) {
                opts.inDensity = density;
            }
        }
        
        if(opts.inTargetDensity == 0 && res ! = null) { opts.inTargetDensity = res.getDisplayMetrics().densityDpi; }return decodeStream(is, pad, opts);
    }
    Copy the code
  • Exactly. What about this idea? The calculation formula is as follows
    • For resource files: width * height * nTargetDensity/inDensity * nTargetDensity/inDensity * memory occupied by a pixel;
    • Width * height * memory occupied by a pixel;

1.3 How much memory a pixel takes up

  • Bitmap.Config describes how image pixels are stored.
    • ARGB_8888: 4 bytes per pixel. The default value is 32 bits.
    • Alpha_8: Saves transparency only, a total of 8 bits, 1 byte.
    • ARGB_4444: 16 bits, 2 bytes.
    • RGB_565: a total of 16 bits, 2 bytes, store only RGB values.

02. There are four common color formats for bitmaps

2.1 What is a Bitmap

  • A Bitmap file with a. BMP or. Dib extension. Bitmaps are Windows standard format graphics files that define images as dots (pixels), each of which can be represented by a variety of colors, including 2, 4, 8, 16, 24, and 32 bit colors. Bitmap files are in uncompressed format and require large storage space.

2.2 Android is usually the kind

  • In a Gesture class
  • In the Notification class
  • In the FW source code, bitmap images are usually stored in ARGB_8888 (ARGB stands for transparency, red, green, and blue respectively, and each value is recorded with 8 bits, that is, a pixel will occupy 4 bytes, a total of 32 bits).

2.3 This section describes four common color formats

  • The four color formats are shown below
  • instructions
    • In practical applications, ARGB_8888 and RGB_565 are recommended. If you don’t need transparency, choose RGB_565 to cut your memory footprint in half.
    • ARGB_8888: ARGB represents transparency, red, green, and blue. Each value is recorded in 8bits, i.e., a pixel takes up 4bytes, a total of 32bits.
    • ARGB_4444: ARGB is for each value to be recorded in 4bits, each pixel will occupy 2bytes, a total of 16 bits.
    • RGB_565: R=5bit,G=6bit,B=5bit, there is no transparency, each pixel will occupy 2byte, a total of 16 bits
    • ALPHA_8: this pixel only stores transparency and will occupy 1byte, a total of 8 bits.

2.4 How many color formats do Bitmaps have

  • I mentioned four common ones above, but I mean more than four. How many are there? Check the source code, there are six types. Check the Bitmap source code for the Config configuration.
  • Config.HARDWARE configuration is abnormal, see the following source code tips

03.Bitmap compression technology

3.1 Quality compression

  • Quality compression method: under the premise of maintaining the pixel to change the depth and transparency of the picture, to achieve the purpose of compression of the picture, so suitable for the transfer of binary picture data, such as sharing pictures, to pass binary data in the past, limited to 500KB.
    • 1. The size of the bitmap image does not change
    • 2. Bytes. length decreases as quality decreases.
    @param maxSize Specifies the maximum image sizereturnBitmap. */ public static bitmap by compressImage(bitmap image, long maxSize) { int byteCount = image.getByteCount(); Log.i("Yc compressed image"."Size before compression"+byteCount); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayInputStream Bitmap = null; / / quality compression method, the value of the options is 0-100 to 100 indicates the quality of the original pictures here, without compression, the compressed data stored in baos image.com press (Bitmap.Com pressFormat. JPEG, 100, baos); int options = 90; // Check if the compressed image is larger than maxSizewhile(baos.tobytearray ().length > maxSize) {// Reset baos baos.reset(); / / compression options here %, the compressed data stored in baos image.com press (Bitmap.Com pressFormat. JPEG, options, baos); // Decrease by 10 each time, stop when it is 1, and decrease by 1 when options<10if(options == 1){
                break;
            }else if (options <= 10) {
                options -= 1;
            } else {
                options -= 10;
            }
        }
        byte[] bytes = baos.toByteArray();
        if(bytes.length ! = 0) {/ / baos deposit to the compressed data bytes in the bitmap. = BitmapFactory decodeByteArray (bytes, 0, bytes. Length); int byteCount1 = bitmap.getByteCount(); Log.i("Yc compressed image"."Compressed size"+byteCount1);
        }
        returnbitmap; } /** * first: quality compression ** @param SRC source image * @param maxByteSize maximum number of bytes allowed * @param recycle whether to recycle * @return*/ public static Bitmap compressByQuality(final Bitmap SRC, final Long maxByteSize, final Boolean recycle) {if (src == null || src.getWidth() == 0 || src.getHeight() == 0 || maxByteSize <= 0) {
            return null;
        }
        Log.i("Yc compressed image"."Size before compression"+src.getByteCount());
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        src.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        byte[] bytes;
        if(baos.size() <= maxByteSize) {// If the quality of bytes is not greater than the maximum size, return the best quality bytes = baos.tobytearray (); }else {
            baos.reset();
            src.compress(Bitmap.CompressFormat.JPEG, 0, baos);
            if(baos.size() >= maxByteSize) {// If the worst quality is not less than the maximum number of bytes, return the worst quality bytes = baos.tobytearray (); }else{// dichotomy to find the best quality int st = 0; int end = 100; int mid = 0;while (st < end) {
                    mid = (st + end) / 2;
                    baos.reset();
                    src.compress(Bitmap.CompressFormat.JPEG, mid, baos);
                    int len = baos.size();
                    if (len == maxByteSize) {
                        break;
                    } else if (len > maxByteSize) {
                        end = mid - 1;
                    } else{ st = mid + 1; }}if(end == mid - 1) { baos.reset(); src.compress(Bitmap.CompressFormat.JPEG, st, baos); } bytes = baos.toByteArray(); }}if(recycle && ! src.isRecycled()){ src.recycle(); } Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); Log.i("Yc compressed image"."Compressed size"+bitmap.getByteCount());
        returnbitmap; } /** * first: quality compression ** @param SRC source image * @param quality * @param recycle whether to recycle * @return*/ public static Bitmap compressByQuality(final Bitmap SRC, @intrange (from = 0, to = 100) final int quality, final boolean recycle) {if (src == null || src.getWidth() == 0 || src.getHeight() == 0) {
            return null;
        }
        Log.i("Yc compressed image"."Size before compression"+src.getByteCount());
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        src.compress(Bitmap.CompressFormat.JPEG, quality, baos);
        byte[] bytes = baos.toByteArray();
        if(recycle && ! src.isRecycled()) { src.recycle(); } Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); Log.i("Yc compressed image"."Compressed size"+bitmap.getByteCount());
        return bitmap;
    }
    Copy the code

3.2 Sampling rate compression

  • What is sampling rate compression?
    • If inSampleSize (int) is set to n, the width and height of inSampleSize are 1/n, and the memory size is reduced. The above code used options. InJustDecodeBounds = true; Why is this compression method called sampling rate compression because I am fixed to sample the data? Because with inJustDecodeBounds, first get the width and height of the image (this process is sampling). Then set the inSampleSize value dynamically based on the width and height obtained. When inJustDecodeBounds is set to true, BitmapFactory will return a null Bitmap when decoding images through decodeResource or decodeFile to avoid memory allocation. But it can return the Bitmap width, height, and MimeType.
    /** * second: compress by sampleSize ** @param SRC source image * @param sampleSize sample rate size * @param recycle whether to recycle * @return*/ public static Bitmap compressBySampleSize(final Bitmap SRC, final int sampleSize, final Boolean recycle) {if (src == null || src.getWidth() == 0 || src.getHeight() == 0) {
            return null;
        }
        Log.i("Yc compressed image"."Size before compression"+src.getByteCount());
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = sampleSize;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        src.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        byte[] bytes = baos.toByteArray();
        if(recycle && ! src.isRecycled()) { src.recycle(); } Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options); Log.i("Yc compressed image"."Compressed size"+bitmap.getByteCount());
        returnbitmap; ** @param SRC source image * @param maxWidth Maximum width * @param maxHeight Maximum height * @param recycle whether to recycle * @return*/ public static Bitmap compressBySampleSize(final Bitmap SRC, final int maxWidth, final int maxHeight, final boolean recycle) {if (src == null || src.getWidth() == 0 || src.getHeight() == 0) {
            return null;
        }
        Log.i("Yc compressed image"."Size before compression"+src.getByteCount());
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        src.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        byte[] bytes = baos.toByteArray();
        BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
        options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight);
        options.inJustDecodeBounds = false;
        if(recycle && ! src.isRecycled()) { src.recycle(); } Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options); Log.i("Yc compressed image"."Compressed size"+bitmap.getByteCount());
        returnbitmap; } /** * computes to get the scaleinSampleSize
     */
    private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        final float totalPixels = width * height;
        final float totalReqPixelsCap = reqWidth * reqHeight * 2;
        while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
            inSampleSize++;
        }
        return inSampleSize;
    }
    Copy the code

3.3 Compression by scaling

  • In Android, Matrix is used for image scaling, rotation, translation, miter and other transformations.
    • Matrix provides methods to control image transformations: Matrix calls a series of set,pre, and post methods as if they were inserted into a queue. Of course, the calls are executed in the order from beginning to end in the queue. Pre indicates that a method is inserted at the head of the queue and POST indicates that a method is inserted at the end of the queue. Set, on the other hand, empties the current queue and is always in the middle of the queue. After a set is executed: the pre method is always inserted at the front of the set, and the POST method is always inserted at the back of the set
    setTranslate(float dx,floatDy) : Control Matrix for displacement.setSkew(float kx,floatKy) : Control Matrix to tilt, kx and ky are the proportions in X and Y directions.setSkew(float kx,float ky,float px,floatPy) : Control Matrix tilts px and Py as axes, and Kx and KY are tilting ratios in X and Y directions.setRotate(floatDegrees) : controls the Matrix to rotate the depress Angle with the axis of (0,0).setRotate(float degrees,float px,floatPy) : Control the Matrix to rotate the depress Angle, and the axis is (px,py).setScale(float sx,floatSy) : set Matrix for scaling, and sx and SY are the scaling ratios in the X and Y directions.setScale(float sx,float sy,float px,floatPy) : set Matrix to scale with (px,py) as the axis, and sx and SY as the scaling ratio in X and Y directions.Copy the code
    • Zooming compresses utility class code
    @param SRC source image @param newWidth newWidth @param newHeight newHeight @param recycle whether to recycle * @return*/ public static Bitmap compressByScale(final Bitmap SRC, final int newWidth, final int newHeight, final boolean recycle) {return scale(src, newWidth, newHeight, recycle);
    }
    
    public static Bitmap compressByScale(final Bitmap src, final float scaleWidth, final float scaleHeight, final boolean recycle) {
        returnscale(src, scaleWidth, scaleHeight, recycle); } /** ** scaled image ** @param SRC Source image * @param scaleWidth Scaled width multiple * @param scaleHeight Scaled height multiple * @param Recycle Whether to recycle * @return*/ Private static Bitmap scale(final Bitmap SRC, finalfloat scaleWidth, final float scaleHeight, final boolean recycle) {
        if (src == null || src.getWidth() == 0 || src.getHeight() == 0) {
            return null;
        }
        Matrix matrix = new Matrix();
        matrix.setScale(scaleWidth, scaleHeight);
        Bitmap ret = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true);
        if(recycle && ! src.isRecycled()) { src.recycle(); }return ret;
    }
    Copy the code

04.Bitmap recycling problem

4.1 recycle () method

  • How do I call the recycle() method
    if(bitmap ! = null && ! bitmap.isRecycled()) { bitmap.recycle(); bitmap = null; }Copy the code
  • Consider the following: why does a call to recycle() require a non-null judgment? This leads to the bitmap system reclamation function. Xiao Yang, if my analysis is wrong, welcome feedback.
    • First look at the source code… Check out the comments for this method! Release native objects associated with this bitmap and clear references to pixel data. This will not release pixel data synchronously; If there are no other references, it only allows garbage collection. Bitmaps are marked “dead,” which means that if getPixels() or setPixels() is called, it will throw an exception and nothing will be drawn. This operation cannot be reversed, so it should be invoked only if it is certain that no further use of bitmaps has been made. This is an advanced call and is usually not needed because the normal GC process frees the memory when there is no reference to this bitmap.
    public void recycle() {
        if(! mRecycled && mNativePtr ! = 0) {if (nativeRecycle(mNativePtr)) {
                // return value indicates whether native pixel object was actually recycled.
                // false indicates that it is still in use at the native level and these
                // objects should not be collected now. They will be collected later when the
                // Bitmap itself is collected.
                mNinePatchChunk = null;
            }
            mRecycled = true; }}Copy the code
  • Usually you don’t need to call? Why is that?
    • After Android3.0, bitmaps are stored in the heap, just reclaim the heap memory. It is recommended that we use the recycle() method for recycling after 3.0. This method can not be called actively because the garbage collector will automatically collect unusable Bitmap objects for recycling.
    • So what about recycling? This involves the bitmap caching algorithm and the GC garbage collection mechanism. For more information on GC collection, see my blog: blog.csdn.net/m0_37700275…
    • Remove the least used cache and the oldest used cache, say the conclusion first, and then analyze!

4.2 Cache Principles

  • LruCache principle
    • LruCache is a generic class with internal LinkedHashMap to implement the cache mechanism. It provides get methods and PUT methods to obtain and add caches. The most important method, trimToSize, is used to remove the least used cache and the oldest used cache, and add the latest cache to the queue.

4.3 Reuse of Bitmap

  • Android3.0 doesn’t emphasize bitmap.recycle (); Instead, it emphasizes the reuse of bitmaps.
    • LruCache is used to cache the Bitmap so that when the Bitmap is used again, it can be retrieved directly without reworking the encoding process.
    • Android3.0 (API) after 11 BitmapFactory is introduced. The Options. InBitmap fields, set this field after decoding method will try to reuse of the existence of a Bitmap. This means that Bitmap memory is overused, avoiding the process of memory reclamation and requisition, which is obviously better performance.
    • There are several limitations to using this field:
      • Bitmaps that can be reused must be set to true;
      • Before Android4.4(API 19), only JPG, PNG, same width and height (demanding), inSampleSize 1 Bitmap can be reused;
      • The inPreferredConfig of a Bitmap reused before Android4.4(API 19) overwrites the inPreferredConfig of the Bitmap setting to allocate memory.
      • The memory of the Bitmap to be reused after Android4.4(API 19) must be larger than the memory of the Bitmap to be allocated.
      • The options. inSampleSize of the Bitmap to be loaded on Android4.4(API 19) must be explicitly specified as 1.

05. Common operations of Bitmap

5.1 Compression mode of Bitmap

  • Common compression method Api
    • Bitmap.press (), quality compression, will not affect memory;
    • BitmapFactory. Options. InSampleSize, memory compression;
  • Bitmap.compress()
    • Quality compression does not affect memory
    • It changes the depth and transparency of the picture under the premise of maintaining the pixel, so as to achieve the purpose of compressing the picture, without reducing the pixel of the picture. The compressed image file size will be smaller, but after decoding into bitmap memory is the same.
  • BitmapFactory.Options.inSampleSize
    • Memory compression
    • Options to set the inJustDecodeBounds property to true when decoding an image to obtain the original width and height of a Bitmap without loading it into memory. Setting the inSampleSize property of bitmapFactory. Options can actually compress the memory occupied by bitmaps and load bitmaps with smaller memory.
    • After inSampleSize is set, the width and height of the Bitmap are reduced by a factor of inSampleSize. For example, if the width and height of an image are 2048×1536 and inSampleSize is set to 4, the actual width and height of the image loaded into the memory is 512×384. It takes up 0.75 MB of memory instead of 12 MB, a 15-fold savings.
    • Note: The value of inSampleSize is not set arbitrarily or larger is better. Set the value based on actual conditions. InSampleSize less than 1 is treated as 1, and any inSampleSize value is raised to a power closer to 2.

5.2 How to Reuse Bitmap

  • Bitmap reuse experiment, the code is shown below, and then look at the printed log information
    • From the printing of the memory address, it can be seen that the two objects are actually one object, and the Bitmap is successfully multiplexed.
    • The bitmapReuse reuse uses exactly a quarter as much memory (4346880) as bitmap (1228800);
    • GetByteCount () gets the memory used by the current image, and getAllocationByteCount() gets the memory used by the reused Bitmap. The bitmapReuse memory is 4346880, but it is the reused bitmap memory (1228800). This is why getAllocationByteCount() may be larger than getByteCount().
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private void initBitmap() { BitmapFactory.Options options = new BitmapFactory.Options(); // Image reuse, this property must be set; options.inMutable =true; // Manually set the zoom ratio, so that it is an integer, convenient calculation, observation data; options.inDensity = 320; options.inTargetDensity = 320; Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg_autumn_tree_min, options); // Object memory address; Log.i("ycBitmap"."bitmap = " + bitmap);
        Log.i("ycBitmap"."ByteCount = " + bitmap.getByteCount() + :::bitmap: AllocationByteCount ="+ bitmap.getAllocationByteCount()); / / useinThe Bitmap property, which must be set; options.inBitmap = bitmap; options.inDensity = 320; // Set the zoom width to half of the original width and height; options.inTargetDensity = 160; options.inMutable =true; Bitmap bitmapReuse = BitmapFactory.decodeResource(getResources(), R.drawable.bg_kites_min, options); // Reuse the memory address of the object; Log.i("ycBitmap"."bitmapReuse = " + bitmapReuse);
        Log.i("ycBitmap"."bitmap:ByteCount = " + bitmap.getByteCount() + :::bitmap: AllocationByteCount =" + bitmap.getAllocationByteCount());
        Log.i("ycBitmap".BitmapReuse: ByteCount =" + bitmapReuse.getByteCount() + ":::bitmapReuse:AllocationByteCount = "+ bitmapReuse.getAllocationByteCount()); / / 11-26 18:24:07. 971, 15470-15470 / com. Yc. Cn. Ycbanner I/ycBitmap: Bitmap = android.graphics.Bitmap@9739bff //11-26 18:24:07.972 15470-15470/com.yc.cn. Ycbanner I/ycBitmap: Bitmap: ByteCount = 4346880:: bitmap: AllocationByteCount = 4346880 //11-26 18:24:07.994 15470-15470/com.yc.cn. Ycbanner I/ycBitmap: Reuse = android.graphics.Bitmap@9739bff //11-26 18:24:07.994 15490-15470 /com.yc.cn. Ycbanner I/ycBitmap: Bitmap: ByteCount = 1228800:: bitmap: AllocationByteCount = 4346880 //11-26 18:24:07.994 15470-15470/com.yc.cn. Ycbanner I/ycBitmap: BitmapReuse: ByteCount = 1228800:::bitmapReuse: AllocationByteCount = 4346880}Copy the code

5.3 Bitmap Uses apis to obtain memory

  • getByteCount()
    • The getByteCount() method is added to API12 and represents the minimum amount of memory required to store Bitmap pigments. API19 starts the getAllocationByteCount() method instead of getByteCount().
  • getAllocationByteCount()
    • After API19, Bitmap added an Api: getAllocationByteCount(); Represents the amount of memory allocated in memory for the Bitmap.
    public final int getAllocationByteCount() {
        if (mRecycled) {
            Log.w(TAG, "Called getAllocationByteCount() on a recycle()'d bitmap! "
                    + "This is undefined behavior!");
            return 0;
        }
        return nativeGetAllocationByteCount(mNativePtr);
    }
    Copy the code
  • What is the difference between getByteCount() and getAllocationByteCount()?
    • In general they are equal;
    • The image is decoded by multiplexing the Bitmap. If the memory of the multiplexed Bitmap is larger than that of the Bitmap to be allocated, then getByteCount() represents the memory occupied by the newly decoded image (not the actual memory size, the actual size is the size of the multiplexed Bitmap). GetAllocationByteCount () represents the actual size of memory (that is, the length of the mBuffer) used by the reused Bitmap.
  • GetAllocationByteCount () may be larger than getByteCount() in the case of reusing bitmaps.

5.4 The blog corresponds to the test project address

  • Welcome to see the demo compression effect directly, github.com/yangchong21…

About other content introduction

01. About blog summary links

  • 1. Tech blog round-up
  • 2. Open source project summary
  • 3. Life Blog Summary
  • 4. Himalayan audio summary
  • 5. Other summaries

02. About my blog

  • My personal website: www.yczbj.org, www.ycbjie.cn
  • Github:github.com/yangchong21…
  • Zhihu: www.zhihu.com/people/yczb…
  • Jane: www.jianshu.com/u/b7b2c6ed9…
  • csdn:my.csdn.net/m0_37700275
  • The Himalayan listening: www.ximalaya.com/zhubo/71989…
  • Source: China my.oschina.net/zbj1618/blo…
  • Soak in the days of online: www.jcodecraeer.com/member/cont.
  • Email address: [email protected]
  • Blog: ali cloud yq.aliyun.com/users/artic… 239.headeruserinfo.3.dT4bcV
  • Segmentfault headline: segmentfault.com/u/xiangjian…
  • The Denver nuggets: juejin. Cn/user / 197877…