Skip to content

Commit 0a56b33

Browse files
FOP-3241: Add option to convert image to CMYK
1 parent 5ea6d84 commit 0a56b33

File tree

4 files changed

+61
-1
lines changed

4 files changed

+61
-1
lines changed

src/main/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderImageIO.java

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,20 @@
2020
package org.apache.xmlgraphics.image.loader.impl.imageio;
2121

2222
import java.awt.Color;
23+
import java.awt.Graphics2D;
24+
import java.awt.color.ColorSpace;
2325
import java.awt.color.ICC_ColorSpace;
2426
import java.awt.color.ICC_Profile;
2527
import java.awt.image.BufferedImage;
28+
import java.awt.image.ColorConvertOp;
2629
import java.awt.image.ColorModel;
2730
import java.awt.image.ComponentColorModel;
2831
import java.awt.image.IndexColorModel;
2932
import java.awt.image.Raster;
3033
import java.awt.image.RenderedImage;
3134
import java.awt.image.WritableRaster;
3235
import java.io.ByteArrayOutputStream;
36+
import java.io.FileNotFoundException;
3337
import java.io.IOException;
3438
import java.util.HashSet;
3539
import java.util.Iterator;
@@ -57,6 +61,7 @@
5761
import org.apache.commons.logging.Log;
5862
import org.apache.commons.logging.LogFactory;
5963

64+
import org.apache.xmlgraphics.image.codec.util.ImageInputStreamSeekableStreamAdapter;
6065
import org.apache.xmlgraphics.image.loader.Image;
6166
import org.apache.xmlgraphics.image.loader.ImageException;
6267
import 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);

src/main/java/org/apache/xmlgraphics/image/loader/spi/ImageImplRegistry.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ public class ImageImplRegistry {
6969
private Map additionalPenalties = new java.util.HashMap(); //<String, Penalty>
7070
//Note: String as key chosen to avoid possible class-unloading leaks
7171

72+
private String iccConverter;
73+
7274
/**
7375
* Main constructor. This constructor allows to disable plug-in discovery for testing purposes.
7476
* @param discover true if implementation classes shall automatically be discovered.
@@ -422,4 +424,11 @@ public Penalty getAdditionalPenalty(String className) {
422424
return (p != null ? p : Penalty.ZERO_PENALTY);
423425
}
424426

427+
public void setICCConverter(String iccConverter) {
428+
this.iccConverter = iccConverter;
429+
}
430+
431+
public String getIccConverter() {
432+
return iccConverter;
433+
}
425434
}

src/test/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderImageIOTestCase.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@
1919

2020
package org.apache.xmlgraphics.image.loader.impl;
2121

22+
import java.awt.image.BufferedImage;
23+
import java.io.File;
2224
import java.net.URL;
2325

26+
import org.junit.Assert;
2427
import org.junit.Test;
2528

2629
import static org.junit.Assert.assertNotNull;
@@ -60,4 +63,15 @@ public void testGrayPNGWithCMYKProfile() throws Exception {
6063
assertTrue(im instanceof ImageRendered);
6164
}
6265

66+
@Test
67+
public void testRGBToCMYK() throws Exception {
68+
File file = new File("test/images/bgimg300dpi.jpg");
69+
ImageInfo info = new ImageInfo(file.toURI().toASCIIString(), "");
70+
String icc = new File("test/images/ISOcoated_v2_300_bas.icc").toURI().toASCIIString();
71+
info.getCustomObjects().put(ImageLoaderImageIO.ICC_CONVERTER, icc);
72+
ImageBuffered image = (ImageBuffered) new ImageLoaderImageIO(ImageFlavor.BUFFERED_IMAGE)
73+
.loadImage(info, null, new MockImageSessionContext(MockImageContext.newSafeInstance()));
74+
Assert.assertEquals(image.getBufferedImage().getType(), BufferedImage.TYPE_CUSTOM);
75+
Assert.assertEquals(image.getBufferedImage().getColorModel().getNumColorComponents(), 4);
76+
}
6377
}
1 MB
Binary file not shown.

0 commit comments

Comments
 (0)