我一直在寻找高低无济于事。我希望能够提取每个渐进式 JPEG 图层/扫描发生的字节偏移量。
例如,假设一个 100 kB 的图像有 5 层用于渲染最终图像;第 1 层在 kB 5 处结束,第 2 层在 kB 20 处结束,第 3 层在 kB 60 处结束,等等(例如)。
是否可以为此使用 Imagemagick?该identify
工具似乎不支持这样做。如果是这样,怎么做?否则有什么工具可以做到这一点?我宁愿不必编写自定义 JPEG 解析器。谢谢。
我一直在寻找高低无济于事。我希望能够提取每个渐进式 JPEG 图层/扫描发生的字节偏移量。
例如,假设一个 100 kB 的图像有 5 层用于渲染最终图像;第 1 层在 kB 5 处结束,第 2 层在 kB 20 处结束,第 3 层在 kB 60 处结束,等等(例如)。
是否可以为此使用 Imagemagick?该identify
工具似乎不支持这样做。如果是这样,怎么做?否则有什么工具可以做到这一点?我宁愿不必编写自定义 JPEG 解析器。谢谢。
您可以使用ImageMagick制作像这样的渐进式 JPEG进行测试:
magick -interlace plane -size 400x200 gradient: progressive.jpg
exiftool
会告诉你很多这样的事情:
exiftool -v3 progressive.jpg
样本输出
ExifToolVersion = 12.00
FileName = progressive.jpg
Directory = .
FileSize = 2709
FileModifyDate = 1620144585
FileAccessDate = 1620144586
FileInodeChangeDate = 1620144585
FilePermissions = 33188
FileType = JPEG
FileTypeExtension = JPG
MIMEType = image/jpeg
JPEG APP0 (14 bytes):
0006: 4a 46 49 46 00 01 01 00 00 01 00 01 00 00 [JFIF..........]
+ [BinaryData directory, 9 bytes]
| JFIFVersion = 1 1
| - Tag 0x0000 (2 bytes, int8u[2]):
| 000b: 01 01 [..]
| ResolutionUnit = 0
| - Tag 0x0002 (1 bytes, int8u[1]):
| 000d: 00 [.]
| XResolution = 1
| - Tag 0x0003 (2 bytes, int16u[1]):
| 000e: 00 01 [..]
| YResolution = 1
| - Tag 0x0005 (2 bytes, int16u[1]):
| 0010: 00 01 [..]
| ThumbnailWidth = 0
| - Tag 0x0007 (1 bytes, int8u[1]):
| 0012: 00 [.]
| ThumbnailHeight = 0
| - Tag 0x0008 (1 bytes, int8u[1]):
| 0013: 00 [.]
JPEG DQT (65 bytes):
0018: 00 03 02 02 02 02 02 03 02 02 02 03 03 03 03 04 [................]
0028: 06 04 04 04 04 04 08 06 06 05 06 09 08 0a 0a 09 [................]
0038: 08 09 09 0a 0c 0f 0c 0a 0b 0e 0b 09 09 0d 11 0d [................]
0048: 0e 0f 10 10 11 10 0a 0c 12 13 12 10 13 0f 10 10 [................]
0058: 10 [.]
JPEG SOF2 (9 bytes):
005d: 08 00 c8 01 90 01 01 11 00 [.........]
ImageWidth = 400
ImageHeight = 200
EncodingProcess = 2
BitsPerSample = 8
ColorComponents = 1
JPEG DHT (20 bytes):
006a: 00 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 [................]
007a: 00 00 04 08 [....]
JPEG SOS
JPEG DHT (19 bytes):
0139: 10 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
0149: 00 00 12 [...]
JPEG SOS
JPEG DHT (18 bytes):
0468: 10 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
0478: 00 a0 [..]
JPEG SOS
JPEG DHT (20 bytes):
048a: 10 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 [................]
049a: 00 71 00 70 [.q.p]
JPEG SOS
JPEG SOS
JPEG DHT (21 bytes):
0728: 10 00 03 01 00 00 00 00 00 00 00 00 00 00 00 00 [................]
0738: 00 01 71 00 50 [..q.P]
JPEG SOS
JPEG EOI
您还可以像这样找到 SOS 标记:
xxd -c16 -g1 -u progressive.jpg | grep --color=always -A4 "FF DA"
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 04 08 FF DA ................
00000080: 00 08 01 01 00 00 00 01 D4 60 00 00 00 00 00 08 .........`......
00000090: 40 00 00 00 00 00 11 00 00 00 00 00 00 21 00 00 @............!..
000000a0: 00 00 00 00 42 00 00 00 00 00 00 88 00 00 00 00 ....B...........
000000b0: 00 01 08 00 00 00 00 00 02 10 00 00 00 00 00 04 ................
--
00000140: 00 00 00 00 00 00 00 00 00 00 00 12 FF DA 00 08 ................
00000150: 01 01 00 01 05 02 B5 AD 6B 5A D6 B5 AD 6B 5A D6 ........kZ...kZ.
00000160: B5 AD 6B 5A D6 B5 AD 6B 5A D6 B5 AD 6B 5A D6 B5 ..kZ...kZ...kZ..
00000170: AD 6B 5A D6 B5 AD 6B 5A D6 B5 AD 6B 5A D6 B5 AD .kZ...kZ...kZ...
00000180: 6B 5A D6 B5 AD 6B 5A D6 B5 AD 6B 5A D6 B5 AD 6B kZ...kZ...kZ...k
如果它们落在 16 字节的行尾,它可能会错过一些标记 - 我仍在考虑使这个万无一失。也许以 4 字节的偏移量运行它两次,这样它们就不会落在两个列表的边界上。
或者,我在这里做了另一个答案,可让您查找可以轻松适应的任意二进制序列,从查找 TIFF 标头到查找FF DA
.
您所要做的就是扫描图像流并查找 SOS(扫描开始)标记。
Christoph Erdmann 在这篇文章中有一些 php 示例代码:
$img = "progressive.jpg";
$jpgdata = file_get_contents($img);
$positions = [];
$offset = 0;
while ($pos = strpos($jpgdata, "\xFF\xC4", $offset)) {
$positions[] = $pos+2;
$offset = $pos+2;
}