簡體   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