Some of the most commonly used methods of Android image compression

In android development, images are very easy to cause OOM exceptions. In most cases, images need to be compressed and displayed. This paper mainly records several common image compression methods in development

1, Mass compression

Change the bit depth and transparency of the picture on the premise of maintaining the pixels (that is, erase (assimilate) some similar pixels near a certain point in the picture through the algorithm) to reduce the quality of compressed files. Usage scenario: after compressing the image, upload the image to the server or save it locally according to the actual needs

    /**
     * Mass compression
     * Set the bitmap options attribute to reduce the quality of the picture, and the pixels will not be reduced
     * The first parameter is the bitmap image object to be compressed, and the second parameter is the location where the compressed image is saved
     * Set the options attribute 0-100 to realize compression (because png is lossless compression, this attribute is invalid for png)
     *
     * @param bmp
     * @param file
     */
    public static void qualityCompress(Bitmap bmp, File file) {
        // 0-100 is uncompressed
        int quality = 20;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // Store the compressed data in Bao s
        bmp.compress(Bitmap.CompressFormat.JPEG, quality, baos);
        try {
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(baos.toByteArray());
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

2, Dimensional compression

By reducing the pixel value of the unit size, the real sense of reducing pixels (reducing the memory size of the picture by scaling the picture pixels) usage scenario: when caching thumbnails (avatar processing)

    /**
     * Size compression (reduce the memory occupied by pictures by scaling picture pixels)
     *
     * @param bmp
     * @param file
     */

    public static void sizeCompress(Bitmap bmp, File file) {
        // Size compression factor. The larger the value, the smaller the picture size
        int ratio = 8;
        // Compress Bitmap to corresponding size
        Bitmap result = Bitmap.createBitmap(bmp.getWidth() / ratio, bmp.getHeight() / ratio, Config.ARGB_8888);
        Canvas canvas = new Canvas(result);
        Rect rect = new Rect(0, 0, bmp.getWidth() / ratio, bmp.getHeight() / ratio);
        canvas.drawBitmap(bmp, null, rect, null);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // Store the compressed data in Bao s
        result.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        try {
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(baos.toByteArray());
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

3, Sample rate compression
The advantage of setting the sampling rate of pictures and reducing picture pixels is that large pictures will not be read into memory first, which greatly reduces the use of memory, and there is no need to consider the release after reading large pictures into memory. Problem: because the sampling rate is an integer, the quality of the picture cannot be well guaranteed. If we need a sampling rate between 2 and 3, the picture will be a little larger with 2, but the picture quality will be significantly reduced with 3, which can not fully meet my needs. The famous image compression algorithm on GitHub uses sampling rate compression, and its core algorithm is to calculate the sampling value

 private int computeSize() {
    srcWidth = srcWidth % 2 == 1 ? srcWidth + 1 : srcWidth;
    srcHeight = srcHeight % 2 == 1 ? srcHeight + 1 : srcHeight;

    int longSide = Math.max(srcWidth, srcHeight);
    int shortSide = Math.min(srcWidth, srcHeight);

    float scale = ((float) shortSide / longSide);
    if (scale <= 1 && scale > 0.5625) {
      if (longSide < 1664) {
        return 1;
      } else if (longSide < 4990) {
        return 2;
      } else if (longSide > 4990 && longSide < 10240) {
        return 4;
      } else {
        return longSide / 1280 == 0 ? 1 : longSide / 1280;
      }
    } else if (scale <= 0.5625 && scale > 0.5) {
      return longSide / 1280 == 0 ? 1 : longSide / 1280;
    } else {
      return (int) Math.ceil(longSide / (1280.0 / scale));
    }
  }

4, Picture format

Currently, the commonly used image formats for Android include png, jpeg and webp,

png: lossless compressed picture format, which supports Alpha channel. This format is mostly used for Android cut-off materials

jpeg: lossy compressed image format. It does not support transparent background. It is suitable for large image compression with rich colors such as photos. It is not suitable for logo

Webp: it is a picture format that provides both lossy compression and lossless compression, derived from video coding format VP8. From Google's official website, lossless webp is 26% smaller than png on average, and lossy webp is 25% ~ 34% smaller than jpeg on average. Lossless webp supports Alpha channel, lossy webp also supports under certain conditions, and lossy webp is on Android 4 0 (API 14), lossless and transparent in Android 4 Support after 3 (API18)

webp can effectively reduce the disk space occupied by the picture while maintaining the clarity of the picture

Keywords: Java Android

Added by pixelgirl on Wed, 23 Feb 2022 05:04:46 +0200