【问题标题】:iTextSharp: Convert PdfObject to PdfStreamiTextSharp:将 PdfObject 转换为 PdfStream
【发布时间】:2013-05-02 17:13:53
【问题描述】:

我正在尝试从 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。

【问题讨论】:

  • 好吧,您的代码确实没有提示您检查的对象是否确实是流。请详细说明。
  • 显然我没有得到流对象(只是字典),我还没有找到关于如何正确抓取字体流的好答案。
  • 你有没有做过一些调试并确定了pdfObj的实际类?您是否还按照布鲁诺的提示将演员表移至 PdfStream 以支持 PRStream 的演员表?您发布的代码首先转换为 PdfStream,然后转换为 PRStream...
  • 是的,从转换为 PdfStream 到转换为 PRStream 的更改是根据 Bruno 的建议。我还使用了他建议的代码示例(sorta)来提取流。现在,当我尝试使用 PdfReader.FlateDecode() 时出现错误“缓冲区不能为空”,有什么想法吗?
  • 缓冲区不能为空错误已得到纠正——当然是我的错误。我使用 PRStream.GetBytes() 而不是 PdfReader.GetStreamBytes(PRStream),当然我的 byte[] 是空的。

标签: pdf fonts stream itextsharp itext


【解决方案1】:

您的代码中至少有两处错误:

  1. 您在未执行此检查的情况下将对象转换为流:if (pdfObj == null &amp;&amp; pdfObj.isStream()) { // cast to stream } 当您收到尝试将字典转换为流的错误消息时,我 99% 确定检查的第二部分将返回falsepdfObj.isDictionary() 可能返回true
  2. 您尝试从PdfReader 中提取流,并且尝试将该对象转换为PdfStream 而不是PRStreamPdfStream 是我们用来创建 PDF 的对象,PRStream 是我们使用 PdfReader 检查 PDF 时使用的对象。

你应该先解决这个问题。

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

查看我的书"iText in Action" 中的示例ListFontFiles,以初步了解PDF 中的字体是如何组织的。您需要将此示例与 ISO-32000-1 结合起来,以了解有关 FONTFILEFONTFILE2FONTFILE3 之间区别的更多信息。

我还编写了一个用字体文件替换未嵌入字体的示例:EmbedFontPostFacto。这个例子作为一个介绍来解释字体替换是多么困难。

如需C#版样书请到http://tinyurl.com/iiacsCH16

【讨论】:

  • 没有比这更明确的了!谢谢您,先生。至于有限的字形集,我们只是试图将 PDF 显示为呈现的(尽管是 HTML),所以我们只需要呈现的字符。非常感谢您在这方面的帮助!
  • 那么在您看来,从 pdf 中提取字体流的最佳方法是什么?
  • 我在您的第二条评论上添加了评论,然后我才看到您的第一条评论。你的问题没有简单的答案。字符的映射可能完全不同。作为字符“a”存储在 PDF 中的内容可能与字形“b”相对应。您需要非常仔细地研究 ISO-32000-1 以实现您想要的结果,一个结果(最可能的结果)可能是:我们无法从可用于 HTML 的 PDF 中提取字体。如果你更喜欢一个比喻,你的问题听起来像“从胡萝卜汤中提取整根胡萝卜的最佳方法是什么?”
  • 好吧,我不需要整根胡萝卜——只需要一小部分。我已经解决了这个问题(使用您的建议)并且能够实现我的目标。如果 pdf 在组成字体“DogVotes”(嵌入在 pdf 中(至少只使用所需的字符)中包含大量文本“让你的狗投票更聪明”,并且我想准确地将文档显示为它最初是打算的;那么我只需要一个包含'M''a''k''e''''y''o''u''r''d''g''v''的字形集t' 's' 'm' - 这就是我现在得到的。非常感谢你为我指明了正确的方向。
猜你喜欢
  • 1970-01-01
  • 2022-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-03
相关资源
最近更新 更多