繁体   English   中英

PDFClown复制注释,然后对其进行操作

[英]PDFClown Copy annotations and then manipulate them

我需要将注释从一个PDF文件复制到另一个。 我使用了出色的PDFClown库,但无法处理颜色,旋转等问题。这可能吗? 我可以看到基础对象信息,但也不确定如何直接操作它。

我可以通过复制外观来复制外观,但是不能“编辑”它。

提前致谢。 亚历克斯

PS:如果斯蒂芬诺(Stephano)作者在听,项目是否死亡?

关于一般注释,尤其是标注注释

我仔细研究了一下,恐怕您无法使用高级方法确定性地操作任意输入。 原因是有许多其他方法可以设置标注注释的外观,而PDF Clown仅支持显式高级方法中优先级较低的方法。 从高优先级向下

  • AP流中的显式外观。 如果给出,则使用它,而忽略这种外观是否看起来完全像一个Callout注释,更不用说像其他Callout属性定义的外观了。

    PDF Clown尚未从其他值创建标注注释的外观,更不用说更新现有外观以跟上某些特定属性(例如Color )的更改。 对于ISO 32000-2支持,此处的PDF小丑将必须改进,因为外观流已成为必需。

    如果存在,则可以使用getAppearance()来检索外观,但是您只会获得带有低级绘制指令的FormXObject ,而没有任何特定于标注的形式。

    给定一个FormXObject可以很容易地操作一件事,但是可以通过相应地设置其Matrix来相当容易地旋转或倾斜外观,例如

     annotation.getAppearance().getNormal().get(null).setMatrix(AffineTransform.getRotateInstance(100, 10)); 
  • RC字符串或流中的富文本字符串。 除非给出外观,否则“标注”文本框中的文本将从该富文本数据生成(此处的富文本使用XHTML 1.0子集进行格式化)。

    PDF Clown尚未创建标注文本的富文本表示形式,更不用说更新现有的以遵循某些特定属性(例如Color )的更改了。

    如果存在,则可以使用getBaseDataObject().get(PdfName.RC)通过低级别访问来检索富文本,更改此字符串或流,然后使用getBaseDataObject().put(PdfName.RC, ...) 同样,您可以使用其名称PdfName.DS来检索,操纵和设置RTF默认样式字符串。

  • 在缺少外观流和(就文本内容而言)富文本字符串的情况下,用于从不同方面构建标注的许多不同设置。

    PDF小丑支持(许多)这些属性,特别是如果你投的克隆注释StaticNote使用,如不透明度CA get/set/withAlpha使用,边境边境 / BS get/set/withBorder ,使用背景颜色C get/set/withColor ,...

    顺便说一下,它的行结束样式LE支持有一个错误:显然,复制了Line注释LE属性的代码而未检查; 不幸的是,那里的属性遵循不同的语法...

你的任务

因此,关于您要更改的属性,

  • 轮换 :标注注释本身本身没有轮换属性(除了是否跟随页面轮换的标记外)。 因此,您不能将旋转设置为简单的注释属性。 但是,如果源注释确实具有外观流,则可以操纵其Matrix使其在注释矩形内旋转,请参见上文。

  • 边框颜色字体 :如果您的标注具有外观流,则可以尝试使用ContentScanner解析其内容并操纵颜色和字体设置操作。 否则,如果设置了富文本信息,则可以使用某些XML解析器尝试为字体解析富文本并处理字体样式属性。 否则,您可以解析默认外观DA字符串并操纵其字体和颜色设置说明。

一些示例代码

我使用Adobe Acrobat创建了一个带有示例标注注释的文件: Callout-Yellow.pdf 它包含外观流,富文本和简单属性,因此可以使用此文件进行不同级别的操作。

我将代码应用到了它,并为keepAppearanceStreamkeepRichText使用了不同的值(您没有提到使用的是Java还是.Net的PDF Clown;所以我选择了Java;但是.NET的端口应该很简单)。 :

boolean keepAppearanceStream = ...;
boolean keepRichText = ...;

