jpeg文件学习
相关最全的一篇文章链接:https://www.cnblogs.com/wtysos11/p/14089482.html
YUV基础知识
Y表示亮度分量:如果只显示Y的话,图像看起来会是一张黑白照。
U(Cb)表示色度分量:是照片蓝色部分去掉亮度(Y)。
V(Cr)表示色度分量:是照片红色部分去掉亮度(Y)。
YUV Formats分成两个格式:
紧缩格式(打包格式)(packed formats):将Y、U、V值储存成Macro Pixels阵列,和RGB的存放方式类似。
平面格式(planar formats):将Y、U、V的三个分量分别存放在不同的矩阵中。
YUV422平面:

YUV420平面格式:

YUV420内存布局:

转到YCbCr色彩空间后,就可以将 Cb(U) 和 Cr(V) 这两个通道进行降采样,这里一般是将 22 个像素变为 11 个像素,虽然分辨率下降到了四分之一,但对于人眼来说差别是不大的。
YUV422sp(Semi-Planar Semi)半平面模式:

RGB24一帧的大小size=width×heigth×3 B,RGB32的size=width×heigth×4,YUV标准格式4:2:0 的数据量是 size=width×heigth×1.5 B
平面格式与交错格式内存存储:

YUV与RGB变换

YUV编码例子
https://zhuanlan.zhihu.com/p/106355033
Level Offset 零电平偏置下移
该步骤的作用是,图像内容平均亮度较高,将0电平移到中间,平均亮度降低, 便于DCT变换量化后直流的系数大大降低,也就降低了数据量。
将灰度级 2 n 2^n 2n的像素值,全部减去 2 n − 1 2^{n-1} 2n−1 ,数据形式由无符号数变为有符号数(补码),单极性数据变为双极性数据。
Z形编码

DCT变换
将图像分为8×8的像块;对于宽(高)不是8的整数倍的图像,使用图像边缘像素填充,以不改变频谱分布。然后对每一个子块进行DCT(Discrete Cosine Transform,离散余弦变换)

其中,C是8x8的DCT变换二维核矩阵,F ( u , v ) 是原始的数据。由于DCT变换是一个正交变换,故 C T = C − 1 C^T = C^{-1} CT=C−1
变换核矩阵如下所示:

量化
JPEG系统分别规定了亮度分量和色度分量的量化表,色度分量相应的量化步长比亮度分量大。
对亮度和色度分量的DCT系数进行量化,使用如下量化表,该量化表是从广泛的实验中得出的。当然,也可以自定义量化表。
//标准亮度分量量化表
static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = {16, 11, 10, 16, 24, 40, 51, 61,12, 12, 14, 19, 26, 58, 60, 55,14, 13, 16, 24, 40, 57, 69, 56,14, 17, 22, 29, 51, 87, 80, 62,18, 22, 37, 56, 68, 109, 103, 77,24, 35, 55, 64, 81, 104, 113, 92,49, 64, 78, 87, 103, 121, 120, 101,72, 92, 95, 98, 112, 100, 103, 99
};//标准色度分量量化表
static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {17, 18, 24, 47, 99, 99, 99, 99,18, 21, 26, 66, 99, 99, 99, 99,24, 26, 56, 99, 99, 99, 99, 99,47, 66, 99, 99, 99, 99, 99, 99,99, 99, 99, 99, 99, 99, 99, 99,99, 99, 99, 99, 99, 99, 99, 99,99, 99, 99, 99, 99, 99, 99, 99,99, 99, 99, 99, 99, 99, 99, 99
};
对DCT变换进行量化后,得到的量化结果,会出现大量的0,使用Z形扫描,可以将大量的0连到一起,减小编码后的大小。越偏离左上方,表示频率越高,通过量化,将图像的高频信息干掉了。
编码
直流编码:DPCM + VLC 可变长熵编码(采用Huffman)
8×8图像块经过DCT变换之后得到的DC直流系数有两个特点:
- 系数的数值比较大
- 相邻8×8图像块的DC系数值变化不大,冗余
根据这个特点,JPEG算法使用了差分脉冲调制编码(DPCM)技术,对相邻图像块之间量化DC系数的差值DIFF进行编码:

