PdfBox - PDColorSpaceFactory.createColorSpace(document, iccColorSpace) throws nullpointerexception

匿名 (未验证) 提交于 2019-12-03 02:33:02

问题:

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.

回答1:

Ok, this seems to be a bug with the first constructor. You could use the second constructor, which uses a COSArray:

The PDF spec explains what to do:

"An ICCBased colour space shall be an array: [/ICCBased stream]"

So you need to create a COSArray, with COSName.ICCBASED as first element, and a COSStream with your ICC data in the second. Create a COSStream and write to it with createFilteredStream(). That COSArray you can use for the second constructor.

Alternatively, just use PDDeviceCMYK.INSTANCE as the colorspace :-)

Update: I have opened issue PDFBOX-2812 and it has been fixed. You can get a snapshot in a few hours here.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!