Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert an image to pixels, edit it, and draw the edited image in Javascript

Tags:

javascript

I'm completely new to JS, I want to learn how to do the following:

Get an image data (convert it into an array of pixels so I could edit it) and then return the edited array back from the pixels editing function so that I could use these edited values to draw an edited image.

I'm not even sure if that's the way to go about this, but here's what I got so far:

  var img = new Image();
      img.src = 'img.png';
      var canvas = document.getElementById('canvas');
      var canvasEdited =  document.getElementById('canvasEdited');
      var ctx = canvas.getContext('2d');
      var arr = [];
      img.onload = function() {
          ctx.drawImage(img, 0, 0);
          function editPixels(ctx) {
             for (i of ctx) {
                 // edit pixels values 
                 arr.push(i - 10);    
             }
          }
          console.log(arr);
          function drawEditedImage() {
             var ctxEdited = canvasEdited.getContext('2d');
             ctxEdited.drawImage(img, 0, 0);
          }
     };

Console output shows an array with length:0.

Why doesn't it pushes edited pixels to arr?

like image 927
Un1 Avatar asked Jul 11 '17 23:07

Un1


People also ask

What is pixel manipulation?

The user can manipulate pixels, the basic unit of programmable color on a computer display or in a computer image. The user can erase, create, copy, and move pixels on a screen to show something different than it was originally was (erasing the pixels of a burglar on a video so he wont get caught)

What is ImageData?

image data. [data capture] Data produced by scanning a surface with an optical or electronic device. Common examples include scanned documents, remotely sensed data (for example, satellite images), and aerial photographs.


2 Answers

There are lot of issues that needs to be addressed. If you want to getImageData from canvas then the image needs to be in the same domain. Easier fix is base64 format. Not an url. So convert your image to base64 string.

You are not calling the edit pixels anywhere, even if you are calling it in someplace and have not mentioned in the question, form your argument naming its clear that you are passing context rather than imagedata.

Use getImageData and putImageData to get and set data in canvas.

For loop needs to be changed, so that you don't set negative value on the alpha data. Image data is of format rgba.

Since you didn't mention how to manipulate the pixel. I am just reducing the rgb values by 100 to show the difference between the original image and the new image.

var img = new Image();
      img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsBAMAAACLU5NGAAAAG1BMVEXMzMyWlpa3t7eqqqqcnJyjo6PFxcWxsbG+vr6NAD6nAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACjklEQVR4nO3XO2/bMBDA8fNTGn2OlGS00S8QAWnnaKi7xnBQdJSBFl3joY/RRpHv3SNFykYtdKOm/w8BHOkOIM3HkRYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/uddvWvsI38sj+7xT/2lJ2n8WH64iMbkdCaqurTPteqda98eX6+zKnu9OkdDckIH3W21kbmWlR5F9rrT+6ukTMv3ettFY3JC9UZyfZBJ0czrZxuWjXwtr5KmRSOnmy4ak9PJ3bc+PMveJvJ0a+OwslfNv1knG6Ks7KIhOaGxulYXsl7YmNy1j/XV4nLRXLtoSE4oczN2epLK5mRSuj/x/7tuPImfOfHDKXnRRUNyaq6l17bhu7aX/q1N1fY8Va7TIRqSE/tuS2a78i3Nludu7QsbsW4+54dlFw3JadVqM1Uf3b6XqSsO+4V/n+nrtGt7qrZdYzQkp6WuFLUtNW3DYebqzXoZk0ZqWzZGQ3LqblmLvhFtRq5Ho9Ct9c25OI1c52M0JKftlrzpc+9ozfSilOfbctjRsv226FtbtuBvLpJmOuza8hW7Zyfa4lpeJFl5H24nZr/Fz4srReNQt9ahW5nGpn8d/azFaEhOyJ8hNi+HtnBn5yrvClcsW+44slmL0UPyKj8Jh0/fmVjd12HxV+3hM+CZ6DZUFW4Q9+GOcPShuT6sw5o/3PovEKMhOaG5frZBWPXdt2a2xkMV2JeNuNI62H1LqmJXF9J3O7XbQ65t4xP9+OguFMPdTr9Zkd9I313eLaxt28X5VtUuqAPe5eVH/ckalPyl/THzFn/5jF0H9qEMZC/Fz4toTAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEjpL514clJrNSt2AAAAAElFTkSuQmCC';
      var canvas = document.getElementById('canvas');
      var canvasEdited =  document.getElementById('canvasEdited');
      var ctx = canvas.getContext('2d');
      var arr = [];
      img.onload = function() {
          ctx.drawImage(img, 0, 0);

          var imageData = ctx.getImageData(0,0, canvas.width, canvas.height)

           editPixels(imageData.data);

           drawEditedImage( imageData);
     };

     function editPixels(imgData) {
              for (var i=0; i < imgData.length; i += 4) {
                  imgData[i] = imgData[i] - 100;
                imgData[i+1] = imgData[i+1] - 100;
                imgData[i+2] = imgData[i+2] - 100;
             }
     }

     function drawEditedImage(newData) {
         var ctxEdited = canvasEdited.getContext('2d');
         ctxEdited.putImageData(newData, 0, 0);
     }

jsfiddle for the same https://jsfiddle.net/karthick6891/3yhyyLyf/

like image 168
karthick Avatar answered Nov 14 '22 23:11

karthick


I was not as fast as the others, but I decided to post my answer anyway, because it still has some added value (break-down, base64, tainted canvas mention...).

I assume you want to change pixel data of an image via the canvas.

First, render an image to a canvas. You already got that right:

var canvasEdited =  document.getElementById('canvasEdited');
var ctxEdited = canvasEdited.getContext('2d');
ctxEdited.drawImage(img, 0, 0, canvasEdited.width, canvasEdited.height);

Then, get the pixel data out:

var imageData = ctxEdited.getImageData(0, 0, canvasEdited.width, canvasEdited.height);
// you will get an array of pixel data
// this array consists of rgba values
// each 'set' of four stands for red, green, blue and alpha

Then, do something with it, in this example making it gray:

for(var i = 0; i < imageData.length; i += 4) {
    var brightness = 0.34 * imageData[i] + 0.5 * imageData[i + 1] + 0.16 * imageData[i + 2];
    imageData[i] = brightness;
    imageData[i + 1] = brightness;
    imageData[i + 2] = brightness;
}

Then, draw the changed pixel data back on the canvas:

ctxEdited.putImageData(imageData, 0, 0);

If you would like to re-use that image outside the canvas, you can convert it to base64 like thisM

var base64URI = canvasEdited.toDataURL();

You can then set that data as a source of an element, like this:

img.src = base64URI;

Things to note:

  • You must open your page via localhost or a web server, otherwise the browser will block it. (unless you set the right flags)

  • You cannot get pixel data out a tainted canvas. This happens when you draw an image which does not specify crossOrigin. Read more about this at https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image

like image 35
Zomry Avatar answered Nov 14 '22 22:11

Zomry