possible to use html images like canvas with getImageData / putImageData?
Asked Answered
H

7

16

I'd like to know if there is a way to dynamically modify/access the data contained in html images just as if they were an html5 canvas element. With canvas, you can in javascript access the raw pixel data with getImageData() and putImageData(), but I have thus far been not able to figure out how to do this with images.

Halda answered 18/9, 2009 at 17:26 Comment(0)
P
22
    // 1) Create a canvas, either on the page or simply in code
    var canvas = document.createElement('canvas');
    var ctx    = canvas.getContext('2d');

    // 2) Copy your image data into the canvas
    var myImgElement = document.getElementById('foo');
    ctx.drawImage( myImgElement, 0, 0 );

    // 3) Read your image data
    var w = myImgElement.width, h=myImgElement.height;
    var imgdata = ctx.getImageData(0,0,w,h);
    var rgba = imgdata.data;
    
    // 4) Read or manipulate the rgba as you wish
    for (var px=0,ct=w*h*4;px<ct;px+=4){
      var r = rgba[px  ];
      var g = rgba[px+1];
      var b = rgba[px+2];
      var a = rgba[px+3];
    }

    // 5) Update the context with newly-modified data
    ctx.putImageData(imgdata,0,0);

    // 6) Draw the image data elsewhere, if you wish
    someOtherContext.drawImage( ctx.canvas, 0, 0 );

Note that step 2 can also be brought in from an image loaded directly into script, not on the page:

    // 2b) Load an image from which to get data
    var img = new Image;
    img.onload = function(){
      ctx.drawImage( img, 0, 0 );
      // ...and then steps 3 and on
    };
    img.src = "/images/foo.png"; // set this *after* onload
Peluso answered 30/11, 2010 at 0:20 Comment(4)
your code does not work, someOtherContext.drawImage(ctx,0,0); keeps throwing "Type error" because first attribute must be image, not context (chrome 7, firefox 3.6)Aldershot
If one wants to iterate over all pixels in the image, step 4 should be ...ct=w*h*4... since there are four values per pixel.Schulze
@dvh I think it was intended to be "canvas" instead of ctx. drawImage can take either an image or a canvas.Schulze
Note that browsers now have a cross-origin security restriction on getting data from a canvas after it has had image data from outside the domain written to it. Chrome's message, for instance, says "Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data."Mafala
S
6

You could draw the image to a canvas element with drawImage(), and then get the pixel data from the canvas.

Sigh answered 18/9, 2009 at 17:34 Comment(2)
This does not allow me to put manipulate the image data itself tho, which is what I want to do.Halda
Once the image has been copied to the canvas element, you can manipulate it any way you would normally manipulate canvas pixel data.Sigh
S
4

After having some issues with this code, I want to add one or two things to Phrogz's answer :

// 1) Create a canvas, either on the page or simply in code
var myImgElement = document.getElementById('foo');
var w = myImgElement.width, h=myImgElement.height; // New : you need to set the canvas size if you don't want bug with images that makes more than 300*150

var canvas = document.createElement('canvas');
canvas.height = h;
canvas.width = w;
var ctx    = canvas.getContext('2d');

// 2) Copy your image data into the canvas
ctx.drawImage( myImgElement, 0, 0, w, h ); // Just in case...

// 3) Read your image data
var imgdata = ctx.getImageData(0,0,w,h);
var rgba = imgdata.data;

// And then continue as in the other code !
Stupidity answered 17/1, 2013 at 19:30 Comment(0)
T
2

that worked for me (IE10x64,Chromex64 on win7, chromium arm linux, ...seems to bug with firefox 20 arm linux but not sure ... to re-test)

--html--

<canvas id="myCanvas" width="600" height="300"></canvas>
<canvas id="myCanvasOffscreen" width="1" height="1"></canvas>

-- js --

  // width & height can be used to scale image !!!
  function getImageAsImageData(url, width, height, callack) {
    var canvas = document.getElementById('myCanvasOffscreen');
    canvas.width = width;
    canvas.height = height;
    var context = canvas.getContext('2d');

    var imageObj = new Image();
    imageObj.onload = function() {
      context.drawImage(imageObj, 0, 0, width, height);
      imgData = context.getImageData(0,0,width, height);
      canvas.width = 1;
      canvas.height = 1;

      callack( imgData );
    };
    imageObj.src = url;
  }

-- then --

  var canvas = document.getElementById('myCanvas');
  var ctx = canvas.getContext('2d');

  var imgData;
  getImageAsImageData('central_closed.png', IMG_WIDTH, IMG_HEIGHT, 
    function(imgData) {

      // do what you want with imgData.data (rgba array)
      // ex.  colorize( imgData, 25, 70, 0);

      ctx.putImageData(imgData,0,0);

    }
  );
Tameika answered 9/6, 2013 at 18:47 Comment(0)
C
1

you first want to draw a pic on the canvas and then get the imageData from the canvas ,it is a wrong way,because the js think it is a "Cross-domain access",but the getIamgeData method don't allow the "Cross-domain access" to an image.you can hava a try by put the in the root place and access it by "localhost" .

Cristalcristate answered 16/4, 2012 at 2:26 Comment(0)
K
0

Im not sure if it is possible, but you can try requesting pixel information from PHP, if GD library it will be an easy task, but surely will be slower. Since you didnt specified application so I will suggest checking SVG for this task if they can be vector images than you will be able to query or modify the image.

Kabul answered 18/9, 2009 at 17:32 Comment(3)
I wanted to do this entirely in the browser, not use any server side scripting at all.Halda
Can you give some details, its pretty impossible to do it but there might be alternative solutions.Kabul
if i were to actually implement this in some software, i would probably update the DOM node of the image. However, my question was aimed more at the level of "is this even possible?" to learn more about html itself.Halda
F
0

Directly work on IMG element is also valid:

var image = document.createElement('img'),w,h ;

image.src = "img/test.jpg" ;

$(image).one('load',function(){

    w = image.naturalWidth ;
    h = image.naturalHeight ;

    var cnv = document.createElement('canvas') ;
    $(cnv).attr("width",w) ;
    $(cnv).attr("height",h) ;

    var ctx = cnv.getContext('2d') ;
    ctx.drawImage(image,0,0) ;

    var imgdata = ctx.getImageData(0,0,w,h) ;

    var rgba = imgdata.data ;
    for (var px=0,ct=w*h*4;px<ct;px+=4){
        var r = rgba[px+0] ;
        var g = rgba[px+1] ;
        var b = rgba[px+2] ;
        var a = rgba[px+3] ;
        // Do something
        rgba[px+0] = r ;
        rgba[px+1] = g ;
        rgba[px+2] = b ;
        rgba[px+3] = a ;
    }

    ctx.putImageData(imgdata,0,0) ;

    $("body").append(cnv) ;

}) ;
Farmer answered 6/3, 2016 at 7:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.