2

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

4

1 回答 1

4

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

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

你应该先解决这个问题。

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

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

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

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

于 2013-05-03T09:00:02.807 回答