简体   繁体   中英

Compress JPEG image to specific quality level without using Bitmap#compress() method

I want to compress a Bitmap (JPEG image) to quality 64 , the result with be stored in a byte array. Previously I can achieve this with Bitmap#compress() method:

public static byte[] compressJPEG(Bitmap bmp, int quality) {
    if (quality <= 0)
        return new byte[0];

    byte[] array = new byte[0];
    try {
        ByteArrayOutputStream bmpStream = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.JPEG, quality, bmpStream);
        array = bmpStream.toByteArray();
        bmpStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return array;
}

But the result byte array (with the same input image file) is different when I run this on different devices. (May be because it use nativeCompress() internally)

After checking, I find out the different is in Huffman Table(s), SOS & image data parts, see this: Diff check between 2 image photos

So how can I compress JPEG image to specific quality level without using Bitmap#compress() method? Because I really want the result byte array to be similar in structure.

There is no concept of "quality level" in JPEG. It is a shorthand that some encoders use to select quantization tables. There are a number of variables in JPEG compression, including the type and breakdown of scans, samples, huffman table selection, and quantization table selection. If any of those are different in the encoder you use, you are going to get different output. It's the nature of the beast.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM