Author: tilman
Date: Mon Sep 14 19:50:26 2026
New Revision: 1938209
Log:
PDFBOX-6258: clamp colors for shading in the colorspace class, cache ranges,
add test
Modified:
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDColorSpace.java
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/PDShading.java
pdfbox/branches/3.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/color/PDLabTest.java
Modified:
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDColorSpace.java
==============================================================================
---
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDColorSpace.java
Mon Sep 14 19:38:14 2026 (r1938208)
+++
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDColorSpace.java
Mon Sep 14 19:50:26 2026 (r1938209)
@@ -382,6 +382,26 @@ public abstract class PDColorSpace imple
return dest;
}
+ /**
+ * Clamp color values to allowed ranges, usually 0..1.
+ *
+ * @param values
+ */
+ public void clamp(float[] values)
+ {
+ for (int i = 0; i < values.length; ++i)
+ {
+ if (values[i] < 0)
+ {
+ values[i] = 0;
+ }
+ else if (values[i] > 1)
+ {
+ values[i] = 1;
+ }
+ }
+ }
+
@Override
public COSBase getCOSObject()
{
Modified:
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java
==============================================================================
---
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java
Mon Sep 14 19:38:14 2026 (r1938208)
+++
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java
Mon Sep 14 19:50:26 2026 (r1938209)
@@ -35,6 +35,11 @@ public final class PDLab extends PDCIEDi
{
private PDColor initialColor;
+ private float minA = -100;
+ private float maxA = 100;
+ private float minB = -100;
+ private float maxB = 100;
+
/**
* Creates a new Lab color space.
*/
@@ -70,12 +75,6 @@ public final class PDLab extends PDCIEDi
BufferedImage rgbImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
WritableRaster rgbRaster = rgbImage.getRaster();
- PDRange aRange = getARange();
- PDRange bRange = getBRange();
- float minA = aRange.getMin();
- float maxA = aRange.getMax();
- float minB = bRange.getMin();
- float maxB = bRange.getMax();
float deltaA = maxA - minA;
float deltaB = maxB - minB;
@@ -158,9 +157,7 @@ public final class PDLab extends PDCIEDi
@Override
public float[] getDefaultDecode(int bitsPerComponent)
{
- PDRange a = getARange();
- PDRange b = getBRange();
- return new float[] { 0, 100, a.getMin(), a.getMax(), b.getMin(),
b.getMax() };
+ return new float[] { 0, 100, minA, maxA, minB, maxB };
}
@Override
@@ -170,8 +167,8 @@ public final class PDLab extends PDCIEDi
{
initialColor = new PDColor(new float[] {
0,
- Math.max(0, getARange().getMin()),
- Math.max(0, getBRange().getMin()) },
+ Math.max(0, minA),
+ Math.max(0, minB) },
this);
}
return initialColor;
@@ -263,6 +260,50 @@ public final class PDLab extends PDCIEDi
}
dictionary.setItem(COSName.RANGE, rangeArray);
initialColor = null;
+ cacheRanges();
+ }
+
+ // called at the beginning and when it's changed
+ private void cacheRanges()
+ {
+ PDRange aRange = getARange();
+ PDRange bRange = getBRange();
+ minA = aRange.getMin();
+ maxA = aRange.getMax();
+ minB = bRange.getMin();
+ maxB = bRange.getMax();
}
+ @Override
+ public void clamp(float[] values)
+ {
+ // assumption: 3 elements: L a b
+ // "The range of the first (L*) component shall be 0 to 100;
+ // the ranges of the second and third (a* and b*) components shall be
defined by
+ // the Range entry in the colour space dictionary"
+ if (values[0] < 0)
+ {
+ values[0] = 0;
+ }
+ else if (values[0] > 100)
+ {
+ values[0] = 100;
+ }
+ if (values[1] < minA)
+ {
+ values[1] = minA;
+ }
+ else if (values[1] > maxA)
+ {
+ values[1] = maxA;
+ }
+ if (values[2] < minB)
+ {
+ values[2] = minB;
+ }
+ else if (values[2] > maxB)
+ {
+ values[2] = maxB;
+ }
+ }
}
Modified:
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/PDShading.java
==============================================================================
---
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/PDShading.java
Mon Sep 14 19:38:14 2026 (r1938208)
+++
pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/PDShading.java
Mon Sep 14 19:50:26 2026 (r1938209)
@@ -421,17 +421,7 @@ public abstract class PDShading implemen
// From the PDF spec:
// "If the value returned by the function for a given colour component
// is out of range, it shall be adjusted to the nearest valid value."
- for (int i = 0; i < returnValues.length; ++i)
- {
- if (returnValues[i] < 0)
- {
- returnValues[i] = 0;
- }
- else if (returnValues[i] > 1)
- {
- returnValues[i] = 1;
- }
- }
+ colorSpace.clamp(returnValues);
return returnValues;
}
Modified:
pdfbox/branches/3.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/color/PDLabTest.java
==============================================================================
---
pdfbox/branches/3.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/color/PDLabTest.java
Mon Sep 14 19:38:14 2026 (r1938208)
+++
pdfbox/branches/3.0/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/color/PDLabTest.java
Mon Sep 14 19:50:26 2026 (r1938209)
@@ -93,4 +93,32 @@ class PDLabTest
assertTrue(Arrays.equals(new float[]{0,0,3},
pdLab.getInitialColor().getComponents()));
}
+ @Test
+ void testClamp()
+ {
+ PDLab lab = new PDLab();
+ PDRange aRange = new PDRange();
+ aRange.setMin(-160);
+ aRange.setMax(160);
+ lab.setARange(aRange);
+ PDRange bRange = new PDRange();
+ bRange.setMin(-160);
+ bRange.setMax(160);
+ lab.setBRange(bRange);
+ float[] lab1 = new float[]{-101, -161, -161};
+ float[] lab2 = new float[]{-100, -160, -160};
+ float[] lab3 = new float[]{0, 0, 0};
+ float[] lab4 = new float[]{100, 160, 160};
+ float[] lab5 = new float[]{101, 161, 161};
+ lab.clamp(lab1);
+ lab.clamp(lab2);
+ lab.clamp(lab3);
+ lab.clamp(lab4);
+ lab.clamp(lab5);
+ assertEquals("[0.0, -160.0, -160.0]", Arrays.toString(lab1));
+ assertEquals("[0.0, -160.0, -160.0]", Arrays.toString(lab2));
+ assertEquals("[0.0, 0.0, 0.0]", Arrays.toString(lab3));
+ assertEquals("[100.0, 160.0, 160.0]", Arrays.toString(lab4));
+ assertEquals("[100.0, 160.0, 160.0]", Arrays.toString(lab5));
+ }
}