.net iText 7在第一个PDF页面中抛出InlineImageParseException,而在iText 5中它工作得非常好

.net iText 7在第一个PDF页面中抛出InlineImageParseException,而在iText 5中它工作得非常好,.net,exception,itext,itext7,.net,Exception,Itext,Itext7,我正在为.Net Core 2.0使用iText 7.1.1。当我尝试从PDF的第一页获取文本时,我得到以下异常: iText.Kernel.Pdf.Canvas.Parser.Util.InlineImageParsingUtils.InlineImageParseException: 'Cannot find image data or EI.' 代码: 除第一页外,所有其他页面在iText 7中都能完美工作 使用iText 5不会引发异常,第一页会完全转换为文本 PDF文件:问题的原因是

我正在为.Net Core 2.0使用iText 7.1.1。当我尝试从PDF的第一页获取文本时,我得到以下异常:

iText.Kernel.Pdf.Canvas.Parser.Util.InlineImageParsingUtils.InlineImageParseException: 'Cannot find image data or EI.'
代码:

除第一页外,所有其他页面在iText 7中都能完美工作

使用iText 5不会引发异常,第一页会完全转换为文本


PDF文件:

问题的原因是.Net的iText 7中的
RunLengthDecodeFilter
完全被破坏。当前(7.1.2-SNAPSHOT)代码如下所示:

public class RunLengthDecodeFilter : IFilterHandler {
    public virtual byte[] Decode(byte[] b, PdfName filterName, PdfObject decodeParams, PdfDictionary streamDictionary
        ) {
        MemoryStream baos = new MemoryStream();
        byte dupCount;
        for (int i = 0; i < b.Length; i++) {
            dupCount = b[i];
            if (dupCount == (byte)0x80) {
                // this is implicit end of data
                break;
            }
            if (dupCount >= 0) {
                int bytesToCopy = dupCount + 1;
                baos.Write(b, i, bytesToCopy);
                i += bytesToCopy;
            }
            else {
                // make dupcount copies of the next byte
                i++;
                for (int j = 0; j < 1 - (int)(dupCount); j++) {
                    baos.Write(b[i]);
                }
            }
        }
        return baos.ToArray();
    }
}
公共类RunLengthDecodeFilter:IFilterHandler{
公共虚拟字节[]解码(字节[]b,PdfName筛选器名称,PdfObject decodeParams,PdfDictionary streamDictionary
) {
MemoryStream BAS=新的MemoryStream();
字节重复计数;
for(int i=0;i=0){
int bytesToCopy=dupCount+1;
写(b,i,bytesToCopy);
i+=bytesToCopy;
}
否则{
//对下一个字节进行重复计数
i++;
对于(int j=0;j<1-(int)(dupCount);j++){
写(b[i]);
}
}
}
返回baos.ToArray();
}
}
这看起来很像iText 7 for Java版本,这并不奇怪,因为iText 7 for.Net代码几乎完全是相应Java代码的自动翻译

不幸的是,这里的自动翻译忽略了Java和.Net之间的一个根本区别:Java类型
字节
表示有符号字节,而.Net类型
字节
表示无符号字节

因此,在Java中,
dupCount>=0
仅对0x00..0x7f为真,而对0x80..0xff为假。然而,在.Net中,这总是正确的

因此,Java中对这些字节值范围的不同解释(对应于PDF RLE定义)在.Net中被完全忽略(因此不再对应于PDF RLE定义)。这导致iText 7 for.Net甚至无法正确识别内联图像数据的范围

由于OP共享的PDF页面内容流包含许多内联图像,其中所有图像(或至少大部分图像)都使用运行长度编码,因此此iText 7 for.Net错误使其无法理解内容,最终导致OP观察到异常

OP还提到,对于iText 5,该问题不会发生。查看iText 5.Net代码,可以看到那里使用了.Net类型
sbyte
(带符号字节)(参见示例)。因此,iText 5.Net代码至少能够正确识别内联图像数据的范围,因此不会出现异常


在参考答案中解释的错误仍然存在于iText 5和iText 7代码中,但由于OP对内联图像本身不感兴趣,因此该错误不会干扰他。

我可以使用iText for.Net重现该问题,而使用iText for Java则没有问题。问题可能与您案例中的内联图像使用RLE压缩有关。我不太理解。我应该编辑RunLengthDecodeFilter方法来解决这个问题吗?在源代码中直接覆盖或编辑?我建议按照参考答案中所述修复过滤器,然后再试一次。我现在实际调试了代码,情况甚至比我想象的更糟,iText 7 for.Net中的
RunLengthDecodeFilter
(根据参考答案)不仅仅是稍微偏离了一点因此,解决这个问题的正确途径是直接向iText团队报告。但由于他们建议使用stackoverflow解决此类问题,我不再知道该怎么办。我得另找一个图书馆,也许是Docotic.PDF。谢谢,mkl!该问题已在最新快照版本中修复,并将包含在iText 7.1.3的发行版中。
public class RunLengthDecodeFilter : IFilterHandler {
    public virtual byte[] Decode(byte[] b, PdfName filterName, PdfObject decodeParams, PdfDictionary streamDictionary
        ) {
        MemoryStream baos = new MemoryStream();
        byte dupCount;
        for (int i = 0; i < b.Length; i++) {
            dupCount = b[i];
            if (dupCount == (byte)0x80) {
                // this is implicit end of data
                break;
            }
            if (dupCount >= 0) {
                int bytesToCopy = dupCount + 1;
                baos.Write(b, i, bytesToCopy);
                i += bytesToCopy;
            }
            else {
                // make dupcount copies of the next byte
                i++;
                for (int j = 0; j < 1 - (int)(dupCount); j++) {
                    baos.Write(b[i]);
                }
            }
        }
        return baos.ToArray();
    }
}