You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2012/02/01 21:37:40 UTC
svn commit: r1239309 - in
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics:
pattern/PDShadingPatternResources.java shading/RadialShadingContext.java
shading/RadialShadingPaint.java xobject/PDJpeg.java
Author: lehmi
Date: Wed Feb 1 20:37:39 2012
New Revision: 1239309
URL: http://svn.apache.org/viewvc?rev=1239309&view=rev
Log:
PDFBOX-615, PDFBOX-1094: added the implementation of a radial shading
Added:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingContext.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingPaint.java
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/PDShadingPatternResources.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/PDShadingPatternResources.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/PDShadingPatternResources.java?rev=1239309&r1=1239308&r2=1239309&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/PDShadingPatternResources.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/PDShadingPatternResources.java Wed Feb 1 20:37:39 2012
@@ -33,6 +33,8 @@ import org.apache.pdfbox.pdmodel.graphic
import org.apache.pdfbox.pdmodel.graphics.shading.AxialShadingPaint;
import org.apache.pdfbox.pdmodel.graphics.shading.PDShadingResources;
import org.apache.pdfbox.pdmodel.graphics.shading.PDShadingType2;
+import org.apache.pdfbox.pdmodel.graphics.shading.PDShadingType3;
+import org.apache.pdfbox.pdmodel.graphics.shading.RadialShadingPaint;
import org.apache.pdfbox.util.Matrix;
/**
@@ -206,8 +208,10 @@ public class PDShadingPatternResources e
case PDShadingResources.SHADING_TYPE2:
paint = new AxialShadingPaint((PDShadingType2)getShading(), null, pageHeight);
break;
- case PDShadingResources.SHADING_TYPE1:
case PDShadingResources.SHADING_TYPE3:
+ paint = new RadialShadingPaint((PDShadingType3)getShading(), null, pageHeight);
+ break;
+ case PDShadingResources.SHADING_TYPE1:
case PDShadingResources.SHADING_TYPE4:
case PDShadingResources.SHADING_TYPE5:
case PDShadingResources.SHADING_TYPE6:
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingContext.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingContext.java?rev=1239309&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingContext.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingContext.java Wed Feb 1 20:37:39 2012
@@ -0,0 +1,325 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.shading;
+
+import java.awt.PaintContext;
+import java.awt.color.ColorSpace;
+import java.awt.geom.AffineTransform;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBoolean;
+import org.apache.pdfbox.pdmodel.common.function.PDFunction;
+import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
+import org.apache.pdfbox.util.Matrix;
+
+/**
+ * This class represents the PaintContext of an radial shading.
+ *
+ * @author lehmi
+ * @version $Revision: $
+ *
+ */
+public class RadialShadingContext implements PaintContext
+{
+
+ private ColorModel colorModel;
+ private PDFunction function;
+ private ColorSpace shadingColorSpace;
+
+ private float[] coords;
+ private float[] domain;
+ private boolean[] extend;
+ private double x1x0;
+ private double y1y0;
+ private double r1r0;
+ private double x1x0pow2;
+ private double y1y0pow2;
+ private double r0pow2;
+
+ private float d1d0;
+ private double denom;
+
+ /**
+ * Log instance.
+ */
+ private static final Log LOG = LogFactory.getLog(AxialShadingContext.class);
+
+ /**
+ * Constructor creates an instance to be used for fill operations.
+ *
+ * @param shadingType3 the shading type to be used
+ * @param colorModelValue the color model to be used
+ * @param xform transformation for user to device space
+ * @param ctm current transformation matrix
+ * @param pageHeight height of the current page
+ *
+ */
+ public RadialShadingContext(PDShadingType3 shadingType3, ColorModel colorModelValue,
+ AffineTransform xform, Matrix ctm, int pageHeight)
+ {
+ coords = shadingType3.getCoords().toFloatArray();
+ if (ctm != null)
+ {
+ // the shading is used in combination with the sh-operator
+ float[] coordsTemp = new float[coords.length];
+ // transform the coords from shading to user space
+ ctm.createAffineTransform().transform(coords, 0, coordsTemp, 0, 1);
+ ctm.createAffineTransform().transform(coords, 3, coordsTemp, 3, 1);
+ // move the 0,0-reference
+ coordsTemp[1] = pageHeight - coordsTemp[1];
+ coordsTemp[4] = pageHeight - coordsTemp[4];
+ // transform the coords from user to device space
+ xform.transform(coordsTemp, 0, coords, 0, 1);
+ xform.transform(coordsTemp, 3, coords, 3, 1);
+ }
+ else
+ {
+ // the shading is used as pattern colorspace in combination
+ // with a fill-, stroke- or showText-operator
+ float translateY = (float)xform.getTranslateY();
+ // move the 0,0-reference including the y-translation from user to device space
+ coords[1] = pageHeight + translateY - coords[1];
+ coords[4] = pageHeight + translateY - coords[4];
+ }
+ // colorSpace
+ try
+ {
+ PDColorSpace cs = shadingType3.getColorSpace();
+ if (!(cs instanceof PDDeviceRGB))
+ {
+ // we have to create an instance of the shading colorspace if it isn't RGB
+ shadingColorSpace = cs.getJavaColorSpace();
+ }
+ }
+ catch (IOException exception)
+ {
+ LOG.error("error while creating colorSpace", exception);
+ }
+ // colorModel
+ if (colorModelValue != null)
+ {
+ colorModel = colorModelValue;
+ }
+ else
+ {
+ try
+ {
+ // TODO bpc != 8 ??
+ colorModel = shadingType3.getColorSpace().createColorModel(8);
+ }
+ catch(IOException exception)
+ {
+ LOG.error("error while creating colorModel", exception);
+ }
+ }
+ // shading function
+ try
+ {
+ function = shadingType3.getFunction();
+ }
+ catch(IOException exception)
+ {
+ LOG.error("error while creating a function", exception);
+ }
+ // domain values
+ if (shadingType3.getDomain() != null)
+ {
+ domain = shadingType3.getDomain().toFloatArray();
+ }
+ else
+ {
+ // set default values
+ domain = new float[]{0,1};
+ }
+ // extend values
+ COSArray extendValues = shadingType3.getExtend();
+ if (shadingType3.getExtend() != null)
+ {
+ extend = new boolean[2];
+ extend[0] = ((COSBoolean)extendValues.get(0)).getValue();
+ extend[1] = ((COSBoolean)extendValues.get(1)).getValue();
+ }
+ else
+ {
+ // set default values
+ extend = new boolean[]{false,false};
+ }
+ // calculate some constants to be used in getRaster
+ x1x0 = coords[3] - coords[0];
+ y1y0 = coords[4] - coords[1];
+ r1r0 = coords[5] - coords[2];
+ x1x0pow2 = Math.pow(x1x0,2);
+ y1y0pow2 = Math.pow(y1y0,2);
+ r0pow2 = Math.pow(coords[2],2);
+ denom = x1x0pow2 + y1y0pow2 - Math.pow(r1r0, 2);
+ d1d0 = domain[1]-domain[0];
+ // TODO take a possible Background value into account
+
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public void dispose()
+ {
+ colorModel = null;
+ function = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ColorModel getColorModel()
+ {
+ return colorModel;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Raster getRaster(int x, int y, int w, int h)
+ {
+ // create writable raster
+ WritableRaster raster = getColorModel().createCompatibleWritableRaster(w, h);
+ float[] input = new float[1];
+ float inputValue;
+ int[] data = new int[w * h * 3];
+ for (int j = 0; j < h; j++)
+ {
+ for (int i = 0; i < w; i++)
+ {
+ float[] inputValues = calculateInputValues(x + i, y + j);
+ // choose 1 of the 2 values
+ if (inputValues[0] >= domain[0] && inputValues[0] <= domain[1])
+ {
+ // both values are in the domain -> choose the larger one
+ if(inputValues[1] >= domain[0] && inputValues[1] <= domain[1])
+ {
+ inputValue = Math.max(inputValues[0], inputValues[1]);
+ }
+ // first value is in the domain, the second not -> choose first value
+ else
+ {
+ inputValue = inputValues[0];
+ }
+ }
+ else
+ {
+ // first value is not in the domain, but the second -> choose second value
+ if(inputValues[1] >= domain[0] && inputValues[1] <= domain[1])
+ {
+ inputValue = inputValues[1];
+ }
+ // TODO
+ // both are not in the domain -> choose the first as I don't know it better
+ else
+ {
+ inputValue = inputValues[0];
+ }
+ }
+ // input value is out of range
+ if (inputValue < domain[0])
+ {
+ // the shading has to be extended if extend[0] == true
+ if (extend[0])
+ {
+ inputValue = domain[0];
+ }
+ else
+ {
+ continue;
+ }
+ }
+ // input value is out of range
+ else if (inputValue > domain[1])
+ {
+ // the shading has to be extended if extend[1] == true
+ if (extend[1])
+ {
+ inputValue = domain[1];
+ }
+ else
+ {
+ continue;
+ }
+ }
+ input[0] = (float)(domain[0] + (d1d0*inputValue));
+ float[] values = null;
+ try
+ {
+ values = function.eval(input);
+ }
+ catch (IOException exception)
+ {
+ LOG.error("error while processing a function", exception);
+ }
+ int index = (j * w + i) * 3;
+ // convert color values from shading colorspace to RGB
+ if (shadingColorSpace != null)
+ {
+ values = shadingColorSpace.toRGB(values);
+ }
+ data[index] = (int)(values[0]*255);
+ data[index+1] = (int)(values[1]*255);
+ data[index+2] = (int)(values[2]*255);
+ }
+ }
+ raster.setPixels(0, 0, w, h, data);
+ return raster;
+ }
+
+ private float[] calculateInputValues(int x, int y)
+ {
+
+ /**
+ * According to Adobes Technical Note #5600 we have to do the following
+ *
+ * x0, y0, r0 defines the start circle
+ * x1, y1, r1 defines the end circle
+ *
+ * The parametric equations for the center and radius of the gradient fill
+ * circle moving between the start circle and the end circle as a function
+ * of s are as follows:
+ *
+ * xc(s) = x0 + s * (x1 - x0)
+ * yc(s) = y0 + s * (y1 - y0)
+ * r(s) = r0 + s * (r1 - r0)
+ *
+ * Given a geometric coordinate position (x, y) in or along the gradient fill,
+ * the corresponding value of s can be determined by solving the quadratic
+ * constraint equation:
+ *
+ * [x - xc(s)]2 + [y - yc(s)]2 = [r(s)]2
+ *
+ * The following code calculates the 2 possible values of s
+ */
+
+ float[] values = new float[2];
+ double p = (-0.25)*((x - coords[0])*x1x0 + (y - coords[1])*y1y0 - r1r0) / denom;
+ double q = (Math.pow(x - coords[0],2) + Math.pow(y - coords[1],2) - r0pow2) / denom;
+ double root = Math.sqrt(Math.pow(p , 2) - q);
+ values[0] = (float)((-1)*p + root);
+ values[1] = (float)((-1)*p - root);
+ return values;
+ }
+}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingPaint.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingPaint.java?rev=1239309&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingPaint.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingPaint.java Wed Feb 1 20:37:39 2012
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.shading;
+
+import java.awt.Paint;
+import java.awt.PaintContext;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+
+import org.apache.pdfbox.util.Matrix;
+
+/**
+ * This represents the Paint of an radial shading.
+ *
+ * @author lehmi
+ * @version $Revision: $
+ *
+ */
+public class RadialShadingPaint implements Paint
+{
+
+ private PDShadingType3 shading;
+ private Matrix currentTransformationMatrix;
+ private int pageHeight;
+
+ /**
+ * Constructor.
+ *
+ * @param shadingType3 the shading resources
+ * @param ctm current transformation matrix
+ * @param pageSizeValue size of the current page
+ */
+ public RadialShadingPaint(PDShadingType3 shadingType3, Matrix ctm, int pageHeightValue)
+ {
+ shading = shadingType3;
+ currentTransformationMatrix = ctm;
+ pageHeight = pageHeightValue;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public int getTransparency()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+ Rectangle2D userBounds, AffineTransform xform, RenderingHints hints)
+ {
+ return new RadialShadingContext(shading, cm, xform, currentTransformationMatrix, pageHeight);
+ }
+
+}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java?rev=1239309&r1=1239308&r2=1239309&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java Wed Feb 1 20:37:39 2012
@@ -167,8 +167,11 @@ public class PDJpeg extends PDXObjectIma
{
for(int x = 0; x < alphaWidth; x++)
{
- Color color = new Color(alpha.getRGB(x, y));
- if(color.getRed() != 0 && color.getGreen() != 0 && color.getBlue() != 0)
+ int colorValues = alpha.getRGB(x, y);
+ // TODO check condition PDFBOX-626
+ if( ((colorValues >> 16) & 0xFF) != 0
+ && ((colorValues >> 8) & 0xFF) != 0
+ && ((colorValues >> 0) & 0xFF) != 0 )
{
alpha.setRGB(x, y, whiteRGB);
}