【问题标题】:Progressive JPEG layer/scan offsets (imagemagick?)渐进式 JPEG 图层/扫描偏移(imagemagick?)
【发布时间】:2016-03-16 23:06:32
【问题描述】:

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

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

是否可以为此使用 Imagemagick? identify 工具似乎不支持这样做。如果是这样,怎么做?否则有什么工具可以做到这一点?我宁愿不必编写自定义 JPEG 解析器。谢谢。

【问题讨论】:

    标签: imagemagick jpeg progressive


    【解决方案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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 我想我可能不得不做这样的事情。扫描二进制文件以查找字节标记的最佳方法是什么?我以前从未这样做过。
      • 您需要获得一份 JPEG 标准的副本。所有 JPEG 标记都以 FF 开头。一些标记具有长度字段,您必须使用这些字段来跳过可能包含 FF 值的数据。对于其余部分,您扫描 FF 并简单地跳过您不感兴趣的标记(包括 FF00,表示压缩的 FF 值)。
      • 这真的很有用。谢谢楼主!
      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2016-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-17
        • 2016-01-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多