JPEG文件数据结构以及将位图保存为JPG的代码

2024-01-02 08:18

本文主要是介绍JPEG文件数据结构以及将位图保存为JPG的代码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

JPEG文件数据结构以及将位图保存为JPG的代码

一、简述
  JPEG是一个压缩标准,又可分为标准JPEG、渐进式JPEG及JPEG2000三种:

  ①标准JPEG:以24位颜色存储单个光栅图像,是与平台无关的格式,支持最高级别的压缩,不过,这种压缩是有损耗的。此类型图片在网页下载时只能由上而下依序显示图片,直到图片资料全部下载完毕,才能看到全貌。
  ②渐进式JPEG:渐进式JPG为标准JPG的改良格式,支持交错,可以在网页下载时,先呈现出图片的粗略外观后,再慢慢地呈现出完整的内容,渐进式JPG的文件比标准JPG的文件要来得小。
  ③JPEG2000:新一代的影像压缩法,压缩品质更好,其压缩率比标准JPEG高约30%左右,同时支持有损和无损压缩。一个极其重要的特征在于它能实现渐进传输,即先传输图像的轮廓,然后逐步传输数据,让图像由朦胧到清晰显示。

  以一幅24位彩色图像为例,JPEG的压缩分为四个步骤:

  ①颜色转换:在将彩色图像进行压缩之前,必须先对颜色模式进行数据转换。转换完成之后还需要进行数据采样。
  ②DCT 变换:是将图像信号在频率域上进行变换,分离出高频和低频信息的处理过程,然后再对图像的高频部分(即图像细节)进行压缩。首先以象素为单位将图像划分为多个8×8的矩阵,然后对每一个矩阵作DCT 变换。把8×8的象素矩阵变成8×8的频率系数矩阵(所谓频率就是颜色改变的速度),频率系数都是浮点数。
  ③量化:由于下面第四步编码过程中使用的码本都是整数,因此要对频率系数进行量化,将之转换为整数。数据量化后,矩阵中的数据都是近似值,和原始图像数据之间有了差异,这一差异是造成图像压缩后失真的主要原因。这一过程中,质量因子的选取至为重要。值选得大,可以大幅度提高压缩比,但是图像质量就比较差,质量因子越小图像重建质量越好,但是压缩比越低。
  ④编码:编码是基于统计特性的方法。

  四个步骤都完成后的JPEG文件,其基本数据结构为两大类型:“段”和经过压缩编码的图像数据。


二、数据结构

  1.段的一般结构如下表所示:

表1:段的一般结构
-----------------------------------------------------------------
名称    字节数 数据  说明
-----------------------------------------------------------------
段标识   1     FF    每个新段的开始标识
段类型   1           类型编码(称作“标记码”)
段长度   2           包括段内容和段长度本身,不包括段标识和段类型
段内容               ≤65533字节
-----------------------------------------------------------------
  说明:
①JPG 文件中所有关于宽度高度长度间隔这一类数据,凡是>1字节的,均采用Motorola格式,即:高位在前,低位在后。
②有些段没有长度描述也没有内容,只有段标识和段类型。文件头和文件尾均属于这种段。
③段与段之间无论有多少FF都是合法的,这些FF称为“填充字节”,必须被忽略掉。


  2.段类型有30种,但只有10种是必须被所有程序识别的,其它的类型都可以忽略。所以下面只列出这10种类型。

表2:段类型
---------------------------------------
名称  标记码  说明
---------------------------------------
SOI    D8     文件头
EOI    D9     文件尾
SOF0   C0     帧开始(标准 JPEG)
SOF1   C1     同上
DHT    C4     定义 Huffman 表(霍夫曼表)
SOS    DA     扫描行开始
DQT    DB     定义量化表
DRI    DD     定义重新开始间隔
APP0   E0     定义交换格式和图像识别信息
COM    FE     注释
-----------------------------------------------------------
  说明:有的文章也将DNL段(标记码=DC,定义扫描行数)列为必须段。


  3.以下按一般JPEG文件的段排列顺序详细介绍各种段的结构:

