#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. day133:2RenMJ:TypeScript的变量&函数&类&接口

    目录 1.变量 2.函数 3.类 4.接口 1.变量 1.变量的声明 // 1.即指定数据类型 也指定值 var 变量名:类型 = 值; eg:var username:string = " ...

  2. RESTFul应用分析

    Restful API 近年来应用越来越广泛,各大互联网公司纷纷推出了自己的 Restful API 服务. 本文将从实际应用出发,从 REST 到 Restful 再到 Restful API ,逐 ...

  3. (11)Linux服务器管理维护注意事项

    1.远程服务器关机及重启时的注意事项 为什么远程服务器不能关机?原因很简单,远程服务器没有放置在本地,关机后谁帮你按开机电源键启动服务器?虽然计算机技术曰新月异,但是像插入电源和开机这样的工作还是需要 ...

  4. Java 复习整理day10

    package com.it.demo01_quickstart; /* 案例: 讲解网络编程相关概念. 网络编程简介: 概述: 网络编程也叫: 套接字编程, Socket编程, 就是用来实现 网络互 ...

  5. Centos8上搭建EMQ MQTT

    layout: post title: Centos8上搭建EMQ MQTT subtitle: 在阿里云Centos8搭建EMQ并配置接入 date: 2020-3-11 author: Dapen ...

  6. std::thread线程库详解(4)

    目录 目录 前言 条件变量 一些需要注意的地方 总结 前言 本文主要介绍了多线程中的条件变量,条件变量在多线程同步中用的也比较多.我第一次接触到条件变量的时候是在完成一个多线程队列的时候.条件变量用在 ...

  7. hdu4126Genghis Khan the Conqueror (最小生成树+树形dp)

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others) Total Submiss ...

  8. hdu5886Tower Defence(树形dp)

    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission ...

  9. fiddler抓包+安卓机 完成手机app抓包的配置 遇到的一些问题

    fiddler抓包+安卓模拟器完成手机app抓包的配置:fiddler抓包+雷电模拟器 完成手机app抓包的配置 其实在安卓真机上弄比在虚拟机上弄更麻烦一点,它们的步骤都差不多一样,就是在安卓真机上弄 ...

  10. poj 3436 ACM Computer Factory 最大流+记录路径

    题目 题意: 每一个机器有一个物品最大工作数量,还有一个对什么物品进行加工,加工后的物品是什么样.给你无限多个初始都是000....的机器,你需要找出来经过这些机器操作后最多有多少成功的机器(111. ...