I'm trying to create a PDF which has a single image on a single page. The tricky part is to use a custom (defined in a separate file) CMYK color space.
I've tried to call
PDColorSpaceFactory.createColorSpace(document, iccColorSpace)
but keep getting nullpointerexception. I've managed to track the issue up to the constructor:
public PDICCBased( PDDocument doc )
{
array = new COSArray();
array.add( COSName.ICCBASED );
array.add( new PDStream( doc ) );
}
The PDICCBased object has stream field and it's obviously not set. Thus when it's called at:
public static PDColorSpace createColorSpace( PDDocument doc, ColorSpace cs ) throws IOException
{
PDColorSpace retval = null;
if( cs.isCS_sRGB() )
{
retval = PDDeviceRGB.INSTANCE;
}
else if( cs instanceof ICC_ColorSpace )
{
ICC_ColorSpace ics = (ICC_ColorSpace)cs;
PDICCBased pdCS = new PDICCBased( doc );
retval = pdCS;
COSArray ranges = new COSArray();
for( int i=0; i<cs.getNumComponents(); i++ )
{
ranges.add( new COSFloat( ics.getMinValue( i ) ) );
ranges.add( new COSFloat( ics.getMaxValue( i ) ) );
}
PDStream iccData = pdCS.getPDStream();
OutputStream output = null;
try
{
output = iccData.createOutputStream(); <<<<<<<<<-------------
output.write( ics.getProfile().getData() );
}
finally
{
if( output != null )
{
output.close();
}
}
pdCS.setNumberOfComponents( cs.getNumComponents() );
}
else
{
throw new IOException( "Not yet implemented:" + cs );
}
return retval;
}
A NullPointerException is thrown.
Am I missing something? Is there another\ better way to create PDF usinf CMYK color space?
Updated createColorSpace:
public static PDColorSpace createColorSpace( PDDocument doc, ColorSpace cs ) throws IOException
{
PDColorSpace retval = null;
if( cs.isCS_sRGB() )
{
retval = PDDeviceRGB.INSTANCE;
}
else if( cs instanceof ICC_ColorSpace )
{
ICC_ColorSpace ics = (ICC_ColorSpace)cs;
// CREATING MANUALLY THE COS ARR ****************************
COSArray cosArray = new COSArray();
cosArray.add(COSName.ICCBASED);
PDStream pdStream = new PDStream(doc);
cosArray.add(pdStream.getStream());
// USING DIFFERENT CONSTRUTOR *******************************
PDICCBased pdCS = new PDICCBased( cosArray );
retval = pdCS;
COSArray ranges = new COSArray();
for( int i=0; i<cs.getNumComponents(); i++ )
{
ranges.add( new COSFloat( ics.getMinValue( i ) ) );
ranges.add( new COSFloat( ics.getMaxValue( i ) ) );
}
PDStream iccData = pdCS.getPDStream();
OutputStream output = null;
try
{
output = ((COSStream)iccData.getCOSObject()).createFilteredStream();
output.write( ics.getProfile().getData() );
}
finally
{
if( output != null )
{
output.close();
}
}
pdCS.setNumberOfComponents( cs.getNumComponents() );
}
else
{
throw new IOException( "Not yet implemented:" + cs );
}
return retval;
}
That did the trick from creating the colorSpace.
The creation of ColorSpace from a custom icc and applying it to a given image:
ICC_ColorSpace iccColorSpace = new ICC_ColorSpace(ICC_Profile.getInstance("C:\\...\\USWebCoatedSWOP.icc"));
ColorConvertOp op = new ColorConvertOp(image.getColorModel().getColorSpace(), iccColorSpace, null);
image = op.filter(image, null);
The creation of the PDF:
PDDocument document = new PDDocument();
PDColorSpace colorSpace = createColorSpace(document, iccColorSpace);
PDPage blankPage = new PDPage(new PDRectangle(100, 100));
document.addPage(blankPage);
PDPageContentStream pdPageContentStream = new PDPageContentStream(document, blankPage);
PDXObjectImage pdxObjectImage = new PDPixelMap(document, image);
pdxObjectImage.setColorSpace(colorSpace);
pdPageContentStream.drawXObject(pdxObjectImage, 0, 0, imagePostScriptWidth, imagePostScriptHeight);
pdPageContentStream.close();
document.save(byteArrayOutputStream);
document.close();
Hope this helps.