2020package org .apache .xmlgraphics .image .loader .impl .imageio ;
2121
2222import java .awt .Color ;
23+ import java .awt .Graphics2D ;
24+ import java .awt .color .ColorSpace ;
2325import java .awt .color .ICC_ColorSpace ;
2426import java .awt .color .ICC_Profile ;
2527import java .awt .image .BufferedImage ;
28+ import java .awt .image .ColorConvertOp ;
2629import java .awt .image .ColorModel ;
2730import java .awt .image .ComponentColorModel ;
2831import java .awt .image .IndexColorModel ;
2932import java .awt .image .Raster ;
3033import java .awt .image .RenderedImage ;
3134import java .awt .image .WritableRaster ;
3235import java .io .ByteArrayOutputStream ;
36+ import java .io .FileNotFoundException ;
3337import java .io .IOException ;
3438import java .util .HashSet ;
3539import java .util .Iterator ;
5761import org .apache .commons .logging .Log ;
5862import org .apache .commons .logging .LogFactory ;
5963
64+ import org .apache .xmlgraphics .image .codec .util .ImageInputStreamSeekableStreamAdapter ;
6065import org .apache .xmlgraphics .image .loader .Image ;
6166import org .apache .xmlgraphics .image .loader .ImageException ;
6267import org .apache .xmlgraphics .image .loader .ImageFlavor ;
@@ -80,8 +85,8 @@ public class ImageLoaderImageIO extends AbstractImageLoader {
8085 private ImageFlavor targetFlavor ;
8186
8287 private static final String PNG_METADATA_NODE = "javax_imageio_png_1.0" ;
83-
8488 private static final String JPEG_METADATA_NODE = "javax_imageio_jpeg_image_1.0" ;
89+ public static final String ICC_CONVERTER = "icc-converter" ;
8590
8691 private static final Set PROVIDERS_IGNORING_ICC = new HashSet ();
8792
@@ -247,12 +252,44 @@ public Image loadImage(ImageInfo info, Map<String, Object> hints, ImageSessionCo
247252 }
248253
249254 if (ImageFlavor .BUFFERED_IMAGE .equals (this .targetFlavor )) {
255+ imageData = rgbToCmyk ((BufferedImage ) imageData , info , session );
250256 return new ImageBuffered (info , (BufferedImage )imageData , transparentColor );
251257 } else {
252258 return new ImageRendered (info , imageData , transparentColor );
253259 }
254260 }
255261
262+ /**
263+ * Convert RGB to CMYK using ICC file passed via fop.xconf
264+ */
265+ private BufferedImage rgbToCmyk (BufferedImage image , ImageInfo info , ImageSessionContext session )
266+ throws IOException {
267+ String iccUri = (String ) info .getCustomObjects ().get (ICC_CONVERTER );
268+ if (iccUri != null && image .getColorModel ().getNumColorComponents () < 4 ) {
269+ if (image .getType () != BufferedImage .TYPE_INT_RGB ) {
270+ BufferedImage rgbImage =
271+ new BufferedImage (image .getWidth (), image .getHeight (), BufferedImage .TYPE_INT_RGB );
272+ Graphics2D g = (Graphics2D ) rgbImage .getGraphics ();
273+ g .setBackground (Color .WHITE );
274+ g .clearRect (0 , 0 , image .getWidth (), image .getHeight ());
275+ g .drawImage (image , 0 , 0 , null );
276+ g .dispose ();
277+ image = rgbImage ;
278+ }
279+ try {
280+ Source src = session .needSource (iccUri );
281+ ImageInputStream iccStream = ImageUtil .needImageInputStream (src );
282+ ColorSpace colorSpace = new ICC_ColorSpace (ICC_Profile .getInstance (
283+ new ImageInputStreamSeekableStreamAdapter (iccStream )));
284+ ColorConvertOp convertOp = new ColorConvertOp (image .getColorModel ().getColorSpace (), colorSpace , null );
285+ return convertOp .filter (image , null );
286+ } catch (FileNotFoundException e ) {
287+ throw new IOException (e );
288+ }
289+ }
290+ return image ;
291+ }
292+
256293 private ImageReadParam getParam (ImageReader reader , Map <String , Object > hints ) throws IOException {
257294 if (hints != null && Boolean .TRUE .equals (hints .get ("CMYK" ))) {
258295 Iterator <ImageTypeSpecifier > types = reader .getImageTypes (0 );
0 commit comments