表3:SOI(文件头)
-----------------
名称  字节数   值
-----------------
段标识   1     FF
段类型   1     D8 
-----------------
  说明:这两个字节构成了JPEG文件头。


表4:APP0(图像识别信息)
--------------------------------------------------------------------------
名称       字节数 值          说明
--------------------------------------------------------------------------
段标识        1   FF
段类型        1   E0
段长度        2   0010        如果有RGB缩略图就=16+3n
  (以下为段内容)
交换格式      5   4A46494600  “JFIF”的ASCII码
主版本号      1
次版本号      1  
密度单位      1               0=无单位;1=点数/英寸;2=点数/厘米
X像素密度     2               水平方向的密度   
Y像素密度     2               垂直方向的密度
缩略图X像素   1               缩略图水平像素数目  
缩略图Y像素   1               缩略图垂直像素数目
(如果“缩略图X像素”和“缩略图Y像素”的值均>0,那么才有下面的数据)
RGB缩略图    3×n             n=缩略图像素总数=缩略图X像素×缩略图Y像素
--------------------------------------------------------------------------
  说明:
①JFIF是JPEG File Interchange Format的缩写,即JPEG文件交换格式,另外还有TIFF等格式,很少用
②“如果有RGB缩略图就=16+3n”是什么意思呢?比如说“缩略图X像素”和“缩略图Y像素”的值均为48,就表示有一个48×48像素的缩略图(n=48×48),缩略图是24位真彩位图,用3个字节来表示一个像素,所以共占用3n个字节。但大多数JPG文件都没有这个“鸡肋”缩略图。


表5:COM(注释)
--------------------------------------------------------------------------
名称    字节数   值    说明
--------------------------------------------------------------------------
段标识    1      FF
段类型    1      FE
段长度    2            其值=注释字符的字节数+2
段内容                 注释字符
--------------------------------------------------------------------------
  说明:有的JPEG文件没有这个段。

 

表6:DQT(定义量化表)

--------------------------------------------------------------------------
名称    字节数   值    说明
--------------------------------------------------------------------------
段标识    1      FF
段类型    1      DB
段长度    2      43    其值=3+n(当只有一个QT时)
  (以下为段内容)
QT信息    1            0-3位:QT号
                       4-7位:QT精度(0=8bit,1字节;否则=16bit,2字节)
QT        n            n=64×QT精度的字节数
--------------------------------------------------------------------------
  说明:
①JPEG文件一般有2个DQT段,为Y值(亮度)定义1个, 为C值(色度)定义1个。 
②一个DQT段可以包含多个QT, 每个都有自己的信息字节


表7:SOF0(图像基本信息)
--------------------------------------------------------------------------
名称  字节数   值    说明
--------------------------------------------------------------------------
段标识   1     FF
段类型   1     C0
段长度   2           其值=8+组件数量×3
  (以下为段内容)
样本精度  1    8     每个样本位数(大多数软件不支持12和16)
图片高度  2
图片宽度  2
组件数量  1    3     1=灰度图,3=YCbCr/YIQ 彩色图,4=CMYK 彩色图
  (以下每个组件占用3字节)
组件 ID   1          1=Y, 2=Cb, 3=Cr, 4=I, 5=Q
采样系数  1          0-3位:垂直采样系数
                     4-7位:水平采样系数
量化表号  1
---------------------------------------------------------------------------
  说明:
①JPEG大都采用yCrCb色彩模型(y表示亮度,Cr红色分量,Cb表示蓝色分量),所以组件数量一般=3
②样本就是单个像素的颜色分量,也可理解为一个样本就是一个组件
③采样系数是实际采样方式与最高采样系数之比,而最高采样系数一般=0.5(分数表示为1/2)。比如说,垂直采样系数=2,那么2×0.5=1,表示实际采样方式是每个点采一个样,也就是逐点采样;如果垂直采样系数=1,那么:1×0.5=0.5(分数表示为1/2),表示每2个点采一个样