对DPCM后算出的DIFF差值使用Huffman编码。所以,DC系数会产生一张长度为16的Huffman码表。

交流:ZigZag Scan + Run Length Encoding+VLC
对于量化后的数据,我们将其分为两路进行处理。一路是AC通路,一路是DC通路。
ZigZag Scan+RLE是用于AC通路的,这是因为AC分量出现较多的0。JPEG采用对0系数的游程长度编码。而对非0值,则要保存所需数和实际值。
在编码之前,需要把二维的变换系数矩阵转换为一维序列,由于量化之后右下角高频系数大部分为零,采用ZigZag Scan读取可以制造较长的零游程,提高编码效率。在扫描中,如果后续的系数全部为零,则用“EOB”表示块结束。

RLE编码的过程:
例:例如,现有一个字符串,如下所示:
57,45,0,0,0,0,23,0,-30,-8,0,0,1,000…
经过RLE之后,将呈现出以下的形式:
(0,57) ; (0,45) ; (4,23) ; (1,-30) ; (0,-8) ; (2,1) ; (0,0)
注意,如果AC系数之间连续0的个数超过16,则用一个扩展字节(15,0)来表示16连续的0。

所以,最后总共有4张Huffman码表(亮度DC,亮度AC,色度DC,色度AC)。
那么,这些码表如何存储?源数据又放在哪里?针对这些未解之谜,接下来我们就分析JPEG的存储结构。
JPEG编码示例
1.1 分块
某个图象的一个8*8方块的亮度值:

1.2 Level Offset
Level Offset 后(每个点值减去128):

1.3 DCT变换
DCT变换后:

1.4 量化

其中,参照的量化表是:

量化时,使用量化前的值除以量化表中相应位置的值。具体计算公式如下:
B [ i ] = B [ i ] + 0.5 Q [ i ] B[i] = \frac{B[i] + 0.5}{Q[i]} B[i]=Q[i]B[i]+0.5
在可以损失一部分精度的情况下,如何用更少的空间存储这些浮点数?答案是使用量子化( Quantization ),简称量化。比如把要量化值分成16个区间,用0到16这样的整数来表示,这样只用4个bit就足够了。
随后,对于这个8*8方块的亮度量化后的数据分别进行AC和DC两路的编码。
量化过程可以参看如下网址的说明:
https://blog.csdn.net/weixin_43876729/article/details/121733344
1.5 编码
1.1 建立哈夫曼树
1)第一个码字必定为0。
如果第一个码字位数为1,则码字为0;
如果第一个码字位数为2,则码字为00;
如此类推。
2)从第二个码字开始,
如果它和它前面的码字位数相同,则当前码字为它前面的码字加1;
如果它的位数比它前面的码字位数大,则当前码字是前面的码字加1后再在后边添若干个0,直至满足位数长度为止。
由于没有1位的码字,所以第一个码字的位数为2,即码字为00;
由于2位的码字有两个,所以第二个码字位数仍为2,即码字为00+1=01;
第三个码字为3位,比第二个码字长1位,所以第三个码字为:01+1=10,然后再添1个“0”,得100;
如此类推,最后得到这个哈夫曼树如下:

哈夫曼表ID和表类型
这个字节的值为一般只有四个0x00、0x01、0x10、0x11。
0x00表示DC直流0号表;
0x01表示DC直流1号表;
0x10表示AC交流0号表;
0x11表示AC交流1号表。

