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.