本文介绍了是否使用PDFBox将FormXObject内容从资源添加到内容流?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的page1下有FormXObject-&>资源-&>X对象->;FM0,FM1,FM2..

因此它不是Contents->;Contentstream下不可用的直接内容流。因此,我想将的内容流从fm0-&>内容流移动到page1-&>内容-&>内容流。

当我们像这样并行移动内容流时,我们必须将FM0相关资源转移或复制到页面级资源。

1.内容流需要复制到页面级内容下。

2.色彩空间对象需要复制到page1->;资源->;色彩空间下。

3.ExtGState对象需要复制到page1->;资源->;ExtGState下。

4.属性需要复制到page1下-&>资源(此处需要完全创建)

我尝试了一些代码

private PDDocument parseFormXobject(PDDocument document) throws IOException {
PDDocument newdocument = new PDDocument();
for (int pg_ind = 0; pg_ind < document.getNumberOfPages(); pg_ind++) {
    List<Object> tokens1 = (List<Object>) (getTokens(document)).get(pg_ind);
    PDStream newContents = new PDStream(document);
    OutputStream out = newContents.createOutputStream(COSName.FLATE_DECODE);
    ContentStreamWriter writer = new ContentStreamWriter(out);

    PDPage pageinner = document.getPage(pg_ind);
    PDResources resources = pageinner.getResources();
    PDResources new_resources = new PDResources();
    new_resources = resources;

    COSDictionary fntdict = new COSDictionary();
    COSDictionary imgdict = new COSDictionary();
    COSDictionary extgsdict = new COSDictionary();
    COSDictionary colordict = new COSDictionary();
    int img_count = 0;
    for (COSName xObjectName : resources.getXObjectNames()) {
        PDXObject  xObject = resources.getXObject(xObjectName);
        if (xObject instanceof PDFormXObject) {

            PDFStreamParser parser = new PDFStreamParser(((PDFormXObject) xObject).getContentStream());
            parser.parse();
            List<Object>  tokens3 = parser.getTokens();
            int ind =0;
            System.out.println(xObjectName.getName());
                for (COSName colorname :((PDFormXObject) xObject).getResources().getColorSpaceNames())
                {
                    COSName new_name = COSName.getPDFName(colorname.getName()+"_Fm"+img_count);
                    PDColorSpace pdcolor = ((PDFormXObject) xObject).getResources().getColorSpace(colorname);
                    colordict.setItem(new_name,pdcolor);
                }
                for (COSName fontName :((PDFormXObject) xObject).getResources().getFontNames() )
                {
                    COSName new_name = COSName.getPDFName(fontName.getName()+"_Fm"+img_count);
                    PDFont font =((PDFormXObject) xObject).getResources().getFont(fontName);
                    font.getCOSObject().setItem(COSName.NAME, new_name);
                    fntdict.setItem(new_name,font);
                }
                for (COSName ExtGSName :((PDFormXObject) xObject).getResources().getExtGStateNames() )
                {
                    COSName new_name = COSName.getPDFName(ExtGSName.getName()+"_Fm"+img_count);
                    PDExtendedGraphicsState ExtGState =((PDFormXObject) xObject).getResources().getExtGState(ExtGSName);
                    ExtGState.getCOSObject().setItem(COSName.NAME, new_name);
                    extgsdict.setItem(new_name,ExtGState);
                }
                imgdict.setItem(xObjectName, xObject);
                for (COSName Imgname :((PDFormXObject) xObject).getResources().getXObjectNames() )
                {
                    COSName new_name = COSName.getPDFName(Imgname.getName()+"_Fm"+img_count);
                    xObject.getCOSObject().setItem(COSName.NAME, new_name);
                    PDXObject img =((PDFormXObject) xObject).getResources().getXObject(Imgname);
                    imgdict.setItem(new_name, img);
                }

                    for (int k=0; k< tokens1.size(); k++) {
                        if ( ((tokens1.get(k) instanceof Operator) && ((Operator)tokens1.get(k)).getName().toString().equals("Do"))
                                && ((COSName)tokens1.get(k-1)).getName().toString().equals(xObjectName.getName().toString()) ) {
                            System.out.println(tokens1.get(k).toString());
                            tokens1.remove(k-1);
                            tokens1.remove(k-1);
                            ind =k-1;
                            break;
                        }
                    }
                for (int k=0; k< tokens3.size(); k++) {
                    if ( (tokens3.size() > k+1) && (tokens3.get(k+1) instanceof Operator) && (((Operator)tokens3.get(k+1)).getName().toString().equals("Do")
                            || ((Operator)tokens3.get(k+1)).getName().toString().equals("gs")
                            || ((Operator)tokens3.get(k+1)).getName().toString().equals("cs")  ) ) {
                        COSName new_name = COSName.getPDFName( ((COSName) tokens3.get(k)).getName()+"_Fm"+img_count );
                        tokens1.add(ind+k, new_name );
                    }else if ( (tokens3.size() > k+2) && (tokens3.get(k+2) instanceof Operator)
                            && ((Operator)tokens3.get(k+2)).getName().toString().equals("Tf") ) {
                        COSName new_name = COSName.getPDFName( ((COSName) tokens3.get(k)).getName()+"_Fm"+img_count );
                        tokens1.add(ind+k, new_name );
                    }else
                        tokens1.add(ind+k,tokens3.get(k));
                }

                img_count +=1;
        }else
            imgdict.setItem(xObjectName, xObject);
    }
    for (COSName fontName :new_resources.getFontNames() )
    {
        PDFont font =new_resources.getFont(fontName);
        fntdict.setItem(fontName,font);
    }
    for (COSName ExtGSName :new_resources.getExtGStateNames() )
    {
        PDExtendedGraphicsState extg =new_resources.getExtGState(ExtGSName);
        extgsdict.setItem(ExtGSName,extg);
    }
    for (COSName colorname :new_resources.getColorSpaceNames() )
    {
        PDColorSpace color =new_resources.getColorSpace(colorname);
        colordict.setItem(colorname,color);
    }
    resources.getCOSObject().setItem(COSName.EXT_G_STATE,extgsdict);
    resources.getCOSObject().setItem(COSName.FONT,fntdict);
    resources.getCOSObject().setItem(COSName.XOBJECT,imgdict);
    resources.getCOSObject().setItem(COSName.COLORSPACE, colordict);

    writer.writeTokens(tokens1);
    out.close();
    document.getPage(pg_ind).setContents(newContents);
    document.getPage(pg_ind).setMediaBox(PDFUtils.Media_box);
    document.getPage(pg_ind).setResources(resources);
    newdocument.addPage(document.getPage(pg_ind));
}
newdocument.save("D:/Testfiles/stu.pdf");
return newdocument;
}