try (   InputStream sourceResource = GET_STREAM_FOR("Callout-Yellow.pdf");
        InputStream targetResource = GET_STREAM_FOR("test123.pdf");
        org.pdfclown.files.File sourceFile = new org.pdfclown.files.File(sourceResource);
        org.pdfclown.files.File targetFile = new org.pdfclown.files.File(targetResource); ) {
    Document sourceDoc = sourceFile.getDocument();
    Page sourcePage = sourceDoc.getPages().get(0);
    Annotation<?> sourceAnnotation = sourcePage.getAnnotations().get(0);

    Document targetDoc = targetFile.getDocument();
    Page targetPage = targetDoc.getPages().get(0);

    StaticNote targetAnnotation = (StaticNote) sourceAnnotation.clone(targetDoc);

    if (keepAppearanceStream) {
        // changing properties of an appearance
        // rotating the appearance in the appearance rectangle
        targetAnnotation.getAppearance().getNormal().get(null).setMatrix(AffineTransform.getRotateInstance(100, 10));
    } else {
        // removing the appearance to allow lower level properties changes
        targetAnnotation.setAppearance(null);
    }

    // changing text background color
    targetAnnotation.setColor(new DeviceRGBColor(0, 0, 1));

    if (keepRichText) {
        // changing rich text properties
        PdfString richText = (PdfString) targetAnnotation.getBaseDataObject().get(PdfName.RC);
        String richTextString = richText.getStringValue();
        // replacing the font family
        richTextString = richTextString.replaceAll("font-family:Helvetica", "font-family:Courier");
        richText = new PdfString(richTextString);
        targetAnnotation.getBaseDataObject().put(PdfName.RC, richText);
    } else {
        targetAnnotation.getBaseDataObject().remove(PdfName.RC);
        targetAnnotation.getBaseDataObject().remove(PdfName.DS);
    }

    // changing default appearance properties
    PdfString defaultAppearance = (PdfString) targetAnnotation.getBaseDataObject().get(PdfName.DA);
    String defaultAppearanceString = defaultAppearance.getStringValue();
    // replacing the font
    defaultAppearanceString = defaultAppearanceString.replaceFirst("Helv", "HeBo");
    // replacing the text and line color
    defaultAppearanceString = defaultAppearanceString.replaceFirst(". . . rg", ".5 g");
    defaultAppearance = new PdfString(defaultAppearanceString);
    targetAnnotation.getBaseDataObject().put(PdfName.DA, defaultAppearance);

    // changing the text value
    PdfString contents = (PdfString) targetAnnotation.getBaseDataObject().get(PdfName.Contents);
    String contentsString = contents.getStringValue();
    contentsString = contentsString.replaceFirst("text", "text line");
    contents = new PdfString(contentsString);
    targetAnnotation.getBaseDataObject().put(PdfName.Contents, contents);

    // change the line width and style
    targetAnnotation.setBorder(new Border(0, new LineDash(new double[] {3, 2})));

    targetPage.getAnnotations().add(targetAnnotation);

    targetFile.save(new File(RESULT_FOLDER, "test123-withCalloutCopy.pdf"),  SerializationModeEnum.Standard);
}

CopyCallOut测试testCopyCallout

请注意,该代码仅具有概念验证的质量:对于任意PDF,您不能仅仅期望将字符串“ font-family:Helvetica”替换为“ font-family:Courier”或“ Helv”替换为“ HeBo”或“。 “ .rg”和“ .5g”之间的区别:可以使用不同的样式属性或名称来指定字体,并且可以使用不同的着色说明。

Adobe中的屏幕截图

  • 原始文件:

    原始注释

  • keepAppearanceStream = true

    保持外观流但旋转

  • keepAppearanceStream = falsekeepRichText = true

    外观流下降,富文本保留但被操纵

  • keepAppearanceStream = falsekeepRichText = false

    带有外观流和丰富文本,并且操作了简单属性

作为帖子Mkl,在创建新注释时,您的出色建议确实很有帮助。 我确实将以下内容用作“复制”现有注释的方法,其中note是“克隆的”注释广告库。

 foreach (PdfName t in baseAnnotation.BaseDataObject.Keys)
  {
                if (t.Equals(PdfName.DA) || t.Equals(PdfName.DS) || t.Equals(PdfName.RC) || t.Equals(PdfName.Rotate))
                {
                    note.BaseDataObject[t] = baseAnnotation.BaseDataObject[t];
                }
            }

再次感谢

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM