#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

JPG学习笔记4(附完整代码)的更多相关文章

  1. JPG学习笔记3(附完整代码)

    #topics h2 { background: rgba(43, 102, 149, 1); border-radius: 6px; box-shadow: 0 0 1px rgba(95, 90, ...

  2. Android 监听双卡信号强度(附完整代码)

    Android 监听双卡信号强度 监听单卡信号强度 监听单卡的信号强度非常简单直接用TelephonyManager.listen()去监听sim卡的信号强度. TelephonyManager = ...

  3. JPG学习笔记2(附完整代码)

    #topics h2 { background: rgba(43, 102, 149, 1); border-radius: 6px; box-shadow: 0 0 1px rgba(95, 90, ...

  4. WebGL three.js学习笔记 创建three.js代码的基本框架

    WebGL学习----Three.js学习笔记(1) webgl介绍 WebGL是一种3D绘图协议,它把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的 ...

  5. 学习笔记:python3,代码。小例子习作(2017)

    http://www.cnblogs.com/qq21270/p/7634025.html 学习笔记:python3,一些基本语句(一些基础语法的代码,被挪到这里了) 日期和时间操作 http://b ...

  6. 学习笔记:python3,代码。小例子习作

    http://www.cnblogs.com/qq21270/p/7634025.html 学习笔记:python3,一些基本语句(一些基础语法的代码,被挪到这里了) 日期和时间操作 http://b ...

  7. 雨痕 的《Python学习笔记》--附脑图(转)

    原文:http://www.pythoner.com/148.html 近日,在某微博上看到有人推荐了 雨痕 的<Python学习笔记>,从github上下载下来看了下,确实很不错. 注意 ...

  8. Linux Shell输出颜色字符学习笔记(附Python脚本实现自动化定制生成)

    齿轮发出咔嚓一声,向前进了一格.而一旦向前迈进,齿轮就不能倒退了.这就是世界的规则. 0x01背景 造了个轮子:御剑师傅的ipintervalmerge的Python版本.觉得打印的提示信息如果是普通 ...

  9. 基于C#的内网穿透学习笔记(附源码)

    如何让两台处在不同内网的主机直接互连?你需要内网穿透!          上图是一个非完整版内外网通讯图由内网端先发起,内网设备192.168.1.2:6677发送数据到外网时候必须经过nat会转换成 ...

随机推荐

  1. loj10170

    在 n×n 的棋盘上放 k 个国王,国王可攻击相邻的 8 个格子,求使它们无法互相攻击的方案总数. -------------------------------------------------- ...

  2. 查看文件MD5值

    Windows 打开命令窗口(Win+R),然后输入cmd ·输入命令certutil -hashfile 文件绝对路径 MD5 Linux MD5算法常常被用来验证网络文件传输的完整性,防止文件被人 ...

  3. Codeforces Global Round 9 C. Element Extermination

    题目链接:https://codeforces.com/contest/1375/problem/C 题意 给出一个大小为 $n$ 的排列 $a$,如果 $a_i < a_{i+1}$,则可以选 ...

  4. Codeforces Round #652 (Div. 2) D. TediousLee(dp)

    题目链接:https://codeforces.com/contest/1369/problem/D 题意 最初有一个结点,衍生规则如下: 如果结点 $u$ 没有子结点,添加 $1$ 个子结点 如果结 ...

  5. HDU4467 Graph【轻重点维护】

    HDU4467 Graph 题意: 给出一张染色图,\(n\)个点每个点是黑色或者白色,\(m\)条带权边,\(q\)次操作,有两种操作: 改变一个点的颜色 问所有边中两个端点的颜色为给定情况的边权和 ...

  6. hdu1558 Segment set

    Problem Description A segment and all segments which are connected with it compose a segment set. Th ...

  7. Codeforces Round #307 (Div. 2) B. ZgukistringZ

    Professor GukiZ doesn't accept string as they are. He likes to swap some letters in string to obtain ...

  8. 仿ATM程序软件

    一.目标: ATM仿真软件 1 系统的基本功能 ATM的管理系统其基本功能如下:密码验证机制:吞锁卡机制:存取款功能:账户查询功能:转账功能等. 要求 要能提供以下几个基本功能: (1)系统内的相关信 ...

  9. 后缀数组Da模板+注释 以及 dc3模板

    后缀数组Da模板: 1 /* 2 后缀数组倍增法Da板子 3 */ 4 #include <cstdlib> 5 #include <cstring> 6 #include & ...

  10. Codeforces Round #653 (Div. 3) C. Move Brackets

    题意/题解:经典括号匹配题目,不多说了. 代码: int t; int n; string s; int cnt; int main() { ios::sync_with_stdio(false);c ...