#topics h2 { background: rgba(43, 102, 149, 1); border-radius: 6px; box-shadow: 0 0 1px rgba(95, 90, 75, 1), 1px 1px 6px 1px rgba(10, 10, 0, 0.5); color: rgba(255, 255, 255, 1); font-family: “微软雅黑”, “宋体”, “黑体”, Arial; font-size: 15px; font-weight: bold; height: 24px; line-height: 23px; margin: 12px 0 !important; padding: 5px 0 5px 10px; text-shadow: 2px 2px 3px rgba(34, 34, 34, 1) }
#topics h1 span { font-weight: bold; line-height: 1.5; font-family: “Helvetica Neue”, Helvetica, Verdana, Arial, sans-serif; text-decoration: underline; text-shadow: 2px 2px 3px rgba(34, 34, 34, 1) }

  JPG编码的第3步是量化。对于经过离散余弦变化后的8*8block的数据,我们要对这8*8的数据进行量化。在JPEG中量化就是对数据V除以某个数Q,得到round(V/Q)代替原来的数据。然后在JPG解码的时候再乘以M得到V。

       需要注意的是,量化会丢失图片精度,而且是不可逆的。

       M的大小同时也影响压缩的效果。M越大压缩效果越好,但是图片精度损失越大。

图片引用自”Compressed Image File Formats JPEG, PNG, GIF, XBM, BMP – John Miano”[1]

1.JPEG的量化过程

首先我们会有一个8*8的量化表,这个表可以自定义,也可以用JPEG标准提供的量化表。

直接用我们的8*8的Block数据,除以对应的QuantizationTable的数据即可。

const Block QUANTIZATION_TABLE_Y = {16,  11,  10,  16,  24,   40,   51,   61,   
                                    12,  12,  14,  19,  26,   58,   60,   55,   
                                    14,  13,  16,  24,  40,   57,   69,   56,   
                                    14,  17,  22,  29,  51,   87,   80,   62,   
                                    18,  22,  37,  56,  68,   109,  103,  77,   
                                    24,  35,  55,  64,  81,   104,  113,  92,   
                                    49,  64,  78,  87,  103,  121,  120,  101,  
                                    72,  92,  95,  98,  112,  100,  103,  99  };

const Block QUANTIZATION_TABLE_CBCR = { 17,  18,  24,  47,  99, 99,  99,  99,   
                                        18,  21,  26,  66,  99, 99,  99,  99,   
                                        24,  26,  56,  99,  99, 99,  99,  99,   
                                        47,  66,  99,  99,  99, 99,  99,  99,   
                                        99,  99,  99,  99,  99, 99,  99,  99,   
                                        99,  99,  99,  99,  99, 99,  99,  99,   
                                        99,  99,  99,  99,  99, 99,  99,  99,  
                                        99,  99,  99,  99,  99, 99,  99,  99  };

量化表

 

 

假设我们的数据如左下,量化表如右下. 

 

 则round(V / A)就是我们需要的值了

 

2.代码

void JPG::quantization() {
    for (uint i = 0; i < mcuHeight; i++) {
        for (uint j = 0; j < mcuWidth; j++) {
            MCU& currentMCU = data[i * mcuWidth + j];
            //iterate over 每一个component Y, cb cr
            for (uint componentID = 1; componentID <= 3; componentID++) {
                //遍历block
                for(uint ii = 0; ii < getVerticalSamplingFrequency(componentID); ii++) {
                    for(uint jj = 0; jj < getHorizontalSamplingFrequency(componentID); jj++) {
                        Block& currentBlock = currentMCU[componentID][ii * getHorizontalSamplingFrequency(componentID) + jj];
                        const Block& quantizationTable = getQuantizationTableByID(componentID);
                        //这一步就是对64个像素进行量化
                        for(uint index = 0; index < 64; index++) {
                             currentBlock[index] = currentBlock[index] / quantizationTable[index];
                        }
                    }
                }             
            }
        }
    }  
}

 以上全部的代码在https://github.com/Cheemion/JPEG_COMPRESS/tree/main/Day4

 完结

  Thanks for reading,

  Wish you have a good day.

                                                                                                                                                                                              >>>> JPG学习笔记5(待续)


 

参考资料

[1]https://github.com/Cheemion/JPEG_COMPRESS/blob/main/resource/Compressed%20Image%20File%20Formats%20JPEG%2C%20PNG%2C%20GIF%2C%20XBM%2C%20BMP%20-%20John%20Miano.pdf

版权声明:本文为robsann原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/robsann/p/14399452.html