JPEG Basics

JPEG (Joint Photographic Experts Group) is a widely used standard method for lossy compression of Photographic images.

JPG is the most commonly used extension for image files compressed in JPEG format. Other commonly used extensions include.jpeg,.jpe,.jfif, and.jif.

JEPG coding principle

While JEPG files can be encoded in a variety of ways, the most common is using JFIF encoding, which involves the following steps:

  • Color space conversion

    Convert the image from RGB to Y ‘cbCR in different color Spaces. The Y’ component represents the brightness of the pixel, while Cb and Cr represent the “chromatic difference” (blue and red components). Y ‘CBCR color space allows for greater compression without having a significant impact on perceived image quality.

    About “Chromatic aberration”

    “Color” this concept originated in the television industry, the earliest is black and white TV, then need to transport the luminance signal transmit television signals only, namely Y signal can, color TV appeared, people outside of the Y signal increases the two color difference signal to transfer color information, and the aim is for the sake of compatibility with black and white TV set, Because black and white TV only needs to process the Y signal in the signal.

    According to the principle of three primary colors, it is found that the brightness contributed by red, green and blue is different. Green has the highest “brightness”, while blue has the darkest. If the proportion of brightness contributed by red is KR, and the proportion of brightness contributed by blue is KB, then brightness is

    As a rule of thumb, KR=0.299, KB=0.114, then

    The color difference between blue and red is defined as follows

    Finally, the mathematical formula for RGB conversion to YCbCr can be obtained as

  • The sampling

    The human eye is more sensitive to the brightness of the image (Y’ component) in image fineness than the color of the image (Cb and Cr component).

    For the human eye, the change of light and shade in the image is more easily perceived, which is caused by the structure of the human eye. There are two types of photoreceptors in the retina, rods, which sense changes in brightness, and cones, which sense colors. Since rods are much more numerous than cones, we are more likely to perceive light and dark details. Take the picture below

    Just keep the Y prime component

    Just keep the Cb component

    Just keep the Cr component

    Using this property, the Y ‘CBCR color space can be further downsampled, that is, the spatial resolution of Cb and Cr components can be reduced.

    The lower sampling rate is “4:4:4”, indicating that no lower sampling is carried out.

    A downsampling rate of “4:2:2” means a horizontal decrease of 2 times

    A lower sampling rate of “4:2:0” means a two-fold reduction in both horizontal and vertical directions (most commonly used)

    The downsampling rate is usually expressed as a three-part ratio J: A :b, or four parts if transparency is present, which describes the number of luminance and chroma samples in a conceptual region j pixels wide and 2 pixels high.

    • J represents the horizontal sampling rate reference (width of concept area)
    • A represents the chromatic aberration sampling (Cr, Cb) of the first row.
    • B represents the color difference sampling (Cr, Cb) change between the second and first rows
  • Block segmentation

    After downsampling, each channel must be split into 8×8 pixel blocks, with the minimum coding unit (MCU) depending on the downsampling used.

    If the down-sampling rate is “4:4:4”, the size of the minimum coding unit block is 8×8.

    If the down-sampling rate is “4:2:2”, the minimum coding unit block size is 16×8.

    If the down-sampling rate is “4:2:0”, the minimum coding unit block size is 16×16.

    If the channel data cannot be cut into integer multiples of blocks, it is usually filled with a solid color, such as black.

  • Discrete cosine transform

  • quantitative

    The human eye is good at seeing small brightness differences over relatively large areas, but not very good at distinguishing the exact intensity of high-frequency brightness changes. This allows one to greatly reduce the amount of information in the high-frequency component. You simply divide each component in the frequency domain by its constant, and then round (lossy) to the nearest integer.

    This step is irreversible

  • All 8×8 blocks of data are further compressed using lossless algorithms (a variant of Huffman coding).

JEPG compression effect

The picture Quality ([1,100]) Size (bytes) The compression ratio
Highest quality (100) 81447 2.7:1.
High quality (50) 14679 15:1
Medium quality (25) 9407 then
Low quality (10) 4787 His journey
Minimum quality (1) 1523 144:1.

JEPG coding implementation

  • libjpeg

    Widely used C library for reading and writing JPEG image files.

  • libjpeg-turbo

    High-performance JEPG image decomcoder that uses SIMD instructions to accelerate JEPG file compression and decompression on x86, x86-64, Arm, and PowerPC systems, as well as progressive compression on x86, x86-64 systems.

    Libjpeg-turbo is 2-6 times faster than libjpeg on x86 and x86-64 systems, and can be significantly faster than libjpeg on other systems.

Android image decoding

To display an image on Android, the image needs to be decoded into a Bitmap object, which represents a collection of image pixels. The memory occupied by pixels depends on the Bitmap configuration. Currently, Android supports the following configurations:

  • ALPHA_8

    Only transparency channels are stored

  • ARGB_4444

    Each pixel uses 2 bytes of storage

  • ARGB_8888

    Use 4 bytes of storage per pixel (default)

  • HARDWARE

    Special configuration, Bitmap data stored in dedicated graphics memory (Native)

  • RGBA_F16

    Each pixel uses 8 bytes of storage

  • RGB_565

    Each pixel uses 2 bytes of storage, with only RGB channels.

The source code parsing

. Usually, we can call BitmapFactory decodeStream method from the image stream decoding, Java is just a simple layer of entrance, related implementation in the Native BitmapFactory. DoDecode method.

// frameworks/base/libs/hwui/jni/BitmapFactory.cpp
static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream,jobject padding, jobject options, jlong inBitmapHandle,jlong colorSpaceHandle) {
  // ...  
}
Copy the code

1. Initialize related parameters

  • sampleSize

    Sampling rate

  • onlyDecodeSize

    Whether to decode size only

  • prefCodeType

    Preferred color type

  • isHardware

    Whether to store in dedicated image memory

  • isMutable

    If the variable

  • scale

    The zoom factor

  • requireUnpremultiplied

    Whether the color channel does not require a “preloaded” transparent channel

  • javaBitmap

    Reusable Bitmaps

Create a decoder

According to the image format decoded, create different decoders SkCodec.

Image format SkCodec
JPEG SkJpegCodec
WebP SkWebpCodec
Gif SkGifCodec
PNG SkPngCodec

SkCodec is responsible for the core implementation, and SkAndroidCodec is a wrapper class for SkCodec that provides some Android-specific apis. Similarly, SkAndroidCodec also creates different SkAndroidCodec based on the image format.

Image format SkAndroidCodec
JPEG, PNG, Gif SkSampledCodec
WebP SkAndroidCodecadapter

Create a memory allocator

Depending on whether there are reusable bitmaps and whether scaling is required, a different memory Allocator is used.

Allocate pixel memory

Call the skbitmap. tryAllocPixels method to try to allocate the required pixel memory.

  • Java Heap OOM
  • Native Heap OOM
  • The reusable Bitmap used is too small

Five. Perform decoding

Start the encoding operation. Call SkAndroidCodec getAndroidPixels method.

SkCodec::Result SkAndroidCodec::getAndroidPixels(const SkImageInfo& requestInfo,
        void* requestPixels, size_t requestRowBytes, const AndroidOptions* options) {
  // ...
return this->onGetAndroidPixels(requestInfo,requestPixels,requestRowBytes,*options);
}
Copy the code

SkAndroid onGetAndroidPixels method has two, respectively is SkSampledCodec and SkAndroidCodecadapter.

Here we take JPEG image decoding as an example, from the above, it uses SkSampledCodec and SkJpegCodec, SkJpegCodec is the core implementation.

In addition to supporting full decoding using BitmapFactory, Android also supports partial decoding using BitmapRegionDecoder, which is especially useful when working with very large images.

Android JPEG compression

Android has a problem with image compression. IOS displays images of the same size with more detail, which means better compression. For a more detailed discussion of this problem, see github.com/bither/bith…

Skia is an open source 2D rendering engine used by Android. Skia relies on the libjpeg library to decomcode JPEG image files. Optimize_coding, which is TRUE, provides better compression but also consumes more time.

Up to 7.0, Google has set this value to FALSE for compatibility with less powerful devices, 7.0 and above has been set to TRUE.

For more information about optimize_coding being FALSE, see groups.google.com/g/skia-disc…

Below 7.0: androidxref.com/6.0.1_r10/x…

7.0 and above: androidxref.com/7.0.0_r1/xr…

As a result, JPEG image files can be compressed based on libjPEg-Turbo in versions 7.0 and below.

The source code parsing

Image compression can be done by calling the bitmap.press method. Optional configurations are:

  • format

    Compressed image format, JPEG, PNG, WEBP.

  • quality

    Compression quality, available values range from 0 to 100.

Again, the Java layer only provides API entry and implements the bitmap.bitmap_comperss () method in the Native layer.

// framework/base/libs/hwui/jni/Bitmap.cpp
static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,jint format, jint quality,jobject jstream, jbyteArray jstorage) {}Copy the code

Create an encoder

Create different encoders based on the image format.

Image format The encoder
JPEG SkJpegEncoder
PNG SkPngEnccoder
WebP SkWebpEncoder

Set coding parameters

Android JPEG decoding is dependent on libjpeg and libjpeg-Turbo.

A series of parameters are set before compression encoding begins.

  • Image size

  • Color type

    Common color types are:

    JCS_EXT_BGRA,           /* blue/green/red/alpha */
    JCS_EXT_BGRA,           /* blue/green/red/alpha */
    Copy the code
  • The sampling rate

    Currently Android supports “4:2:0” (default), “4:2:2” and “4:4:4”.

  • Best Huffman coding table

    The default value is true, indicating that using the best Huffman encoding table reduces the compression performance but improves the compression efficiency.

    // Tells libjpeg-turbo to compute optimal Huffman coding tables
    // for the image. This improves compression at the cost of
    // slower encode performance.
    fCInfo.optimize_coding = TRUE;
    Copy the code
  • The quality of

    This parameter affects the “quantization” step in JPEG encoding

Three. Perform coding

