渐进式JPEG图层/扫描偏移(imagemagick?)

时间:2016-03-16 23:06:33

标签: imagemagick jpeg progressive

我一直在寻找高低,但无济于事。我希望能够提取每个渐进式JPEG图层/扫描发生的字节偏移。

例如,假设一个100 kB图像有5层用于渲染最终图像;第1层以kB 5结束,第2层以kB 20结束,第3层以kB 60等结束(例如)。

是否可以使用Imagemagick? identify工具似乎不支持这样做。如果是这样,怎么样?否则,哪些工具可以实现这一目标?我宁愿不必编写自定义JPEG解析器。感谢。

3 个答案:

答案 0 :(得分:1)

您可以使用 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 字节的偏移量运行它两次,这样它们就不会落在两个列表的边界上。

或者,我做了另一个答案 here,它可以让您查找任意二进制序列,您可以轻松地从查找 TIFF 标头到查找 FF DA

答案 1 :(得分:0)

您所要做的就是扫描图像流并查找SOS(扫描开始)标记。

答案 2 :(得分:0)

Christoph Erdmann 在这篇文章中有一些 php 示例代码:

https://www.smashingmagazine.com/2019/08/faster-image-loading-embedded-previews/#creating-frontend-javascript-code

$img = "progressive.jpg";
$jpgdata = file_get_contents($img);
$positions = [];
$offset = 0;
while ($pos = strpos($jpgdata, "\xFF\xC4", $offset)) {
    $positions[] = $pos+2;
    $offset = $pos+2;
}