之前一直很好奇图片和视频是如何压缩的,由于视频格式会更复杂,所以先从JPEG下手

因为网上资料太难找太分散,有些又看不太懂,所以根据自己的理解整理了一下

JPEG简介

JPEG(Joint Photographic Experts Group),全称为联合图像专家小组,同时也是我们生活中很常见的一种图像格式,一般以.jpg作扩展名。JPEG采用了多种方法来对图像进行有损压缩,从而使得观感相差不大的情况下减小了较多的文件体积


压缩流程

常见的JPEG图像数据按照如下流程进行压缩:

flowchart TD
原始图像 --> 8x8分块 --> DCT变换 --> 量化 --> Z字形扫描 --> 对系数编码 --> 熵编码 --> 压缩数据
subgraph 对系数编码
对AC系数游程编码
对DC系数差分脉冲编码
end

1.分块

JPEG中会首先对图像以8x8的块为单位划分,不足8x8的会填充剩余部分。不过具体填充什么我没研究过,但是解码显示出来的时候会忽略掉这部分,所以应该是无所谓的。

对图像进行8x8分块也是为了方便下一步进行DCT变化

2.DCT变换

DCT(Discrete Cosine Transform,离散余弦变换)是一种把数据从时域转化到频域的数学方法,把图像数据转换到频域之后,我们就可以从中分离出各种频率的信息。

DCT变换过后数据按照不同频率进行划分,得到的数据实际上是不同频率余弦波的系数,把这些系数乘上对应频率的余弦函数就能得到原来的数据

但要注意的是DCT变换过后数据的大小也不会发生改变,相当于把数据用另一种方式表示,就好像同一句话你用普通话和方言讲出来就是两种表达方式。

3.量化

DCT变换后我们就能区分不同频率的信息了,其中高频信息是图像中的一些细节,将变换后的高频部分系数置0则可以去除这些细节。因为人眼对高频信息不是很敏感,所以观感差距不会很大,就像你有轻度的近视,但不影响你看清一个物体。

比如下图

我们会发现,假如只保留DCT变换后左上角的低频部分,还原出来的图像其实和原图差距不大;而如果看保留高频后还原出来的图像,仔细看会发现只留下了物体边缘等细节部分的一些痕迹(也就是高频部分)

此时选择去除哪些频率的信息就成了关键点,我们要给图片选择一个“近视程度”来让减少高频信息。好在JPEG标准已经准备好了几种量化表,对应了不同的图像质量,我们只需要把DCT变换后的数据除以量化表中的对应项就完成了量化操作。

4.Z字形扫描

对数据进行过量化之后仍然没有减小体积,因为去除的高频系数只是被替换成了0,占用的空间还是不变,这时候就轮到Z字形扫描(Zig-Zag Scan)出场了。

Z字形扫描就如同字面意思一样,按照上图顺序重新排序顺序。因为高频信息聚集在右下角,按照这种方式扫描后就可以把被替换成0的高频系数连续排列了

顺带一提,知名音视频编解码工具FFmpeg的图标就来源于Z字形扫描

5.对DC和AC系数编码

什么是DC系数和AC系数?

简单地说,DC系数就是一个块中第一个数,而AC系数就是剩余的数



(图源网络)

上图中1就是DC系数,2-9就是AC系数

对AC系数编码

前面的Z字形扫描完成了准备操作,真正压缩则是交给游程编码(Run Length Encode, RLE)

游程编码以两个数为一组,第一个数表示第二个数的重复次数,对于压缩经过Z字形扫描过后,存在大量连续的0的数据来说再合适不过了

假如直接舍弃后面一半的信息,对画质影响不大的情况下,减少了差不多一半的数据量!

对DC系数编码

对于DC系数,采用的是一种叫差分脉冲编码调制(Differential Pulse code modulation,DPCM)的编码方式

听起来很高深,实际上就是把DC系数换成这一个块和上一个块的DC系数的差值。比如上一个块的DC系数是20,这一个块的DC系数是10,那就写入-10。如果是第一个块,那就不用变(或者也可以看作前面有一个不存在的DC系数为0)。

JPEG中DC系数和AC系数的存储格式:

在实际存储的数据中,一个系数分成两部分

第一部分长度为一个byte。

对于AC系数来说采用了游程编码,低四位表示第二部分的长度(以bit为单位),高四位表示这一数据前0的个数;

对于DC系数来说这一整个byte就表示第二部分数据的长度(也是以bit为单位)

第二部分的第1位是符号位,0表示负数,1表示正数。如果是正数,无需处理;如果是负数,则是对原数包括符号位在内的每一位取反的结果

6.熵编码

最后是对所有的数据进行熵编码,一般用的是范式霍夫曼编码(Canonical Huffman Code)。

范式霍夫曼编码基于霍夫曼编码,霍夫曼编码核心思想是为出现频率更高的数据分配更短的编号,为出现频率低的数据分配更长的编号,这样就可以实现无损压缩数据。而由于霍夫曼编码以bit为单位,长度又不确定,读取时无法区分,所以采用了范式霍夫曼编码。

JPEG中范式霍夫曼编码的存储格式:

首先用一个大小为16个字节的数组存储编码后数据中对应长度为1bit~16bit的原始数据的种类数,后面按同样的顺序紧跟所有种类的原始数据

而编码后的数据要通过如下方式得到:

数从长度为1bit的0开始,长度相同时每编码一个数就+1,长度每增加1bit就要左移1位

当然,JPEG标准中也给出了参考的范式霍夫曼编码的对照表

参考资料

