提问人:malz 提问时间:10/31/2023 最后编辑:Tilman Hausherrmalz 更新时间:11/1/2023 访问量:55
如何在 PDF 渲染器中反转参考底图颜色
How to invert underlaying colors in a PDF Renderer
问:
我目前正在使用 Apache PDFBox 3.0.0 在 Java 中实现 PDF 渲染器,我想添加使用 XOR(独占 OR)模式绘制 PDF 元素(如字符串、矩形和线条)的功能,以反转基础元素的颜色。此效果通常用于突出显示或反转图形。
例:
PDFRenderer:
public class PDFRenderer {
private PDDocument pdDocument;
private PDPageContentStream contentStream;
private float originY;
private float originX;
public PDFRenderer() {
this.pdDocument = new PDDocument();
PDPage pdPage = new PDPage();
this.pdDocument.addPage(pdPage);
try {
this.contentStream = new PDPageContentStream(pdDocument, pdPage, AppendMode.APPEND, false, false);
} catch (IOException e) {
e.printStackTrace();
}
originY = pdPage.getMediaBox().getHeight();
originX = 0;
}
/**
* Draws a string on the canvas.
*
* @param text The text to draw.
* @param x The x-coordinate of the top-left corner of the text.
* @param y The y-coordinate of the top-left corner of the text.
* @param width The width of the text box.
* @param height The height of the text box.
* @param color The color of the text.
* @param font The font to use.
*/
public void drawString(String text, int x, int y, int width, int height, CustomColor color, CustomFont font) {
try {
setStrokingColor(color);
int fontHeight = Math.round((font.getFont().getFontDescriptor().getCapHeight()) / 1000 * height);
float textWidth = font.getFont().getStringWidth(text) / 1000 * height;
contentStream.setFont(font.getFont(), height);
contentStream.setHorizontalScaling(100 + width);
contentStream.beginText();
contentStream.newLineAtOffset(originX + x, originY - fontHeight - y);
contentStream.showText(text);
contentStream.endText();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Draws a rectangle on the canvas.
*
* @param x The x-coordinate of the top-left corner of the rectangle.
* @param y The y-coordinate of the top-left corner of the rectangle.
* @param width The width of the rectangle.
* @param height The height of the rectangle.
* @param borderThickness The thickness of the rectangle's border.
* @param color The color of the rectangle.
* @param degreeOfCornerRounding The degree of corner rounding for the rectangle accepted are values from 1 to 8.
* @param colorInverted Indicates if the rectangle color is inverted.
*/
public void drawRectangle(int x, int y, int width, int height, int borderThickness, CustomColor color, int degreeOfCornerRounding, boolean colorInverted) {
try {
setStrokingColor(color);
if (borderThickness > width / 2) {
borderThickness = width / 2;
} else if (borderThickness > height / 2) {
borderThickness = height / 2;
}
float borderOffset = borderThickness / 2.0f;
float adjustedX = originX + x + borderOffset;
float adjustedY = originY - y - height + borderOffset;
float adjustedWidth = width - borderThickness;
float adjustedHeight = height - borderThickness;
contentStream.setLineWidth(borderThickness);
contentStream.addRect(adjustedX, adjustedY, adjustedWidth, adjustedHeight);
contentStream.stroke();
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Draws a line on the canvas.
*
* @param x The x-coordinate of the starting point of the line.
* @param y The y-coordinate of the starting point of the line.
* @param width The horizontal length of the line.
* @param height The vertical length of the line.
* @param thickness The thickness of the line.
* @param color The color of the line.
*/
public void drawLine(int x, int y, int width, int height, int thickness, CustomColor color) {
try {
setStrokingColor(color);
float adjustedX = originX + x;
float adjustedY = originY - y;
contentStream.setLineWidth(thickness);
contentStream.moveTo(adjustedX, adjustedY);
contentStream.lineTo(adjustedX + width, adjustedY - height);
contentStream.stroke();
} catch (IOException e) {
e.printStackTrace();
}
}
private void setStrokingColor(CustomColor color) throws NumberFormatException, IOException {
contentStream.setStrokingColor(
Integer.parseInt(color.getHexadecimal().substring(1, 3), 16) / 255f,
Integer.parseInt(color.getHexadecimal().substring(3, 5), 16) / 255f,
Integer.parseInt(color.getHexadecimal().substring(5, 7), 16) / 255f
);
}
}
用法:
PDFRenderer pdfRenderer = new PDFRenderer();
pdfRenderer.drawRectangle(50, 50, 100, 100, 100, CustomColortim.BLACK, 2);
pdfRenderer.drawLine(50, 500, 700, 3, 3, CustomColor.BLACK);
pdfRenderer.drawString("Hello, World!", 220, 195, 100, 30, CustomColor.BLACK, CustomFont.A);
具体问题
在 Java 中使用 Apache PDFBox 3.0.0 绘制矩形、线条和文本等 PDF 元素时,如何修改 PDFRenderer 类以实现异或颜色反转?
PDFBox 中是否有任何内置函数或方法支持用于颜色处理的 XOR 模式?
您能否提供在此上下文中实现 XOR 颜色反转的代码示例或建议?
答:
在 PDF 中更改颜色的一个常见问题是,您无法确定其他查看器可能会呈现哪种颜色模式。经常有人问我,为什么有些观众将图案显示为青色和绿色,而另一些观众则显示单色红色,两者可以是不同的形状。
这很大程度上归因于连续修改的“图形状态”的复杂性,然后添加了“扩展”设置!这是一个文件,不同的PDF查看器,不,Acrobat不是正确的。正确的是左上角。右上角是简单的反转,因此所有RGBW颜色都显示为CMYK,只需按下反转按钮。 因此,所有的“粉红色面孔”都变成了“蓝精灵蓝”,并抱怨只有一些颜色需要改变,但是哪种简单的方法可以过滤图像像素?
左下角的 Acrobat 可以过滤某些有限类型的对象,因此文本已指定为“绿色”,或者可以通过设置停止结束颜色来扭曲整个范围以方便访问。右下角的“黑是红”“白是绿”。
然而,要做到这一点,在复杂文件中逐项执行通常会导致对象丢失,因为有些对象自然是 RGB,有些是 CMYK。因此,每个对象和运行状态都需要分析,以免被否定而被遗忘。
评论