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编码过程中的霍夫曼编码相关推荐

  1. 多媒体技术 || 自适应的霍夫曼编码与原始的霍夫曼编码的比较

    第一题: (a) 自适应的霍夫曼编码与原始的霍夫曼编码相比什么优点: 原始的Huffman算法给出了一种静态的编码树构造方案,要求在实际编码之前统计被编码对象中符号出现的几率,并据此进行编码树的构造. ...

  2. JPEG霍夫曼编码教程

    转译自:https://www.impulseadventure.com/photo/jpeg-huffman-coding.html 量化后,霍夫曼/熵编码是JPEG压缩文件大小节省的重要因素之一. ...

  3. 灵光一现的创造——霍夫曼编码

    点击上方"LiveVideoStack"关注我们 作者 | Alex 技术审校 | 赵军 霍夫曼 声影传奇 #004# 作为一名科学家和老师,我真的非常执着.如果我觉得自己还没有找 ...

  4. 哈夫曼编码压缩率计算_程序员的算法课(8)-贪心算法:理解霍夫曼编码

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/ ...

  5. 程序员的算法课(8)-贪心算法:理解霍夫曼编码

    一.一种很贪婪的算法定义 贪心是人类自带的能力,贪心算法是在贪心决策上进行统筹规划的统称. [百度百科]贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体 ...

  6. 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的实现 ...

  7. 霍夫曼算法_霍夫曼编码算法

    霍夫曼算法 In this tutorial, we'll be discussing and implementing the Huffman Coding Algorithm in Java. 在 ...

  8. 霍夫曼树和霍夫曼编码以及霍夫曼编码的应用

    文章目录 霍夫曼树介绍 1.1霍夫曼树的定义 1.2霍夫曼树的几个概念 1.3构建霍夫曼树的过程 1.4代码实现霍夫曼树 霍夫曼编码介绍 什么是霍夫曼编码 通信领域的应用 字符串压缩 1.构造霍夫曼树 ...

  9. 霍夫曼编码(Huffman Coding)

    霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种. 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符 ...

最新文章

  1. 2017年前端开发工具趋势
  2. 一般服务器崩了要多久能修复,阴阳师服务器崩了修复了吗?阴阳师最新4月15日更新内容...
  3. 编译器在处理const变量跟一般变量时的区别
  4. Centos7 修改防火墙,开放端口、转发端口
  5. HTML5清爽博客自媒体网站模板
  6. Java并发基础(六) - 线程池
  7. 大数据分析平台由哪些部分组成
  8. GNN | 从序列神经网络到GCN、GraphSage、GAT图模型总结
  9. 基本数据类型与字符串之间的转换
  10. 利用JDBC开发图书管理系统
  11. android 自动打开qq,qq自动发消息脚本
  12. 苹果手机录屏软件_手机端录屏软件哪个好 手机上最好的录屏软件
  13. win10新建文件夹必须刷新才能显示
  14. 推荐一款免费开源的pdf编辑器
  15. TP框架和Laravel框架的区别
  16. Adobe Experience Cloud落地中国,Adobe、微软与世纪互联共庆三方合作
  17. CUBA 7 新特性(上篇)
  18. word被加密不能编辑如何破解
  19. 心血来潮:重新温习一下C语言的指针
  20. 窥探现代浏览器架构(四)

热门文章

  1. python三角形面积公式
  2. 常见的面试题 (二)
  3. 某验 空间推理验证码识别
  4. 为什么只能重置密码不能找回密码?
  5. 帮我写一篇外骨骼文献综述
  6. Alfred安装与使用
  7. linux系统备份及还原
  8. 双机热备 ip地址_SBC双机热备方案
  9. 用API函数设置颜色
  10. VS对战平台发布1.1.7内部测试版