You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ja...@apache.org on 2014/02/20 07:31:05 UTC
svn commit: r1570086 [4/7] - in /pdfbox/trunk:
examples/src/main/java/org/apache/pdfbox/examples/pdmodel/
examples/src/main/java/org/apache/pdfbox/examples/util/
pdfbox/src/main/java/org/apache/pdfbox/cos/
pdfbox/src/main/java/org/apache/pdfbox/filter/...
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=1570086&r1=1570085&r2=1570086&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 Thu Feb 20 06:31:01 2014
@@ -24,270 +24,283 @@ import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.common.PDRange;
-import java.awt.Transparency;
import java.awt.color.ColorSpace;
-import java.awt.image.ColorModel;
-import java.awt.image.ComponentColorModel;
-import java.awt.image.DataBuffer;
-
import java.io.IOException;
/**
- * This class represents a Lab color space.
+ * A Lab colour space is a CIE-based ABC colour space with two transformation stages.
*
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.4 $
+ * @author Ben Litchfield
+ * @author John Hewson
*/
-public class PDLab extends PDColorSpace
+public final class PDLab extends PDCIEBasedColorSpace
{
- /**
- * The name of this color space.
- */
- public static final String NAME = "Lab";
+ private static final ColorSpace CIEXYZ = ColorSpace.getInstance(ColorSpace.CS_CIEXYZ);
private COSArray array;
private COSDictionary dictionary;
+ private PDColor initialColor;
/**
- * Constructor.
+ * Creates a new Lab color space.
*/
public PDLab()
{
array = new COSArray();
dictionary = new COSDictionary();
- array.add( COSName.LAB );
- array.add( dictionary );
+ array.add(COSName.LAB);
+ array.add(dictionary);
}
/**
- * Constructor with array.
- *
- * @param lab The underlying color space.
+ * Creates a new Lab color space from a PDF array.
+ * @param lab the color space array
*/
- public PDLab( COSArray lab )
+ public PDLab(COSArray lab)
{
array = lab;
- dictionary = (COSDictionary)array.getObject( 1 );
+ dictionary = (COSDictionary)array.getObject(1);
}
- /**
- * This will return the name of the color space.
- *
- * @return The name of the color space.
- */
+ @Override
public String getName()
{
- return NAME;
+ return COSName.LAB.getName();
}
- /**
- * Convert this standard java object to a COS object.
- *
- * @return The cos object that matches this Java object.
- */
+ @Override
public COSBase getCOSObject()
{
return array;
}
- /**
- * Create a Java colorspace for this colorspace.
- *
- * @return A color space that can be used for Java AWT operations.
- *
- * @throws IOException If there is an error creating the color space.
- */
- protected ColorSpace createColorSpace() throws IOException
+ @Override
+ public float[] toRGB(float[] value)
{
- return new ColorSpaceLab(getWhitepoint(), getBlackPoint(), getARange(), getBRange());
+ float minA = getARange().getMin();
+ float maxA = getARange().getMax();
+ float minB = getBRange().getMin();
+ float maxB = getBRange().getMax();
+
+ // scale to range
+ float l = value[0] * 100;
+ float a = minA + (value[1] * (maxA - minA));
+ float b = minB + (value[2] * (maxB - minB));
+
+ return labToRGB(l, a, b, getWhitepoint(), getBlackPoint());
}
- /**
- * Create a Java color model for this colorspace.
- *
- * @param bpc The number of bits per component.
- *
- * @return A color model that can be used for Java AWT operations.
- *
- * @throws IOException If there is an error creating the color model.
- */
- public ColorModel createColorModel( int bpc ) throws IOException
+ // 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)
{
- int[] nBits = {bpc, bpc, bpc};
- return new ComponentColorModel( getJavaColorSpace(),
- nBits,
- false,
- false,
- Transparency.OPAQUE,
- DataBuffer.TYPE_BYTE);
+ // 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
+ float x = wpX * inverse(lstar + a * (1f / 500f));
+ float y = wpY * inverse(lstar);
+ float z = wpZ * inverse(lstar - b * (1f / 200f));
+
+ // XYZ to RGB
+ return CIEXYZ.toRGB(new float[] { x, y, z });
}
- /**
- * This will get the number of components that this color space is made up of.
- *
- * @return The number of components in this color space.
- *
- * @throws IOException If there is an error getting the number of color components.
- */
- public int getNumberOfComponents() throws IOException
+ // reverse transformation (f^-1)
+ private float inverse(float x)
+ {
+ if (x > 6.0 / 29.0)
+ {
+ return x * x * x;
+ }
+ else
+ {
+ return (108f / 841f) * (x - (4f / 29f));
+ }
+ }
+
+ @Override
+ public int getNumberOfComponents()
{
return 3;
}
- /**
- * This will return the whitepoint tristimulus. As this is a required field
- * this will never return null. A default of 1,1,1 will be returned if the
- * pdf does not have any values yet.
- *
- * @return The whitepoint tristimulus.
- */
- public PDTristimulus getWhitepoint()
+ @Override
+ public float[] getDefaultDecode()
{
- COSArray wp = (COSArray)dictionary.getDictionaryObject( COSName.WHITE_POINT );
- if( wp == null )
+ PDRange a = getARange();
+ PDRange b = getARange();
+ return new float[] { 0, 100, a.getMin(), a.getMax(), b.getMin(), b.getMax() };
+ }
+
+ @Override
+ public PDColor getInitialColor()
+ {
+ if (initialColor != null)
{
- wp = new COSArray();
- wp.add( new COSFloat( 1.0f ) );
- wp.add( new COSFloat( 1.0f ) );
- wp.add( new COSFloat( 1.0f ) );
- dictionary.setItem( COSName.WHITE_POINT, wp );
+ initialColor = new PDColor(new float[] {
+ 0,
+ Math.max(0, getARange().getMin()),
+ Math.max(0, getBRange().getMin()) });
}
- return new PDTristimulus( wp );
+ return initialColor;
}
/**
- * This will set the whitepoint tristimulus. As this is a required field
- * this null should not be passed into this function.
- *
- * @param wp The whitepoint tristimulus.
+ * This will return the whitepoint tristimulus.
+ * As this is a required field this will never return null.
+ * A default of 1,1,1 will be returned if the pdf does not have any values yet.
+ * @return the whitepoint tristimulus
*/
- public void setWhitepoint( PDTristimulus wp )
+ public PDTristimulus getWhitepoint()
{
- COSBase wpArray = wp.getCOSObject();
- if( wpArray != null )
+ COSArray wp = (COSArray)dictionary.getDictionaryObject(COSName.WHITE_POINT);
+ if(wp == null)
{
- dictionary.setItem( COSName.WHITE_POINT, wpArray );
+ wp = new COSArray();
+ 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);
}
/**
- * This will return the BlackPoint tristimulus. This is an optional field but
- * has defaults so this will never return null.
+ * This will return the BlackPoint tristimulus.
+ * This is an optional field but has defaults so this will never return null.
* A default of 0,0,0 will be returned if the pdf does not have any values yet.
- *
- * @return The blackpoint tristimulus.
+ * @return the blackpoint tristimulus
*/
public PDTristimulus getBlackPoint()
{
- COSArray bp = (COSArray)dictionary.getDictionaryObject( COSName.BLACK_POINT );
- if( bp == null )
+ COSArray bp = (COSArray)dictionary.getDictionaryObject(COSName.BLACK_POINT);
+ if(bp == null)
{
bp = new COSArray();
- bp.add( new COSFloat( 0.0f ) );
- bp.add( new COSFloat( 0.0f ) );
- bp.add( new COSFloat( 0.0f ) );
- dictionary.setItem( COSName.BLACK_POINT, bp );
+ 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 );
+ return new PDTristimulus(bp);
+ }
+
+ private COSArray getRangeArray()
+ {
+ 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));
+ }
+ return range;
}
/**
- * This will set the BlackPoint tristimulus. As this is a required field
- * this null should not be passed into this function.
- *
- * @param bp The BlackPoint tristimulus.
+ * 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
*/
- public void setBlackPoint( PDTristimulus bp )
+ public PDRange getARange()
{
+ COSArray range = getRangeArray();
+ return new PDRange(range, 0);
+ }
- COSBase bpArray = null;
- if( bp != null )
- {
- bpArray = bp.getCOSObject();
- }
- dictionary.setItem( COSName.BLACK_POINT, bpArray );
+ /**
+ * 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
+ */
+ public PDRange getBRange()
+ {
+ COSArray range = getRangeArray();
+ return new PDRange(range, 1);
}
- private COSArray getRangeArray()
+ /**
+ * This will set the whitepoint tristimulus.
+ * 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)
{
- COSArray range = (COSArray)dictionary.getDictionaryObject( COSName.RANGE );
- if( range == null )
+ COSBase wpArray = whitepoint.getCOSObject();
+ if(wpArray != 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 ) );
+ dictionary.setItem(COSName.WHITE_POINT, wpArray);
}
- 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.
+ * This will set the BlackPoint tristimulus.
+ * As this is a required field this null should not be passed into this function.
+ * @param blackpoint the BlackPoint tristimulus
*/
- public PDRange getARange()
+ public void setBlackPoint(PDTristimulus blackpoint)
{
- COSArray range = getRangeArray();
- return new PDRange( range, 0 );
+ COSBase bpArray = null;
+ if(blackpoint != null)
+ {
+ bpArray = blackpoint.getCOSObject();
+ }
+ dictionary.setItem(COSName.BLACK_POINT, bpArray);
}
/**
- * This will set the a range for this color space.
- *
- * @param range The new range for the a component.
+ * This will set the a range for the "a" component.
+ * @param range the new range for the "a" component
*/
- public void setARange( PDRange range )
+ public void setARange(PDRange range)
{
COSArray rangeArray = null;
//if null then reset to defaults
- if( range == null )
+ if(range == null)
{
rangeArray = getRangeArray();
- rangeArray.set( 0, new COSFloat( -100 ) );
- rangeArray.set( 1, new COSFloat( 100 ) );
+ rangeArray.set(0, new COSFloat(-100));
+ rangeArray.set(1, new COSFloat(100));
}
else
{
rangeArray = range.getCOSArray();
}
- dictionary.setItem( COSName.RANGE, rangeArray );
- }
-
- /**
- * 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.
- */
- public PDRange getBRange()
- {
- COSArray range = getRangeArray();
- return new PDRange( range, 1 );
+ dictionary.setItem(COSName.RANGE, rangeArray);
+ initialColor = null;
}
/**
- * This will set the b range for this color space.
- *
- * @param range The new range for the b component.
+ * This will set the "b" range for this color space.
+ * @param range the new range for the "b" component
*/
- public void setBRange( PDRange range )
+ public void setBRange(PDRange range)
{
COSArray rangeArray = null;
//if null then reset to defaults
- if( range == null )
+ if(range == null)
{
rangeArray = getRangeArray();
- rangeArray.set( 2, new COSFloat( -100 ) );
- rangeArray.set( 3, new COSFloat( 100 ) );
+ rangeArray.set(2, new COSFloat(-100));
+ rangeArray.set(3, new COSFloat(100));
}
else
{
rangeArray = range.getCOSArray();
}
- dictionary.setItem( COSName.RANGE, rangeArray );
+ dictionary.setItem(COSName.RANGE, rangeArray);
+ initialColor = null;
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDOutputIntent.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDOutputIntent.java?rev=1570086&r1=1570085&r2=1570086&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDOutputIntent.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDOutputIntent.java Thu Feb 20 06:31:01 2014
@@ -27,72 +27,90 @@ import org.apache.pdfbox.pdmodel.PDDocum
import org.apache.pdfbox.pdmodel.common.COSObjectable;
import org.apache.pdfbox.pdmodel.common.PDStream;
-public class PDOutputIntent implements COSObjectable {
-
- private COSDictionary dictionary;
-
- public PDOutputIntent(PDDocument doc, InputStream colorProfile) throws Exception{
- dictionary = new COSDictionary();
- dictionary.setItem(COSName.TYPE, COSName.OUTPUT_INTENT);
- dictionary.setItem(COSName.S, COSName.GTS_PDFA1);
+/**
+ * An Output Intent describes the colour reproduction characteristics of a possible output
+ * device or production condition.
+ * Output intents provide a means for matching the colour characteristics of a PDF document with
+ * those of a target output device or production environment in which the document will be printed.
+ *
+ * @author Guillaume Bailleul
+ */
+public final class PDOutputIntent implements COSObjectable
+{
+ private COSDictionary dictionary;
+
+ public PDOutputIntent(PDDocument doc, InputStream colorProfile) throws Exception
+ {
+ dictionary = new COSDictionary();
+ dictionary.setItem(COSName.TYPE, COSName.OUTPUT_INTENT);
+ dictionary.setItem(COSName.S, COSName.GTS_PDFA1);
PDStream destOutputIntent = configureOutputProfile(doc, colorProfile);
- dictionary.setItem(COSName.DEST_OUTPUT_PROFILE, destOutputIntent);
- }
+ dictionary.setItem(COSName.DEST_OUTPUT_PROFILE, destOutputIntent);
+ }
- public PDOutputIntent (COSDictionary dictionary) {
+ public PDOutputIntent(COSDictionary dictionary)
+ {
this.dictionary = dictionary;
}
-
- public COSBase getCOSObject() {
- return dictionary;
- }
- public COSStream getDestOutputIntent () {
- return (COSStream)dictionary.getItem(COSName.DEST_OUTPUT_PROFILE);
+ public COSBase getCOSObject()
+ {
+ return dictionary;
+ }
+
+ public COSStream getDestOutputIntent()
+ {
+ return (COSStream) dictionary.getItem(COSName.DEST_OUTPUT_PROFILE);
}
-
- public String getInfo () {
+
+ public String getInfo()
+ {
return dictionary.getString(COSName.INFO);
}
-
- public void setInfo( String value )
- {
- dictionary.setString(COSName.INFO, value);
- }
- public String getOutputCondition () {
+ public void setInfo(String value)
+ {
+ dictionary.setString(COSName.INFO, value);
+ }
+
+ public String getOutputCondition()
+ {
return dictionary.getString(COSName.OUTPUT_CONDITION);
}
-
- public void setOutputCondition( String value )
- {
- dictionary.setString(COSName.OUTPUT_CONDITION, value);
- }
- public String getOutputConditionIdentifier () {
+ public void setOutputCondition(String value)
+ {
+ dictionary.setString(COSName.OUTPUT_CONDITION, value);
+ }
+
+ public String getOutputConditionIdentifier()
+ {
return dictionary.getString(COSName.OUTPUT_CONDITION_IDENTIFIER);
}
-
- public void setOutputConditionIdentifier( String value )
- {
- dictionary.setString(COSName.OUTPUT_CONDITION_IDENTIFIER, value);
- }
- public String getRegistryName () {
+ public void setOutputConditionIdentifier(String value)
+ {
+ dictionary.setString(COSName.OUTPUT_CONDITION_IDENTIFIER, value);
+ }
+
+ public String getRegistryName()
+ {
return dictionary.getString(COSName.REGISTRY_NAME);
}
-
- public void setRegistryName( String value )
- {
- dictionary.setString(COSName.REGISTRY_NAME, value);
- }
-
- private PDStream configureOutputProfile (PDDocument doc, InputStream colorProfile) throws IOException {
- PDStream stream = new PDStream(doc,colorProfile, false);
- stream.getStream().setFilters(COSName.FLATE_DECODE);
- stream.getStream().setInt( COSName.LENGTH, stream.getByteArray().length );
- stream.getStream().setInt(COSName.N, 3);
- stream.addCompression();
+
+ public void setRegistryName(String value)
+ {
+ dictionary.setString(COSName.REGISTRY_NAME, value);
+ }
+
+ private PDStream configureOutputProfile(PDDocument doc, InputStream colorProfile)
+ throws IOException
+ {
+ PDStream stream = new PDStream(doc, colorProfile, false);
+ stream.getStream().setFilters(COSName.FLATE_DECODE);
+ stream.getStream().setInt(COSName.LENGTH, stream.getByteArray().length);
+ stream.getStream().setInt(COSName.N, 3);
+ stream.addCompression();
return stream;
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java?rev=1570086&r1=1570085&r2=1570086&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java Thu Feb 20 06:31:01 2014
@@ -16,93 +16,166 @@
*/
package org.apache.pdfbox.pdmodel.graphics.color;
-import org.apache.pdfbox.cos.COSArray;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.graphics.pattern.PDPatternResources;
+import org.apache.pdfbox.pdmodel.graphics.pattern.PDShadingPatternResources;
+import org.apache.pdfbox.pdmodel.graphics.pattern.PDTilingPatternResources;
+import org.apache.pdfbox.pdmodel.graphics.pattern.tiling.ColoredTilingPaint;
+import org.apache.pdfbox.pdmodel.graphics.shading.AxialShadingPaint;
+import org.apache.pdfbox.pdmodel.graphics.shading.PDShadingResources;
+import org.apache.pdfbox.pdmodel.graphics.shading.PDShadingType1;
+import org.apache.pdfbox.pdmodel.graphics.shading.PDShadingType2;
+import org.apache.pdfbox.pdmodel.graphics.shading.PDShadingType3;
+import org.apache.pdfbox.pdmodel.graphics.shading.PDShadingType4;
+import org.apache.pdfbox.pdmodel.graphics.shading.PDShadingType5;
+import org.apache.pdfbox.pdmodel.graphics.shading.RadialShadingPaint;
+import org.apache.pdfbox.pdmodel.graphics.shading.Type1ShadingPaint;
+import org.apache.pdfbox.pdmodel.graphics.shading.Type4ShadingPaint;
+import org.apache.pdfbox.pdmodel.graphics.shading.Type5ShadingPaint;
+
+import java.awt.Color;
+import java.awt.Paint;
+import java.awt.image.BufferedImage;
-import java.awt.color.ColorSpace;
-import java.awt.image.ColorModel;
-
+import java.awt.image.WritableRaster;
import java.io.IOException;
+import java.util.Map;
/**
- * This class represents a Pattern color space.
+ * A Pattern color space is either a Tiling pattern or a Shading pattern.
*
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.4 $
+ * @author John Hewson
+ * @author Ben Litchfield
*/
-public class PDPattern extends PDColorSpace
+public final class PDPattern extends PDSpecialColorSpace
{
- private COSArray array;
+ private static final Log LOG = LogFactory.getLog(PDPattern.class);
- /**
- * The name of this color space.
- */
- public static final String NAME = "Pattern";
+ private Map<String, PDPatternResources> patterns;
/**
- * Default constructor.
+ * Creates a new Pattern color space.
*/
- public PDPattern()
+ public PDPattern(Map<String, PDPatternResources> patterns)
{
- array = new COSArray();
- array.add( COSName.PATTERN );
+ this.patterns = patterns;
}
- /**
- * Constructor.
- *
- * @param pattern The pattern array.
- */
- public PDPattern( COSArray pattern)
+ @Override
+ public String getName()
{
- array = pattern;
+ return COSName.PATTERN.getName();
}
- /**
- * This will return the name of the color space.
- *
- * @return The name of the color space.
- */
- public String getName()
+ @Override
+ public int getNumberOfComponents()
{
- return NAME;
+ throw new UnsupportedOperationException();
}
- /**
- * This will get the number of components that this color space is made up of.
- *
- * @return The number of components in this color space.
- *
- * @throws IOException If there is an error getting the number of color components.
- */
- public int getNumberOfComponents() throws IOException
+ @Override
+ public float[] getDefaultDecode()
{
- return -1;
+ throw new UnsupportedOperationException();
}
- /**
- * Create a Java colorspace for this colorspace.
- *
- * @return A color space that can be used for Java AWT operations.
- *
- * @throws IOException If there is an error creating the color space.
- */
- protected ColorSpace createColorSpace() throws IOException
+ @Override
+ public PDColor getInitialColor()
{
- throw new IOException( "Not implemented" );
+ return PDColor.EMPTY_PATTERN;
}
- /**
- * Create a Java color model for this colorspace.
- *
- * @param bpc The number of bits per component.
- *
- * @return A color model that can be used for Java AWT operations.
- *
- * @throws IOException If there is an error creating the color model.
- */
- public ColorModel createColorModel( int bpc ) throws IOException
+ @Override
+ public float[] toRGB(float[] value)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public BufferedImage toRGBImage(WritableRaster raster) throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Paint toPaint(PDColor color) throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Paint toPaint(PDColor color, int pageHeight) throws IOException
+ {
+ if (!patterns.containsKey(color.getPatternName()))
+ {
+ throw new IOException("pattern " + color.getPatternName() + " was not found");
+ }
+
+ PDPatternResources pattern = patterns.get(color.getPatternName());
+ if (pattern instanceof PDTilingPatternResources)
+ {
+ return toTilingPaint((PDTilingPatternResources)pattern, color);
+ }
+ else
+ {
+ return toShadingPaint((PDShadingPatternResources)pattern, pageHeight);
+ }
+ }
+
+ public Paint toTilingPaint(PDTilingPatternResources tilingPattern, PDColor color)
+ throws IOException
+ {
+ if (tilingPattern.getPatternType() == PDTilingPatternResources.COLORED_TILING_PATTERN)
+ {
+ // colored tiling pattern
+ // TODO we should be passing the color to ColoredTilingPaint
+ return new ColoredTilingPaint(tilingPattern);
+ }
+ else
+ {
+ // uncolored tiling pattern
+ // TODO ...
+ LOG.debug("Not implemented: uncoloured tiling patterns");
+ return new Color(0, 0, 0, 0); // transparent
+ }
+ }
+ public Paint toShadingPaint(PDShadingPatternResources shadingPattern, int pageHeight)
+ throws IOException
+ {
+ PDShadingResources shadingResources = shadingPattern.getShading();
+ int shadingType = shadingResources != null ? shadingResources.getShadingType() : 0;
+ switch (shadingType)
+ {
+ case PDShadingResources.SHADING_TYPE1:
+ return new Type1ShadingPaint((PDShadingType1)shadingResources,
+ shadingPattern.getMatrix(), pageHeight);
+ case PDShadingResources.SHADING_TYPE2:
+ return new AxialShadingPaint((PDShadingType2)shadingResources,
+ shadingPattern.getMatrix(), pageHeight);
+ case PDShadingResources.SHADING_TYPE3:
+ return new RadialShadingPaint((PDShadingType3)shadingResources,
+ shadingPattern.getMatrix(), pageHeight);
+ case PDShadingResources.SHADING_TYPE4:
+ return new Type4ShadingPaint((PDShadingType4)shadingResources,
+ shadingPattern.getMatrix(), pageHeight);
+ case PDShadingResources.SHADING_TYPE5:
+ return new Type5ShadingPaint((PDShadingType5)shadingResources,
+ shadingPattern.getMatrix(), pageHeight);
+ case PDShadingResources.SHADING_TYPE6:
+ case PDShadingResources.SHADING_TYPE7:
+ // TODO ...
+ LOG.debug("Not implemented, shading type: " + shadingType);
+ return new Color(0, 0, 0, 0); // transparent
+ default:
+ throw new IOException("Invalid shading type: " + shadingType);
+ }
+ }
+
+ @Override
+ public String toString()
{
- throw new IOException( "Not implemented" );
+ return "Pattern";
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDSeparation.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDSeparation.java?rev=1570086&r1=1570085&r2=1570086&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDSeparation.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDSeparation.java Thu Feb 20 06:31:01 2014
@@ -16,205 +16,185 @@
*/
package org.apache.pdfbox.pdmodel.graphics.color;
-import java.awt.color.ColorSpace;
-import java.awt.image.ColorModel;
+import java.awt.Point;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBuffer;
+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.COSBase;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.common.function.PDFunction;
/**
- * This class represents a Separation color space.
+ * A Separation color space used to specify either additional colorants or for isolating the
+ * control of individual colour components of a device colour space for a subtractive device.
+ * When such a space is the current colour space, the current colour shall be a single-component
+ * value, called a tint, that controls the given colorant or colour components only.
*
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.5 $
+ * @author Ben Litchfield
+ * @author John Hewson
*/
-public class PDSeparation extends PDColorSpace
+public class PDSeparation extends PDSpecialColorSpace
{
- /**
- * Log instance.
- */
- private static final Log log = LogFactory.getLog(PDSeparation.class);
+ private static final PDColor INITIAL_COLOR = new PDColor(new float[] { 1 });
- /**
- * The name of this color space.
- */
- public static final String NAME = "Separation";
+ // array indexes
+ private static final int COLORANT_NAMES = 1;
+ private static final int ALTERNATE_CS = 2;
+ private static final int TINT_TRANSFORM = 3;
+ // fields
+ private PDColorSpace alternateColorSpace = null;
+ private PDFunction tintTransform = null;
/**
- * Constructor.
+ * Creates a new Separation color space.
*/
public PDSeparation()
{
array = new COSArray();
- array.add( COSName.SEPARATION );
- array.add( COSName.getPDFName( "" ) );
+ array.add(COSName.SEPARATION);
+ array.add(COSName.getPDFName(""));
}
/**
- * Constructor.
- *
- * @param separation The array containing all separation information.
+ * Creates a new Separation color space from a PDF color space array.
+ * @param separation an array containing all separation information
*/
- public PDSeparation( COSArray separation )
+ public PDSeparation(COSArray separation) throws IOException
{
array = separation;
+ alternateColorSpace = PDColorSpace.create(array.getObject(ALTERNATE_CS));
+ tintTransform = PDFunction.create(array.getObject(TINT_TRANSFORM));
}
- /**
- * This will return the name of the color space. For a PDSeparation object
- * this will always return "Separation"
- *
- * @return The name of the color space.
- */
+ @Override
public String getName()
{
- return NAME;
+ return COSName.SEPARATION.getName();
}
- /**
- * This will get the number of components that this color space is made up of.
- *
- * @return The number of components in this color space.
- *
- * @throws IOException If there is an error getting the number of color components.
- */
- public int getNumberOfComponents() throws IOException
+ @Override
+ public int getNumberOfComponents()
{
- return getAlternateColorSpace().getNumberOfComponents();
+ return 1;
}
- /**
- * Create a Java colorspace for this colorspace.
- *
- * @return A color space that can be used for Java AWT operations.
- *
- * @throws IOException If there is an error creating the color space.
- */
- protected ColorSpace createColorSpace() throws IOException
+ @Override
+ public float[] getDefaultDecode()
{
- try
- {
- PDColorSpace alt = getAlternateColorSpace();
- return alt.getJavaColorSpace();
- }
- catch (IOException ioexception)
- {
- log.error(ioexception, ioexception);
+ return new float[] { 0, 1 };
+ }
- throw ioexception;
- }
- catch (Exception exception)
- {
- log.error(exception, exception);
- throw new IOException("Failed to Create ColorSpace");
- }
+ @Override
+ public PDColor getInitialColor()
+ {
+ return INITIAL_COLOR;
}
- /**
- * Create a Java color model for this colorspace.
- *
- * @param bpc The number of bits per component.
- *
- * @return A color model that can be used for Java AWT operations.
- *
- * @throws IOException If there is an error creating the color model.
- */
- public ColorModel createColorModel( int bpc ) throws IOException
+ @Override
+ public float[] toRGB(float[] value) throws IOException
{
- log.info("About to create ColorModel for " + getAlternateColorSpace().toString());
- return getAlternateColorSpace().createColorModel(bpc);
+ float[] altColor = tintTransform.eval(value);
+ return alternateColorSpace.toRGB(altColor);
}
- /**
- * This will get the separation name.
- *
- * @return The name in the separation.
- */
- public String getColorantName()
+ //
+ // WARNING: this method is performance sensitive, modify with care!
+ //
+ @Override
+ public BufferedImage toRGBImage(WritableRaster raster) throws IOException
{
- COSName name = (COSName)array.getObject( 1 );
- return name.getName();
+ // use the tint transform to convert the sample into
+ // the alternate color space (this is usually 1:many)
+ WritableRaster altRaster = Raster.createBandedRaster(DataBuffer.TYPE_BYTE,
+ raster.getWidth(), raster.getHeight(),
+ alternateColorSpace.getNumberOfComponents(),
+ new Point(0, 0));
+
+ int numAltComponents = alternateColorSpace.getNumberOfComponents();
+ int width = raster.getWidth();
+ int height = raster.getHeight();
+ float[] samples = new float[1];
+ int[] alt = new int[numAltComponents];
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ raster.getPixel(x, y, samples);
+ samples[0] /= 255; // 0..1
+
+ // TODO special colorants: None, All
+
+ float[] result = tintTransform.eval(samples);
+ for (int s = 0; s < numAltComponents; s++)
+ {
+ // scale to 0..255
+ alt[s] = (int)(result[s] * 255);
+ }
+
+ altRaster.setPixel(x, y, alt);
+ }
+ }
+
+ // convert the alternate color space to RGB
+ return alternateColorSpace.toRGBImage(altRaster);
}
/**
- * This will set the separation name.
- *
- * @param name The separation name.
+ * Returns the colorant name.
+ * @return the name of the colorant
*/
- public void setColorantName( String name )
+ public String getColorantName()
{
- array.set( 1, COSName.getPDFName( name ) );
+ COSName name = (COSName)array.getObject(COLORANT_NAMES);
+ return name.getName();
}
/**
- * This will get the alternate color space for this separation.
- *
- * @return The alternate color space.
- *
- * @throws IOException If there is an error getting the alternate color space.
+ * Sets the colorant name.
+ * @param name the name of the colorant
*/
- public PDColorSpace getAlternateColorSpace() throws IOException
+ public void setColorantName(String name)
{
- COSBase alternate = array.getObject( 2 );
- PDColorSpace cs = PDColorSpaceFactory.createColorSpace( alternate );
- return cs;
+ array.set(1, COSName.getPDFName(name));
}
/**
- * This will set the alternate color space.
- *
- * @param cs The alternate color space.
+ * Sets the alternate color space.
+ * @param colorSpace The alternate color space.
*/
- public void setAlternateColorSpace( PDColorSpace cs )
+ public void setAlternateColorSpace(PDColorSpace colorSpace)
{
+ alternateColorSpace = colorSpace;
COSBase space = null;
- if( cs != null )
+ if (colorSpace != null)
{
- space = cs.getCOSObject();
+ space = colorSpace.getCOSObject();
}
- array.set( 2, space );
+ array.set(ALTERNATE_CS, space);
}
/**
- * This will get the tint transform function.
- *
- * @return The tint transform function.
- *
- * @throws IOException If there is an error creating the PDFunction
+ * Sets the tint transform function.
+ * @param tint the tint transform function
*/
- public PDFunction getTintTransform() throws IOException
+ public void setTintTransform(PDFunction tint)
{
- return PDFunction.create( array.getObject( 3 ) );
+ tintTransform = tint;
+ array.set(TINT_TRANSFORM, tint);
}
- /**
- * This will set the tint transform function.
- *
- * @param tint The tint transform function.
- */
- public void setTintTransform( PDFunction tint )
- {
- array.set( 3, tint );
- }
-
- /**
- * Returns the components of the color in the alternate colorspace for the given tint value.
- * @param tintValue the tint value
- * @return COSArray with the color components
- * @throws IOException If the tint function is not supported
- */
- public COSArray calculateColorValues(COSBase tintValue) throws IOException
+ @Override
+ public String toString()
{
- PDFunction tintTransform = getTintTransform();
- COSArray tint = new COSArray();
- tint.add(tintValue);
- return tintTransform.eval(tint);
+ return getName() + "{" +
+ "\"" + getColorantName() + "\"" + " " +
+ alternateColorSpace.getName() + " " +
+ tintTransform + "}";
}
}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDSpecialColorSpace.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDSpecialColorSpace.java?rev=1570086&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDSpecialColorSpace.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDSpecialColorSpace.java Thu Feb 20 06:31:01 2014
@@ -0,0 +1,33 @@
+/*
+ * 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.color;
+
+import org.apache.pdfbox.cos.COSBase;
+
+/**
+ * Special colour spaces add features or properties to an underlying colour space.
+ *
+ * @author John Hewson
+ */
+public abstract class PDSpecialColorSpace extends PDColorSpace
+{
+ @Override
+ public COSBase getCOSObject()
+ {
+ return array;
+ }
+}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDTristimulus.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDTristimulus.java?rev=1570086&r1=1570085&r2=1570086&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDTristimulus.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDTristimulus.java Thu Feb 20 06:31:01 2014
@@ -24,55 +24,50 @@ import org.apache.pdfbox.cos.COSNumber;
import org.apache.pdfbox.pdmodel.common.COSObjectable;
/**
- * A tristimulus, or collection of three floating point parameters used for
- * color operations.
+ * A tristimulus, or collection of three floating point parameters used for color operations.
*
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.2 $
+ * @author Ben Litchfield
*/
-public class PDTristimulus implements COSObjectable
+public final class PDTristimulus implements COSObjectable
{
private COSArray values = null;
/**
- * Constructor. Defaults all values to 0, 0, 0.
+ * Constructor. Defaults all values to 0, 0, 0.
*/
public PDTristimulus()
{
values = new COSArray();
- values.add( new COSFloat( 0.0f ) );
- values.add( new COSFloat( 0.0f ) );
- values.add( new COSFloat( 0.0f ) );
+ values.add(new COSFloat(0.0f));
+ values.add(new COSFloat(0.0f));
+ values.add(new COSFloat(0.0f));
}
/**
* Constructor from COS object.
- *
- * @param array The array containing the XYZ values.
+ * @param array the array containing the XYZ values
*/
- public PDTristimulus( COSArray array )
+ public PDTristimulus(COSArray array)
{
values = array;
}
/**
* Constructor from COS object.
- *
- * @param array The array containing the XYZ values.
+ * @param array the array containing the XYZ values
*/
- public PDTristimulus( float[] array )
+ public PDTristimulus(float[] array)
{
values = new COSArray();
- for( int i=0; i<array.length && i<3; i++ )
+ for(int i=0; i<array.length && i<3; i++)
{
- values.add( new COSFloat( array[i] ) );
+ values.add(new COSFloat(array[i]));
}
}
/**
* Convert this standard java object to a COS object.
- *
- * @return The cos object that matches this Java object.
+ * @return the cos object that matches this Java object
*/
public COSBase getCOSObject()
{
@@ -80,62 +75,56 @@ public class PDTristimulus implements CO
}
/**
- * This will get the x value of the tristimulus.
- *
- * @return The X value.
+ * Returns the x value of the tristimulus.
+ * @return the X value
*/
public float getX()
{
- return ((COSNumber)values.get( 0 )).floatValue();
+ return ((COSNumber)values.get(0)).floatValue();
}
/**
- * This will set the x value of the tristimulus.
- *
- * @param x The x value for the tristimulus.
+ * Sets the x value of the tristimulus.
+ * @param x the x value for the tristimulus
*/
- public void setX( float x )
+ public void setX(float x)
{
- values.set( 0, new COSFloat( x ) );
+ values.set(0, new COSFloat(x));
}
/**
- * This will get the y value of the tristimulus.
- *
- * @return The Y value.
+ * Returns the y value of the tristimulus.
+ * @return the Y value
*/
public float getY()
{
- return ((COSNumber)values.get( 1 )).floatValue();
+ return ((COSNumber)values.get(1)).floatValue();
}
/**
- * This will set the y value of the tristimulus.
- *
- * @param y The y value for the tristimulus.
+ * Sets the y value of the tristimulus.
+ * @param y the y value for the tristimulus
*/
- public void setY( float y )
+ public void setY(float y)
{
- values.set( 1, new COSFloat( y ) );
+ values.set(1, new COSFloat(y));
}
/**
- * This will get the z value of the tristimulus.
- *
- * @return The Z value.
+ * Returns the z value of the tristimulus.
+ * @return the Z value
*/
public float getZ()
{
- return ((COSNumber)values.get( 2 )).floatValue();
+ return ((COSNumber)values.get(2)).floatValue();
}
/**
- * This will set the z value of the tristimulus.
- *
- * @param z The z value for the tristimulus.
+ * Sets the z value of the tristimulus.
+ * @param z the z value for the tristimulus
*/
- public void setZ( float z )
+ public void setZ(float z)
{
- values.set( 2, new COSFloat( z ) );
+ values.set(2, new COSFloat(z));
}
}
Copied: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDFormXObject.java (from r1568222, pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDXObjectForm.java)
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDFormXObject.java?p2=pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDFormXObject.java&p1=pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDXObjectForm.java&r1=1568222&r2=1570086&rev=1570086&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDXObjectForm.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDFormXObject.java Thu Feb 20 06:31:01 2014
@@ -14,60 +14,84 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.pdfbox.pdmodel.graphics.xobject;
+package org.apache.pdfbox.pdmodel.graphics.form;
import java.awt.geom.AffineTransform;
+import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.cos.COSArray;
+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.cos.COSNumber;
import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.graphics.PDXObject;
import org.apache.pdfbox.util.Matrix;
+/*
+TODO There are further Form XObjects to implement:
+
++ PDFormXObject
+|- PDReferenceXObject
+|- PDGroupXObject
+ |- PDTransparencyXObject
+
+See PDF 32000 p111
+
+When doing this all methods on PDFormXObject should probably be made
+final and all fields private.
+*/
+
/**
- * A form xobject.
- *
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
+ * A Form XObject.
*
+ * @author Ben Litchfield
*/
-public class PDXObjectForm extends PDXObject
+public final class PDFormXObject extends PDXObject
{
+ private static final Log LOG = LogFactory.getLog(PDFormXObject.class);
+
+ // name of XObject in resources, to prevent recursion
+ private String name;
/**
- * The XObject subtype.
+ * Creates a Form XObject for reading.
+ * @param stream The XObject stream
*/
- public static final String SUB_TYPE = "Form";
-
+ public PDFormXObject(PDStream stream)
+ {
+ super(stream, COSName.FORM);
+ }
+
/**
- * Standard constructor.
- *
- * @param formStream The XObject is passed as a COSStream.
+ * Creates a Form XObject for reading.
+ * @param stream The XObject stream
+ * @param name The name of the form XObject, to prevent recursion.
*/
- public PDXObjectForm(PDStream formStream)
+ public PDFormXObject(PDStream stream, String name)
{
- super(formStream);
- getCOSStream().setName(COSName.SUBTYPE, SUB_TYPE);
+ super(stream, COSName.FORM);
+ this.name = name;
}
/**
- * Standard constructor.
- *
- * @param formStream The XObject is passed as a COSStream.
+ * Creates a Form Image XObject for writing, in the given document.
+ * @param document The current document
*/
- public PDXObjectForm(COSStream formStream)
+ public PDFormXObject(PDDocument document)
{
- super(formStream);
- getCOSStream().setName(COSName.SUBTYPE, SUB_TYPE);
+ super(document, COSName.FORM);
}
-
+
/**
* This will get the form type, currently 1 is the only form type.
- *
* @return The form type.
*/
public int getFormType()
@@ -77,7 +101,6 @@ public class PDXObjectForm extends PDXOb
/**
* Set the form type.
- *
* @param formType The new form type.
*/
public void setFormType(int formType)
@@ -86,9 +109,9 @@ public class PDXObjectForm extends PDXOb
}
/**
- * This will get the resources at this page and not look up the hierarchy. This attribute is inheritable, and
- * findResources() should probably used. This will return null if no resources are available at this level.
- *
+ * This will get the resources at this page and not look up the hierarchy.
+ * This attribute is inheritable, and findResources() should probably used.
+ * This will return null if no resources are available at this level.
* @return The resources at this level in the hierarchy.
*/
public PDResources getResources()
@@ -98,13 +121,32 @@ public class PDXObjectForm extends PDXOb
if (resources != null)
{
retval = new PDResources(resources);
+ // check for a recursion, see PDFBOX-1813
+ if (name != null)
+ {
+ Map<String, PDXObject> xobjects = retval.getXObjects();
+ if (xobjects != null && xobjects.containsKey(name))
+ {
+ PDXObject xobject = xobjects.get(name);
+ if (xobject instanceof PDFormXObject)
+ {
+ int length1 = getCOSStream().getInt(COSName.LENGTH);
+ int length2 = xobject.getCOSStream().getInt(COSName.LENGTH);
+ // seems to be the same object
+ if (length1 == length2)
+ {
+ retval.removeXObject(name);
+ LOG.debug("Removed XObjectForm "+name+" to avoid a recursion");
+ }
+ }
+ }
+ }
}
return retval;
}
/**
* This will set the resources for this page.
- *
* @param resources The new resources for this page.
*/
public void setResources(PDResources resources)
@@ -113,10 +155,10 @@ public class PDXObjectForm extends PDXOb
}
/**
- * An array of four numbers in the form coordinate system (see below), giving the coordinates of the left, bottom,
- * right, and top edges, respectively, of the form XObject's bounding box. These boundaries are used to clip the
- * form XObject and to determine its size for caching.
- *
+ * An array of four numbers in the form coordinate system (see below),
+ * giving the coordinates of the left, bottom, right, and top edges, respectively,
+ * of the form XObject's bounding box.
+ * These boundaries are used to clip the form XObject and to determine its size for caching.
* @return The BBox of the form.
*/
public PDRectangle getBBox()
@@ -132,7 +174,6 @@ public class PDXObjectForm extends PDXOb
/**
* This will set the BBox (bounding box) for this form.
- *
* @param bbox The new BBox for this form.
*/
public void setBBox(PDRectangle bbox)
@@ -149,7 +190,6 @@ public class PDXObjectForm extends PDXOb
/**
* This will get the optional Matrix of an XObjectForm. It maps the form space into the user space
- *
* @return the form matrix
*/
public Matrix getMatrix()
@@ -171,7 +211,6 @@ public class PDXObjectForm extends PDXOb
/**
* Sets the optional Matrix entry for the form XObject.
- *
* @param transform the transformation matrix
*/
public void setMatrix(AffineTransform transform)
@@ -187,9 +226,9 @@ public class PDXObjectForm extends PDXOb
}
/**
- * This will get the key of this XObjectForm in the structural parent tree. Required if the form XObject contains
- * marked-content sequences that are structural content items.
- *
+ * This will get the key of this XObjectForm in the structural parent tree.
+ * Required if the form XObject contains marked-content sequences that are
+ * structural content items.
* @return the integer key of the XObjectForm's entry in the structural parent tree
*/
public int getStructParents()
@@ -199,12 +238,10 @@ public class PDXObjectForm extends PDXOb
/**
* This will set the key for this XObjectForm in the structural parent tree.
- *
* @param structParent The new key for this XObjectForm.
*/
public void setStructParents(int structParent)
{
getCOSStream().setInt(COSName.STRUCT_PARENTS, structParent);
}
-
}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/package.html
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/package.html?rev=1570086&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/package.html (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/package.html Thu Feb 20 06:31:01 2014
@@ -0,0 +1,25 @@
+<!--
+ ! 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.
+ !-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+
+</head>
+<body>
+This package deals with Form XObjects that are stored in a PDF document.
+</body>
+</html>
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/CCITTFactory.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/CCITTFactory.java?rev=1570086&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/CCITTFactory.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/CCITTFactory.java Thu Feb 20 06:31:01 2014
@@ -0,0 +1,273 @@
+/*
+ * 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.image;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.io.RandomAccess;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceGray;
+
+/**
+ * Factory for creating a PDImageXObject containing a CCITT Fax compressed TIFF image.
+ * @author Ben Litchfield
+ * @author Paul King
+ */
+public final class CCITTFactory
+{
+ private CCITTFactory()
+ {
+ }
+
+ /**
+ * Creates a new CCITT Fax compressed Image XObject from a TIFF file.
+ * @param document the document to create the image as part of.
+ * @param reader the random access TIFF file which contains a suitable CCITT compressed image
+ * @throws IOException if there is an error reading the TIFF data.
+ */
+ public static PDImageXObject createFromRandomAccess(PDDocument document, RandomAccess reader)
+ throws IOException
+ {
+ PDImageXObject pdImage = new PDImageXObject(document);
+
+ COSDictionary decodeParms = new COSDictionary();
+ COSDictionary dict = pdImage.getCOSStream();
+ extractFromTiff(reader, pdImage.getCOSStream().createFilteredStream(), decodeParms);
+
+ dict.setItem(COSName.FILTER, COSName.CCITTFAX_DECODE);
+ dict.setItem(COSName.SUBTYPE, COSName.IMAGE);
+ dict.setItem(COSName.TYPE, COSName.XOBJECT);
+ dict.setItem(COSName.DECODE_PARMS, decodeParms);
+
+ pdImage.setBitsPerComponent(1);
+ pdImage.setColorSpace(PDDeviceGray.INSTANCE);
+ pdImage.setWidth(decodeParms.getInt(COSName.COLUMNS));
+ pdImage.setHeight(decodeParms.getInt(COSName.ROWS));
+
+ return pdImage;
+ }
+
+ // extracts the CCITT stream from the TIFF file
+ private static void extractFromTiff(RandomAccess reader, OutputStream os, COSDictionary params)
+ throws IOException
+ {
+ try
+ {
+ // First check the basic tiff header
+ reader.seek(0);
+ char endianess = (char) reader.read();
+ if ((char) reader.read() != endianess)
+ {
+ throw new IOException("Not a valid tiff file");
+ }
+ // ensure that endianess is either M or I
+ if (endianess != 'M' && endianess != 'I')
+ {
+ throw new IOException("Not a valid tiff file");
+ }
+ int magicNumber = readshort(endianess, reader);
+ if (magicNumber != 42)
+ {
+ throw new IOException("Not a valid tiff file");
+ }
+
+ // Relocate to the first set of tags
+ reader.seek(readlong(endianess, reader));
+
+ int numtags = readshort(endianess, reader);
+
+ // The number 50 is somewhat arbitary, it just stops us load up junk from somewhere
+ // and tramping on
+ if (numtags > 50)
+ {
+ throw new IOException("Not a valid tiff file");
+ }
+
+ // Loop through the tags, some will convert to items in the parms dictionary
+ // Other point us to where to find the data stream
+ // The only parm which might change as a result of other options is K, so
+ // We'll deal with that as a special;
+
+ int k = -1000; // Default Non CCITT compression
+ int dataoffset = 0;
+ int datalength = 0;
+
+ for (int i = 0; i < numtags; i++)
+ {
+ int tag = readshort(endianess, reader);
+ int type = readshort(endianess, reader);
+ int count = readlong(endianess, reader);
+ int val = readlong(endianess, reader); // See note
+
+ // Note, we treated that value as a long. The value always occupies 4 bytes
+ // But it might only use the first byte or two. Depending on endianess we might
+ // need to correct.
+ // Note we ignore all other types, they are of little interest for PDFs/CCITT Fax
+ if (endianess == 'M')
+ {
+ switch (type)
+ {
+ case 1:
+ {
+ val = val >> 24;
+ break; // byte value
+ }
+ case 3:
+ {
+ val = val >> 16;
+ break; // short value
+ }
+ case 4:
+ {
+ break; // long value
+ }
+ default:
+ {
+ // do nothing
+ }
+ }
+ }
+ switch (tag)
+ {
+ case 256:
+ {
+ params.setInt(COSName.COLUMNS, val);
+ break;
+ }
+ case 257:
+ {
+ params.setInt(COSName.ROWS, val);
+ break;
+ }
+ case 259:
+ {
+ if (val == 4)
+ {
+ k = -1;
+ }
+ if (val == 3)
+ {
+ k = 0;
+ }
+ break; // T6/T4 Compression
+ }
+ case 262:
+ {
+ if (val == 1)
+ {
+ params.setBoolean(COSName.BLACK_IS_1, true);
+ }
+ break;
+ }
+ case 273:
+ {
+ if (count == 1)
+ {
+ dataoffset = val;
+ }
+ break;
+ }
+ case 279:
+ {
+ if (count == 1)
+ {
+ datalength = val;
+ }
+ break;
+ }
+ case 292:
+ {
+ if (val == 1)
+ {
+ k = 50; // T4 2D - arbitary K value
+ }
+ break;
+ }
+ case 324:
+ {
+ if (count == 1)
+ {
+ dataoffset = val;
+ }
+ break;
+ }
+ case 325:
+ {
+ if (count == 1)
+ {
+ datalength = val;
+ }
+ break;
+ }
+ default:
+ {
+ // do nothing
+ }
+ }
+ }
+
+ if (k == -1000)
+ {
+ throw new IOException("First image in tiff is not CCITT T4 or T6 compressed");
+ }
+ if (dataoffset == 0)
+ {
+ throw new IOException("First image in tiff is not a single tile/strip");
+ }
+
+ params.setInt(COSName.K, k);
+
+ reader.seek(dataoffset);
+
+ byte[] buf = new byte[8192];
+ int amountRead = -1;
+ while ((amountRead = reader.read(buf, 0, Math.min(8192, datalength))) > 0)
+ {
+ datalength -= amountRead;
+ os.write(buf, 0, amountRead);
+ }
+
+ }
+ finally
+ {
+ os.close();
+ }
+ }
+
+ private static int readshort(char endianess, RandomAccess raf) throws IOException
+ {
+ if (endianess == 'I')
+ {
+ return raf.read() | (raf.read() << 8);
+ }
+ return (raf.read() << 8) | raf.read();
+ }
+
+ private static int readlong(char endianess, RandomAccess raf) throws IOException
+ {
+ if (endianess == 'I')
+ {
+ return raf.read() | (raf.read() << 8) | (raf.read() << 16) | (raf.read() << 24);
+ }
+ return (raf.read() << 24) | (raf.read() << 16) | (raf.read() << 8) | raf.read();
+ }
+}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/ImageFactory.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/ImageFactory.java?rev=1570086&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/ImageFactory.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/ImageFactory.java Thu Feb 20 06:31:01 2014
@@ -0,0 +1,114 @@
+/*
+ * 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.image;
+
+import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceCMYK;
+import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceGray;
+import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
+
+import java.awt.AlphaComposite;
+import java.awt.Graphics2D;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.WritableRaster;
+
+/**
+ * An image factory.
+ *
+ * @author John Hewson
+ * @author Brigitte Mathiak
+ */
+class ImageFactory
+{
+ protected ImageFactory()
+ {
+ }
+
+ // sets Image XObject properties from an AWT buffered image
+ protected static void setPropertiesFromAWT(BufferedImage awtImage, PDImageXObject pdImage)
+ {
+ pdImage.setColorSpace(toPDColorSpace(awtImage.getColorModel().getColorSpace()));
+ pdImage.setBitsPerComponent(awtImage.getColorModel().getComponentSize(0));
+ pdImage.setHeight(awtImage.getHeight());
+ pdImage.setWidth(awtImage.getWidth());
+ }
+
+ // returns a PDColorSpace for a given AWT ColorSpace
+ protected static PDColorSpace toPDColorSpace(ColorSpace awtColorSpace)
+ {
+ if (awtColorSpace instanceof ICC_ColorSpace)
+ {
+ throw new UnsupportedOperationException("ICC color spaces not implemented");
+ }
+ else
+ {
+ switch (awtColorSpace.getType())
+ {
+ case ColorSpace.TYPE_RGB: return PDDeviceRGB.INSTANCE;
+ case ColorSpace.TYPE_GRAY: return PDDeviceGray.INSTANCE;
+ case ColorSpace.TYPE_CMYK: return PDDeviceCMYK.INSTANCE;
+ default: throw new UnsupportedOperationException("color space not implemented: " +
+ awtColorSpace.getType());
+ }
+ }
+ }
+
+ // returns the alpha channel of an image
+ protected static BufferedImage getAlphaImage(BufferedImage image)
+ {
+ if (!image.getColorModel().hasAlpha())
+ {
+ return null;
+ }
+
+ // extract the alpha information
+ WritableRaster alphaRaster = image.getAlphaRaster();
+ ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY),
+ false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
+ return new BufferedImage(cm, alphaRaster, false, null);
+ }
+
+ // returns the color channels of an image
+ protected static BufferedImage getColorImage(BufferedImage image)
+ {
+ if (!image.getColorModel().hasAlpha())
+ {
+ return image;
+ }
+
+ if (image.getColorModel().getColorSpace().getType() != ColorSpace.TYPE_RGB)
+ {
+ throw new UnsupportedOperationException("only RGB color spaces are implemented");
+ }
+
+ // create an RGB image without alpha
+ BufferedImage rgbImage = new BufferedImage(image.getWidth(), image.getHeight(),
+ BufferedImage.TYPE_INT_RGB);
+
+ Graphics2D g = rgbImage.createGraphics();
+ g.setComposite(AlphaComposite.Src);
+ g.drawImage(image, 0, 0, null);
+
+ return rgbImage;
+ }
+}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/JPEGFactory.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/JPEGFactory.java?rev=1570086&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/JPEGFactory.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/JPEGFactory.java Thu Feb 20 06:31:01 2014
@@ -0,0 +1,196 @@
+/*
+ * 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.image;
+
+import java.awt.image.BufferedImage;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.io.IOUtils;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.util.ImageIOUtil;
+import org.w3c.dom.Element;
+
+import javax.imageio.IIOImage;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.ImageWriter;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
+import javax.imageio.stream.ImageOutputStream;
+
+/**
+ * Factory for creating a PDImageXObject containing a JPEG compressed image.
+ * @author John Hewson
+ */
+public final class JPEGFactory extends ImageFactory
+{
+ private JPEGFactory()
+ {
+ }
+
+ /**
+ * Creates a new JPEG Image XObject from an input stream containing JPEG data.
+ * The input stream data will be preserved and embedded in the PDF file without modification.
+ * @param document the document where the image will be created
+ * @param stream a stream of JPEG data
+ * @return a new Image XObject
+ * @throws IOException if the input stream cannot be read
+ */
+ public static PDImageXObject createFromStream(PDDocument document, InputStream stream)
+ throws IOException
+ {
+ // create Image XObject from stream
+ PDImageXObject pdImage = new PDImageXObject(new PDStream(document, stream, true), null);
+
+ // add DCT filter
+ pdImage.getCOSStream().setItem(COSName.FILTER, COSName.DCT_DECODE);
+
+ // read image
+ ImageIO.setUseCache(false);
+ BufferedImage awtImage = ImageIO.read(stream);
+
+ // no alpha
+ if (awtImage.getColorModel().hasAlpha())
+ {
+ throw new UnsupportedOperationException("alpha channel not implemented");
+ }
+
+ // set properties (width, height, depth, color space, etc.)
+ setPropertiesFromAWT(awtImage, pdImage);
+
+ return pdImage;
+ }
+
+ /**
+ * Creates a new JPEG Image XObject from a Buffered Image.
+ * @param document the document where the image will be created
+ * @param image the buffered image to embed
+ * @return a new Image XObject
+ * @throws IOException if the JPEG data cannot be written
+ */
+ public static PDImageXObject createFromImage(PDDocument document, BufferedImage image)
+ throws IOException
+ {
+ return createFromImage(document, image, 0.75f);
+ }
+
+ /**
+ * Creates a new JPEG Image XObject from a Buffered Image and a given quality.
+ * @param document the document where the image will be created
+ * @param image the buffered image to embed
+ * @param quality the desired JPEG compression quality
+ * @return a new Image XObject
+ * @throws IOException if the JPEG data cannot be written
+ */
+ public static PDImageXObject createFromImage(PDDocument document, BufferedImage image,
+ float quality) throws IOException
+ {
+ return createFromImage(document, image, quality, ImageIOUtil.DEFAULT_SCREEN_RESOLUTION);
+ }
+
+ /**
+ * Creates a new JPEG Image XObject from a Buffered Image, a given quality and DPI.
+ * @param document the document where the image will be created
+ * @param image the buffered image to embed
+ * @param quality the desired JPEG compression quality
+ * @param dpi the desired DPI (resolution) of the JPEG
+ * @return a new Image XObject
+ * @throws IOException if the JPEG data cannot be written
+ */
+ public static PDImageXObject createFromImage(PDDocument document, BufferedImage image,
+ float quality, int dpi) throws IOException
+ {
+ return createJPEG(document, image, quality, dpi);
+ }
+
+ // Creates an Image XObject from a Buffered Image using JAI Image I/O
+ private static PDImageXObject createJPEG(PDDocument document, BufferedImage image,
+ float quality, int dpi) throws IOException
+ {
+ // extract alpha channel (if any)
+ BufferedImage awtColor = getColorImage(image);
+ BufferedImage awtAlpha = getAlphaImage(image);
+
+ // create XObject
+ PDImageXObject pdImage = new PDImageXObject(new PDStream(document), null);
+
+ // add DCT filter
+ COSDictionary dict = pdImage.getCOSStream();
+ pdImage.getCOSStream().setItem(COSName.FILTER, COSName.DCT_DECODE);
+
+ // alpha -> soft mask
+ if (awtAlpha != null)
+ {
+ PDImage xAlpha = JPEGFactory.createFromImage(document, awtAlpha, quality);
+ dict.setItem(COSName.SMASK, xAlpha);
+ }
+
+ // set properties (width, height, depth, color space, etc.)
+ setPropertiesFromAWT(awtColor, pdImage);
+
+ // encode to JPEG
+ OutputStream out = null;
+ ImageOutputStream ios = null;
+ ImageWriter imageWriter = null;
+ try
+ {
+ out = pdImage.getCOSStream().createFilteredStream();
+
+ // find JAI writer
+ imageWriter = ImageIO.getImageWritersBySuffix("jpeg").next();
+ ios = ImageIO.createImageOutputStream(out);
+ imageWriter.setOutput(ios);
+
+ // add compression
+ JPEGImageWriteParam jpegParam = (JPEGImageWriteParam)imageWriter.getDefaultWriteParam();
+ jpegParam.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
+ jpegParam.setCompressionQuality(quality);
+
+ // add metadata
+ ImageTypeSpecifier imageTypeSpecifier = new ImageTypeSpecifier(image);
+ IIOMetadata data = imageWriter.getDefaultImageMetadata(imageTypeSpecifier, jpegParam);
+ Element tree = (Element)data.getAsTree("javax_imageio_jpeg_image_1.0");
+ Element jfif = (Element)tree.getElementsByTagName("app0JFIF").item(0);
+ jfif.setAttribute("Xdensity", Integer.toString(dpi));
+ jfif.setAttribute("Ydensity", Integer.toString(dpi));
+ jfif.setAttribute("resUnits", "1"); // 1 = dots/inch
+
+ // write
+ imageWriter.write(data, new IIOImage(image, null, null), jpegParam);
+ }
+ finally
+ {
+ // clean up
+ IOUtils.closeQuietly(out);
+ if (ios != null)
+ {
+ ios.close();
+ }
+ if (imageWriter != null)
+ {
+ imageWriter.dispose();
+ }
+ }
+
+ return pdImage;
+ }
+}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImage.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImage.java?rev=1570086&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImage.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImage.java Thu Feb 20 06:31:01 2014
@@ -0,0 +1,130 @@
+/*
+ * 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.image;
+
+import java.awt.Paint;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.pdmodel.common.COSObjectable;
+import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
+
+/**
+ * An image in a PDF document.
+ * @author John Hewson
+ */
+public interface PDImage extends COSObjectable
+{
+ /**
+ * Returns the content of this image as an AWT buffered image with an (A)RGB color space.
+ * @return content of this image as a buffered image.
+ * @throws IOException
+ */
+ public BufferedImage getImage() throws IOException;
+
+ /**
+ * Returns an ARGB image filled with the given paint and using this image as a mask.
+ * @param paint the paint to fill the visible portions of the image with
+ * @return a masked image filled with the given paint
+ * @throws IOException if the image cannot be read
+ * @throws IllegalStateException if the image is not a stencil.
+ */
+ public BufferedImage getStencilImage(Paint paint) throws IOException;
+
+ /**
+ * Returns a stream containing this image's data.
+ * @return stream containing the image data
+ * @throws IOException if the
+ */
+ public PDStream getStream() throws IOException;
+
+ /**
+ * Returns true if the image is a stencil mask.
+ * @return true if the image is a stencil mask.
+ */
+ public boolean isStencil();
+
+ /**
+ * Sets whether or not the image is a stencil.
+ * This corresponds to the {@code ImageMask} entry in the image stream's dictionary.
+ * @param isStencil True to make the image a stencil.
+ */
+ public void setStencil(boolean isStencil);
+
+ /**
+ * Returns bits per component of this image, or -1 if one has not been set.
+ * @return The number of bits per component.
+ */
+ public int getBitsPerComponent();
+
+ /**
+ * Set the number of bits per component.
+ * @param bitsPerComponent The number of bits per component.
+ */
+ public void setBitsPerComponent(int bitsPerComponent);
+
+ /**
+ * Returns the image's color space
+ * @return The color space for this image.
+ * @throws IOException If there is an error getting the color space.
+ */
+ public PDColorSpace getColorSpace() throws IOException;
+
+ /**
+ * Sets the color space for this image.
+ * @param colorSpace The color space for this image.
+ */
+ public void setColorSpace(PDColorSpace colorSpace);
+
+ /**
+ * Returns height of this image, or -1 if one has not been set.
+ * @return The height.
+ */
+ public int getHeight();
+
+ /**
+ * Sets the height of the image.
+ * @param height The height of the image.
+ */
+ public void setHeight(int height);
+
+ /**
+ * Returns the width of this image, or -1 if one has not been set.
+ * @return The width.
+ */
+ public int getWidth();
+
+ /**
+ * Sets the width of the image.
+ * @param width The width of the image.
+ */
+ public void setWidth(int width);
+
+ /**
+ * Sets the decode array.
+ * @param decode the new decode array.
+ */
+ public void setDecode(COSArray decode);
+
+ /**
+ * Returns the decode array.
+ * @return the decode array.
+ */
+ public COSArray getDecode();
+}