添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I need to convert a PNG-File into a CMYK JPEG.

During my research i've found multiple articles on SO decribing that problem. I've copied this answer using BufferedImage and ColorConvertOp .

I came up with this little example:

public static void main(final String[] args) throws IOException
    final String imageFile = "/tmp/page0.png";
    final BufferedImage pngImage = ImageIO.read(new File(imageFile));
    // convert PNG to JPEG
    // http://www.mkyong.com/java/convert-png-to-jpeg-image-file-in-java/
    final BufferedImage rgbImage = new BufferedImage(pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_INT_RGB);
    rgbImage.createGraphics().drawImage(pngImage, 0, 0, Color.WHITE, null);
    // RGB to CMYK using ColorConvertOp
    // https://stackoverflow.com/questions/380678/how-to-set-icc-color-profile-in-java-and-change-colorspace/2804370#2804370
    final ICC_Profile ip = ICC_Profile.getInstance("icc/ISOcoated_v2_300_eci.icc");
    // final ICC_Profile ip = ICC_Profile.getInstance("icc/CoatedFOGRA27.icc");
    // final ICC_Profile ip = ICC_Profile.getInstance("icc/USWebUncoated.icc");
    final ColorConvertOp cco = new ColorConvertOp(new ICC_ColorSpace(ip), null);
    final BufferedImage cmykImage = cco.filter(rgbImage, null);
    // Write the result into an bytearray
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(cmykImage, "jpg", baos);
    baos.flush();
    final byte[] imageInByte = baos.toByteArray();

The problem is, that it leads me into this exception:

Exception in thread "main" javax.imageio.IIOException: Invalid argument to native writeImage
    at com.sun.imageio.plugins.jpeg.JPEGImageWriter.writeImage(Native Method)
    at com.sun.imageio.plugins.jpeg.JPEGImageWriter.writeOnThread(JPEGImageWriter.java:1058)
    at com.sun.imageio.plugins.jpeg.JPEGImageWriter.write(JPEGImageWriter.java:360)
    at javax.imageio.ImageWriter.write(ImageWriter.java:615)
    at javax.imageio.ImageIO.doWrite(ImageIO.java:1612)
    at javax.imageio.ImageIO.write(ImageIO.java:1578)
    at ... .pdf.ReportGeneratorPublicContentTest.main(ReportGeneratorPublicContentTest.java:69)

The message of the Exception doesn't help me. On this thread they say that sun jdk or JAI will fix the problem.

I tried apt-get install libjai-core-java and the oracle JDK jdk1.7.0_51. The error still persists.

@Christian Schneider : After i download your image file with link of CMYK JPEG, i open file's property. I see color space of image is still RGB. This picture isn't converted to CMYK color. Please see the below link :

how can I convert an RGB image to CMYK and vice versa in Java?

lovelywib 's answer solved this.

The problem was solved by using TYPE_3BYTE_BGR instead of TYPE_INT_RGB.

public static void main(String[] args) throws Exception
    final String imageFile = "/tmp/page0.png";
    final BufferedImage pngImage = ImageIO.read(new File(imageFile));
    // convert PNG to JPEG
    // http://www.mkyong.com/java/convert-png-to-jpeg-image-file-in-java/
    final BufferedImage rgbImage = new BufferedImage(pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
    rgbImage.createGraphics().drawImage(pngImage, 0, 0, Color.WHITE, null);
    // RGB to CMYK using ColorConvertOp
    // http://stackoverflow.com/questions/380678/how-to-set-icc-color-profile-in-java-and-change-colorspace/2804370#2804370
    final ICC_Profile ip = ICC_Profile.getInstance("icc/USWebUncoated.icc");
    final ColorConvertOp cco = new ColorConvertOp(rgbImage.getColorModel().getColorSpace(), new ICC_ColorSpace(ip), null);
    final BufferedImage cmykImage = new BufferedImage(pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
    cco.filter(rgbImage, cmykImage);
    // Write the result into an bytearray
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(cmykImage, "JPEG", baos);
    baos.flush();
  • RGB PNG: https://raw.github.com/d0x/questions/master/stackoverflowPlayground/src/main/resources/so22298328/page0.png

  • CMYK JPEG: https://raw.github.com/d0x/questions/master/stackoverflowPlayground/src/main/resources/so22298328/page0.cmyk.jpg

  • Maven Code at GitHub: https://github.com/d0x/questions/blob/master/stackoverflowPlayground/src/main/java/so22298328/Main.java

  • Does the image look OK? I don't understand how the TYPE_3BYTE_BGR image can even hold the resulting image data, as there is not enough channels (RGB == 3 channels cs CMYK == 4 channels). Unfortunately, writing a CMYK JPEG using the normal JPEGImageWriter is something of a black art, but it should be possible by writing Raster. – Harald K Mar 11, 2014 at 8:32 @haraldK i added the converted screenshots and a link to a running maven project at github – d0x Mar 11, 2014 at 12:46 Thanks for sharing those links! Just as I thought, your JPEG is not a CMYK JPEG, it's a normal YCbCr 4:2:2 subsampled JFIF (without embedded ICC profile). But this might be just what you need/expect, so I'm happy if you are happy. :-) – Harald K Mar 11, 2014 at 19:32 I see. I think the code in your question is logically sound (unfortunately, the JPEGImageWriter doesn't support CMYK BufferedImages per now, so you'll get an exception). The one in your answer isn't. As I said, the 3 channel RGB image cmykImage doesn't even have enough channels to hold CMYK data... And you can't change the color model/number of channels of a BufferedImage after creation. Maybe iText converts the JPEG to CMYK for you, or CMYK isn't really mandatory? I'm working on a project to simplify all this, but in the mean time, I think I'll just have to leave it up to you. :-/ – Harald K Mar 12, 2014 at 12:39

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.