JPEG格式研究——(4)反量化、逆ZigZag变化和IDCT变换
反量化
反量化其实很简单,将霍夫曼解码出来的数据乘上对应的量化表就好了
通过当前色度选择出SOF中的Component,其中的Tqi指出了这一色度所需的量化表id

Component的结构如下:
| 名称 | 长度(bit) | 备注 |
|---|---|---|
| Ci | 8 | Compoenent的id |
| Hi | 4 | 水平缩放因子 |
| Vi | 4 | 垂直缩放因子 |
| Tqi | 8 | 对应的量化表id |
然后就可以根据量化表id找到量化表,将其中每一个元素与霍夫曼解码的结果相乘就OK了
// 就是简单粗暴的直接相乘
for (int i = 0; i < 8; ++i) {
for (int j = 0; j < 8; ++j) {
result[i][j] = input[i][j] * dqt[i][j];
}
}
逆ZigZag变换
逆ZigZag变换实际上和ZigZag变换做的是同样的操作,直接按Z字形重新排序就好
参考代码
// 直接查表大法
const int zigzag_table[8*8][2] = {
{0, 0}, {0, 1}, {1, 0}, {2, 0}, {1, 1}, {0, 2}, {0, 3}, {1, 2},
{2, 1}, {3, 0}, {4, 0}, {3, 1}, {2, 2}, {1, 3}, {0, 4}, {0, 5},
{1, 4}, {2, 3}, {3, 2}, {4, 1}, {5, 0}, {6, 0}, {5, 1}, {4, 2},
{3, 3}, {2, 4}, {1, 5}, {0, 6}, {0, 7}, {1, 6}, {2, 5}, {3, 4},
{4, 3}, {5, 2}, {6, 1}, {7, 0}, {7, 1}, {6, 2}, {5, 3}, {4, 4},
{3, 5}, {2, 6}, {1, 7}, {2, 7}, {3, 6}, {4, 5}, {5, 4}, {6, 3},
{7, 2}, {7, 3}, {6, 4}, {5, 5}, {4, 6}, {3, 7}, {4, 7}, {5, 6},
{6, 5}, {7, 4}, {7, 5}, {6, 6}, {5, 7}, {6, 7}, {7, 6}, {7, 7}
};
void zigzag_transform(int input[8][8], int output[8][8]) {
for (int i = 0; i < 8*8; ++i) {
int row = zigzag_table[i][0];
int col = zigzag_table[i][1];
output[row][col] = input[i/8][i%8];
}
}
IDCT变换
最后再进行IDCT2D,IDCT变换就是DCT变换的逆变换,IDCT2D就是横着变换一次再竖着变换一次。这个更多是数学上的东西我就不多说了,怕误人子弟
话不多说,上代码:
pub struct DCT {
pub idct2d_data: [[[[f32; 8]; 8]; 8]; 8],
}
fn cc(i: usize, j: usize) -> f32 {
if i == 0 && j == 0 {
return 1.0 / 2.0;
} else if i == 0 || j == 0 {
return 1.0 / (2.0 as f32).sqrt();
} else {
return 1.0;
}
}
impl DCT {
// 先提前算好一部分
pub fn new() -> DCT {
let mut tmp: [[[[f32; 8]; 8]; 8]; 8] = Default::default();
for i in 0..8 {
for j in 0..8 {
for x in 0..8 {
let i_cos = ((2 * i + 1) as f32 * PI / 16.0 * x as f32).cos();
for y in 0..8 {
let j_cos = ((2 * j + 1) as f32 * PI / 16.0 * y as f32).cos();
tmp[i][j][x][y] = cc(x, y) * i_cos * j_cos / 4.0;
}
}
}
}
DCT { idct2d_data: tmp }
}
pub fn idct2d(&self, data: [[f32; 8]; 8]) -> [[f32; 8]; 8] {
let mut tmp: [[f32; 8]; 8] = Default::default();
for i in 0..8 {
for j in 0..8 {
tmp[i][j] = {
let mut tmp = 0.0;
for x in 0..8 {
for y in 0..8 {
tmp += self.idct2d_data[i][j][x][y] * data[x][y];
}
}
tmp
};
}
}
tmp
}
// 后面还有SSE和AVX加速的代码就不放了,直接看源代码就好了
}
尾声
到这里JPEG解码的部分就全部结束了。需要注意的是,这里解码出来的数据颜色格式并不是可以直接输出到屏幕的RGB888(其实允许这种格式,但很少见,比较常见的是YCbCr格式),还要根据需要处理。
提醒一下,解码出来的是分割出来的8x8的块,还要再拼起来
参考资料
博客园博客:JPEG解码——(4)霍夫曼解码 - OnlyTime_唯有时光 - 博客园 (cnblogs.com)
JPEG标准:Microsoft Word - T081E.DOC (w3.org)
一个Rust写的JPEG解码器:MROS/jpeg_tutorial: 跟我寫 JPEG 解碼器 (Write a JPEG decoder with me) (github.com)
友情链接
我学习过程中写的JPEG图片查看器:Ryan1202/my-tiny-jpeg-viewer: A Tiny Jpeg Viewer (github.com)
JPEG格式研究——(4)反量化、逆ZigZag变化和IDCT变换的更多相关文章
- JPEG解码——(5)反量化和逆ZigZag变换
本篇是该系列的第五篇,承接上篇huffman解码,介绍接下来的两个步骤--反量化和逆zigzag变换,即IDCT前的两个步骤. 需要说明的是,这两个步骤可以颠倒,本人的实现是,先反量化,再逆ZigZa ...
- 图像JPEG格式介绍
1 JPG格式介绍 JPEG (Joint PhotographicExperts GROUP)是由国际标准组织和国际电话电报咨询委员会为静态图像所建立的第一个国际数字图像压缩标准,也是至今一直在使用 ...
- 嵌入式Linux基于framebuffer的jpeg格式本地LCD屏显示
在基于Linux的视频监控采集系统中,摄像头采集到的一帧视频图像数据一般都是经过硬件自动压缩成jpeg格式的,然后再保存到摄像头设备的缓冲区.如果要把采集到的jpeg格式显示在本地LCD屏上,由于我们 ...
- JPEG格式 介绍
JPEG格式 jpeg是有损压缩格式, 将像素信息用jpeg保存成文件再读取出来,其中某些像素值会有少许变化.在保存时有个质量参数可在[0,100]之间选择,参数越大图片就越保真,但图片的体积也就越大 ...
- 让阿里云的Centos,PHP组件 ImageMagick支持png和jpeg格式
我们在Centos安装ImageMagick教程中讲述了如何安装ImageMagick,安装完毕之后发现程序并不支持png和jpeg格式的图片,但是这两种图片又是我们平时所常见的,所以我们还要进一步地 ...
- ecshop图片上传JPEG格式失败问题
在根目录下找到includes文件目录,在其目录中找到cls_image.php打开并找到: $allow_file_types = '|GIF|JPG|JEPG|PNG|BMP|SWF|'; 此处J ...
- 超图不支持JPEG格式的WMTS服务
就目前面而言,超图不支持JPEG格式的WMTS服务,只支持PNG格式的. <本篇完>
- 一般源码安装添加的GD库 是不支持 jpeg 格式的图片的
一般源码安装添加的GD库 是不支持 jpeg 格式的图片的,只支持如下格式 GD Support enabled GD Version bundled (2.0.34 compatible) GIF ...
- linux下将jpg,jpeg格式转为PDF
1.安装imagemagick(用其中的convert)和gthumb sudo apt-get install imagemagick gthumb 2.将tiff图片转换为png或jpeg ...
- Call to undefined function imagecreatefromjpeg() 让GD支持JPEG格式的图片扩展
安装扩展支持jpeg格式: 第一步:首先下载文件: 版本v8: wget http://www.ijg.org/files/jpegsrc.v8b.tar.gz 版本v9: wget http://w ...
随机推荐
- sql日期创建
TRUNCATE TABLE SYS_DATEINFO declare @i int set @i=-30000 WHILE @i<1000000 BEGIN INSERT INTO SYS_D ...
- Azure Computer Vision 之 Smart Crop 智能裁剪图片
前言 一个网站通常有许多地方会用到同一张图,但是比例又不一样. 一般的做法就是用 CSS 的 cover 和 contain 来处理. 由于 cover 只会保留中间信息, 所以很多时候需要人工裁剪. ...
- 简单粗暴的实现 Blazor Server 登录鉴权
既然是简单粗暴,那么就不用关心诸如 IDentityServer4,OAuth 之类的组件,也不使用 AuthenticationStateProvider.IAuthService, razor 页 ...
- cf1632 Codeforces Round #769 (Div. 2)题解
A ABC 水题0.0 B Roof Construction 构造题,经过实验构造出了0的右边是不超过\(n\)的最大的\(2^k\rightarrow n\),左边是\(2^k-1,2^k-2,. ...
- 6款支持C#语言的AI辅助编程工具,开发效率提升利器!
前言 在这个AI迅速发展的阶段,涌现出了一大批好用的AI辅助编程工具.AI辅助编程工具能够提高开发效率.改善代码质量.降低bug率,是现代软件开发过程中的重要助手.今天大姚给大家分享6款AI辅助编程工 ...
- iOS关于列表布局的几种实现方式小结
最近在项目开发中,遇到了常见的列表布局样式,功能的要求是最多六行,动态展示.当时想到的方案是,抽象出一个cell,初始化六个标签,动态的控制显示和隐藏,这样功能上没有问题,就是代码有些冗余.请教了身边 ...
- 1. java + react 实现 HRM
1. 云服务的三种方式 1.1 IAAS 基础设施即服务 ,只会提供基础的设施,eg:服务器,网络等 : 1.2 PAAS 平台即服务 ,提供平台,可以把自己写好的代码部署到平台上 : 1.3 SAA ...
- 「模拟赛」CSP-S 模拟 11(T2 超详细)
比赛链接 A.玩水 (water) 签到.发现如果要找两条路径的话,能找到的充要条件是存在一个点的上方和左方的字母相同.(即使两条走过的点截然不同的路径也符合,这时终点会成为这个点). 即存在一个位置 ...
- 云原生爱好者周刊:玩 Kubernetes 游戏,赢取免费机票
云原生一周动态要闻: Grafana 8.2.2 发布 OSM(Open Service Mesh)发布 v1.0 的第一个候选版本 谷歌宣布推出 Google Distributed Cloud K ...
- KubeSphere 社区双周报 | KubeKey v3.0.2 发布 | 2022-11-24
KubeSphere 从诞生的第一天起便秉持着开源.开放的理念,并且以社区的方式成长,如今 KubeSphere 已经成为全球最受欢迎的开源容器平台之一.这些都离不开社区小伙伴的共同努力,你们为 Ku ...