jpeg 计算最大大小
我不得不说,我对文件格式的工作原理知之甚少。我的问题是假设我有一个jpeg文件,它是200 px x 200 px,如何计算出该文件的最大大小(以兆字节/字节为单位) ?
我认为导致这个问题的推理将有助于有人回答我。我有一个Java小程序,人们用它绘制的图像上传到我的服务器。我需要知道这个文件可以达到的最大大小。它总是会是200x200。
这听起来很愚蠢,但是否有颜色比其他颜色需要更多的字节大小,如果是这样,最昂贵的一种是什么?
我不得不说,我对文件格式的工作原理知之甚少。我的问题是假设我有一个jpeg文件,它是200 px x 200 px,如何计算出该文件的最大大小(以兆字节/字节为单位) ?
我认为导致这个问题的推理将有助于有人回答我。我有一个Java小程序,人们用它绘制的图像上传到我的服务器。我需要知道这个文件可以达到的最大大小。它总是会是200x200。
这听起来很愚蠢,但是否有颜色比其他颜色需要更多的字节大小,如果是这样,最昂贵的一种是什么?
有很多方法可以制作一个“病态的”JPEG / JFIF文件,该文件非常大。
在频谱的最末端,大小没有限制,因为该标准不限制某些类型的标记出现多次 - 例如,一个JFIF文件充满了许多GB的DRI(定义重启间隔)标记,然后最后一个8x8像素的MCU在技术上是有效的。
如果我们将自己限制在“正常”标记用法,那么我们会找到如下上限:
一些背景 -
JPEG将像素编码为8x8像素块(DCT块)的MCU(组),每个组件(Y,Cb,Cr)一个DCT块。
为了获得最佳压缩(和最小尺寸),使用4:2:0色度子采样方案,其中省略了75%的色度信息。为了获得最佳质量(和最大大小),文件是2/3的色度,1/3的亮度信息。
霍夫曼比特流符号用于编码DCT组件,其中每个DCT块最多有65个(64 AC + 1 DC)。
霍夫曼符号的范围可以从1到16位,并由编码器选择尽可能小;但是,可以指定符号长度的选择。
必须对霍夫曼比特流进行最终编码,以便可以唯一地识别标记。也就是说,输出中出现0xff字节的任何必须替换为两个字节 - 0xff,0x00。
使用所有这些信息,我们可以构建一个病态但有效的JPEG文件,libjpeg(最常见的JPEG解码器实现)很乐意解码。
首先,我们需要尽可能长的霍夫曼符号。乍一看,定义所有1的最大长度的霍夫曼符号(16位)将使用大部分空间,但是libjpeg拒绝处理所有1的霍夫曼符号,这似乎并没有被标准排除在外 - 因为它仍然是一个独特的符号,因为大小已经知道是16位,不像其他可变长度符号, 事实上,一些解码器可以处理它(JPEGSnoop)。
因此,我们定义了一个 huffman 表,它设置了最后两个符号,如下所示:
11111111_1111110 -> (0,0) (EOB - end of block value)
11111111_11111110 -> (0,15)
这样的霍夫曼表将在JPEG文件中显示为:
0xFF, 0xC4 ; DHT - define huffman table
0x00, 35 ; length
0x00 ; DC 0
1,1,1,1,1,1,1,1,1,1, 1, 1, 1, 1, 1, 1 ; histogram
1,2,3,4,5,6,7,8,9,10,11,12,13,14,0,15 ; symbols
现在对最大长度的 DCT 块进行编码:
1 x DC of 31 bits ( 11111111 11111110 11111111 1111111 )
64 x AC of 31 bits ( 11111111 11111110 11111111 1111111 )
= 2015 bits
由于一个MCU将是3个DCT块(每个组件一个),因此MCU大小将为6045位。
这些字节中的大多数将被0xff,根据标准,这些字节在输出流中被0xff,0x00替换,以便将比特流与有效标记区分开来。
执行此映射,完整的 DCT 由以下字节模式的 8 个重复表示:
0xff,0x00,0xfe,0xff,0x00,0xff,0x00
0xff,0x00,0xfd,0xff,0x00,0xff,0x00
0xff,0x00,0xfb,0xff,0x00,0xff,0x00
0xff,0x00,0xf7,0xff,0x00,0xff,0x00
0xff,0x00,0xef,0xff,0x00,0xff,0x00
0xff,0x00,0xdf,0xff,0x00,0xff,0x00
0xff,0x00,0xbf,0xff,0x00,0xff,0x00
0xff,0x00,0x7f,0xff,0x00
总计 8*54 = 432 字节
将所有这些加起来,我们有:3个组件*(每个组件432字节)= 1296字节/8x8像素
SOI/DHT/DQT/SOS 段需要 339 字节的标头来设置图像属性和霍夫曼表,需要一个 2 字节的 EOI 标记来结束图像。
由于200x200的图像将是25x25 MCU,因此我们的最终大小为:
339 + (25 * 25 * 1296) + 2 = 810341 字节
其工作原理是每像素略高于20.25字节,比未压缩的BMP / TGA大6倍以上。
根据经验,任何 JPEG 都不会大于等效大小的 32 位位图。32 位位图在图像中每像素有 4 个字节,因此将尺寸相乘 (200x200 = 40000),然后将其乘以 4 个字节 (40000x4 = 160000),您将有一个以字节为单位的上限 - 例如,160000 字节大约是 156kb。