表8:DHT(定义Huffman表)
--------------------------------------------------------------------------
名称    字节数   值    说明
--------------------------------------------------------------------------
段标识    1      FF
段类型    1      C4
段长度    2            其值=19+n(当只有一个HT表时)
  (以下为段内容)
HT信息    1            0-3位:HT号
                       4位:   HT类型, 0=DC表,1=AC表
            5-7位:必须=0
HT位表    16           这16个数的和应该≤256
HT值表    n            n=表头16个数的和
--------------------------------------------------------------------------
  说明:
①JPEG文件里有2类Haffman 表:一类用于DC(直流量),一类用于AC(交流量)。一般有4个表:亮度的DC和AC,色度的DC和AC。最多可有6个。
②一个DHT 段可以包含多个HT表, 每个都有自己的信息字节
③HT表是一个按递增次序代码长度排列的符号表。


表9:DRI(定义重新开始间隔)
--------------------------------------------------------------------------
名称    字节数   值    说明
--------------------------------------------------------------------------
段标识    1      FF
段类型    1      DD
段长度    2      4 
  (以下为段内容)
开始间隔  2      n    复位标记的间隔距离
---------------------------------------------------------------------------
  说明:
①开始间隔表示在压缩数据流中,每隔n个MCU 块就有一个RST标记,RST标记将Huffman 的解码数据流复位,DC也重新从0开始,因此,RST标记是一种复位标记
②RST 标记是一种特殊的段,它只具有段标识和段类型(长度=2字节),但它不是独立的段,只能穿插在数据流中(文件头和文件尾段也只有段标识和段类型,却都是独立的段)。
③RST标记共有8个(RST0-RST7),从RST0起开始使用,然后是RST1....直至RST7,再从RST0重复。
④RST标记的标识码是 FFD0-FFD7,对应 RST0-RST7
⑤笔者查看了许多自己电脑上的JPG文件的数据,未发现DRI段和RST标记,所以无法进行详尽的考察


表10:SOS(扫描行开始)
--------------------------------------------------------------------------
名称          字节数   值    说明
--------------------------------------------------------------------------
段标识           1     FF
段类型           1     DA
段长度           2     000C  其值=6+2×扫描行内组件数量
  (以下为段内容)
扫描行内组件数量 1     3     必须≥1,≤4(否则错误),通常=3
  (以下每个组件占用2字节)
组件ID           1           1 = Y, 2 = Cb, 3 = Cr, 4 = I, 5 = Q
Huffman表号      1           0-3位:AC表号 (其值=0...3)
                             4-7位:DC表号(其值=0...3)

                 3           最后3个字节用途不明,忽略
--------------------------------------------------------------------------
  说明:紧接SOS段后的是压缩的图像数据(一个个扫描行),数据存放顺序是从左到右、从上到下。


表11:EOI(文件尾)
------------------
名称  字节数   值
------------------
段标识   1     FF
段类型   1     D9 
------------------
  说明:这两个字节构成了JPEG文件尾。

 

三、实例分析
  用系统自带的画图程序画一个32×24的红色方块,另存为JPG文件,这个文件的全部数据如下:

