Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trying to convert image to CMYK and display it - rgbData is not a valid imageData format #1

Open
iroth opened this issue Mar 15, 2024 · 5 comments

Comments

@iroth
Copy link

iroth commented Mar 15, 2024

I am trying to follow your code example for coverting an image to CMYK.
This part is failing:
var rgbData = cmyk2rgb.transformArray(cmykData, false, true);
ctx.putImageData(rgbData, 0, 0);

where I get an exception for putImageData parameter 1 is not of type ImageData.

I tried to fix the code by putting the result rgbData as the data field of a synthetic imageData object, but all my attempts failed. What am I missing?

@glennwilton
Copy link
Owner

Hey the example is not complete, I will update it, you need to use createImageData to create a new object to to accept the converted colours

image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
var imageData = ctx.getImageData(0, 0, image.width, image.height);

// convert RGB to RGB with soft proofing
var data = proofTransform.transformArray(imageData.data, true, true, true);

// Create a new ImageData object with the modified pixel data
var newImageData = ctx.createImageData(image.width, image.height);
newImageData.data.set(data);

ctx.putImageData(newImageData, 0, 0);
document.body.appendChild(canvas);

}

@iroth
Copy link
Author

iroth commented Mar 16, 2024

Thanks a lot for the quick response! now the code is working, however, both images in the following example - based on your image to cmyk snippet with the fixes - look the same (original loaded, and the rgb->cmyk->rgb).

EDIT: I had a bug in my code which caused the clamped array not to be manipulated at all, I now edited the code, but now it seems the conversion creates a white image...

I had to go through format conversion since by default the transform array returns a float array.

      var cmykData = rgb2cmyk.transformArray(imageData.data, true, false);
      // convert from CMYK to RGB
      let dataArray = cmyk2rgb.transformArray(
        cmykData,
        false,
        true,
        false, // this is needed as the original does not have alpha
        imageData.width * imageData.height,
        "int8"
      );
      let clamped = new Uint8ClampedArray(imageData.data);
      let dataArrayIndex = 0;
      for (let i = 0; i < imageData.data.length; i++) {
        if (i % 4 === 3) {
          clamped[i] = 255;
        } else {
          clamped[i] = dataArray[dataArrayIndex++];
        }
      }
      var rgbData = ctx.createImageData(image.width, image.height);
      rgbData.data.set(clamped);
      ctx.putImageData(rgbData, 0, 0);

Note: if this makes a difference, I am using the JapanColor2002Newspaper.icc profile for the cmyk coversion

@glennwilton
Copy link
Owner

glennwilton commented Mar 16, 2024

Hi

A few things

  1. Your cmyk2rgb transform should be relative-Colorimetric; if you choose perceptuall it may re-expand the colours to a wider gamut in RGB. If you want to simulate the paper colour choose absolute Colorimetric.

  2. If you are just soft proofing and you don't care about the CMYK values, you can create a multi-stage transform proofTransform.createMultiStage(['*srgb', eIntent.perceptual, CMYKprofile, eIntent.relative, '*srgb']); see the example in the MD

  3. My default the result of the transform will be array or object, new Transform({dataFormat: 'int8'}); will cause all output to be 0-255 and setting precession to 0 will round for you.

  4. If you want speed at the expense of a little accuracy, pre-build a LUT with the transform, but keep the transform in memory as you don't want to constantly be pre-building the same lut new Transform({ buildLUT: true})

  5. The transformArray can take care of all the conversions for you, including handing the alpha, So you should no need to be copying to a clamped Array, set the output format to int8, AND set your transform to dataFormat : 'int8' and it will create a Uint8ClampedArray, Look at the function transformArray on line 923 in the Transform.js module,

  6. Test your transform on a single pixel. For example, transform the array CMYK [0,0,0,0] should come out as [255,255,255] or close. and the same with black [255,255,255,255] would be something like [32,32,32] as CMYK black is not a pure rgb black, Again with a red [0,255,255,0] would be an RGB red, you can easily just console.log those

If you're still having issues post your createTransform code and options as well.

@iroth
Copy link
Author

iroth commented Mar 19, 2024

Thanks again, but still no luck. I failed to mention that I am trying this with the web in-browser file (jsColorEngineWeb.js).
I now created a proofTransform as proposed, but still I am getting float rather than int8.
I placed all my code in this repo, so maybe this can help understand the issue: https://github.com/iroth/color-test
I am probably missing something basic, as I am not so experienced with canvas and image manipulation in JS.

@iroth
Copy link
Author

iroth commented Mar 20, 2024

one small note: in the docs/readme you use {buildLUT: true}, but the code seems to expect builtLut as an option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants