解码 PDF:我可以使用 PIL/Pillow 访问 PNG 预测器算法,以便反转它以摄取到 PIL 吗?

问题描述 投票:0回答:1

我正在参考 2008 规范使用 Python 解码 PDF 文件: https://web.archive.org/web/20081203002256/https://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf 特别是第 7.4.4.4.

图像通常以字节流的形式嵌入 PDF 中,每个流都与一个包含该流信息的字典相关联。例如,流通常是原始数据的压缩形式;这些细节由字典中的

Filter
条目描述。

当我得到一个过滤器为

FlateDecode
的流时,这意味着数据是使用 deflate 进行压缩的,并且可以使用
zlib.decompress
轻松反转。但是......为了提高压缩率,原始数据可以通过过滤器进行预处理,例如区分相邻字节 - 当数据有很多相似的值时,结果会压缩得更好。预处理由字典中的
Predictor
条目标识。

Predictor
值15表示使用PNG差分算法;不幸的是,2008 年的 PDF 文档基本上说“PNG 预测(关于编码,PNG 最佳)”。耶。

有人可以向我解释一下(a)这到底意味着哪种 PNG 过滤算法(参考其规范)和(b)理想情况下向我指出一个可以反转它的库。如果缺少后者,我就必须用纯 Python 来反转它,这会很慢。对于我最初的用例来说,速度慢得可以接受,而且我想如果我的需求变得更频繁,我可以(很久)以后将其编写为 C 扩展。

我现在所在的位置是:

  • 我将未压缩的流数据作为
    bytes
    对象,这是原始像素数据
  • 我知道
    Predictor
    值,在我当前的示例文档中为 15
  • 如果我不反转预测器算法并按原样解码数据,我会得到一个图像,该图像(a)看起来像边缘,因为数据表达差异而不是直接颜色分量,(b)是倾斜的,因为行有一个领先的指示符某种类型(PDF 规范规定“每个 PNG 预测行的预测后数据应以显式算法标记开始;因此,可以使用不同的算法来预测不同的行以提高压缩率。TIFF Predictor 2 没有这样的标识符;相同算法适用于所有行。”并且我将标签解码为像素数据,使每行有点太长

目前我的

image
属性方法如下所示:

  @property
  def image(self):
    im = self._image
    if im is None:
      decoded_bs = self.decoded_payload
      print(".image: context_dict:")
      print(decoded_bs[:10])
      pprint(self.context_dict)
      decode_params = self.context_dict.get(b'DecodeParms', {})
      color_transform = decode_params.get(b'ColorTransform', 0)
      color_space = self.context_dict[b'ColorSpace']
      bits_per_component = decode_params.get(b'BitsPerComponent')
      if not bits_per_component:
        bits_per_component = {b'DeviceRGB': 8, b'DeviceGray': 8}[color_space]
      colors = decode_params.get(b'Colors')
      if not colors:
        colors = {b'DeviceRGB': 3, b'DeviceGray': 1}[color_space]
      mode_index = (color_space, bits_per_component, colors, color_transform)
      width = self.context_dict[b'Width']
      height = self.context_dict[b'Height']
      print("mode_index =", mode_index)
      PIL_mode = {
          (b'DeviceGray', 1, 1, 0): 'L',
          (b'DeviceGray', 8, 1, 0): 'L',
          (b'DeviceRGB', 8, 3, 0): 'RGB',
      }[mode_index]
      print(
          "Image.frombytes(%r,(%d,%d),%r)...", PIL_mode, width, height,
          decoded_bs[:32]
      )
      im = Image.frombytes(PIL_mode, (width, height), decoded_bs)
      im.show()
      exit(1)
      self._image = im
    return im

这向我显示了“前卫”和倾斜的图像,因为我将差异数据解码为颜色数据,并将行标签解码为像素数据,稍微倾斜了后续行。

python pdf python-imaging-library png libpng
1个回答
0
投票

如果“预测器”参数为 10 或更大,则每行使用的预测器由 每行中的第一个字节给出。在这种情况下,该参数的值没有进一步的意义。 15 并不重要,除了 15 >= 10 之外。

© www.soinside.com 2019 - 2024. All rights reserved.