javascriptimage-processingrgbcolor-spacecmyk

Image not showing when I convert from RGB to CMYK in javascript


I am doing a project where I need to make some filters that change images, and 2 of the filters need to change the colour space. All the other functions that are very similar to this one work perfectly fine, but trying to run this on just makes the image completely black if the alpha is 255. Essentially its just making the whole image one colour with darkness based on the alpha value.

** edit - I am using the p5.min.js library **

After debugging and looking through the reported pixel colours, it seems it is looping over the function twice, doing fine the first time, but then the second time setting all the RGB values to 0. I cannot for the life of me figure this out, but that is what I understand is happening.

Here is the code:

//CMYK Colour space conversion
function rgbToCMYK(imgIn)
{
    var imgOut = createImage(imgIn.width, imgIn.height);
    
    imgOut.loadPixels();
    imgIn.loadPixels();
    
    //Loop through pixels
    for (var x=0; x<imgIn.width; x++){
        for (var y=0; y<imgIn.height; y++){
            var index = (x + (y * imgIn.width)) * 4;
            
            var r = imgIn.pixels[index +0];
            var g = imgIn.pixels[index +1];
            var b = imgIn.pixels[index +2];
            var a = imgIn.pixels[index +3];
            
            //Just checking that the program is reading the pixel info correctly
            console.log(r, "  ", g, "  ", b, "  ", a);
            
            //Convert rgb to CMY
            var computedC = 1 - (r/255);
            var computedM = 1 - (g/255);
            var computedY = 1 - (b/255);
            
            console.log(computedC, "  ", computedM, "  ", computedY);
            
            //Compute min CMY
            var minCMY = Math.min(computedC, Math.min(computedM, computedY));
            
            //Complete Conversion
            computedC = (computedC - minCMY) / (1 - minCMY);
            computedM = (computedM - minCMY) / (1 - minCMY);
            computedY = (computedY - minCMY) / (1 - minCMY);
            
            console.log(computedC, "  ", computedM, "  ", computedY);
            
            //K is not used yet
            var k = minCMY;
            
            imgOut.pixels[index + 0] = computedC;
            imgOut.pixels[index + 1] = computedM;
            imgOut.pixels[index + 2] = computedY;
            imgOut.pixels[index + 3] = 125;
        }
    }
    imgOut.updatePixels();
    return imgOut;
}

The code only runs this function once, and the function takes an image as the arg, computes the colour space change (at least it's meant to), and then returns the changed image.

I am very new to this colour space conversion stuff, and I dont even know if I have the right approach.


Solution

  • I am very new to this colour space conversion stuff,
    and I dont even know if I have the right approach.

    Your approach is fine and correct. You're doing a simple mistake of scaling down (the r/g/b values) but then later you don't scale them up for usage in the imgOut part.

    Using (r/255) scales it down (or will "normalize" it) from being a value in 0 to 255 range, into now being a value in a 0 to 1 range.

    Re-scale it up, into being within 0-255 range like this:

    imgOut.pixels[index + 0] = ( 255 * computedC );
    imgOut.pixels[index + 1] = ( 255 * computedM );
    imgOut.pixels[index + 2] = ( 255 * computedY );
    imgOut.pixels[index + 3] = 125;
    

    If the new imgOut colours are not exact:
    Then try something like: Math.round( 255 * computedC );

    Round down using: imgOut.pixels[index + 0] = Math.floor( 255 * computedC );
    Round up using :imgOut.pixels[index + 0] = Math.ceil( 255 * computedC );

    Now do you see multiple colours instead of just black?