JPEG解码:反zig_zag变换

2024-03-11 22:40
文章标签 解码 jpeg 变换 zig zag

本文主要是介绍JPEG解码:反zig_zag变换,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


反量化模块就是对输入的64个数据进行重新排列,64个数据为8*8的数据,即8行8列。在进行编码的时候,DCT变换实际上是将图像从色彩域转向频频域,进过DCT变换的数据要经过量化,量化是实际上是对DCT系数的一个优化过程,它是利用人眼对高频部分不敏感的特性来实现数据的大幅度简化,具体操作时把频率域上的每个成分除以一个对于该成分的常数,去四舍五入接近的整数(已经在huffman解码模块实现反量化),是一种有损压缩。量化后的数据有个很大的特点,就是数列上的相邻点在图像上也是相邻的,还有个特点是直流分量对于交流分量来说要大,而且交流分量中含有大量的0,对于量化后的数据如何进行简化,从而再更大的进行数据压缩,这是就出现了Zig_Zag排列(“Z”字编排),如下图:

 

这样做的特点就是后面的数据会出现多个0,方便后面的游程长度编码(RLE)。由上图可以看出编码的时候对数据并不是顺序排列的,而是一种类似Z字型排列的,那么在解码的时候对接收到的数据是不可以直接用的,必须把数据还原过来,就是一个对数据重新排列的过程,这是就要用到反量化表,如下图:

由上表可以很清楚的看到数据的排列,对来到的每个数据从表中找到与之对应的位置然后存下即可,再读出的时候一次读出就可以了。

 

经过分析可以知道:

1:每次来需要等到64个数据全部来齐才可以操作

2:需要一个存储器来保存这64个数据。本设计中使用了2个存储器来是为了提高速度,一个存储器用来接收数据,另个存储器用来输出数据,两个存储器实现循环操纵,如果只用一个存储器操作,则在数据输入的时候,输出必须等待64个数据全部输入完毕,在数据输出的时候出入又必须等待64个数据全部输出结束才可以接受新的数据。

 

