Why does canvas putImageData not work when I specify the target location?

When trying to find documentation on the Canvas context putImageData () method, I found things like this:

context.putImageData (imgData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight);

(from http://www.w3schools.com/tags/canvas_putimagedata.asp )

According to the documentation I read, x and y are a pointer to the source image, while dirtyX and dirtyY determine the coordinates in the target canvas where to draw the image. However, as you will see from the example below (and JSFiddle), a call to putImageData (imgData, x, y) works until putImageData (imgData, 0, 0, locX, locY) does this. I'm not sure why.

EDIT:

I think my real question is why the top line of the image is black, but only 7 lines, not 8. Images should start in the upper left corner of the Canvas. They start on the left (and have 8 columns). Why don't they start upstairs?

Answer: which divides by 0 by this line when yLoc is 0:

xoff = imgWidth / (yLoc/3); 

JSFiddle:

http://jsfiddle.net/WZynM/

The code:

 <html> <head> <title>Canvas tutorial</title> <script type="text/javascript"> var canvas; var context; // The canvas 2d context function setupCanvas() { canvas = document.getElementById('myCanvas'); if (canvas.getContext) { context = canvas.getContext('2d'); context.fillStyle = "black"; // this is default anyway context.fillRect(0, 0, canvas.width, canvas.height); } } function init() { loadImages(); startGating(); } var images = new Array(); var gatingTimer; var curIndex, imgWidth=0, imgHeight; // Load images function loadImages() { for (n = 1; n <= 16; n++) { images[n] = new Image(); images[n].src = "qxsImages/frame" + n + ".png"; // document.body.appendChild(images[n]); console.log("width = " + images[n].width + ", height = " + images[n].height); } curIndex = 1; imgWidth = images[1].width; imgHeight = images[1].height; } function redrawImages() { if (imgWidth == 0) return; curIndex++; if (curIndex > 16) curIndex = 1; // To do later: use images[1].width and .height to layout based on image size for (var x=0; x<8; x++) { for (var y=0; y<8; y++) { //if (x != 1) // context.drawImage(images[curIndex], x*150, y*100); // context.drawImage(images[curIndex], x*150, y*100, imgWidth/2, imgHeight/2); // scale // else self.drawCustomImage(x*150, y*100); } } } function drawCustomImage(xLoc, yLoc) { // create a new pixel array imageData = context.createImageData(imgWidth, imgHeight); pos = 0; // index position into imagedata array xoff = imgWidth / (yLoc/3); // offsets to "center" yoff = imgHeight / 3; for (y = 0; y < imgHeight; y++) { for (x = 0; x < imgWidth; x++) { // calculate sine based on distance x2 = x - xoff; y2 = y - yoff; d = Math.sqrt(x2*x2 + y2*y2); t = Math.sin(d/6.0); // calculate RGB values based on sine r = t * 200; g = 125 + t * 80; b = 235 + t * 20; // set red, green, blue, and alpha: imageData.data[pos++] = Math.max(0,Math.min(255, r)); imageData.data[pos++] = Math.max(0,Math.min(255, g)); imageData.data[pos++] = Math.max(0,Math.min(255, b)); imageData.data[pos++] = 255; // opaque alpha } } // copy the image data back onto the canvas context.putImageData(imageData, xLoc, yLoc); // Works... kinda // context.putImageData(imageData, 0, 0, xLoc, yLoc, imgWidth, imgHeight); // Doesn't work. Why? } function startGating() { gatingTimer = setInterval(redrawImages, 1000/25); // start gating } function stopGating() { clearInterval(gatingTimer); } </script> <style type="text/css"> canvas { border: 1px solid black; } </style> </head> <body onload="setupCanvas(); init();"> <canvas id="myCanvas" width="1200" height="800"></canvas> </body> </html> 

http://jsfiddle.net/WZynM/

+7
html5 canvas
source share
2 answers

You just had your coordinates back.

 context.putImageData(imageData, xLoc, yLoc, 0, 0, imgWidth, imgHeight); 

Live demo

xLoc , and yLoc is the place where you put it, and 0,0,imgWidth,imgHeight is the data that you put on the canvas.

Another example showing this.

Many online docs seem a bit controversial, but for a version with seven options

 putImageData(img, dx, dy, dirtyX, dirtyY, dirtyRectWidth, dirtyRectheight) 

dx, and dy is your destination, the next four parameters are the dirty rectangle options, basically controlling what you draw from the original canvas. One of the most detailed descriptions I can find was in an HTML5 book published by Simon Sarris (p. 165).

+9
source share

Using this recently, I discovered that Loktar above raised a VERY important issue. Basically, some documentation on this method on the Internet is incorrect, a particularly dangerous example is W3Schools, which many people will refer to the link.

Their documentation states the following:

Description:

  • context.putImageData (imgData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight);

Arguments:

  • imgData: indicates the ImageData object to return to the canvas
  • x: x coordinate in pixels in the upper left corner of the ImageData object [WRONG]
  • y: y coordinate in pixels in the upper left corner of the ImageData object [WRONG]
  • dirtyX: Optional. The horizontal (x) value, in pixels, where to place the image on the canvas [WRONG]
  • dirtyY: Optional. The vertical (y) value in pixels, where to place the image on the canvas [WRONG]
  • dirtyWidth: Optional. Width used to draw the image on canvas
  • dirtyHeight: optional. The height used to draw the image on the canvas.

As Loktar claims above, the CORRECT synopsis is as follows:

The correct synopsis:

  • context.putImageData (imgData, canvasX, canvasY, srcX, srcY, srcWidth, srcHeight);

Arguments:

  • imgData: specifies the ImageData object to return to the canvas (as before);
  • canvasX: the x coordinate of the location on CANVAS where you draw your images;
  • canvasY: the y coordinate of the location on CANVAS where you draw your ImageData;
  • srcX: Optional. The x coordinate of the upper left corner of your ImageData;
  • srcY: Optional. The y coordinate of the upper left corner of your ImageData;
  • srcWidth: Optional. The width of your ImageData;
  • srcHeight: optional. The height of your ImageData.

Use the correct synopsis above and you will not have the problems that were discovered above.

I will give Loktar a big hat tip to find out about it initially, but I thought that he should provide an extended answer if others come across the same problem.

+1
source share

All Articles