Author: tilman
Date: Sat Apr 26 12:27:52 2014
New Revision: 1590229

URL: http://svn.apache.org/r1590229
Log:
PDFBOX-2047: A read operation must not alter the pdf; optimize toRGB(); created 
a test

Added:
    pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/color/
    
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/color/PDLabTest.java
   (with props)
Modified:
    
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java

Modified: 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java?rev=1590229&r1=1590228&r2=1590229&view=diff
==============================================================================
--- 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java
 (original)
+++ 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDLab.java
 Sat Apr 26 12:27:52 2014
@@ -21,11 +21,8 @@ import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSFloat;
 import org.apache.pdfbox.cos.COSName;
-
 import org.apache.pdfbox.pdmodel.common.PDRange;
-
 import java.awt.color.ColorSpace;
-import java.io.IOException;
 
 /**
  * A Lab colour space is a CIE-based ABC colour space with two transformation 
stages.
@@ -40,6 +37,13 @@ public final class PDLab extends PDCIEBa
     private COSArray array;
     private COSDictionary dictionary;
     private PDColor initialColor;
+    
+    // we need to cache whitepoint values, because using getWhitePoint()
+    // would create a new default object for each pixel conversion if the 
original
+    // PDF didn't have a whitepoint array
+    private float wpX = 1;
+    private float wpY = 1;
+    private float wpZ = 1;
 
     /**
      * Creates a new Lab color space.
@@ -60,6 +64,12 @@ public final class PDLab extends PDCIEBa
     {
         array = lab;
         dictionary = (COSDictionary)array.getObject(1);
+        
+        // init whitepoint cache
+        PDTristimulus whitepoint = getWhitepoint();
+        wpX = whitepoint.getX();
+        wpY = whitepoint.getY();
+        wpZ = whitepoint.getZ();
     }
 
     @Override
@@ -87,22 +97,11 @@ public final class PDLab extends PDCIEBa
         float a = minA + (value[1] * (maxA - minA));
         float b = minB + (value[2] * (maxB - minB));
 
-        return labToRGB(l, a, b, getWhitepoint(), getBlackPoint());
-    }
+        // CIE LAB to RGB, see http://en.wikipedia.org/wiki/Lab_color_space
 
-    // CIE LAB to RGB, see http://en.wikipedia.org/wiki/Lab_color_space
-    private float[] labToRGB(float l, float a, float b,
-                             PDTristimulus whitepoint,
-                             PDTristimulus blackpoint)
-    {
         // L*
         float lstar = (l + 16f) * (1f / 116f);
 
-        // white point
-        float wpX = whitepoint.getX();
-        float wpY = whitepoint.getY();
-        float wpZ = whitepoint.getZ();
-
         // TODO: how to use the blackpoint? scale linearly between black & 
white?
 
         // XYZ
@@ -144,7 +143,7 @@ public final class PDLab extends PDCIEBa
     @Override
     public PDColor getInitialColor()
     {
-        if (initialColor != null)
+        if (initialColor == null)
         {
             initialColor = new PDColor(new float[] {
                     0,
@@ -169,7 +168,6 @@ public final class PDLab extends PDCIEBa
             wp.add(new COSFloat(1.0f));
             wp.add(new COSFloat(1.0f));
             wp.add(new COSFloat(1.0f));
-            dictionary.setItem(COSName.WHITE_POINT, wp);
         }
         return new PDTristimulus(wp);
     }
@@ -189,46 +187,52 @@ public final class PDLab extends PDCIEBa
             bp.add(new COSFloat(0.0f));
             bp.add(new COSFloat(0.0f));
             bp.add(new COSFloat(0.0f));
-            dictionary.setItem(COSName.BLACK_POINT, bp);
         }
         return new PDTristimulus(bp);
     }
 
-    private COSArray getRangeArray()
+    /**
+     * creates a range array with default values (-100..100 -100..100).
+     * @return the new range array.
+     */
+    private COSArray getDefaultRangeArray()
     {
-        COSArray range = 
(COSArray)dictionary.getDictionaryObject(COSName.RANGE);
-        if(range == null)
-        {
-            range = new COSArray();
-            dictionary.setItem(COSName.RANGE, array);
-            range.add(new COSFloat(-100));
-            range.add(new COSFloat(100));
-            range.add(new COSFloat(-100));
-            range.add(new COSFloat(100));
-        }
+        COSArray range = new COSArray();
+        range.add(new COSFloat(-100));
+        range.add(new COSFloat(100));
+        range.add(new COSFloat(-100));
+        range.add(new COSFloat(100));
         return range;
     }
 
     /**
      * This will get the valid range for the "a" component.
-     * If none is found then the default will be returned, which is -100 to 
100.
-     * @return the "a" range
+     * If none is found then the default will be returned, which is -100..100.
+     * @return the "a" range.
      */
     public PDRange getARange()
     {
-        COSArray range = getRangeArray();
-        return new PDRange(range, 0);
+        COSArray rangeArray = (COSArray) 
dictionary.getDictionaryObject(COSName.RANGE);
+        if (rangeArray == null)
+        {
+            rangeArray = getDefaultRangeArray();
+        }
+        return new PDRange(rangeArray, 0);
     }
 
     /**
      * This will get the valid range for the "b" component.
-     * If none is found  then the default will be returned, which is -100 to 
100.
-     * @return the "b" range
+     * If none is found  then the default will be returned, which is -100..100.
+     * @return the "b" range.
      */
     public PDRange getBRange()
     {
-        COSArray range = getRangeArray();
-        return new PDRange(range, 1);
+        COSArray rangeArray = (COSArray) 
dictionary.getDictionaryObject(COSName.RANGE);
+        if (rangeArray == null)
+        {
+            rangeArray = getDefaultRangeArray();
+        }
+        return new PDRange(rangeArray, 1);
     }
 
     /**
@@ -236,13 +240,18 @@ public final class PDLab extends PDCIEBa
      * As this is a required field this null should not be passed into this 
function.
      * @param whitepoint the whitepoint tristimulus
      */