0000: FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 60
0010: 00 60 00 00 FF DB 00 43 00 08 06 06 07 06 05 08
0020: 07 07 07 09 09 08 0A 0C 14 0D 0C 0B 0B 0C 19 12
0030: 13 0F 14 1D 1A 1F 1E 1D 1A 1C 1C 20 24 2E 27 20
0040: 22 2C 23 1C 1C 28 37 29 2C 30 31 34 34 34 1F 27
0050: 39 3D 38 32 3C 2E 33 34 32 FF DB 00 43 01 09 09
0060: 09 0C 0B 0C 18 0D 0D 18 32 21 1C 21 32 32 32 32
0070: 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32
0080: 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32
0090: 32 32 32 32 32 32 32 32 32 32 32 32 32 32 FF C0
00A0: 00 11 08 00 18 00 20 03 01 22 00 02 11 01 03 11
00B0: 01 FF C4 00 1F 00 00 01 05 01 01 01 01 01 01 00
00C0: 00 00 00 00 00 00 00 01 02 03 04 05 06 07 08 09
00D0: 0A 0B FF C4 00 B5 10 00 02 01 03 03 02 04 03 05
00E0: 05 04 04 00 00 01 7D 01 02 03 00 04 11 05 12 21
00F0: 31 41 06 13 51 61 07 22 71 14 32 81 91 A1 08 23
0100: 42 B1 C1 15 52 D1 F0 24 33 62 72 82 09 0A 16 17
0110: 18 19 1A 25 26 27 28 29 2A 34 35 36 37 38 39 3A
0120: 43 44 45 46 47 48 49 4A 53 54 55 56 57 58 59 5A
0130: 63 64 65 66 67 68 69 6A 73 74 75 76 77 78 79 7A
0140: 83 84 85 86 87 88 89 8A 92 93 94 95 96 97 98 99
0150: 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 B4 B5 B6 B7
0160: B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA D2 D3 D4 D5
0170: D6 D7 D8 D9 DA E1 E2 E3 E4 E5 E6 E7 E8 E9 EA F1
0180: F2 F3 F4 F5 F6 F7 F8 F9 FA FF C4 00 1F 01 00 03
0190: 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 01
01A0: 02 03 04 05 06 07 08 09 0A 0B FF C4 00 B5 11 00
01B0: 02 01 02 04 04 03 04 07 05 04 04 00 01 02 77 00
01C0: 01 02 03 11 04 05 21 31 06 12 41 51 07 61 71 13
01D0: 22 32 81 08 14 42 91 A1 B1 C1 09 23 33 52 F0 15
01E0: 62 72 D1 0A 16 24 34 E1 25 F1 17 18 19 1A 26 27
01F0: 28 29 2A 35 36 37 38 39 3A 43 44 45 46 47 48 49
0200: 4A 53 54 55 56 57 58 59 5A 63 64 65 66 67 68 69
0210: 6A 73 74 75 76 77 78 79 7A 82 83 84 85 86 87 88
0220: 89 8A 92 93 94 95 96 97 98 99 9A A2 A3 A4 A5 A6
0230: A7 A8 A9 AA B2 B3 B4 B5 B6 B7 B8 B9 BA C2 C3 C4
0240: C5 C6 C7 C8 C9 CA D2 D3 D4 D5 D6 D7 D8 D9 DA E2
0250: E3 E4 E5 E6 E7 E8 E9 EA F2 F3 F4 F5 F6 F7 F8 F9
0260: FA FF DA 00 0C 03 01 00 02 11 03 11 00 3F 00 E2
0270: E8 A2 8A F9 93 F7 10 A2 8A 28 00 A2 8A 28 00 A2
0280: 8A 28 03 FF D9

分析:
0000-0001:FF D8(文件头)
0002-0013:APP0段,其中:
  0002-0003:FF E0(段标记)
  0004-0005:00 10(段长度=16字节)
  0006-000A:4A 46 49 46 00(“JFIF”的ASCII码)
  000B-000C:01 01(主次版本号=1.01)
  000D     :01(密度单位为 点数/英寸)
  000E-0011:00 60 00 60(水平和垂直的密度均为每英寸96像素)
  0012-0013:00 00(没有缩略图)
0014-0058:DQT段,其中:
  0014-0015:FF DB(段标记)
  0016-0017:00 43(段长度=67字节)
  0018     :00(QT号=0,QT精度=8bit)
  0019-0058:QT
0059-009D:DQT段,其中:
  0059-005A:FF DB(段标记)
  005B-005C:00 43(段长度=67字节)
  005D     :01(QT号=1,QT精度=8bit)
  005E-009D:QT
