简体   繁体   中英

Apply pseudo-color palette to canvas image

How to apply a custom palette to a canvas image?

for example, turn a black-white image to a color image:

在此处输入图像描述 在此处输入图像描述

const colorstops = ["white", "#ffd700", "#cc0077", "#20008c", "black"]; // palette

const imageData = ctx.getImageData(x, y, width, height);
for(let i = 0; i < imageData.data.length; i +=4){
  imageData.data[i] = ?
  imageData.data[i + 1] = ?
  imageData.data[i + 2] = ?
}

ctx.putImageData(imageData, x, y);

so the imageData.data is an array of 0-255 numbers. Each 4 elements from the array correspond to a rgba value. I have no clue how to map these to colors from the custom palette.

I guess that one solution would be to convert the colorstops hex colors array to an array that fully maps colors to the entire range from rgb(0,0,0) until rgb(255,255,255) but that sounds terribly inefficient. Is there some math formula I can use instead?

You could calculate the average of the red, green and blue values of every pixel, and then use this value to mapp it to neares color in your custom palette.To find the values for each color channel based on the distance between the average value and the closest color in the palette you can use linear interpolation.

for (let i = 0; i < imageData.data.length; i += 4) {
    let avg = (imageData.data[i] + imageData.data[i + 1] + imageData.data[i + 2]) / 3;

    // find the closest color in the custom palette
    let closestColorIndex = 0;
    for (let j = 0; j < colorstops.length - 1; j++) {
        if (avg >= (j * 255 / (colorstops.length - 1)) && avg <= ((j + 1) * 255 / (colorstops.length - 1))) {
            closestColorIndex = j;
            break;
        }
    }

    // determine the values for each color channel based on linear interpolation
    let color1 = colorstops[closestColorIndex];
    let color2 = colorstops[closestColorIndex + 1];
    let t = (avg - (closestColorIndex * 255 / (colorstops.length - 1))) / (255 / (colorstops.length - 1));

    imageData.data[i] = color1[0] + (color2[0] - color1[0]) * t;
    imageData.data[i + 1] = color1[1] + (color2[1] - color1[1]) * t;
    imageData.data[i + 2] = color1[2] + (color2[2] - color1[2]) * t;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM