由於沒有人回答,我在自己的問題的評論中嘗試了我的建議。第一個結果是:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdfviewer.PageDrawer;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.PDGraphicsState;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
public class AnnotationDrawer extends PageDrawer
{
public AnnotationDrawer(int imageType, int resolution) throws IOException
{
super();
this.imageType = imageType;
this.resolution = resolution;
}
public Map<String, BufferedImage> convertToImages(PDPage p) throws IOException
{
page = p;
final Map<String, BufferedImage> result = new HashMap<String, BufferedImage>();
List<PDAnnotation> annotations = page.getAnnotations();
for (PDAnnotation annotation: annotations)
{
String appearanceName = annotation.getAppearanceStream();
PDAppearanceDictionary appearDictionary = annotation.getAppearance();
if(appearDictionary != null)
{
if(appearanceName == null)
{
appearanceName = "default";
}
Map<String, PDAppearanceStream> appearanceMap = appearDictionary.getNormalAppearance();
if (appearanceMap != null)
{
PDAppearanceStream appearance =
(PDAppearanceStream)appearanceMap.get(appearanceName);
if(appearance != null)
{
BufferedImage image = initializeGraphics(annotation);
setTextMatrix(null);
setTextLineMatrix(null);
getGraphicsStack().clear();
processSubStream(page, appearance.getResources(), appearance.getStream());
String name = annotation.getAnnotationName();
if (name == null || name.length() == 0)
{
name = annotation.getDictionary().getString(COSName.T);
if (name == null || name.length() == 0)
{
name = Long.toHexString(annotation.hashCode());
}
}
result.put(name, image);
}
}
}
}
return result;
}
BufferedImage initializeGraphics(PDAnnotation annotation)
{
PDRectangle rect = annotation.getRectangle();
float widthPt = rect.getWidth();
float heightPt = rect.getHeight();
float scaling = resolution/(float)DEFAULT_USER_SPACE_UNIT_DPI;
int widthPx = Math.round(widthPt * scaling);
int heightPx = Math.round(heightPt * scaling);
//TODO The following reduces accuracy. It should really be a Dimension2D.Float.
Dimension pageDimension = new Dimension((int)widthPt, (int)heightPt);
BufferedImage retval = new BufferedImage(widthPx, heightPx, imageType);
Graphics2D graphics = (Graphics2D)retval.getGraphics();
graphics.setBackground(TRANSPARENT_WHITE);
graphics.clearRect(0, 0, retval.getWidth(), retval.getHeight());
graphics.scale(scaling, scaling);
setGraphics(graphics);
pageSize = pageDimension;
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
setGraphicsState(new PDGraphicsState(new PDRectangle(widthPt, heightPt)));
return retval;
}
void setGraphics(Graphics2D graphics)
{
try {
Field field = PageDrawer.class.getDeclaredField("graphics");
field.setAccessible(true);
field.set(this, graphics);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static final int DEFAULT_USER_SPACE_UNIT_DPI = 72;
private static final Color TRANSPARENT_WHITE = new Color(255, 255, 255, 0);
private int imageType;
private int resolution;
}
如果你想呈現給定的PDPage page,
你只是做了註解:
AnnotationDrawer drawer = new AnnotationDrawer(8, 288);
Map<String, BufferedImage> images = drawer.convertToImages(page);
構造函數的參數對應於那些PDPage.convertToImage(int imageType, int resolution).
當心,這有
a。基於PDFBox 1.8.2一起被黑客入侵;它可能包含版本特定的代碼; b。僅僅檢查了我在這裏的一些可見的簽名註釋;它可能不完整,尤其對其他註釋類型可能會失敗。
來源
2013-06-17 10:45:50
mkl
是的,這是可能的,但不是,它不像調用一種方法那麼簡單,但它也不是魔術。只要研究'PDPage.convertToImage'和'PageDrawer.drawPage.'中發生了什麼。在後一種方法中,您將看到在頁面內容之後如何繪製頁面註釋的外觀。基本上,您必須找到簽名字段的註釋,並在* *各自的大小畫布上繪製*只*。 – mkl
這兩個問題:1.透明度不被尊重(所以我會在這個位置得到可見的捕獲+文檔)2.兩個重疊的簽名是不可恢復的。通過添加評論的匹配完成的匹配不是很聰明。 – ctvoigt
這就是爲什麼你應該看看這些方法和(因爲我遺憾地沒有清楚地說明)**把它們作爲自己的代碼的靈感,只渲染簽名註釋和每個單獨的代碼** – mkl