ImageIO.write converting color space RGB to CMYK for a JPG image

1.1k views Asked by At

I am sending a jpg image from client. the image is sent in form of blob. Here is the code in javascript which is sending a canvas image

canvas.toBlob((blob) => {
    this.setState({preview: blob},
        () => {
            console.log(blob.size);
            let data = new FormData();
            // const test = URL.createObjectURL(blob);
            // console.log(test);
            const file = new File([blob], "File name", {type: "image/png"});
            data.append("file", file);
            console.log(this.state.preview);
            axios({
                method: "POST",
                data: data,
                url: "/media",
                headers: {
                    'Content-Type': 'multipart/form-data'
                }
            }).then().catch()
            // axios.post("http://localhost:8085/api/media", data).then(r => {}).catch()
        }
    );
}, "image/jpg", 0)

The selected file is a jpg file which is converted to canvas for some reasons and then that is sent to the server as blob.

Here is the server image handling code which is written in java:

public void uploadMedia(MultipartFile mediaFile) {

  try{
    BufferedImage image = ImageIO.read(mediaFile.getInputStream());

    System.out.println(image.getColorModel().getColorSpace().getType() == ColorSpace.TYPE_RGB); //TRUE

    ImageIO.write(image, "jpg", new File("/Users/puspender/Desktop/Test/image.jpg"));  //BLACK IMAGE with CMYK color space
    ImageIO.write(image, "png", new File("/Users/puspender/Desktop/Test/image.png"));

  }catch(Exception e){}      

}

If I choose png format for ImageIO.write the image gets saved successfully fine but if the format is jpg then a black image gets saved and the color space of that black image gets changed to CMYK. Even though it was RGB with the original file and I have also printed it on console before saving the file.

This issue only comes up when on client the image is cropped(or something) and then a canvas is created from that and blob from that canvas is sent as the payload. No issue comes up when file is selected using <input type="file />

Update: As asked by Mike, I read and re-generated black jpg which gets generated by ImageIo. And the result is the same, a black image.

File file = new File("/location/generated_black.jpg");
BufferedImage image = ImageIO.read(file);
ImageIO.write(image, "jpg", new File("/location/from-java-main-400x400.jpg"));

I also tested the above code with the original file and that time ImageIo handles it correctly.

One important thing I noticed: the black image is actually not black, it is just the disturbed color because of change of color space. I noticed this when I upload this to AWS S3. Here is the image(CMYK) CMYK converted file The original file below: Original file

I managed to work it correctly. A great personal person on this thread suggested this solution and it even worked well.

But few questions remained the same:

  1. Why this is only happening with blob data sent by javascript and not with normal file selector as mentioned earlier
  2. Why issue only when setting image format to jpg and not with png? And why change of color space in jpg by ImageIo
1

There are 1 answers

0
troy_s On

RGB and CMYK are not colour spaces, but rather colour encoding models.

There is not enough information in either state to provide a meaningful solution.

An RGB colour space, as defined by the ISO 22028-1 standard in the glossary, stipulates that it must include definitions of: 1. Colour primaries 2. Transfer function(s) 3. White point

For CMYK, the responses must be clearly identified for variables such as paper type, ink composition, and illuminant.

Ignoring any of these facets means the resulting colour transformation is utterly meaningless, and doing no one any good.