// external/skia/src/imagess/SkImageEncoder.cpp
bool SkEncoder::encodeRows(int numRows) {
	// ...
  this->onEncodeRows(numRows);
}
Copy the code

JPEG image encoding is implemented by SkJpegEncoder.

// txternal/skia/src/images/SkJpegEncoder.cpp
bool SkJpegEncoder::onEncodeRows(int numRows) {
	// ...
  for (int i = 0; i < numRows; i++) {
    // Perform the libjpeg-turbo encoding operation
  	jpeg_write_scanlines(fEncoderMgr->cinfo(), &jpegSrcRow, 1); }}Copy the code

Sampling algorithm

When adjusting the size of the image, it is necessary to reprocess the pixel data of the original image, which is called image sampling processing.

Currently, Nearest Neighbor and Bilinear sampling algorithms are supported by default on Android.

  • Nearest neighbor

    Each pixel in a resampled grid gets the same value as the nearest pixel in the original grid, which is the fastest processing time, but also causes the image to jagged.

  • Bilinear (Bilinear sampling)

    Each pixel in the resampled grid is the result of a weighted average of the 2×2 4 nearest pixels in the original grid.

In addition to the above two, there are several better algorithms:

  • Bicubic (Double cube sampling)

    Each pixel in the resampled grid is the result of a weighted value of 4×4 16 nearest pixel values from the original grid, with closer pixels having higher weights.

  • Lanczos

    Higher-order interpolation algorithm, which considers more surrounding pixels and retains the most image information.

  • Magic Kernel

    Fast and efficient, but it can produce amazing clear and sharp as a result, more detail: www.johncostella.com/magic/.

Spectrum

Spectrum is Facebook’s open source cross-platform image transcoding dependency library. Compared with jPEG-Turbo, which comes with the default Android operating system, Spectrum has the following advantages:

  • JPEG encoding is based on MozJPEG, which improves compression rates compared to JPEG-Turbo, but also increases compression processing time.
  • Bicubic and Magic Kernel sampling algorithms are supported.
  • The core is implemented using CPP, which can achieve consistent compression effect on both Android and iOS platforms.
  • Support for more custom configurations, including chroma sampling mode and more.

The benchmark

Using Google/Butteraugli to compare the quality difference between the original image and the compressed image, the smaller the value, the better.

Device information: Huawei P20 Pro, Android 10

A Compression mass 80

The core The compression quality Chroma sampling mode The quality differences The file size Time consuming The compression ratio
The original image S444 8.7 MB
jpeg-turbo 80 S444 2.943352 2.5 MB 2255ms 71%
mozjpeg 80 S444 2.486266 2.8 MB 3567ms 67%
mozjpeg 80 S420 2.493475(-15%) 2.3 MB 2703ms 73% (+ 2%)

B Compression mass 75

The core The compression quality Chroma sampling mode The quality differences The file size Time consuming The compression ratio
The original image S444 8.7 MB
jpeg-turbo 75 S444 3.075884 2.3 MB 2252ms 73%
mozjpeg 75 S444 2.698983 2.4 MB 3188ms 72%
mozjpeg 75 S420 2.670076(-13%) 2MB 2470ms 77% (+ 4%)

C Compression mass 70

The core The compression quality Chroma sampling mode The quality differences The file size Time consuming The compression ratio
The original image S444 8.7 MB
jpeg-turbo 70 S444 2.739794 2.1 MB 2230ms 75%
mozjpeg 70 S444 2.838595 2.2 MB 3089ms 74%
mozjpeg 70 S420 2.810702 (+ 2%) 1.8 MB 2404ms 79% (+ 4%)

D Compression mass 65

The core The compression quality Chroma sampling mode The quality differences The file size Time consuming The compression ratio
The original image S444 8.7 MB
jpeg-turbo 65 S444 3.734105 1.9 MB 2227ms 78%
mozjpeg 65 S444 3.177706 2MB 2775ms 77%
mozjpeg 65 S420 3.251182(-12%) 1.6 MB 2116ms 81% (+ 3%)

E Compression mass 60

The core The compression quality Chroma sampling mode The quality differences The file size Time consuming The compression ratio
The original image S444 8.7 MB
jpeg-turbo 60 S444 4.526981 1.8 MB 2189ms 79%
mozjpeg 60 S444 3.486347 1.8 MB 2454ms 79%
mozjpeg 60 S420 3.479777(-23%) 1.5 MB 2035ms 82% (+ 3%)

According to the above data, the average compression rate and image quality of MozJPEG + S420 are improved by 3% and 12% compared to JPEG-Turbo + S444.

Refer to the link

www.cnblogs.com/Arvin-JIN/p…

zh.wikipedia.org/wiki/JPEG

Scc.ustc.edu.cn/zlsc/sugon/…

www.robertstocker.co.uk/jpeg/jpeg_n…

libjpeg.sourceforge.net/

libjpeg-turbo.org/

Github.com/bither/bith…

Groups.google.com/g/skia-disc…

Mp.weixin.qq.com/s/H9Tz1n4O2…

Abraia. Me/docs/image -…