-1

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
The Coder
  • 3,447
  • 7
  • 46
  • 81
  • Question: why are you using `toBlob()` instead of [`canvas.toDataURL('image/jpeg')`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL), and then sending that data over to your server for unpacking instead? – Mike 'Pomax' Kamermans Jan 17 '20 at 11:12
  • Because the string generated by `toDataURL` is not recognized by the server's `MultipartFile` and the request is considered as if there are no handlers for that – The Coder Jan 17 '20 at 11:16
  • previously I was doing that only and was getting `400` error. – The Coder Jan 17 '20 at 11:19
  • This sounds like something you should be able to test without a client/server behind it at all: if you create a `Test.java` with static main that simply reads in the png file you get when saving the canvas to file, and you then try to ImageIO.write it as a jpg, what happens? (basically, this should be quite easy to turn into a [mcve], especially as, if that also goes wrong, you can add that png directly into your post so people have both the code + assets to reproduce what you're seeing) – Mike 'Pomax' Kamermans Jan 17 '20 at 11:27
  • @mike `toDataURL` is slower/larger than raw binary. – Endless Jan 17 '20 at 12:30
  • slower/larger "but working" is never better than faster/smaller "but it doesn't work". The order is "make it work", _then_ "optimize it". Not the other way around. – Mike 'Pomax' Kamermans Jan 17 '20 at 12:36
  • @Mike'Pomax'Kamermans I found the solution to the problem. Please see the update. – The Coder Jan 17 '20 at 18:05
  • If you solve your own problem, _don't_ edit it into your post. Either delete the post, if this was just a solution that you needed to spend a bit more time on, or write an answer, and then accept that, so that future visitors see an answered question when they search SO in the same way you searched SO. – Mike 'Pomax' Kamermans Jan 17 '20 at 18:22
  • I am sorry if my comment sounded harsh, but had no intention to. I just requested you to plz reconsider **if you downvoted**. – The Coder Jan 18 '20 at 08:43

1 Answers1

-1

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.

troy_s
  • 142
  • 1
  • 8