跳到内容

JPEG - 想法与实践/头部部分

来自维基教科书,开放的书籍,为开放的世界

JPEG 文件的头部部分被划分为,每个段以一个标记开始,标识该段。 通常,JPEG 文件包含 7 个不同的标记。标记是一个字节对,第一个字节是 255,第二个字节不同于 0 和 255。我们通过第二个字节来标识一个标记。有两个标记是独立的(因此不打开一个段):打开文件的标记 SOI(开始图像)= 216 和关闭文件的标记 EOI(结束图像)= 217。(还有另一种独立的标记,但它不在我们这里讨论的顺序 DCT 模式中使用:它标志着扫描的重启,并由 0、1、...、7 中的一个数字索引:RST0、...、RST7(重启)= 208、...、215)。其他标记打开一个段,在这种情况下,接下来的两个字节(b1,b2)表示段的长度(包括这两个字节):l = b1 * 256 + b2。接下来的 l - 2 个字节序列是该段的内容。以下是段的类型(用它们的标记标识)

APP0、APP1、...、APP15(应用) 224-239
COM(注释) 254
SOF(开始帧) 192-207,除了 196、200 和 204
DHT(定义霍夫曼表) 196
DQT(定义量化表) 219
SOS(开始扫描) 218

(以及其他几个在此处未使用的标记:DNL(定义行数 = 220)、DRI(定义重启间隔 = 221)、DHP(定义分层渐进 = 222)、EXP(扩展参考分量 = 223)、DAC(定义算术编码条件 = 204)、TEM(用于算术编码中的 TEMporary 使用 = 1)以及一些保留标记:JPG(保留用于 JPeG 扩展 = 200、240、241、...、253)和 RES(REServed = 2、...、191))

前两个 - APP 和 COM - 指定了在 JPEG 程序之外的内容。通常只存在一个 APP 段(即 APP0),它指定了实现。APP 段还可以包含有关相机类型和拍摄图片时间的信息。COM 可以说明用于创建文件的程序、选择的质量百分比等。

帧段 SOF

[编辑 | 编辑源代码]

JPEG 程序的出发点是“图片”,图片可以定义为数字、数字对、数字三元组或数字四元组的(矩形)矩阵。也就是说,图片是具有 1-4 之间的一个数字的长度的数组的矩阵。灰度图片是字节矩阵。彩色图片是 RGB 三元组(字节)矩阵或 YCbCr 三元组(有符号字节)矩阵。因此,图片可以被认为是由一个或多个(最多四个)整数矩阵组成的,这样的矩阵被称为图片的分量。每个分量都分配一个分量标识符(字节):例如,灰度图片的(一个)分量为 0,彩色图片的三个分量为 0、1 和 2。

图片的尺寸、分量标识符和分量的顺序在帧段 SOF 中指定,以及如何处理分量之间的关系。由于颜色通常只在位置之间缓慢变化(而且我们不太擅长区分颜色的微小变化),对于两个颜色分量,我们可以例如将图片分成 2x2 像素的方块并取平均值,这样我们就可以将这个方块看作是一个像素,从而处理四倍小的彩色图片。我们也可以只限于两个像素,要么水平排列,要么垂直排列。每个分量的数字对 (Hi, Vi) 决定了如何扫描分量之间的关系。Hi 和 Vi 可以从 1 到 4(Hi 和 Vi 必须比较小:它们的乘积之和不能超过 10)。分别设 H 和 V 为最大的 Hi 和 Vi 值。这些最大值通常与 Y 分量相关联,而 ((Hi, Vi) = (H, V)) 意味着像素按原样取值:水平样本数与图片的宽度相同,水平行数与图片的高度相同。如果一个(颜色)分量的对为 (Hi, Vi),则水平线上的样本数是 (Hi/H) 乘以宽度,采样线的数量是 (Vi/V) 乘以高度,也就是说,收集了 (H/Hi)x(V/Vi) 像素的小矩形(并被认为是一个像素)。通常情况下,颜色分量的 (Hi, Vi) = (1, 1),而 Y 分量的 (Hi, Vi) = (1, 1) 或 (2, 1) 或 (1, 2) 或 (2, 2)。(Hi, Vi) = (2, 2) 意味着收集了四个颜色像素,并且“这个”像素与四个 Y 像素组合在一起。由于图片被划分为 8x8 的方块,这意味着 Y 分量的四个 8x8 方块与颜色分量的一个 8x8 方块组合在一起。四个 Y 方块的编码数据(编码的 64 数组)按通常的扫描顺序写入文件:从左到右沿行,从上到下。接下来是两个颜色分量的编码数据(编码的 64 数组)。当只收集两个像素(水平或垂直)时,类似的过程。由所有分量和收集的 8x8 方块产生的数据流的这一部分被称为最小编码单元(MCU)。

这张图片展示了当收集四个 Y 分量 8x8 方块时的绘制方式(像素对像素 - 并且按放大的比例) - 你要想象中间的四个 8x8 方块,两个(最上面的)已经绘制了,第三个正在绘制

