如何在PDFBox中创建渐变?或者“我可以吗?”。
我不想创建它们并导出到jpeg或其他东西。我需要一个轻量级的文档,所以必须以某种方式进行编程。
有什么想法吗?
答案 0 :(得分:2)
经过大量的研究,我终于创造了一个自己渐变的小型创作者"!它看起来像这样:
{{1}}
我会把这个留给别人。留下您的意见并随意向我展示一些改进此代码的聪明主意:)
答案 1 :(得分:0)
这是我制作的一门课,旨在简化渐变的创建。它支持多种颜色的轴向渐变。它使用java.awt.Color
指定颜色,但可以轻松替换。
public class PDGradient extends PDShadingType2 {
public PDGradient(List<GradientPart> parts) {
super(new COSDictionary());
// PDF 1.7 - 8.7.4.5.3 Type 2 (Axial) Shadings
setColorSpace(PDDeviceRGB.INSTANCE);
setShadingType(PDShadingType2.SHADING_TYPE2);
setFunction(createGradientFunction(parts));
}
private static PDFunction createGradientFunction(List<GradientPart> parts) {
if (parts.size() < 2) {
throw new IllegalArgumentException("Gradient must have at least 2 colors.");
}
GradientPart first = parts.get(0);
GradientPart last = parts.get(parts.size() - 1);
if (first.ratio != 0f) {
throw new IllegalArgumentException("Gradient first color ratio must be 0.");
} else if (last.ratio != 1f) {
throw new IllegalArgumentException("Gradient last color ratio must be 1.");
}
if (parts.size() == 2) {
// Only two colors, use exponential function.
return createColorFunction(first.color, last.color);
}
// Multiple colors, use stitching function to combine exponential functions
// PDF 1.7 - 7.10.4 Type 3 (Stitching) Functions
COSDictionary dict = new COSDictionary();
COSArray functions = new COSArray();
COSArray bounds = new COSArray();
COSArray encode = new COSArray();
GradientPart lastPart = first;
for (int i = 1; i < parts.size(); i++) {
GradientPart part = parts.get(i);
// Add exponential function for interpolating between these two colors.
functions.add(createColorFunction(lastPart.color, part.color));
// Specify function bounds, except for first and last, which are specified by domain.
if (i != parts.size() - 1) {
bounds.add(new COSFloat(part.ratio));
}
// Used to interpolate stitching function subdomain (eg: [0.2 0.5]
// to the exponential function domain, which is always [0.0 1.0].
encode.add(COSInteger.ZERO);
encode.add(COSInteger.ONE);
lastPart = part;
}
dict.setInt(COSName.FUNCTION_TYPE, 3);
dict.setItem(COSName.DOMAIN, new PDRange()); // [0.0 1.0]
dict.setItem(COSName.FUNCTIONS, functions);
dict.setItem(COSName.BOUNDS, bounds);
dict.setItem(COSName.ENCODE, encode);
return new PDFunctionType3(dict);
}
private static PDFunction createColorFunction(Color start, Color end) {
// PDF 1.7 - 7.10.3 Type 2 (Exponential Interpolation) Functions
COSDictionary dict = new COSDictionary();
dict.setInt(COSName.FUNCTION_TYPE, 2);
dict.setItem(COSName.DOMAIN, new PDRange()); // [0.0 1.0]
dict.setItem(COSName.C0, createColorCOSArray(start));
dict.setItem(COSName.C1, createColorCOSArray(end));
dict.setInt(COSName.N, 1); // Linear interpolation
return new PDFunctionType2(dict);
}
private static COSArray createColorCOSArray(Color color) {
// Create a COSArray for a color.
// java.awt.Color uses 0-255 values while PDF uses 0-1.
COSArray a = new COSArray();
a.add(new COSFloat(color.getRed() / 255f));
a.add(new COSFloat(color.getGreen() / 255f));
a.add(new COSFloat(color.getBlue() / 255f));
return a;
}
/**
* Specifies a color and its position in a {@link PDGradient}.
*/
public static class GradientPart {
public final Color color;
public final float ratio;
public GradientPart(Color color, float ratio) {
this.color = color;
this.ratio = ratio;
}
}
}
用法示例:
List<GradientPart> parts = new ArrayList<>();
parts.add(new GradientPart(Color.RED, 0.0f));
parts.add(new GradientPart(Color.YELLOW, 0.5f));
parts.add(new GradientPart(Color.GREEN, 1.0f));
PDGradient gradient = new PDGradient(parts);
gradient.setCoords(...);
pdfStream.shadingFill(gradient)
这与两种颜色渐变的其他答案基本相同,使用指数函数(类型2)在两种颜色之间线性插值。如果有更多颜色,则可以使用拼接(类型3)功能将具有不同子域的多个指数功能组合在一起。