JPEG解码系列博客:多媒体-编解码 - 随笔分类 - OnlyTime_唯有时光 - 博客园 (cnblogs.com)

JPEG标准:Microsoft Word - T081E.DOC (w3.org)

白话文理解DCT离散余弦变换 - 乂墨EMO - 博客园 (cnblogs.com)

一个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格式研究——(1)压缩原理及流程的更多相关文章

  1. JPEG格式 介绍

    JPEG格式 jpeg是有损压缩格式, 将像素信息用jpeg保存成文件再读取出来,其中某些像素值会有少许变化.在保存时有个质量参数可在[0,100]之间选择,参数越大图片就越保真,但图片的体积也就越大 ...

  2. 图像JPEG格式介绍

    1 JPG格式介绍 JPEG (Joint PhotographicExperts GROUP)是由国际标准组织和国际电话电报咨询委员会为静态图像所建立的第一个国际数字图像压缩标准,也是至今一直在使用 ...

  3. Java 详解 JVM 工作原理和流程

    Java 详解 JVM 工作原理和流程 作为一名Java使用者,掌握JVM的体系结构也是必须的.说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成:Java ...

  4. Linux可插拔认证模块(PAM)的配置文件、工作原理与流程

    PAM的配置文件: 我们注意到,配置文件也放在了在应用接口层中,他与PAM API配合使用,从而达到了在应用中灵活插入所需鉴别模块的目的.他的作用主要是为应用选定具体的鉴别模块,模块间的组合以及规定模 ...

  5. InnoDB 数据表压缩原理与限制

    http://liuxin1982.blog.chinaunix.net/uid-24485075-id-3523032.html 压缩理念 通过提高CPU利用率和节约成本,降低数据库容量及I/O负载 ...

  6. hadoop深入研究:(七)——压缩

    转载请标明出处:hadoop深入研究:(七)——压缩 文件压缩主要有两个好处,一是减少了存储文件所占空间,另一个就是为数据传输提速.在hadoop大数据的背景下,这两点尤为重要,那么我现在就先来了解下 ...

  7. 嵌入式Linux基于framebuffer的jpeg格式本地LCD屏显示

    在基于Linux的视频监控采集系统中,摄像头采集到的一帧视频图像数据一般都是经过硬件自动压缩成jpeg格式的,然后再保存到摄像头设备的缓冲区.如果要把采集到的jpeg格式显示在本地LCD屏上,由于我们 ...

  8. HTTP协议:从原理到流程|乐字节

    这次给大家带来的是HTTP协议:从原理到流程的详解 一.HTTP 协议 HTTP 协议(Hypertext Transfer Protocol, 超文本传输协议),是一个客户端请求和回应的 标准协议, ...

  9. C++ 图片格式转化和压缩

    在做人脸识别底库图片导入的时候,需要支持主流的图片的格式,如jpeg.bmp.png等格式.所以需要对图片进行格式转化.图片过大的话,还有进行缩放等.本文介绍的是利用cximage开源库,来进行对图片 ...

  10. 【5】肿瘤DNA甲基化数据分析原理及流程

    目录 导论 DNA甲基化基本概论 检测DNA甲基化的方法 DNA甲基化数据分析流程及方法 DNA甲基化在肿瘤研究中的应用 导论 表观遗传:非DNA决定的基因表达,或表型改变中可遗传因素的研究 DNA水 ...

随机推荐

  1. CSS – Transform

    前言 之前写的 W3Schools 学习笔记 (3) – CSS 2D Transforms. 这篇作为整理. 参考: Youtube – Learn CSS Transform In 15 Minu ...

  2. 八皇后dfs全排列——洛谷1219

    [USACO1.5] 八皇后 Checker Challenge 题目描述 一个如下的 \(6 \times 6\) 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行.每列有且只有一个,每条对角线(包括 ...

  3. 使用 fabric.js 开发移动端 H5 图片编辑器

    大家好,我是开源图片编辑器的 https://github.com/ikuaitu/vue-fabric-editor 的作者,它是一款基于 PC 版本的开源图片编辑器. 最近很多开发者咨询,是否可以 ...

  4. el-table 宽度自适应bug

    和 flex 一起使用的时候会有这个问题.只能自动变宽不能自动变窄. 在  flex-grow:1;  的那一层设置  overflow: auto;

  5. 使用composer创建项目时报错:Composer could not find the config file?

    使用composer创建项目时报错:Composer could not find the config file:C:\Composer ....? 一般报这个错就是composer安装的时候配置了 ...

  6. dotnet 委托delegate的使用 定义和使用

    void Main() { // 委托 - 初级和高级的分水岭 // 1. 委托的初体验 // 委托是一个引用类型,其实是一个类型,保存方法的指针(地址) (变量名字都是地址 都是指针) // 是一个 ...

  7. C#的引用类型

    引用类型的基类为 Object 引用类型:类Class.接口Interface.委Delegrate.数组Array

  8. Docker升阶

    一.Docker镜像 镜像的定义:镜像是一种轻量级.可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码.运行时需要的库以及环境变量和 ...

  9. manim边做边学--直角平面

    直角平面NumberPlane是Manim库中用于创建二维坐标平面的对象,它可以帮助用户在场景中可视化坐标轴以及网格线. 通过坐标轴.网格线以及刻度,它能够动态地展示函数曲线.几何图形以及它们的变换过 ...

  10. dirseach目录扫描工具-安装详细教程

    安装: 1.github源码下载解压 使用 git 安装: 推荐git clone https://github.com/maurosoria/dirsearch.git --depth 1 zip文 ...