PDFbox 1.7.0 - 如何在使用 PDFBox 添加新图像时保留现有图像?
PDFbox 1.7.0 - How to keep existing image while adding new one with PDFBox?
我正在使用 PDFBox 1.7.0(由于生产服务器中的旧版本,我无法选择版本)。我正在尝试将图像添加到已有徽标的现有 PDF 中。
当我添加新图像时,旧图像就像被替换一样消失了。
// Use for convert mm to dots
// ... 72 dots per inch
static final int DEFAULT_USER_SPACE_UNIT_DPI = 72;
// ... mm -> inch -> dots
static final float MM_TO_UNITS = 1 / (10 * 2.54f) * DEFAULT_USER_SPACE_UNIT_DPI;
/**
* Add a given image to a specific page of a PDF
* @param document PDF document to manipulate
* @param input image inputStream
* @param pdfpage page number to target
* @param x image position (en mm)
* @param y image position (en mm)
* @param width max width of the image (mm)
* @param height max height of the image (en mm)
* @param opacity opacity level of the image (fraction)
*/
void addImageToPage (PDDocument document, InputStream input, int pdfpage, int x, int y, int width, int height, float opacity) throws IOException {
if (input != null) {
// Convert inputstream to usable BufferedImage
BufferedImage tmp_image = ImageIO.read (input);
// User TYPE_4BYTE_ABGR to fix PDFBox issue with transparent PNG
BufferedImage image = new BufferedImage (tmp_image.getWidth(), tmp_image.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
// Prepare the image
image.createGraphics().drawRenderedImage (tmp_image, null);
PDXObjectImage ximage = new PDPixelMap (document, image);
// Resize the image
int iWidth = ximage.getWidth();
int iHeight = ximage.getHeight();
if (width / height > iWidth / iHeight) {
ximage.setWidth (Math.round (width * MM_TO_UNITS));
ximage.setHeight (Math.round ((iHeight * width / iWidth) * MM_TO_UNITS));
} else {
ximage.setWidth (Math.round ((iWidth * height / iHeight) * MM_TO_UNITS));
ximage.setHeight (Math.round (height * MM_TO_UNITS));
}
// Retrieve the page to update
PDPage page = (PDPage)document.getDocumentCatalog().getAllPages().get (pdfpage);
PDResources resources = page.findResources();
// Get graphics states
Map graphicsStates = resources.getGraphicsStates();
if (graphicsStates == null) {
graphicsStates = new HashMap();
}
// Set graphics states configurations
PDExtendedGraphicsState extendedGraphicsState = new PDExtendedGraphicsState();
// Set the opacity of the image
extendedGraphicsState.setNonStrokingAlphaConstant (opacity);
graphicsStates.put ("TransparentState", extendedGraphicsState);
// Restore graphics states
resources.setGraphicsStates (graphicsStates);
// Retrieve the content stream
PDPageContentStream contentStream = new PDPageContentStream (document, page, true, true);
// Activate transparency options
contentStream.appendRawCommands ("/TransparentState gs\n");
contentStream.endMarkedContentSequence();
// Insert image
contentStream.drawImage (
ximage,
(float) x * MM_TO_UNITS,
(float) y * MM_TO_UNITS
);
// close the stream
contentStream.close();
}
}
我希望页面中有新图片,但页面中的现有图片已消失,而不是新图片。
使用的 PDF 示例:http://www.mediafire.com/folder/g6p7c2b5ob1c7/PDFBox_issue
1.7 中有几个错误...我在评论中提到的一个(事实证明它不会影响您),另一个是资源做了一些缓存但管理不当...长话短说简而言之,您需要像这样保存和恢复您的 xobject 资源:
Map<String, PDXObject> xObjectsMap = page.getResources().getXObjects(); // save xobjects
…
PDXObjectImage ximage = new PDPixelMap (document, image);
String imgName = page.getResources().addXObject(ximage, "Im");
cs.drawImage(ximage, 0, 0); // bug happens here, old xobjects gets lost
xObjectsMap.put(imgName, ximage);
page.getResources().setXObjects(xObjectsMap); // restore xobjects
这真的只是一个变通办法……可能会有更多的意外。你不应该使用旧版本。他们不再激发喜悦。你应该感谢他们的服务,然后让他们毫无愧疚地离开。
好的。我已经放弃尝试使用 PDFbox 1.7 进行这部分开发。它需要许多修复来实现一些东西。对于未来的作品来说,它并不是真正可维护的。感谢大家的提示和帮助。
我正在使用 PDFBox 1.7.0(由于生产服务器中的旧版本,我无法选择版本)。我正在尝试将图像添加到已有徽标的现有 PDF 中。 当我添加新图像时,旧图像就像被替换一样消失了。
// Use for convert mm to dots
// ... 72 dots per inch
static final int DEFAULT_USER_SPACE_UNIT_DPI = 72;
// ... mm -> inch -> dots
static final float MM_TO_UNITS = 1 / (10 * 2.54f) * DEFAULT_USER_SPACE_UNIT_DPI;
/**
* Add a given image to a specific page of a PDF
* @param document PDF document to manipulate
* @param input image inputStream
* @param pdfpage page number to target
* @param x image position (en mm)
* @param y image position (en mm)
* @param width max width of the image (mm)
* @param height max height of the image (en mm)
* @param opacity opacity level of the image (fraction)
*/
void addImageToPage (PDDocument document, InputStream input, int pdfpage, int x, int y, int width, int height, float opacity) throws IOException {
if (input != null) {
// Convert inputstream to usable BufferedImage
BufferedImage tmp_image = ImageIO.read (input);
// User TYPE_4BYTE_ABGR to fix PDFBox issue with transparent PNG
BufferedImage image = new BufferedImage (tmp_image.getWidth(), tmp_image.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
// Prepare the image
image.createGraphics().drawRenderedImage (tmp_image, null);
PDXObjectImage ximage = new PDPixelMap (document, image);
// Resize the image
int iWidth = ximage.getWidth();
int iHeight = ximage.getHeight();
if (width / height > iWidth / iHeight) {
ximage.setWidth (Math.round (width * MM_TO_UNITS));
ximage.setHeight (Math.round ((iHeight * width / iWidth) * MM_TO_UNITS));
} else {
ximage.setWidth (Math.round ((iWidth * height / iHeight) * MM_TO_UNITS));
ximage.setHeight (Math.round (height * MM_TO_UNITS));
}
// Retrieve the page to update
PDPage page = (PDPage)document.getDocumentCatalog().getAllPages().get (pdfpage);
PDResources resources = page.findResources();
// Get graphics states
Map graphicsStates = resources.getGraphicsStates();
if (graphicsStates == null) {
graphicsStates = new HashMap();
}
// Set graphics states configurations
PDExtendedGraphicsState extendedGraphicsState = new PDExtendedGraphicsState();
// Set the opacity of the image
extendedGraphicsState.setNonStrokingAlphaConstant (opacity);
graphicsStates.put ("TransparentState", extendedGraphicsState);
// Restore graphics states
resources.setGraphicsStates (graphicsStates);
// Retrieve the content stream
PDPageContentStream contentStream = new PDPageContentStream (document, page, true, true);
// Activate transparency options
contentStream.appendRawCommands ("/TransparentState gs\n");
contentStream.endMarkedContentSequence();
// Insert image
contentStream.drawImage (
ximage,
(float) x * MM_TO_UNITS,
(float) y * MM_TO_UNITS
);
// close the stream
contentStream.close();
}
}
我希望页面中有新图片,但页面中的现有图片已消失,而不是新图片。
使用的 PDF 示例:http://www.mediafire.com/folder/g6p7c2b5ob1c7/PDFBox_issue
1.7 中有几个错误...我在评论中提到的一个(事实证明它不会影响您),另一个是资源做了一些缓存但管理不当...长话短说简而言之,您需要像这样保存和恢复您的 xobject 资源:
Map<String, PDXObject> xObjectsMap = page.getResources().getXObjects(); // save xobjects
…
PDXObjectImage ximage = new PDPixelMap (document, image);
String imgName = page.getResources().addXObject(ximage, "Im");
cs.drawImage(ximage, 0, 0); // bug happens here, old xobjects gets lost
xObjectsMap.put(imgName, ximage);
page.getResources().setXObjects(xObjectsMap); // restore xobjects
这真的只是一个变通办法……可能会有更多的意外。你不应该使用旧版本。他们不再激发喜悦。你应该感谢他们的服务,然后让他们毫无愧疚地离开。
好的。我已经放弃尝试使用 PDFbox 1.7 进行这部分开发。它需要许多修复来实现一些东西。对于未来的作品来说,它并不是真正可维护的。感谢大家的提示和帮助。