mem
  1 `timescale 1ps/1ps
2 module zig_zag_mem
3 (
4 clk,
5 rst_n,
6 wr_en,
7 wr_addr,
8 data,
9
10 rd_addr,
11 q
12 );
13
14 input clk;
15 input rst_n;
16
17 input wr_en;
18 input [5:0]wr_addr;
19 input [15:0]data;
20
21 input [5:0]rd_addr;
22 output [15:0]q;
23 //--------------------------------------------
24 reg [15:0]RegData [0:63];
25 always @(posedge clk or negedge rst_n)
26 begin
27 if(!rst_n)
28 begin
29 RegData[0] <= 16'h0000;
30 RegData[1] <= 16'h0000;
31 RegData[2] <= 16'h0000;
32 RegData[3] <= 16'h0000;
33 RegData[4] <= 16'h0000;
34 RegData[5] <= 16'h0000;
35 RegData[6] <= 16'h0000;
36 RegData[7] <= 16'h0000;
37 RegData[8] <= 16'h0000;
38 RegData[9] <= 16'h0000;
39 RegData[10] <= 16'h0000;
40 RegData[11] <= 16'h0000;
41 RegData[12] <= 16'h0000;
42 RegData[13] <= 16'h0000;
43 RegData[14] <= 16'h0000;
44 RegData[15] <= 16'h0000;
45 RegData[16] <= 16'h0000;
46 RegData[17] <= 16'h0000;
47 RegData[18] <= 16'h0000;
48 RegData[19] <= 16'h0000;
49 RegData[20] <= 16'h0000;
50 RegData[21] <= 16'h0000;
51 RegData[22] <= 16'h0000;
52 RegData[23] <= 16'h0000;
53 RegData[24] <= 16'h0000;
54 RegData[25] <= 16'h0000;
55 RegData[26] <= 16'h0000;
56 RegData[27] <= 16'h0000;
57 RegData[28] <= 16'h0000;
58 RegData[29] <= 16'h0000;
59 RegData[30] <= 16'h0000;
60 RegData[31] <= 16'h0000;
61 RegData[32] <= 16'h0000;
62 RegData[33] <= 16'h0000;
63 RegData[34] <= 16'h0000;
64 RegData[35] <= 16'h0000;
65 RegData[36] <= 16'h0000;
66 RegData[37] <= 16'h0000;
67 RegData[38] <= 16'h0000;
68 RegData[39] <= 16'h0000;
69 RegData[40] <= 16'h0000;
70 RegData[41] <= 16'h0000;
71 RegData[42] <= 16'h0000;
72 RegData[43] <= 16'h0000;
73 RegData[44] <= 16'h0000;
74 RegData[45] <= 16'h0000;
75 RegData[46] <= 16'h0000;
76 RegData[47] <= 16'h0000;
77 RegData[48] <= 16'h0000;
78 RegData[49] <= 16'h0000;
79 RegData[50] <= 16'h0000;
80 RegData[51] <= 16'h0000;
81 RegData[52] <= 16'h0000;
82 RegData[53] <= 16'h0000;
83 RegData[54] <= 16'h0000;
84 RegData[55] <= 16'h0000;
85 RegData[56] <= 16'h0000;
86 RegData[57] <= 16'h0000;
87 RegData[58] <= 16'h0000;
88 RegData[59] <= 16'h0000;
89 RegData[60] <= 16'h0000;
90 RegData[61] <= 16'h0000;
91 RegData[62] <= 16'h0000;
92 RegData[63] <= 16'h0000;
93 end
94 else
95 begin
96 if(wr_en == 1'b1)
97 begin
98 RegData[wr_addr] <= data;
99 if(wr_addr == 6'h00)
100 begin
101 RegData[1] <= 16'h0000;
102 RegData[2] <= 16'h0000;
103 RegData[3] <= 16'h0000;
104 RegData[4] <= 16'h0000;
105 RegData[5] <= 16'h0000;
106 RegData[6] <= 16'h0000;
107 RegData[7] <= 16'h0000;
108 RegData[8] <= 16'h0000;
109 RegData[9] <= 16'h0000;
110 RegData[10] <= 16'h0000;
111 RegData[11] <= 16'h0000;
112 RegData[12] <= 16'h0000;
113 RegData[13] <= 16'h0000;
114 RegData[14] <= 16'h0000;
115 RegData[15] <= 16'h0000;
116 RegData[16] <= 16'h0000;
117 RegData[17] <= 16'h0000;
118 RegData[18] <= 16'h0000;
119 RegData[19] <= 16'h0000;
120 RegData[20] <= 16'h0000;
121 RegData[21] <= 16'h0000;
122 RegData[22] <= 16'h0000;
123 RegData[23] <= 16'h0000;
124 RegData[24] <= 16'h0000;
125 RegData[25] <= 16'h0000;
126 RegData[26] <= 16'h0000;
127 RegData[27] <= 16'h0000;
128 RegData[28] <= 16'h0000;
129 RegData[29] <= 16'h0000;
130 RegData[30] <= 16'h0000;
131 RegData[31] <= 16'h0000;
132 RegData[32] <= 16'h0000;
133 RegData[33] <= 16'h0000;
134 RegData[34] <= 16'h0000;
135 RegData[35] <= 16'h0000;
136 RegData[36] <= 16'h0000;
137 RegData[37] <= 16'h0000;
138 RegData[38] <= 16'h0000;
139 RegData[39] <= 16'h0000;
140 RegData[40] <= 16'h0000;
141 RegData[41] <= 16'h0000;
142 RegData[42] <= 16'h0000;
143 RegData[43] <= 16'h0000;
144 RegData[44] <= 16'h0000;
145 RegData[45] <= 16'h0000;
146 RegData[46] <= 16'h0000;
147 RegData[47] <= 16'h0000;
148 RegData[48] <= 16'h0000;
149 RegData[49] <= 16'h0000;
150 RegData[50] <= 16'h0000;
151 RegData[51] <= 16'h0000;
152 RegData[52] <= 16'h0000;
153 RegData[53] <= 16'h0000;
154 RegData[54] <= 16'h0000;
155 RegData[55] <= 16'h0000;
156 RegData[56] <= 16'h0000;
157 RegData[57] <= 16'h0000;
158 RegData[58] <= 16'h0000;
159 RegData[59] <= 16'h0000;
160 RegData[60] <= 16'h0000;
161 RegData[61] <= 16'h0000;
162 RegData[62] <= 16'h0000;
163 RegData[63] <= 16'h0000;
164 end
165 end
166 end
167 end
168
169
170 assign q = RegData [rd_addr];
171 endmodule


这是一个位宽为16位,深度为64的存储器。

 

Z
  1 `timescale 1ps / 1ps
