JPEG编码过程中的霍夫曼编码
JPEG编码过程中的霍夫曼编码
jpeg文件中的霍夫曼编码分两个部分对DC系数编码和对AC系数的编码。
DC系数的编码
编码过程
DC系数的编码由两部分组成, huffman 编码的bitlen + additional bits。
y的bitlen是能够表示DC 系数y的最小bit数,它的定义为:
通过上面的定义获取y的bitlen,通过jpeg提供的DC 霍夫曼编码树获得bitlen的编码。bitlen就把DC系数值分成12个type(8bit精度),实际值不用霍夫曼编码而直接用二进制的编码。
bitvalue倍分成了12类,负数是在bitlen下的补码表示。用两部分的表示的好处,前面的bitlen使用霍夫曼编码可以区分前缀,保证可以成功解码。(使得bitvalue数据的bit前缀不会有重合)
给出DC系数为63 则bitlen = 6,它的霍夫曼编码是1110,它的二进制编码是11111,所以得到的DC系数最后的编码是1110111111.
DC霍夫曼码表
霍夫曼码表的提供方式是,前16个字节,每个字节的值表示可以分别用1bit~16bit长度的码字表示的符号的数目。后边的字节串表示每一个符号。
下面是jpeg提供的亮度DC系数的霍夫曼码表
const BYTE STD_HUFTAB_LUMIN_DC[] =
{0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
};
0x00, //表示使用1bit表示的码字数量为0 0x01, //使用2bits表示的码字数量为1 0x05, //使用3bits表示的码字数量为50x01, //使用4bits表示的码字数量为10x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //总共有12个符号
12个符号值为0~11
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
由给出的霍夫曼表获得霍夫曼树过程参考DIGITAL COMPRESSION AND CODINGOF CONTINUOUS-TONE STILL IMAGES –REQUIREMENTS AND GUIDELINES(Annex C),它的matlab代码如下:
function [ ehufco, ehufsi ] = dedht( dht)
%dedht creat huffman code list
% dht define huffman tablebits = dht(1:16);
huffval = dht(17:end);
n = 0;
for j=1:16n = n + bits(j);
end
huffsize = zeros(1,n);
huffcode = zeros(1,n);
k = 0;
j = 1;
for i=1:16for j = 1:bits(i)huffsize(k+1)=i;k = k+ 1;end
endhuffsize(k+1) = 0;
lastk = k;code = 0;
k=1;
% si code bit size
si= huffsize(1);
while huffsize(k) > 0huffcode(k) = code;code = code + 1;k= k+ 1;while huffsize(k) == sihuffcode(k)=code;code = code + 1;k = k+ 1;endif huffsize(k) == 0break;endcode = code * 2;si = si + 1;while huffsize(k)~=sicode = code *2;si = si + 1;end
endfor k=1:lastki = huffval(k);ehufco(i +1) = uint32(huffcode(k));ehufsi(i+1) = uint32(huffsize(k));
end
end
C代码
/* 类型定义 */
/* 编码表项类型定义 */#define MAX_HUFFMAN_CODE_LEN 16typedef struct
{int symbol; /* 符号 */int freq; /* 频率 */int group; /* 分组 */int depth; /* 码长 */int code; /* 码字 */
} HUFCODEITEM;
/* 编码器类型定义 */
typedef struct
{BYTE huftab[MAX_HUFFMAN_CODE_LEN + 256]; /* 哈夫曼表 */int first [MAX_HUFFMAN_CODE_LEN]; /* first */int index [MAX_HUFFMAN_CODE_LEN]; /* index */HUFCODEITEM codelist[256];/* 编码表 */void *input; /* input bit stream */void *output; /* output bit stream */
} HUFCODEC;static void huffman_encode_init_from_huftab(HUFCODEC *phc)
{int i, j, k;int symbol;int code;BYTE hufsize[256];int hufcode[256];int tabsize;k = 0;code = 0x00;for (i=0; i<MAX_HUFFMAN_CODE_LEN; i++) {for (j=0; j<phc->huftab[i]; j++) {hufsize[k] = i + 1;hufcode[k] = code;code++; k++;}code <<= 1;}tabsize = k;for (i=0; i<tabsize; i++) {symbol = phc->huftab[MAX_HUFFMAN_CODE_LEN + i];phc->codelist[symbol].depth = hufsize[i];phc->codelist[symbol].code = hufcode[i];}
}
输入上面的标准亮度DC huffman table获得的霍夫曼树如下:
{ 2,0x0000}, /* 00 */{ 3,0x0002}, /* 010 */ { 3,0x0003}, /* 011 */ { 3,0x0004}, /* 100 */ { 3,0x0005}, /* 101 */ { 3, 0x0006},/* 110 */ { 4,0x000e}, /* 1110 */ { 5,0x001e}, /* 11110 */ { 6,0x003e}, /* 111110 */ { 7,0x007e}, /* 1111110*/ { 8,0x00fe}, /* 11111110 */ { 9,0x01fe} /* 111111110 */
AC系数的编码
ZZ表示经过zig-zag 排序的DCT系数。AC 系数ZZ(1)~ZZ(63)被表示为一个8bit复合数RS,这个数被叫做Run length code(行程编码)
低4位SSSS表示下一个非零系数的尺寸,高四位RRRR表示从当前非零系数到下一个非零系数之间零的数目。
特殊编码:
- 0的长度有时会超过16,RRRRSSSS=0xf0 表示连续16个0.
- block的结尾EOB被表示为 RRRRSSSS = 0x00,表示后边所有的数据都为0
复合行程编码数据经过霍夫曼编码,后边需要接additional bits,附加bit类似DC系数的编码,通过SSSS 非零系数尺寸进行分类后获得补码二进制编码。
AC霍夫曼码表
AC霍夫曼编码表的格式跟DC霍夫曼编码表的格式相同,前16个byte表示使用各个bits表示的符号数,后边的huffman value是行程编码的值。
从霍夫曼编码表中获得霍夫曼树的方式跟DC霍夫曼码表相同。
获得的AC霍夫曼树例子
标准中亮度AC霍夫曼码表
const BYTE STD_HUFTAB_LUMIN_AC[] =
{0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,0xf9, 0xfa,
};
参考
数值分析–11章 压缩
JPEG中Huffman解码详解
JPEG文件中默认Huffman表说明
JPEG编码过程中的霍夫曼编码相关推荐
- 多媒体技术 || 自适应的霍夫曼编码与原始的霍夫曼编码的比较
第一题: (a) 自适应的霍夫曼编码与原始的霍夫曼编码相比什么优点: 原始的Huffman算法给出了一种静态的编码树构造方案,要求在实际编码之前统计被编码对象中符号出现的几率,并据此进行编码树的构造. ...
- JPEG霍夫曼编码教程
转译自:https://www.impulseadventure.com/photo/jpeg-huffman-coding.html 量化后,霍夫曼/熵编码是JPEG压缩文件大小节省的重要因素之一. ...
- 灵光一现的创造——霍夫曼编码
点击上方"LiveVideoStack"关注我们 作者 | Alex 技术审校 | 赵军 霍夫曼 声影传奇 #004# 作为一名科学家和老师,我真的非常执着.如果我觉得自己还没有找 ...
- 哈夫曼编码压缩率计算_程序员的算法课(8)-贪心算法:理解霍夫曼编码
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/ ...
- 程序员的算法课(8)-贪心算法:理解霍夫曼编码
一.一种很贪婪的算法定义 贪心是人类自带的能力,贪心算法是在贪心决策上进行统筹规划的统称. [百度百科]贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体 ...
- Zlib压缩算法:LZ77、LZ78、霍夫曼编码、滑动窗口、Rabin-Karp算法、哈希链、I/O缓冲区
Table of Contents 1.简介 1.1 什么是zlib 2.压缩算法 2.1 放气 2.2 LZ77 2.2.1 滑动窗口 2.2.2 长距离对 2.3 霍夫曼编码 3. zlib的实现 ...
- 霍夫曼算法_霍夫曼编码算法
霍夫曼算法 In this tutorial, we'll be discussing and implementing the Huffman Coding Algorithm in Java. 在 ...
- 霍夫曼树和霍夫曼编码以及霍夫曼编码的应用
文章目录 霍夫曼树介绍 1.1霍夫曼树的定义 1.2霍夫曼树的几个概念 1.3构建霍夫曼树的过程 1.4代码实现霍夫曼树 霍夫曼编码介绍 什么是霍夫曼编码 通信领域的应用 字符串压缩 1.构造霍夫曼树 ...
- 霍夫曼编码(Huffman Coding)
霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种. 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符 ...
最新文章
- 2017年前端开发工具趋势
- 一般服务器崩了要多久能修复,阴阳师服务器崩了修复了吗?阴阳师最新4月15日更新内容...
- 编译器在处理const变量跟一般变量时的区别
- Centos7 修改防火墙,开放端口、转发端口
- HTML5清爽博客自媒体网站模板
- Java并发基础(六) - 线程池
- 大数据分析平台由哪些部分组成
- GNN | 从序列神经网络到GCN、GraphSage、GAT图模型总结
- 基本数据类型与字符串之间的转换
- 利用JDBC开发图书管理系统
- android 自动打开qq,qq自动发消息脚本
- 苹果手机录屏软件_手机端录屏软件哪个好 手机上最好的录屏软件
- win10新建文件夹必须刷新才能显示
- 推荐一款免费开源的pdf编辑器
- TP框架和Laravel框架的区别
- Adobe Experience Cloud落地中国,Adobe、微软与世纪互联共庆三方合作
- CUBA 7 新特性(上篇)
- word被加密不能编辑如何破解
- 心血来潮:重新温习一下C语言的指针
- 窥探现代浏览器架构(四)