Pdf 当长度未知时,是否可以使用libtiff对CCITT编码的数据进行解码?

Pdf 当长度未知时,是否可以使用libtiff对CCITT编码的数据进行解码?,pdf,tiff,Pdf,Tiff,在对这一问题的答复中: 指出libtiff可用于CCITT编码图像的解码。当然,我们必须预先添加TIFF头,以使CCITT流成为有效的TIFF文件 但是,PDF文件中的某些图像是内联图像,虽然它们的宽度、高度和位深度都已给出,但它们的长度没有给出。读取PDF的程序预计将对CCITT流进行解码,读取解码数据的(宽度*高度*深度)位,并且在读取数据后,无论它位于何处,都是内联图像的结尾。然后应该转到下一页标记命令,依此类推 这带来了一个问题。TIFF图像文件目录必须指定图像数据的每个条带中有多少字节

在对这一问题的答复中:

指出libtiff可用于CCITT编码图像的解码。当然,我们必须预先添加TIFF头,以使CCITT流成为有效的TIFF文件

但是,PDF文件中的某些图像是内联图像,虽然它们的宽度、高度和位深度都已给出,但它们的长度没有给出。读取PDF的程序预计将对CCITT流进行解码,读取解码数据的(宽度*高度*深度)位,并且在读取数据后,无论它位于何处,都是内联图像的结尾。然后应该转到下一页标记命令,依此类推

这带来了一个问题。TIFF图像文件目录必须指定图像数据的每个条带中有多少字节,但在解码之前,我们不知道编码数据中有多少字节实际属于图像,但如果不使用libtiff,我们无法解码图像

这里有没有使用libtiff的方法,或者我们需要定制的CCITT过滤代码?

严格来说(是否可以使用libtiff…?),是的。它涉及一些黑客行为,但不是太多

事实:数据将由一个条带组成,因为没有任何偏移信息,所以我们唯一的偏移量是零。我们只需要把这篇文章读进去

事实:该数据是W*H 1位深像素矩阵的压缩

步骤1:估计压缩流的最大可能长度。这大约是W*H的15%,即W=1000和H=1000时,得到150000字节。此值将始终大于实际值。如果我们有一个更好的估计由于找到了适当的EI端图像标签,这是更好的,但不是必要的

步骤2:构建一个“虚拟”TIF文件。这将由形式为
49 49 2a 00 AA BB CC DD
的标题组成,其中0xDDCCBBAA是估计长度加上8;然后是我们估计的数据流;后跟一个TIFF目录

步骤3:TIFF目录将始终具有相同的结构;其中的一些值是偏移量,与IFD位置0xDDCCBBAA无关。引用TIFF 6规范(请注意,字节顺序是颠倒的-摩托罗拉,而不是Intel endian):

在上面的例子中,0xDDCCBBAA实际上是0014,所有其他偏移量如下

我使用ImageMagick生成的单条TIFFG4图像进行了一些测试,并将
tiffcp
”转换为单条CCITT格式。那里的标题稍有不同(我没有看到规范中所说的软件和日期时间标签)。否则它会检查

我们现在有一个损坏的TIFF图像,其中有一个超长的条带,它在内存中

使用
TIFFClientOpen
,我们可以

尝试读取第一个条带将导致错误和程序中止:

TIFFFillStrip: Read error on strip 0; got 143151 bytes, expected 762826.
通过使用
TIFFSetErrorHandler
TIFFSetErrorHandlerExt
我们设置自己来截获此错误,并对其进行解析,从而恢复
143151
信息,而不是中止

我们需要提供对
TIFFClientOpen
的回调,但它们都非常简单:

TIFFReadWriteProc readproc(h, *ptr, n) // copy n bytes from FakeBuffer+pos into ptr, update pos to pos + n, ignore h.
TIFFReadWriteProc writeproc            // Throw an error. We don't write
TIFFSeekProc seekproc                  // update pos appropriately
TIFFCloseProc closeproc                // do nothing
TIFFSizeProc sizeproc                  // return total buffer size
TIFFMapFileProc mapproc                // Set to NULL
TIFFUnmapFileProc unmapproc            // Set to NULL
处理过程确实令人尴尬和费解,但就可行性而言,它是可行的 这是可以做到的

我已经用C语言运行了测试,手动从在线找到的内联图像BI/ID/EI PDF中提取CCITT流,并如上所述读取它


如果我有一个确定正确的EI的可靠方法-我已经解释了一个黑客识别EI后的有效PDF操作符,以便这样做,这使我认为可能没有很多更好的方法-我总是可以估计正确的偏移量,并直接从PDF中生成一个正确且可读的TIFF文件,而根本不涉及libtiff。

为什么不能使用流的
Length
属性?(,应该始终存在。)发布一个示例文件,这样我们就可以看到您正在使用的内容。@Phillip不适用于内联图像对象,它直接出现在页面描述中。啊,这让事情变得复杂了。在这件事上确实是相当模糊的。在我看来,似乎禁止在二进制数据中包含EI运算符,这意味着您可以安全地跳过字节,直到找到“EI”,但这从未明确说明。poppler和pdfjs确实都会先解码CCITT数据,然后才继续跳过字节,直到找到“EI”,这表明您可能需要添加自定义过滤器。请查看tiff加载程序,而不是lib tiff,这可能是您想要的。
TIFFReadWriteProc readproc(h, *ptr, n) // copy n bytes from FakeBuffer+pos into ptr, update pos to pos + n, ignore h.
TIFFReadWriteProc writeproc            // Throw an error. We don't write
TIFFSeekProc seekproc                  // update pos appropriately
TIFFCloseProc closeproc                // do nothing
TIFFSizeProc sizeproc                  // return total buffer size
TIFFMapFileProc mapproc                // Set to NULL
TIFFUnmapFileProc unmapproc            // Set to NULL