2 module zig_zag
3 (
4 clk,
5 rst_n,
6
7 datain_en,
8 datain_addr,
9 zig_zagIDLE,
10 datain,
11
12 unit_en,
13
14 //DataOutOver,
15 dataout_en,
16 zig_dataout
17 );
18
19 input clk;
20 input rst_n;
21
22 input datain_en;
23 input [5:0] datain_addr;
24 input [15:0] datain;
25
26 input unit_en;
27 //input DataOutOver;
28
29 output zig_zagIDLE;
30 output dataout_en;
31 output [11:0] zig_dataout;
32 //-----------------------------------------------------
33 wire [5:0] wr_addr;
34 reg [5:0] rd_addr;
35
36 //ram使能
37 reg wr_ram; //0选择ram0,1选择ram1
38 always @(posedge clk or negedge rst_n) begin
39 if(!rst_n) begin
40 wr_ram <= 1'b0;
41 end else if (unit_en == 1'b1) begin
42 wr_ram <= ~wr_ram;
43 end
44 end
45
46
47 wire wr_ram0;
48 wire wr_ram1;
49 assign wr_ram0 = (datain_en == 1'b1 & wr_ram == 1'b0);
50 assign wr_ram1 = (datain_en == 1'b1 & wr_ram == 1'b1);
51
52
53
54
55 function [5:0] result;
56 input [5:0] count;
57 case(count)
58 6'd0: result = 6'd0;
59 6'd1: result = 6'd1;
60 6'd2: result = 6'd8;
61 6'd3: result = 6'd16;
62 6'd4: result = 6'd9;
63 6'd5: result = 6'd2;
64 6'd6: result = 6'd3;
65 6'd7: result = 6'd10;
66 6'd8: result = 6'd17;
67 6'd9: result = 6'd24;
68 6'd10: result = 6'd32;
69 6'd11: result = 6'd25;
70 6'd12: result = 6'd18;
71 6'd13: result = 6'd11;
72 6'd14: result = 6'd04;
73 6'd15: result = 6'd05;
74 6'd16: result = 6'd12;
75 6'd17: result = 6'd19;
76 6'd18: result = 6'd26;
77 6'd19: result = 6'd33;
78 6'd20: result = 6'd40;
79 6'd21: result = 6'd48;
80 6'd22: result = 6'd41;
81 6'd23: result = 6'd34;
82 6'd24: result = 6'd27;
83 6'd25: result = 6'd20;
84 6'd26: result = 6'd13;
85 6'd27: result = 6'd06;
86 6'd28: result = 6'd07;
87 6'd29: result = 6'd14;
88 6'd30: result = 6'd21;
89 6'd31: result = 6'd28;
90 6'd32: result = 6'd35;
91 6'd33: result = 6'd42;
92 6'd34: result = 6'd49;
93 6'd35: result = 6'd56;
94 6'd36: result = 6'd57;
95 6'd37: result = 6'd50;
96 6'd38: result = 6'd43;
97 6'd39: result = 6'd36;
98 6'd40: result = 6'd29;
99 6'd41: result = 6'd22;
100 6'd42: result = 6'd15;
101 6'd43: result = 6'd23;
102 6'd44: result = 6'd30;
103 6'd45: result = 6'd37;
104 6'd46: result = 6'd44;
105 6'd47: result = 6'd51;
106 6'd48: result = 6'd58;
107 6'd49: result = 6'd59;
108 6'd50: result = 6'd52;
109 6'd51: result = 6'd45;
110 6'd52: result = 6'd38;
111 6'd53: result = 6'd31;
112 6'd54: result = 6'd39;
113 6'd55: result = 6'd46;
114 6'd56: result = 6'd53;
115 6'd57: result = 6'd60;
116 6'd58: result = 6'd61;
117 6'd59: result = 6'd54;
118 6'd60: result = 6'd47;
119 6'd61: result = 6'd55;
120 6'd62: result = 6'd62;
121 6'd63: result = 6'd63;
122 endcase
123 endfunction
124 //读ram选择
125 reg rd_ram;
126 always @(posedge clk or negedge rst_n) begin
127 if(!rst_n) begin
128 rd_ram <= 1'b0;
129 end else if (rd_addr == 6'd63) begin
130 rd_ram <= ~rd_ram;
131 end
132 end
133
134 assign wr_addr = result(datain_addr);
135 wire ram0_release;
136 wire ram1_release;
137 assign ram0_release = (rd_addr == 6'd63 & rd_ram == 1'b0);
138 assign ram1_release = (rd_addr == 6'd63 & rd_ram == 1'b1);
139
140 reg rd_ram0;
141 reg rd_ram1;
142
143 always @(posedge clk or negedge rst_n) begin
144 if(!rst_n)
145 begin
146 rd_ram0= 1'b0;
147 rd_ram1= 1'b0;
148 end
149 else
150 begin
151 if(rd_ram0 == 1'b0 & wr_ram == 1'b0)
152 begin
153 if(unit_en == 1'b1 & zig_zagIDLE == 1'b1)
154 rd_ram0 = 1'b1;
155 end
156 else
157 if(ram0_release == 1'b1)
158 rd_ram0 = 1'b0;
159 if(rd_ram1 == 1'b0 & wr_ram== 1'b1)
160 begin
161 if(unit_en == 1'b1 & zig_zagIDLE == 1'b1)
162 rd_ram1 = 1'b1;
163 end
164 else
165 if(ram1_release== 1'b1)
166 rd_ram1 = 1'b0;
167 end
168 end
169
170 //产生读地址
171 always @(posedge clk or negedge rst_n)
172 begin
173 if(!rst_n)
174 begin
175 rd_addr <= 6'd0;
176 end
177 else
178 begin
179 if (dataout_en == 1'b1)
180 begin
181 if (rd_addr == 6'd63)
182 begin
183 rd_addr <= 6'd0;
184 end
185 rd_addr <= rd_addr + 6'd1;
186 end
187 end
188 end
189
190
191
192
193
194
195 wire [11:0]q0;
196 wire [11:0]q1;
197 zig_zag_mem m1(
198 .clk ( clk ),
199 .rst_n ( rst_n ),
200 .wr_en ( wr_ram0 ),
201 .wr_addr( wr_addr ),
202 .data ( datain ),
203 .rd_addr( rd_addr ),
204 .q ( q0 )
205 );
206
207 zig_zag_mem m2(
208 .clk ( clk ),
209 .rst_n ( rst_n ),
210 .wr_en ( wr_ram1 ),
211 .wr_addr ( wr_addr ),
212 .data ( datain ),
213 .rd_addr ( rd_addr ),
214 .q (q1 )
215 );
216
217
218 assign zig_zagIDLE = rd_ram0 == 1'b0 | rd_ram1 == 1'b0;
219 assign dataout_en = rd_ram0 == 1'b1 | rd_ram1 == 1'b1 ;
220 assign zig_dataout = (rd_ram)?q1[11:0]:q0[11:0];
221
222 endmodule


这是Z变换的顶层模块,

36-50行是定义连个ram使能进行循环操作,unit_en信号是huffman解码输出信号,高表示解码到64的数据,然后存储器转换。

 

55-123行定义一个functiom,他的作用是对于输入的每个数据按照反Zig表分别计算出需要存储器的地址。

 

124-169行是进行读取不同的ram的设置。

 

170-188行是产生读地址,0-63循环操作。

 

195-216行是例化2个存储器。

 

218行是当两个ram都为空闲状态时,向huffman解码模块发出读取数据请求。

 

219行是产生输出使能。

 

220行是对输出有效数据的选择。

 

到这里反Z变换已经结束,接下来将讨论IDCT模块,IDCT变换模块比较灵活,方法很多种,可优化的地方也很多,由于本人水平有限,现在只先讨论一种比较简单直接的没有任何优化的IDCT变换模块。


 

转载于:https://www.cnblogs.com/tony1224/archive/2012/03/20/2407277.html

这篇关于JPEG解码:反zig_zag变换的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/799309

相关文章

研究人员在RSA大会上演示利用恶意JPEG图片入侵企业内网

安全研究人员Marcus Murray在正在旧金山举行的RSA大会上公布了一种利用恶意JPEG图片入侵企业网络内部Windows服务器的新方法。  攻击流程及漏洞分析 最近,安全专家兼渗透测试员Marcus Murray发现了一种利用恶意JPEG图片来攻击Windows服务器的新方法,利用该方法还可以在目标网络中进行特权提升。几天前,在旧金山举行的RSA大会上,该Marcus现场展示了攻击流程,

Verybot之OpenCV应用二:霍夫变换查找圆

其实我是想通过这个程序来测试一下,OpenCV在Verybot上跑得怎么样,霍夫变换的原理就不多说了,下面是程序: #include "cv.h"#include "highgui.h"#include "stdio.h"int main(int argc, char** argv){cvNamedWindow("vedio",0);CvCapture* capture;i

FFmpeg系列-视频解码后保存帧图片为ppm

在正常开发中遇到花屏时怎么处理呢?可以把解码后的数据直接保存成帧图片保存起来,然后直接看图片有没有花屏来排除是否是显示的问题,如果花屏,则代表显示无问题,如果图片中没有花屏,则可以往显示的方向去排查了。 void saveFrame(AVFrame* pFrame, int width, int height, int iFrame){FILE *pFile;char szFilename[

Unstructured cannot write mode RGBA as JPEG 错误解决

Unstructured cannot write mode RGBA as JPEG 错误解决 0. 错误详细1. 解决方法 0. 错误详细 Image Extraction Error: Skipping the failed imageTraceback (most recent call last):File "/root/miniconda3/envs/learn-y

【Hot100】LeetCode—394. 字符串解码

目录 1- 思路栈实现+四种情况处理 2- 实现⭐394. 字符串解码——题解思路 3- ACM 实现 原题链接:394. 字符串解码 1- 思路 栈实现+四种情况处理 ① 遇到数字,进行倍数相加 、②遇到左括号,压栈之前的元素、③遇到右括号弹出,栈进行拼接、④否则遇到字母,直接拼接在 res通过栈,实现先进后出的思想 对于输入 3[a2[c]] 的输入,在读到 3[得

基于FPGA的开源项目:FOC/SHA/USB/JPEG等

文章目录 [1. USB 1.1控制器](https://github.com/WangXuan95/FPGA-USB-Device)[2. FOC控制算法](https://github.com/WangXuan95/FPGA-FOC)[3. BSV高级硬件描述语言入门指南](https://github.com/WangXuan95/BSV_Tutorial_cn)[4. 基于XDMA的

libmad音频解码库-Linux交叉编译移植

下载并解压libmad-0.15.1b.tar.gz 下载链接:https://downloads.sourceforge.net/mad/libmad-0.15.1b.tar.gz $tar -xvf libmad-0.15.1b.tar.gz$cd libmad-0.15.1b 1、先执行下面的命令:这条命令是为了适配高版本的gcc,因为高版本的gcc已经将-fforce-mem去除了:

【数字信号处理】一文讲清FFT(快速傅里叶变换)

目录 快速傅里叶变换(Fast Fourier Transform,FFT)FFT的背景快速傅里叶变换(Fast Fourier Transform,FFT)DFT的数学表达实际计算重要性和应用频谱泄露、频谱混叠奈奎斯特采样定理参考链接 快速傅里叶变换(Fast Fourier Transform,FFT) FFT的背景 1、为什么要时域→频域频率?50Hz+频率120Hz

通过 Flash 让所有浏览器支持 WebP 格式图像解码

http://www.guao.hk/tag/webp#userconsent# http://www.etherdream.com/WebP/

优化采样参数提升大语言模型响应质量:深入分析温度、top_p、top_k和min_p的随机解码策略

当向大语言模型(LLM)提出查询时,模型会为其词汇表中的每个可能标记输出概率值。从这个概率分布中采样一个标记后,我们可以将该标记附加到输入提示中,使LLM能够继续输出下一个标记的概率。这个采样过程可以通过诸如 temperature 和 top_p 等参数进行精确控制。但是你是否曾深入思考过temperature和top_p参数的具体作用? 本文将详细解析并可视化定义LLM输出行为的