Aleksandar Jeftic
Aleksandar Jeftic

Reputation: 87

Image input to canvas and color picker

I have found 2 scripts, one for loading image from file input into canvas and the other is a color picker from image in canvas, but I can't find a way to fuse them into one script.

My goal is to have script that takes file from input, puts it into canvas and than targets at x=10,y=10 coordinates on image and calculates rgb and hex codes of it without submitting form.

html

<label>Image File:</label><br/>
<input type="file" id="uploadImage" name="uploadImage"/>
<canvas id="cvs" ></canvas>
<div id="hex">HEX: <input type="text"></input></div>
<div id="rgb">RGB: <input type="text"></input></div>

File to canvas without submit code

  var imageLoader = document.getElementById('uploadFile');
        imageLoader.addEventListener('change', handleImage, false);
        var canvas = document.getElementById('cvs');
        var ctx = canvas.getContext('2d');


        function handleImage(e) {
            var reader = new FileReader();
            reader.onload = function (event) {
                var img = new Image();
                img.onload = function () {
                    canvas.width = img.width;
                    canvas.height = img.height;
                    ctx.drawImage(img, 0, 0);
                }
                img.src = event.target.result;
            }
            reader.readAsDataURL(e.target.files[0]);
        }

I want to do something like this together with working script from above.

function rgbToHex(R,G,B) {return toHex(R)+toHex(G)+toHex(B)}
        function toHex(n) {
          n = parseInt(n,10);
          if (isNaN(n)) return "00";
          n = Math.max(0,Math.min(n,255));
          return "0123456789ABCDEF".charAt((n-n%16)/16)  + "0123456789ABCDEF".charAt(n%16);
        }
        $('#cvs').click(function(event){
          // getting image data and RGB values
          var img_data = ctx.getImageData(10, 10, 1, 1).data;
          var R = img_data[0];
          var G = img_data[1];
          var B = img_data[2];  
          var rgb = R + ',' + G + ',' + B;
          // convert RGB to HEX
          var hex = rgbToHex(R,G,B);
          // making the color the value of the input
          $('#rgb input').val(rgb);
          $('#hex input').val('#' + hex);
        });

Upvotes: 2

Views: 1870

Answers (1)

Roko C. Buljan
Roko C. Buljan

Reputation: 206565

Instead of $('#cvs').click(function(event){ create a function that takes as arguments the two x and y coordinates. Then, to retrieve the RGBA value use CanvasRenderingContext2D: getImageData() method:

const getColor = (x, y) => {
  const [r, g, b, a] = ctx.getImageData(x, y, 1, 1).data;
  console.log(r, g, b, a);
};

const el = (sel, par = document) => par.querySelector(sel);

const elUpload = el("#uploadImage");
const elCanvas = el("#canvas");
const ctx = elCanvas.getContext("2d", { willReadFrequently: true });

const handleImage = (ev) => {
  Object.assign(new FileReader(), {
    onload(evt) {
      Object.assign(new Image(), {
        src: evt.target.result,
        onload() {
          ctx.canvas.width = this.naturalWidth;
          ctx.canvas.height = this.naturalHeight;
          ctx.drawImage(this, 0, 0);
          getColor(10, 10);  //  <<< GET IMMEDIATELY AT x10 y10
        }
      });
    }
  }).readAsDataURL(ev.target.files[0]);
};

const rgbToHex = (r, g, b, a = 255) => {
  const hex = ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
  const alpha = Math.round(a).toString(16).padStart(2, "0");
  return `#${hex}${alpha}`;
};

const getColor = (x, y) => {
  const [r, g, b, a] = ctx.getImageData(x, y, 1, 1).data;
  const rgb = `rgb(${r} ${g} ${b} / ${a/255})`;
  const hex = rgbToHex(r, g, b, a);
  el("#pos").value = `X:${x} Y:${y}`;
  el("#rgb").value = rgb;
  el("#hex").value = hex;
  el("#preview").style.setProperty("--bg", rgb);
};

elUpload.addEventListener("change", handleImage);
elCanvas.addEventListener("click", ({x, y}) => {
  const xOrg = (x - elCanvas.offsetLeft) / elCanvas.offsetWidth * elCanvas.width;
  const yOrg = (y - elCanvas.offsetTop) / elCanvas.offsetHeight * elCanvas.height;
  getColor(xOrg, yOrg);  // <<< GET ON CLICK
});
#canvas {
  display: block;
  width: auto;
  height: 150px;
  cursor: crosshair;
}

#preview {
  width: 50px;
  height: 50px;
  border: 1px solid #000;

  &::after {
    content: "";
    display: block;
    width: 100%;
    height: 100%;
    background-color: var(--bg, #0000);
  }
}

#preview, 
#canvas {
  background: 50% / 12px 12px repeating-conic-gradient(#ddd 0% 25%, #fff 0% 50%);
}
Read image pixel color at coordinates: X=10 Y=10:<br>
<label>Image: <input type="file" id="uploadImage"></label>
<canvas id="canvas"></canvas>
Click on the image to read the color
<div>Coordinate: <input id="pos" type="text"></div>
<div>HEXa: <input id="hex" type="text"></div>
<div>RGBa: <input id="rgb" type="text"></div>
Color preview: <div id="preview"></div>

Upvotes: 2

Related Questions