我在Java 8 Spring Boot应用程序中使用PDFBox 2.1.0-SNAPSHOT在其他只有图像的PDF文档的每一页上添加透明文本水印。在视觉上,它工作正常,因为我能够通过任何阅读器和所有浏览器内联PDF查看器上的水印看到图像。
但是,当我从IE打印这些文档时,不透明的白色背景会覆盖文本背后的图像。水印文本仍然是透明的,但文本的边界框是白色的。同样,从所有其他浏览器打印工作正常。 (得爱IE。)
这是我用来为每个页面添加水印的代码:
public void watermark(File pdfFile, OutputStream output) throws IOException {
try (final InputStream sourceStream = new FileInputStream(pdfFile);
final PDDocument document = PDDocument.load(sourceStream)) {
for (int pageNumber = 0; pageNumber < document.getNumberOfPages(); pageNumber++) {
PDPage currPage = document.getPage(pageNumber);
writeWatermarkOnPage(document, currPage);
}
document.save(output);
}
}
private void writeWatermarkOnPage(PDDocument document, PDPage page) throws IOException {
try (PDPageContentStream contentStream = new PDPageContentStream(
document, page, PDPageContentStream.AppendMode.APPEND, true, true)) {
PDRectangle rect = page.getBBox();
// Set the opacity
PDExtendedGraphicsState extendedGraphicsState = new PDExtendedGraphicsState();
extendedGraphicsState.setNonStrokingAlphaConstant(0.3f);
contentStream.setGraphicsStateParameters(extendedGraphicsState);
// Add the text
contentStream.beginText();
contentStream.setFont(PDType1Font.HELVETICA_BOLD, 75);
contentStream.setNonStrokingColor(Color.GRAY);
AffineTransform at = new AffineTransform(1, 0, 0, 1,
rect.getUpperRightX() / 4,
rect.getUpperRightY() / 4);
Matrix matrix = new Matrix(at);
matrix.rotate(Math.toRadians(45));
contentStream.setTextMatrix(matrix);
contentStream.showText("WATERMARK-TEXT");
contentStream.endText();
}
}
我尝试使用Overlay类,但结果相同。我尝试删除旋转和转换,但这没有帮助。只有当我删除nonStrokingAlphaConstant设置时,从IE的内联PDF渲染器打印时,不透明的白色背景才会消失,但此后文本不再透明。
在每个上下文中,我需要做些什么才能告诉每个PDF阅读器文本的背景应该是完全透明的吗?
更新
以下是PDF Document that shows this behavior示例。在Windows上,我只是拖动&amp;将其放入IE中,打印出来,水印文本的白色背景会覆盖底层图像。
以下是来自IE的另一个示例PDF created and watermarked with the same code that actually prints just fine。水印是透明的,没有白色背景。
我认为不同的是,损坏的文档是合法大小的图像,而工作文档是字母大小。也许某些与缩放有关的问题导致了这个问题?
答案 0 :(得分:0)
我能够通过使用透明PNG作为水印来实现我的目标,而不是将其添加为文本。现在可以从所有浏览器(包括IE)正确打印新的水印文件。以下是我用于将水印添加到PDF的每个页面的代码:
private static final String WATERMARK_RESOURCE_PATH = "/watermark/hcro_copy.png";
public void watermark(File pdfFile, OutputStream output) throws IOException {
try (final InputStream sourceStream = new FileInputStream(pdfFile);
final PDDocument document = PDDocument.load(sourceStream)
) {
for (int pageNumber = 0; pageNumber < document.getNumberOfPages(); pageNumber++) {
PDPage currPage = document.getPage(pageNumber);
writeWatermarkWithTransparentImageOnPage(document, currPage);
}
document.save(output);
}
}
private void writeWatermarkWithTransparentImageOnPage(PDDocument document, PDPage page)
throws IOException {
try (PDPageContentStream contentStream = new PDPageContentStream(
document, page, PDPageContentStream.AppendMode.APPEND, true, true);
InputStream watermarkFileStream = getWatermarkFileStream()
) {
// Load watermark image
BufferedImage image = ImageIO.read(watermarkFileStream);
PDImageXObject pdxImage = LosslessFactory.createFromImage(document, image);
// Set the opacity
PDExtendedGraphicsState extendedGraphicsState = new PDExtendedGraphicsState();
extendedGraphicsState.setNonStrokingAlphaConstant(0.35f);
contentStream.setGraphicsStateParameters(extendedGraphicsState);
// Center watermark image on page
PDRectangle rect = page.getBBox();
int imageX = Math.floorDiv((Math.round(rect.getWidth()) - pdxImage.getWidth()), 2);
int imageY = Math.floorDiv((Math.round(rect.getHeight()) - pdxImage.getHeight()), 2);
contentStream.drawImage(pdxImage, imageX, imageY);
}
}
private InputStream getWatermarkFileStream() {
try {
Resource resource = new ClassPathResource(WATERMARK_RESOURCE_PATH);
return resource.getInputStream();
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
我仍然愿意接受纯文字答案,但现在这对我有用。