-    public void setWhitepoint(PDTristimulus whitepoint)
+    public void setWhitePoint(PDTristimulus whitepoint)
     {
         COSBase wpArray = whitepoint.getCOSObject();
         if(wpArray != null)
         {
             dictionary.setItem(COSName.WHITE_POINT, wpArray);
         }
+        
+        // update cached values
+        wpX = whitepoint.getX();
+        wpY = whitepoint.getY();
+        wpZ = whitepoint.getZ();
     }
 
     /**
@@ -262,21 +271,26 @@ public final class PDLab extends PDCIEBa
 
     /**
      * This will set the a range for the "a" component.
-     * @param range the new range for the "a" component
+     * @param range the new range for the "a" component, 
+     * or null if defaults (-100..100) are to be set.
      */
     public void setARange(PDRange range)
     {
-        COSArray rangeArray = null;
+        COSArray rangeArray = (COSArray) 
dictionary.getDictionaryObject(COSName.RANGE);
+        if (rangeArray == null)
+        {
+            rangeArray = getDefaultRangeArray();
+        }
         //if null then reset to defaults
         if(range == null)
         {
-            rangeArray = getRangeArray();
             rangeArray.set(0, new COSFloat(-100));
             rangeArray.set(1, new COSFloat(100));
         }
         else
         {
-            rangeArray = range.getCOSArray();
+            rangeArray.set(0, new COSFloat(range.getMin()));
+            rangeArray.set(1, new COSFloat(range.getMax()));
         }
         dictionary.setItem(COSName.RANGE, rangeArray);
         initialColor = null;
@@ -284,21 +298,26 @@ public final class PDLab extends PDCIEBa
 
     /**
      * This will set the "b" range for this color space.
-     * @param range the new range for the "b" component
+     * @param range the new range for the "b" component,
+     * or null if defaults (-100..100) are to be set.
      */
     public void setBRange(PDRange range)
     {
-        COSArray rangeArray = null;
+        COSArray rangeArray = (COSArray) 
dictionary.getDictionaryObject(COSName.RANGE);
+        if (rangeArray == null)
+        {
+            rangeArray = getDefaultRangeArray();
+        }
         //if null then reset to defaults
         if(range == null)
         {
-            rangeArray = getRangeArray();
             rangeArray.set(2, new COSFloat(-100));
             rangeArray.set(3, new COSFloat(100));
         }
         else
         {
-            rangeArray = range.getCOSArray();
+            rangeArray.set(2, new COSFloat(range.getMin()));
+            rangeArray.set(3, new COSFloat(range.getMax()));
         }
         dictionary.setItem(COSName.RANGE, rangeArray);
         initialColor = null;

Added: 
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/color/PDLabTest.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/color/PDLabTest.java?rev=1590229&view=auto
==============================================================================
--- 
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/color/PDLabTest.java
 (added)
+++ 
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/color/PDLabTest.java
 Sat Apr 26 12:27:52 2014
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2014 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pdfbox.pdmodel.graphics.color;
+
+import java.util.Arrays;
+import junit.framework.TestCase;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.pdmodel.common.PDRange;
+
+/**
+ *
+ * @author Tilman Hausherr
+ */
+public class PDLabTest extends TestCase
+{
+
+    /**
+     * This test checks that getting default values do not alter the object, 
+     * and checks getters and setters.
+     */
+    public void testLAB()
+    {
+        PDLab pdLab = new PDLab();
+        COSArray cosArray = (COSArray) pdLab.getCOSObject();
+        COSDictionary dict = (COSDictionary) cosArray.getObject(1);
+        
+        // test with default values
+        assertEquals("Lab", pdLab.getName());
+        assertEquals(3, pdLab.getNumberOfComponents());
+        assertNotNull(pdLab.getInitialColor());
+        assertTrue(Arrays.equals(new float[]{0,0,0}, 
pdLab.getInitialColor().getComponents()));
+        assertEquals(0f, pdLab.getBlackPoint().getX());
+        assertEquals(0f, pdLab.getBlackPoint().getY());
+        assertEquals(0f, pdLab.getBlackPoint().getZ());
+        assertEquals(1f, pdLab.getWhitepoint().getX());
+        assertEquals(1f, pdLab.getWhitepoint().getX());
+        assertEquals(1f, pdLab.getWhitepoint().getX());
+        assertEquals(-100f, pdLab.getARange().getMin());
+        assertEquals(100f, pdLab.getARange().getMax());
+        assertEquals(-100f, pdLab.getBRange().getMin());
+        assertEquals(100f, pdLab.getBRange().getMax());
+        assertEquals("read operations should not change the size of /Lab 
objects", 0, dict.size());
+        dict.toString(); // rev 1571125 did a stack overflow here
+
+        // test setting specific values
+        PDRange pdRange = new PDRange();
+        pdRange.setMin(-1);
+        pdRange.setMax(2);
+        pdLab.setARange(pdRange);
+        pdRange = new PDRange();
+        pdRange.setMin(3);
+        pdRange.setMax(4);
+        pdLab.setBRange(pdRange);
+        assertEquals(-1f, pdLab.getARange().getMin());
+        assertEquals(2f, pdLab.getARange().getMax());
+        assertEquals(3f, pdLab.getBRange().getMin());
+        assertEquals(4f, pdLab.getBRange().getMax());
+        PDTristimulus pdTristimulus = new PDTristimulus();
+        pdTristimulus.setX(5);
+        pdTristimulus.setY(6);
+        pdTristimulus.setZ(7);
+        pdLab.setWhitePoint(pdTristimulus);
+        pdTristimulus = new PDTristimulus();
+        pdTristimulus.setX(8);
+        pdTristimulus.setY(9);
+        pdTristimulus.setZ(10);
+        pdLab.setBlackPoint(pdTristimulus);
+        assertEquals(5f, pdLab.getWhitepoint().getX());
+        assertEquals(6f, pdLab.getWhitepoint().getY());
+        assertEquals(7f, pdLab.getWhitepoint().getZ());
+        assertEquals(8f, pdLab.getBlackPoint().getX());
+        assertEquals(9f, pdLab.getBlackPoint().getY());
+        assertEquals(10f, pdLab.getBlackPoint().getZ());
+        assertTrue(Arrays.equals(new float[]{0,0,3}, 
pdLab.getInitialColor().getComponents()));
+    }
+
+}

Propchange: 
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/graphics/color/PDLabTest.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to