查阅标记SOF0,可以得到图像不同颜色分量的采样因子,即Y、Cr、Cb三个分量各自的水平和垂直采样因子。
大多图片的采样因子为4:1:1或1:1:1。
4:1:1 即(22):(11):(1*1)
1:1:1 即(11):(11):(1*1)
记三个分量中水平采样因子最大值为Hmax,垂直采样因子最大值为Vmax,那么单个MCU矩阵的宽就是Hmax8像素,高就是Vmax8像素。
JPEG的压缩方法与BMP文件有所不同,它不是把每个像素的颜色分量连续存储在一起的,而是把图片分成Y,Cr,Cb三张子图,然后分别压缩。
解压缩实现细节:https://www.cnblogs.com/leaven/archive/2010/04/06/1705846.html
JPEG文件
JPEG的文件格式一般有两种文件扩展名:.jpg和.jpeg。严格来讲,JPEG的文件扩展名应该为.jpeg,由于DOS时代的8.3文件名命名原则,就使用了.jpg的扩展名,这种情况类似于.htm和.html的区别。
1992年颁布了JPEG File Interchange Format(JFIF),目前在互联网上用的最多的jpeg格式,接着又出现了EXIF格式,主要用于数码产品,记录了媒体的时间地点信息。
JPEG文件由一系列字段组成,每个字段都有marker(标记),由0xff开头。

(1)SOF marker(Start of Frame),这个字段定义了文件的起始

(2)APP0(Application-specific),这个字段定义了JFIF格式

(3)APPn(Application-specific),定义了其它格式,如APP1表示exif格式

(4)DQT(Define Quantization Table(s)),定义了量化表

