dragfire
dragfire

Reputation: 443

ColorPicker implementation using JavaScript and Canvas

I'm trying to implement ColorPicker using Canvas just for fun. But i seem lost. as my browser is freezing for a while when it loads due to all these for loops. I'm adding the screenshot of the result of this script: enter image description here

window.onload = function(){ colorPicker(); } function colorPicker(){ var canvas = document.getElementById("colDisp"), frame = canvas.getContext("2d"); var r=0, g=0, b= 0; function drawColor(){ for(r=0;r<255;r++){ for(g=0;g<255;g++){ for(b=0;b<255;b++){ frame.fillStyle="rgb("+r+","+g+","+b+")"; frame.fillRect(r,g,1,1); } } } } drawColor();

Currently , i only want a solution about the freezing problem with better algorithm and it's not displaying the BLACK and GREY colors. Please someone help me.

Upvotes: 0

Views: 853

Answers (3)

micnic
micnic

Reputation: 11275

A way to go, using .createImageData():

window.onload = function() {

    var canvas = document.getElementById("colDisp");
    var frame = canvas.getContext("2d");
    var width = canvas.width;
    var height = canvas.height;
    var imagedata = frame.createImageData(width, height);

    var index, x, y;

    for (x = 0; x < width; x++) {
        for (y = 0; y < height; y++) {
            index = (x * width + y) * 4;

            imagedata.data[index + 0] = x;
            imagedata.data[index + 1] = y;
            imagedata.data[index + 2] = x + y - 255;
            imagedata.data[index + 3] = 255;
        }
    }

    frame.putImageData(imagedata, 0, 0);
};

http://codepen.io/anon/pen/vGcaF

Upvotes: 1

markE
markE

Reputation: 105035

If you want to fetch the rgba of the pixel under the mouse, you must use context.getImageData.

getImageData returns an array of pixels.

var pixeldata=context.getImageData(0,0,canvas.width,canvas.height);

Each pixel is defined by 4 sequential array elements.

So if you have gotten a pixel array with getImageData:

// first pixel defined by the first 4 pixel array elements

pixeldata[0]  =  red component of pixel#1
pixeldata[1]  =  green component of pixel#1
pixeldata[2]  =  blue component of pixel#1
pixeldata[4]  =  alpha (opacity) component of pixel#1

// second pixel defined by the next 4 pixel array elements


pixeldata[5]  =  red component of pixel#2
pixeldata[6]  =  green component of pixel#2
pixeldata[7]  =  blue component of pixel#2
pixeldata[8]  =  alpha (opacity) component of pixel#2

So if you have a mouseX and mouseY then you can get the r,g,b,a values under the mouse like this:

// get the offset in the array where mouseX,mouseY begin

var offset=(imageWidth*mouseY+mouseX)*4;

// read the red,blue,green and alpha values of that pixel

var red =   pixeldata[offset];
var green = pixeldata[offset+1];
var blue =  pixeldata[offset+2];
var alpha = pixeldata[offset+3];

Here's a demo that draws a colorwheel on the canvas and displays the RGBA under the mouse:

http://jsfiddle.net/m1erickson/94BAQ/

Upvotes: 2

Philipp
Philipp

Reputation: 69783

Instead of calling fillRect for every single pixel, it might be a lot more efficient to work with a raw RGBA buffer. You can obtain one using context.getImageData, fill it with the color values, and then put it back in one go using context.putImageData.

Note that your current code overwrites each single pixel 255 times, once for each possible blue-value. The final pass on each pixel is 255 blue, so you see no grey and black in the output.

Finding a good way to map all possible RGB values to a two-dimensional image isn't trivial, because RGB is a three-dimensional color-space. There are a lot of strategies for doing so, but none is really optimal for any possible use-case. You can find some creative solutions for this problem on AllRGB.com. A few of them might be suitable for a color-picker for some use-cases.

Upvotes: 2

Related Questions