009E-00B0:SOF0段,其中:
  009E-009F:FF C0(段标记)
  00A0-00A1:00 11(段长度=17字节)
  00A2     :08(样本精度=8bit)
  00A3-00A6:00 18 00 20(图像高=24,图像宽=32)
  00A7     :03(组件数量=3,YCbCr彩色图)
  00A8     :01(ID号=1,这是亮度Y组件)
  00A9     :22(化为二进制=00100010,表明垂直和水平采样系数均=2)
  00AA     :00(使用QT号=0的量化表)
  00AB     :02(ID号=2,这是色度Cb组件)
  00AC     :11(化为二进制=00010001,表明垂直和水平采样系数均=1)
  00AD     :01(使用QT号=1的量化表)
  00AE     :03(ID号=3,这是色度Cr组件)
  00AF     :11(化为二进制=00010001,表明垂直和水平采样系数均=1)
  00B0     :01(使用QT号=1的量化表)
00B1-00D1:DHT段,其中:
  00B1-00B2:FF C4(段标记)
  00B3-00B4:00 1F(段长度=31字节)
  00B5     :00(HT号=0,DC表)
  00B6-00C5:这16个数字之和=12,说明下面的HT值表的长度=12字节)
  00C6-00D1:HT值表
00D2-0188:DHT段,这是HT号=0的AC表,参照上面分析
0189-01A9:DHT段,这是HT号=1的DC表,参照上面分析
01AA-0260:DHT段,这是HT号=1的AC表,参照上面分析
0261-026E:SOS段,其中:
  0261-0262:FF DA(段标记)
  0263-0264:00 0C(段长度=12字节)
  0265     :03(组件数量=3)
  0266-0267:01 00(组件ID=1,Y组件,使用HT表号=0的AC表)
  0268-0269:02 11(组件ID=2,Cb组件,使用HT表号=1的DC表)
  026A-026B:03 11(组件ID=3,Cr组件,使用HT表号=1的DC表)
  026C-026E:00 3F 00(几乎每个JPG文件中这3个字节的值都相同,但用途不明)
026F-0282:图像压缩数据
0283-0284:FF D9(文件尾)

转自: http://bbs.pfan.cn/post-316797.html

 

这篇关于JPEG文件数据结构以及将位图保存为JPG的代码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

使用Python实现全能手机虚拟键盘的示例代码

《使用Python实现全能手机虚拟键盘的示例代码》在数字化办公时代,你是否遇到过这样的场景:会议室投影电脑突然键盘失灵、躺在沙发上想远程控制书房电脑、或者需要给长辈远程协助操作?今天我要分享的Pyth... 目录一、项目概述:不止于键盘的远程控制方案1.1 创新价值1.2 技术栈全景二、需求实现步骤一、需求

Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码

《Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码》:本文主要介绍Java中日期时间转换的多种方法,包括将Date转换为LocalD... 目录一、Date转LocalDateTime二、Date转LocalDate三、LocalDateTim

jupyter代码块没有运行图标的解决方案

《jupyter代码块没有运行图标的解决方案》:本文主要介绍jupyter代码块没有运行图标的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录jupyter代码块没有运行图标的解决1.找到Jupyter notebook的系统配置文件2.这时候一般会搜索到

Python通过模块化开发优化代码的技巧分享

《Python通过模块化开发优化代码的技巧分享》模块化开发就是把代码拆成一个个“零件”,该封装封装,该拆分拆分,下面小编就来和大家简单聊聊python如何用模块化开发进行代码优化吧... 目录什么是模块化开发如何拆分代码改进版:拆分成模块让模块更强大:使用 __init__.py你一定会遇到的问题模www.

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

C#数据结构之字符串(string)详解

《C#数据结构之字符串(string)详解》:本文主要介绍C#数据结构之字符串(string),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录转义字符序列字符串的创建字符串的声明null字符串与空字符串重复单字符字符串的构造字符串的属性和常用方法属性常用方法总结摘

Spring Boot 3.4.3 基于 Spring WebFlux 实现 SSE 功能(代码示例)

《SpringBoot3.4.3基于SpringWebFlux实现SSE功能(代码示例)》SpringBoot3.4.3结合SpringWebFlux实现SSE功能,为实时数据推送提供... 目录1. SSE 简介1.1 什么是 SSE?1.2 SSE 的优点1.3 适用场景2. Spring WebFlu