以下图片(占用 3.2 Kb)下面的两张图片是这张图片,每隔一条垂直线都绘制为黑色,但以不同的方式扫描:对于颜色分量,分别在垂直和水平方向上收集两个像素(即颜色分量的 (Hi, Vi) = (1, 1),而 Y 分量的 (Hi, Vi) = (1, 2) 和 (2, 1))。在第一张图片(占用 5.9 Kb)中,颜色是正确的,在第二张图片(占用 4.7 Kb)中,颜色是褪色的,因为它们与线的黑色混合在一起

帧段 SOF 由以下字节组成:标记 (255, b),其中字节 b 指定扫描模式。我们假设这里 b = 192,表示基线顺序 DCT 模式;然后是表示段长度的字节对(包括这两个字节),这对字节为 (0, 8 + 3 * 分量数);然后是一个表示颜色值位数的字节,这里设置为 8(表示颜色值为字节),但在扩展模式中为 12;然后是一对字节 (b1, b2) 表示图片的高度 (= b1 * 256 + b2) 和一对字节表示宽度;最后是一个表示分量数(1-4)的字节,以及每个分量的以下字节:分量标识符(字节)、Hi(½ 字节)和 Vi(½ 字节)(字节 = Hi * 16 + Vi)以及量化表目标选择器(字节)。

这里,颜色分量的对 (Hi, Vi) 为 (1, 1),而 Y 分量的 (Hi, Vi) 为 (1, 1)、(1, 2)、(2, 1) 或 (2, 2)。量化表目标选择器是 0-3 之间的数字之一,例如,Y 分量为 0,颜色分量为 1。

霍夫曼表段 DHT

[编辑 | 编辑源代码]

通常,灰度图片的文件中会有两个霍夫曼表段,彩色图片中有四个:每个分量的 DC 和 AC 数字的编码方式不同,Y 分量和两个颜色分量的编码方式也不同。在霍夫曼段中,信息(在标记和表示长度的字节对之后)以这种方式排列:如果霍夫曼表用于 DC 数字,则第一个半字节为 0,如果用于 AC 数字,则为 1。下一个半字节是霍夫曼表目标标识符(0 或 1),例如,Y 分量为 0,颜色分量为 1(将在扫描段 SOS 中引用,在 SOS 中指定了霍夫曼表)。接下来的 16 个字节序列是列表 BITS,它表示 i = 1、...、16 时长度为 i 的代码数量。然后是列表 HUFFVAL,它表示霍夫曼值:对于每个非零的代码长度,将有与该长度的代码数量相同的数值。如果我们将霍夫曼值的数量称为 nhv,则段中的字节数(包括表示长度的字节对)为 19 + nhv。

量化表段 DQT

[编辑 | 编辑源代码]

量化表是一个 8x8 字节矩阵,按之字形原则排序。通常情况下,Y 分量和颜色分量有不同的量化表。在 T.81 的附录“示例和指南”中,你可以分别找到 Y 分量和颜色分量的以下内容

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
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

它指出“如果将这些量化值除以 2,则生成的重建图像通常与源图像几乎无法区分”。通过我们的程序“JPEG_File”,你可以看到一张图片的表格(使用顺序 DCT 程序,并且)指定了名称“pict”。在我们生成(真实的)JPEG 文件的程序中,我们为 Y 分量选择了另一个表格,而不是上面的表格,即在图像编辑程序(IrfanView)中使用,将质量设置为 70% 时使用的表格

10 7   6   10 14 24 31 37
7   8   11 16 35 36 33
8   8   10 14 24 34 41 34
10 13 17 31 52 48 37
11 13 22 34 41 65 62 46
14 21 33 38 49 62 68 55
29 38 47 52 62 73 72 61
43 55 57 59 67 60 62 59

量化表在 DQT 段中指定。DQT 段以标记 DQT = 219 和长度开头,长度为 (0, 67)。然后是一个字节,其前半部分为 0,表示该表由字节(8 位数字 - 对于扩展模式,为 1,表示该表由字,16 位数字)组成,后半部分为表的 *目标标识符* (0-3),例如,Y 分量为 0,颜色分量为 1。接下来是表的 64 个数字(字节)。

扫描段 SOS

[编辑 | 编辑源代码]

紧接扫描段 SOS 之后是图片的编码数据,扫描段指定了用于分量的哈夫曼表。该段以标记 SOS = 218 和长度开头,长度为 (0, 6 + 2 * 分量数)。然后是一个字节,表示分量数 (1-4),然后是每个分量的两个字节,第一个是分量标识符(在帧段中定义),第二个分为两部分,第一部分表示 DC 哈夫曼表的目标选择器,第二部分表示 AC 哈夫曼表的目标选择器(例如,Y 分量为 0,颜色分量为 1)。该段以三个字节结束,在我们的案例(顺序 DCT)中,它们是 0、63 和 0(最后一个分为两个半字节)。

华夏公益教科书