需要注意的问题
- jpeg文件使用网络字节顺序
参考链接
- https://zhuanlan.zhihu.com/p/62286932
- https://blog.csdn.net/weixin_44874766/article/details/117444843
- https://blog.csdn.net/yun_hen/article/details/78135122
相关文章:
jpeg文件学习
相关最全的一篇文章链接:https://www.cnblogs.com/wtysos11/p/14089482.html YUV基础知识 Y表示亮度分量:如果只显示Y的话,图像看起来会是一张黑白照。 U(Cb)表示色度分量:是照片蓝色部分去掉亮度&#x…...
c++基于过程
前言: 笔记基于C黑马程序员网课视频:黑马程序员匠心之作|C教程从0到1入门编程,学习编程不再难_哔哩哔哩_bilibili 在此发布笔记,只是为方便学习,不做其他用途,原作者为黑马程序员。 1. C基础 1.1 用Visual Studio写C程…...
FOC软件 STM32CubeMX 使用
1、安装-及相关软件版本 展示版本注意事项:keil MDK和STM32CubeMX版本至少要大于等于图中版本。 2、 Motor Profiler 5.2.0使用方法...
leetcode hot 100 全排列
46. 全排列 已解答 中等 相关标签 相关企业 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 class Solution(object): def permute(self, nums): """ :type nums: List[int] :rtype: List[List[int…...
使用qrcode.vue生成当前网页的二维码(H5)
使用npm: npm install qrcode.vue 使用yarn: yarn add qrcode.vue package.json: 实现: <template><div class"code"><qrcode-vue :value"currentUrl" :size"size" render-as&…...
0055. shell命令--useradd
目录 55. shell命令--useradd 功能说明 语法格式 选项说明 选项 退出值 相关文件 /etc/passwd /etc/shadow /etc/group /etc/gshadow /etc/skel/ /etc/login.defs /etc/default/useradd 实践操作 注意事项 55. shell命令--useradd 功能说明 useradd 命令是 Lin…...
blender中合并的模型,在threejs中显示多个mesh;blender多材质烘培成一个材质
描述:在blender中合并的模型导出为glb,在threejs中导入仍显示多个mesh,并不是统一的整体,导致需要整体高亮或者使用DragControls等不能统一控制。 原因:模型有多个材质,在blender中合并的时候,…...
vue 本地自测iframe通讯
使用 postMessage API 来实现跨窗口(跨域)的消息传递。postMessage 允许你安全地发送消息到其他窗口,包括嵌套的 iframe,而不需要担心同源策略的问题。 发送消息(父应用) 1. 父应用:发送消息给…...
C++:单例模式
创建自己的对象,同时确保对象的唯一性。 单例类只能有一个实例☞静态成员static☞静态成员 必须类外初始化 单例类必须自己创建自己的唯一实例 单例类必须给所有其他对象提供这一实例 静态成员类内部可以访问 构造函数私有化☞构造函数私有外部不能创建&#x…...
SOME/IP 协议详解——信息格式
文章目录 1. 头部格式1.1 消息 ID(Message ID)1.2 长度(Length)1.3 请求 ID(Request ID)1.4 协议版本(Protocol Version):1.5 接口版本(Interface Version&am…...
C# GDI+数码管数字控件
调用方法 int zhi 15;private void button1_Click(object sender, EventArgs e){if (zhi > 19){zhi 0;}lcdDisplayControl1.DisplayText zhi.ToString();} 运行效果 控件代码 using System; using System.Collections.Generic; using System.Drawing.Drawing2D; using …...
在交叉编译中,常见的ELF(elf)到底是什么意思?
ELF 是 Executable and Linkable Format 的缩写,中文翻译为“可执行与可链接格式”。它是一种通用的文件格式,主要用于存储可执行文件、目标文件(编译后的中间文件)、动态库(.so 文件)以及内存转储文件&…...
Unity开发AR之Vuforia-MultiTarget笔记
前言 在增强现实(AR)技术蓬勃发展的今天,越来越多的开发者开始探索如何将AR应用于各种场景中。Vuforia作为一个领先的AR开发平台,为开发者提供了强大的工具和功能,使得创建AR体验变得更加简单和直观。本文将为您介绍Vuforia的基本概念、特点,以及如何配置和使用MultiTar…...
深入解析 Oracle 的聚合函数 ROLLUP
目录 深入解析 Oracle 的聚合函数 ROLLUP一、ROLLUP 函数概述二、ROLLUP 函数语法三、ROLLUP 实例详解(一)基础分组聚合(二)引入 ROLLUP 函数(三)ROLLUP 与 NULL 值(四)多列复杂分组…...
Wend看源码-Java-集合学习(List)
摘要 本篇文章深入探讨了基于JDK 21版本的Java.util包中提供的多样化集合类型。在Java中集合共分类为三种数据结构:List、Set和Queue。本文将详细阐述这些数据类型的各自实现,并按照线程安全性进行分类,分别介绍非线程安全与线程安全的实现方…...
【软件】教务系统成绩提交工具使用步骤
【软件】教务系统成绩提交工具使用步骤 零、快速开始 安装 与大多数软件一样,安装步骤很简单,一直点击“下一步”即可快速完成安装,安装完成后,在桌面会有一个软件图标,双击即可打开软件主界面。 导入成绩到Excel中…...
IPsec协议,网络安全的秘密
IPsec概述 IPsec是一组基于网络层的安全协议,是保护IP数据包在网络传输过程中保持安全、隐秘以及真实。通过对IP数据包进行一些加密、认证,来防止数据在传输过程中被窃取、篡改甚至伪造,IPsec在企业内部网络的通信、远程办公、云服务连接等场…...
浅谈下Spring MVC的执行流程
什么是Spring MVC Spring MVC是一个基于Java的Web框架,用于构建Web应用程序。 它是Spring Framework的一部分,它提供了模型-视图-控制器(MVC)架构。 支持RESTful风格的URL请求,易于与其他视图技术集成,如…...
khadas edge2安装ubuntu22.04与ubuntu20.04 docker镜像
khadas edge2安装ubuntu22.04与ubuntu20.04 docker镜像 一、资源准备1.1 镜像文件1.2 刷机工具1.3 ubuntu20.04 docker镜像(具备demon无人机所需各种驱动) 二、开始刷机(安装ubuntu22.04系统)2.1 进入刷机状态2.2 刷机 三、docker…...
GitLab 服务变更提醒:中国大陆、澳门和香港用户停止提供服务(GitLab 服务停止)
目录 前言 一. 变更详情 1. 停止服务区域 2. 邮件通知 3. 新的服务提供商 4. 关键日期 5. 行动建议 二. 迁移指南 三. 注意事项 四. 相关推荐 前言 近期,许多位于中国大陆、澳门和香港的 GitLab 用户收到了一封来自 GitLab 官方的重要通知。根据这封邮件…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
