<style>#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) }</style>
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
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/260849.html
標籤:C++
上一篇:C++模板沉思錄
下一篇:JPG學習筆記5(附完整代碼)
