使用 PDFBox 创建透明组或设置图形状态软遮罩
Creating a transparency group or setting graphics state soft mask with PDFBox
我有一个用作软蒙版的灰度图像,我想在一组 PDF 对象(图像或路径)上使用它。
掩码和对象不一定使用相同的变换矩阵,并且可能有多个对象需要掩码,因此排除了使用 ImageXObject 字典的 SMask
属性的可能性。
所以在阅读了一些 PDF 规范之后,看起来我应该做以下事情:用要遮罩的对象创建一个透明组,然后用在图形状态上设置的软遮罩来绘制它。
这行得通吗?我怎样才能做到这一点,最好是使用 PDFBox?
这是一个例子。我有这两张图片:面具和另一张图片。
- 遮罩图像为 200x200。它是用矩阵
[[4 0 100] [0 4 100]]
. 绘制的
- 图片为 400x300。它是用矩阵
[[2 0 100] [0 2 150]]
. 绘制的
- 此外,在没有变换矩阵的图像下方绘制了一个 400x400 的黑色正方形。
所以用图像和正方形创建了一个透明组,然后用蒙版图像绘制它。这是预期的结果:
就效果而言相当丑陋,但这只是一个例子。
据我所知,在 PDFBox 中建立扩展图形状态软掩码是一项非常手动的任务。您可以这样做:
try ( PDDocument document = new PDDocument() ) {
final PDImageXObject image = RETRIEVE PHOTO IMAGE;
final PDImageXObject mask = RETRIEVE MASK IMAGE;
PDTransparencyGroupAttributes transparencyGroupAttributes = new PDTransparencyGroupAttributes();
transparencyGroupAttributes.getCOSObject().setItem(COSName.CS, COSName.DEVICEGRAY);
PDTransparencyGroup transparencyGroup = new PDTransparencyGroup(document);
transparencyGroup.setBBox(PDRectangle.A4);
transparencyGroup.setResources(new PDResources());
transparencyGroup.getCOSObject().setItem(COSName.GROUP, transparencyGroupAttributes);
try ( PDFormContentStream canvas = new PDFormContentStream(transparencyGroup) ) {
canvas.drawImage(mask, new Matrix(400, 0, 0, 400, 100, 100));
}
COSDictionary softMaskDictionary = new COSDictionary();
softMaskDictionary.setItem(COSName.S, COSName.LUMINOSITY);
softMaskDictionary.setItem(COSName.G, transparencyGroup);
PDExtendedGraphicsState extendedGraphicsState = new PDExtendedGraphicsState();
extendedGraphicsState.getCOSObject().setItem(COSName.SMASK, softMaskDictionary);
PDPage page = new PDPage(PDRectangle.A4);
document.addPage(page);
try ( PDPageContentStream canvas = new PDPageContentStream(document, page) ) {
canvas.saveGraphicsState();
canvas.setGraphicsStateParameters(extendedGraphicsState);
canvas.setNonStrokingColor(Color.BLACK);
canvas.addRect(100, 100, 400, 400);
canvas.fill();
canvas.drawImage(image, new Matrix(400, 0, 0, 300, 100, 150));
canvas.restoreGraphicsState();
}
document.save(new File(RESULT_FOLDER, "SoftMaskedImageAndRectangle.pdf"));
}
结果:
不过,如果我是你,我不会使用位图图像作为软蒙版,而是使用 PDF 渐变。结果很可能像素化要少得多。
我有一个用作软蒙版的灰度图像,我想在一组 PDF 对象(图像或路径)上使用它。
掩码和对象不一定使用相同的变换矩阵,并且可能有多个对象需要掩码,因此排除了使用 ImageXObject 字典的 SMask
属性的可能性。
所以在阅读了一些 PDF 规范之后,看起来我应该做以下事情:用要遮罩的对象创建一个透明组,然后用在图形状态上设置的软遮罩来绘制它。
这行得通吗?我怎样才能做到这一点,最好是使用 PDFBox?
这是一个例子。我有这两张图片:面具和另一张图片。
- 遮罩图像为 200x200。它是用矩阵
[[4 0 100] [0 4 100]]
. 绘制的
- 图片为 400x300。它是用矩阵
[[2 0 100] [0 2 150]]
. 绘制的
- 此外,在没有变换矩阵的图像下方绘制了一个 400x400 的黑色正方形。
所以用图像和正方形创建了一个透明组,然后用蒙版图像绘制它。这是预期的结果:
就效果而言相当丑陋,但这只是一个例子。
据我所知,在 PDFBox 中建立扩展图形状态软掩码是一项非常手动的任务。您可以这样做:
try ( PDDocument document = new PDDocument() ) {
final PDImageXObject image = RETRIEVE PHOTO IMAGE;
final PDImageXObject mask = RETRIEVE MASK IMAGE;
PDTransparencyGroupAttributes transparencyGroupAttributes = new PDTransparencyGroupAttributes();
transparencyGroupAttributes.getCOSObject().setItem(COSName.CS, COSName.DEVICEGRAY);
PDTransparencyGroup transparencyGroup = new PDTransparencyGroup(document);
transparencyGroup.setBBox(PDRectangle.A4);
transparencyGroup.setResources(new PDResources());
transparencyGroup.getCOSObject().setItem(COSName.GROUP, transparencyGroupAttributes);
try ( PDFormContentStream canvas = new PDFormContentStream(transparencyGroup) ) {
canvas.drawImage(mask, new Matrix(400, 0, 0, 400, 100, 100));
}
COSDictionary softMaskDictionary = new COSDictionary();
softMaskDictionary.setItem(COSName.S, COSName.LUMINOSITY);
softMaskDictionary.setItem(COSName.G, transparencyGroup);
PDExtendedGraphicsState extendedGraphicsState = new PDExtendedGraphicsState();
extendedGraphicsState.getCOSObject().setItem(COSName.SMASK, softMaskDictionary);
PDPage page = new PDPage(PDRectangle.A4);
document.addPage(page);
try ( PDPageContentStream canvas = new PDPageContentStream(document, page) ) {
canvas.saveGraphicsState();
canvas.setGraphicsStateParameters(extendedGraphicsState);
canvas.setNonStrokingColor(Color.BLACK);
canvas.addRect(100, 100, 400, 400);
canvas.fill();
canvas.drawImage(image, new Matrix(400, 0, 0, 300, 100, 150));
canvas.restoreGraphicsState();
}
document.save(new File(RESULT_FOLDER, "SoftMaskedImageAndRectangle.pdf"));
}
结果:
不过,如果我是你,我不会使用位图图像作为软蒙版,而是使用 PDF 渐变。结果很可能像素化要少得多。