从PDF中删除PdfImageOject

时间:2014-07-12 00:01:19

标签: itextsharp

我从包含.png的电子邮件中生成了第1000个PDF(我不是生成器的所有者)。由于某些原因,使用我正在使用的成像系统渲染这些PDF非常慢(我不是该系统的开发者,可能不会更改它)。

如果我使用iTextSharp并实现IRenderListener来计算要渲染的图像,则每页有数千个(99%仅为1或2个像素)。但是,如果我计算PDF资源中的图像,只有少数(〜几十)。

我在每页的资源中计算图像,并在

之后使用此处的代码
var dict = pdfReader.GetPageN(currentPage)
PdfDictionary res = (PdfDictionary)PdfReader.GetPdfObject(dict.Get(PdfName.RESOURCES));
PdfDictionary xobj = (PdfDictionary)PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT));

if (xobj != null)
{
 foreach (PdfName name in xobj.Keys)
 {
   PdfObject obj = xobj.Get(name);
   if ((obj.IsIndirect()))
   {
     PdfDictionary tg = (PdfDictionary)PdfReader.GetPdfObject(obj);
     PdfName subtype = (PdfName)PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE));
     if (PdfName.IMAGE.Equals(subtype))
     {
       Count++

我的IRenderListener看起来像这样:

class ImageRenderListener : IRenderListener
{
    public void RenderImage(iTextSharp.text.pdf.parser.ImageRenderInfo renderInfo)
    {
        PdfImageObject image = renderInfo.GetImage();
        if (image == null) return;
        var refObj = renderInfo.GetRef();
        if (refObj == null)
            Count++; // but why no ref ??
        else
            Count++;
    }

我刚刚开始学习PDF规范和今晚的iTextSharp,分析我的PDF并了解可能出现的问题......如果我是正确的,我会看到许多要呈现的图像没有引用资源(refObj) == null)并且它们是.png(image.streamContentType.FileExtension =" png")。所以,我认为这些图像使渲染变得如此缓慢......

出于测试目的,我想从PDF中删除这些图像,但不知道如何继续。

我只找到代码示例来删除资源中的图片...但我要删除的图片不是:/

是否有任何代码示例可以帮助我?我确实在google" iTextSharp删除了对象"等...但是没有类似于我的情况:(

1 个答案:

答案 0 :(得分:2)

让我首先直截了当地观察到你有一个糟糕的PDF。

在PDF查看器中打开PDF时看到的图像似乎由几个小的1或2像素图像组成。无论您使用哪种成像系统,逐个显示这些像素的绘图操作都不是最理想的:您将遇到错误的PDF。

在您的第一个片段中,我看到您遍历存储在每个页面的XObject资源中的所有间接对象以搜索图像。您可以对这些图像进行计数,从而在PDF中存储大量图像XObjects 。如果您为所有页面添加所有Count值,则此数字可能高于PDF中存储的Image XObject的实际数量,因为您没有考虑到某些图像可以在不同页面上重复使用

您不计算存储在内容流中的内联图片。我很有偏见。在PDF的ISO委员会中,我站在一群人的一边说“内嵌图像是邪恶的”“内嵌图像应该死”。目前,我们没有成功摆脱内联图像,但我们引入了一些实质性的限制,应该减少PDF中符合ISO-32000-2(即将到期的PDF 2.0规范)的内联图像的使用(ab)在2016年)。

您已经发现PDF具有内嵌图像。那些是refObj == null的图像。它们不存储为间接对象;它们以内联方式存储在页面的内容流中。根据我对内嵌图像的感受,您可以想象,因此我认为您的PDF是一个糟糕的PDF(尽管它符合ISO-32000-1)。

  1. 内嵌图像的存在首先解释了为什么您有不同的图像计数:当您在间接对象上循环时,您只能找到部分图像。解析文档中的图像时,还可以找到内嵌图像。
  2. 第二种解释可能是Image XObject被多次使用。这是不使用内联图像的重点。例如:如果您的图像表示需要在每个页面上重复的徽标,则可以使用内嵌图像。这将是一个坏主意:PDF中存在的相同图像字节数与页数一样多。应该使用Image XObject。在这种情况下,徽标的图像字节仅在间接对象中存储一次。每个页面都有对此对象的引用,因此图像字节仅存储在文档中一次。在一个10页的文档中,您可以在10个页面上看到10个相同的图像,但是当查看文档时,您将只找到每个页面引用的一个图像。
  3. 如果通过删除包含图像流对象的间接对象来删除Image XObjects,则必须非常小心:您确定没有损坏文档吗?因为在页面的内容流中有对Image XObject的引用。此引用指向页面/XObjects的{​​{1}}条目中的条目。这个/Resources引用带有图像字节的流对象。如果删除该间接对象而不删除引用(例如,从内容流中删除),则会破坏PDF。有些观众会忽略这些错误,但在某些时候某些工具(或某些正文)会抱怨你的PDF已损坏。

    如果要删除内嵌图像,则必须解析PDF中的所有内容流:页面内容流以及Form XObject内容流。您必须重写所有这些流并确保删除所有内嵌图像。即:所有以/XObject运算符(Begin Image)开头并以BI运算符结束的对象(End Image)。

    对于从内到外了解iTextSharp和ISO-32000-1的PDF专家来说,这是一项任务。您的问题的解决方案可能不适合StackOverflow上的应答窗口。

    我是iText的原作者。从某种角度来看,iText就像一把锋利的刀。锋利的刀是一种非常好的工具,可用于许多好东西。但是,当您没有以正确的方式使用刀具时,您也可以严重割伤手指。我希望你会小心,并且你不会创建一系列损坏的PDF文件。

    例如:您假设PDF中的某些文件是PNG,因为iText建议将它们存储为PNG。但是:ISO-32000-1不支持PNG,因此您认为PDF包含PNG是错误的。当我看到像你这样的问题时,我真的很担心。