首页 > 其他分享 >JPEG格式研究——(4)反量化、逆ZigZag变化和IDCT变换

JPEG格式研究——(4)反量化、逆ZigZag变化和IDCT变换

时间:2024-11-24 14:27:26浏览次数:6  
标签:tmp .. int IDCT JPEG f32 ZigZag 解码

反量化

反量化其实很简单,将霍夫曼解码出来的数据乘上对应的量化表就好了

通过当前色度选择出SOF中的Component,其中的Tqi指出了这一色度所需的量化表id

image.png

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)

标签:tmp,..,int,IDCT,JPEG,f32,ZigZag,解码
From: https://www.cnblogs.com/Ryan1202/p/18565753

相关文章

  • yy语音找不到qjpeg4.dll怎么办?YY语音qjpeg4.dll修复大全:多种方法总有一款适合你
    当YY语音找不到qjpeg4.dll文件时,这通常意味着系统或YY语音的安装目录中缺少了必要的动态链接库文件。以下是一些修复方法,你可以根据自己的情况选择适合的一种或多种方法尝试解决:1.重新安装YY语音步骤:卸载当前版本的YY语音。清除可能残留的旧文件或注册表项(可选步骤,如果卸......
  • JPEGWD数据集,焊接缺陷检测NDT专用数据集RGB钢板焊缝缺陷识别任务和分类任务数据集(JPEG
    项目背景:焊接是制造业中的关键工艺之一,焊接质量的好坏直接影响到产品的安全性和可靠性。焊接缺陷检测(Non-DestructiveTesting,NDT)是确保焊接质量的重要手段。传统的焊接缺陷检测方法依赖于人工目视检查,效率低下且易受主观因素影响。近年来,随着计算机视觉技术的发展,基于机器......
  • JPEG格式研究——(2)JPEG文件格式
    JPEG文件除了图像数据之外,还保存了与图片相关的各种信息,这些信息通过不同类型的TAG存储在文件中。TAGJPEG通过TAG标记压缩书记之外的信息。所有的TAG都包含一个TAG类型,TAG类型大小为两个字节,位于一个TAG的最前面。TAG类型的第一个字节一定为0xFF以下是部分常见的TAG类型TAG......
  • CMake构建学习笔记4-libjpeg库的构建
    libjpeg是一个广泛使用的开源库,用于处理JPEG(JointPhotographicExpertsGroup)图像格式的编码、解码、压缩和解压缩功能,是许多图像处理软件和库的基础。libjpeg本身的构建没什么特别的,不过值得说道的是libjpeg存在一个高性能分支叫做libjpeg-turbo,通过汇编代码使用SIMD(SingleIns......
  • lcd屏幕显示jpeg图片,其中lcd每个像素占据4字节
    //编译//arm-openwrt-linux-muslgnueabi-gcc-o17_safe_lcd_camera_test./jpeg_show.c-L./lib/-ljpeg-I./include/#include<stdio.h>#include<stdlib.h>#include<jpeglib.h>#include<setjmp.h>#include<stdint.h>#includ......
  • 为OpenCV1.0添加cvJpeg2Ipl函数
    由于在OpenCV1.0中只提供了从硬盘打开JPEG图像进行解码,有些时候如果JPEG的图像数据是从内存载入的,就无法使用这些曾经很方便高效的接口。为了实现这个目的,我们通过修改OpenCV1.0源码,在其源码包中添加函数,实现把jpeg数据从内存复制到IplImage结构中,这为我们进行相应处理会方......
  • ZigZag :nested loop 的教科书
    ZigZag在PEarray-memoryhierarchylevel上对nested-loopbased算子数据部署设计策略进行详细分析。文章作者来自鲁汶MICAS[1]实验室。软硬件建模软件上只涉及MAC-based的网络算子(Linear、Convolutional),沿用time-loop[2]方法使用nested-loop建模,从operand(Input......
  • DIDCTF-流量分析
    wireshark0某日接到客户应急需求,客户连接工业控制系统的核心网络设备遭到入侵,初步推测可能是网络设备的远程登录密码被破解,请通过对给出的流量包分析,得到黑客登录网络设备后窃取的机密数据key1。flag为8位长度字符串flag:HYDw29ePwireshark0.5下列抓包⽂件中包含了⽤户登录⽹......
  • DIDCTF-电子数据取证
    tomcat-1题目描述在web服务器上发现的可疑活动,流量分析会显示很多请求,这表明存在恶意的扫描行为,通过分析扫描的行为后提交攻击者IPflag格式:flag{ip},如:flag{127.0.0.1}flag{14.0.0.120}tomcat-2题目描述找到攻击者IP后请通过技术手段确定其所在地址flag格式:flag{城市英......
  • 为什么我似乎无法通过编程证明从 jpeg 创建的 png 对于任何给定像素都是相同的?
    因此png是无损的-这意味着它们以某种方式压缩,因此它们代表的数据不会丢失。因此,假设颜色深度和yaddayadda相同,从jpeg创建的png应该是像素相同的。果然,这很容易证明,只需打开Krita或GIMP,然后在像素级别手动检查jpeg与从jpeg创建的png,读取相同任意像素的单独RGB......