但我无法获得准确的页面图形。我失去了一些东西。

input pdf

output pdf

推荐答案

有多个问题,有些是详细问题,有些是概念问题。

包装在保存图形状态/恢复图形状态信封中

在绘制XObject时,该XObject中的图形状态更改不会更改您的当前图形状态。为了确保在将XObject指令复制到页面内容流之后仍然是这样,您必须将该块包装到一个保存图形状态/恢复图形状态信封(q...q)中。您可以通过添加以下两行

来实现此目的
tokens1.add(ind++, Operator.getOperator("q"));
tokens1.add(ind, Operator.getOperator("Q"));

就在您的指令复制循环之前

for (int k=0; k< tokens3.size(); k++) {
    ...
}

坐标系

假设XObject中的坐标系等于页面的坐标系。这并不一定。XObject可能有一个Matrix条目,表示要应用的转换。

边界框

您不会限制XObject指令所绘制的区域。但是XObject有一个bBox条目,表示要将输出裁剪到的框。

可选内容

XObject还可能有OC条目,表示它们的可选内容成员身份。此类成员身份需要转换为等效的可选内容标记。

标记内容、结构树

XObject还可以通过StructParentStructParents条目引用结构父树。为了保持文档的结构完整性,您可能需要大量更新结构树。

分组

XObject可能包含Group条目,表示其内容应被视为一个组。尤其是在透明度组的情况下,这会导致透明度相关功能的行为与复制到页面内容中的相同指令的行为不同。

除非您完全分析以一定透明度绘制的每一位内容的效果,并逐一重写绘制它的指令,否则将指令从XObject复制到页面内容流将导致显示的内容有很大差异。

用法

您的代码假定XObject在页面内容流中只使用了一次。情况并非如此,它也可以更频繁地使用,或者根本不使用。


参考资料

在您要求提供推荐人的评论中。实际上,它都在pdf规范ISO 32000中,已经在公开可用的ISO 32000-1中:

因此,给定页面上的任意数量的使用都是可能的

因此,在复制到页面内容流中时,您应该等效使用q/q信封,并遵守Matrixbbox条目。

因此,在复制到页面内容时,请遵守此可选内容信息。

因此,从透明组复制可能会显著更改外观。

此信息以及同一章中的更多信息应清楚地表明,必须彻底检查从XObject复制到页面内容后的结构信息。

这篇关于是否使用PDFBox将FormXObject内容从资源添加到内容流?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 22:01