iTextSharp: Convert PdfObject to PdfStream



我正在尝试从pdf文件中提取一些字体流(合法性不是问题,因为我的公司已经支付了以原始方式显示这些文档的权利-这需要转换,需要提取字体)。

现在,我一直在使用MUTool -但它也提取pdf中的图像以及没有绕过它们的方法,其中一些包含成千上万的图像。所以,我在网上寻找答案,得出了以下解决方案:

我得到所有的字体到一个字体字典,然后我尝试将它们转换成PdfStreams(用于flatedecode,然后写入文件)使用以下代码:

    PdfDictionary tg = (PdfDictionary)PdfReader.GetPdfObject((PdfObject)cItem.pObj);
        PdfName type = (PdfName)PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE));
        try
        {
            int xrefIdx = ((PRIndirectReference)((PdfObject)cItem.pObj)).Number;
            PdfObject pdfObj = (PdfObject)reader.GetPdfObject(xrefIdx);
            PdfStream str = (PdfStream)(pdfObj);
            byte[] bytes = PdfReader.GetStreamBytesRaw((PRStream)str);
        }
        catch { }

但是,当我得到PdfStream str = (PdfStream)(pdfObj);我得到下面的错误:

    Unable to cast object of type 'iTextSharp.text.pdf.PdfDictionary' 
    to type 'iTextSharp.text.pdf.PdfStream'.

现在,我知道PdfDictionary派生(扩展)PdfObject,所以我不确定我在这里做错了什么。有人请帮助-我要么需要修补这个代码的建议,或者如果完全不正确,要么代码正确提取流或方向到一个地方与所述代码。

谢谢。

编辑修改后的代码在这里:

     public static void GetStreams(PdfReader pdf)
    {
        int page_count = pdf.NumberOfPages;
        for (int i = 1; i <= page_count; i++)
        {
            PdfDictionary pg = pdf.GetPageN(i);
            PdfDictionary fObj = (PdfDictionary)PdfReader.GetPdfObject(res.Get(PdfName.FONT));
            if (fObj != null)
            {
                foreach (PdfName name in fObj.Keys)
                {
                    PdfObject obj = fObj.Get(name);
                    if (obj.IsIndirect())
                    {
                        PdfDictionary tg = (PdfDictionary)PdfReader.GetPdfObject(obj);
                        PdfName type = (PdfName)PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE));
                        int xrefIdx = ((PRIndirectReference)obj).Number;
                        PdfObject pdfObj = pdf.GetPdfObject(xrefIdx);
                        if (pdfObj == null && pdfObj.IsStream())
                        {
                            PdfStream str = (PdfStream)(pdfObj);
                            byte[] bytes = PdfReader.GetStreamBytesRaw((PRStream)str);
                        }
                    }
                }
            }
        }
    }

然而,我仍然收到相同的错误-所以我假设这是一个不正确的方法检索字体流。同样的文档已经使用muTool成功地提取了字体-所以我知道问题出在我身上,而不是pdf。

你的代码中至少有两点是错误的:

  1. 您将对象强制转换为流而不执行此检查:if (pdfObj == null && pdfObj.isStream()) { // cast to stream }当您得到错误消息时,您试图将字典强制转换为流,我99%肯定检查的第二部分将返回false,而pdfObj.isDictionary()可能返回true
  2. 你尝试从PdfReader提取一个流,你试图将该对象转换为PdfStream而不是PRStreamPdfStream是我们用来创建pdf的对象,PRStream是我们使用PdfReader检查pdf时使用的对象。

你应该先解决这个问题。

现在回答你的一般性问题。如果您阅读ISO-32000-1,您会发现字体是使用字体字典定义的。如果字体被(全部或部分)嵌入,字体字典将引用一个流。该流可以包含完整的字体信息,但大多数情况下,您只能获得字形的子集(因为这是创建PDF时的最佳实践)。

看一下我的书《ittext in Action》中的ListFontFiles示例,对字体在PDF中是如何组织的有一个初步的印象。您需要将此示例与ISO-32000-1相结合,以找到有关FONTFILE, FONTFILE2FONTFILE3之间差异的更多信息。

我还写了一个用字体文件代替未嵌入字体的例子:EmbedFontPostFacto。这个例子用来说明字体替换是多么困难。

如果您需要c#版本的书样例,请访问http://tinyurl.com/iiacsCH16。

相关内容

  • 没有找到相关文章

最新更新