[英]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 。 它包含外觀流,富文本和簡單屬性,因此可以使用此文件進行不同級別的操作。
我將代碼應用到了它,並為keepAppearanceStream
和keepRichText
使用了不同的值(您沒有提到使用的是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”之間的區別:可以使用不同的樣式屬性或名稱來指定字體,並且可以使用不同的着色說明。
作為帖子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.