This article is mainly about the optimization of compression, try not to post code, the structure of the article as short as possible.

Ratio of compression

Proportional compression is a very common algorithm, mainly through setting BitmapFactory. Options. InSampleSize to compression, compression ratio, we can set themselves up can also according to the target control width and height to geometric proportion, compression efficiency, So we often work with quality compression to compress.

The quality of compressed

Get the pictures after the geometric compression, we can through bitmap.com press (bitmap.com pressFormat. JPEG, quality, baos) to implement the compression quality, we focus on the following two parameters: 1, CompressFormat is the format we want to compress, including the following formats:

  • JPEG: The compression format is JPEG. The compression quality is as followsqualityChange, it’s always used
  • PNG: Compressed to PNG format. PNG is lossless and will be ignoredqualityValue, generally not
  • WEBP: Compressed in WEBP format with the compression qualityqualityBut starting with Android Q,quality=100, lossless compression will be used, generally not

2. Quality is the quality we want to compress, the compression range is 0 ~ 100, generally we will set the compression quality to 80.

Color value compression

Color compression is set using the inPreferredConfig option in bitmapFactory. Options:

  • ALPHA_8
  • RGB_565
  • ARGB_4444
  • ARGB_8888
  • RGBA_F16
  • HARDWARE

ARGB_8888 (4*8 = 32 bits) and RGB_565 (5+6+5 = 16 bits) are used to represent a pixel. RGB_565 is 1 times smaller than ARGB_8888.

Algorithm of compression

In all of this, there is no escaping the problem of defining values for compression, which values should be set to ensure that the image is clear and that the size compression is extreme. Luban implements a set of inSampleSize algorithm calculations to ensure that the compression of images is extreme. The specific code can be seen in the computeSize method, which will not paste the code here.

Native compression

While Luban takes compression to the extreme, it only computes inSampleSize, which is a step up from native libjpeg. An analysis of libjpeg can be found in my article “Libjpeg Analysis of JNI”. The authors of Luban have also made a libjpeg-based library, Luban-Turbo.

The problem

All of the above algorithms have a fatal problem – they need to be loaded into memory before compression. For large images, loading 100MB images into memory will cause memory to grow desperately, and OOM will cause the application process to crash.

plan

Loading images into memory before compression seems to be a problem, but we can create a new process to deal with image compression, even if the loading of images is very large and the process crashes, it will not affect the main process.

A simpler solution I came up with for starting a new process to handle image compression is to create an Activity that handles compression exclusively and set Process to a separate process:

<activity
      android:name=".ProcessActivity"
      android:process=":compress"/>
Copy the code

For a better experience, we can set the activity to a dialog theme, and then set the layout to a loading box to wait for compression. When compression is complete, setResult returns the compression result: