In my application I need to get some images, process them, and save for later use. So I'm drawing them to a temporary canvas, then getting with getImageData function. But in output transparency is lost...
Here is my code:
var tempCanvas = document.createElement('canvas');
var tempContext = tempCanvas.getContext('2d');
tempContext.drawImage(image, 0, 0);
var imageData = tempContext.getImageData(0, 0, image.width, image.height);
My image has some transparent pixels but after this there are no transparent pixels in imageData how can I solve this issue?
Is there any way to convert Html Image to ImageData, so I can process it and then draw to canvas?
your imageData should contain alpha channel.
However, putImageData will replace the pixel value in the context.
It won't merge it with the previous value of the pixel in the context, it will replace it. So, what you should see is the pixel behind the canvas (in most of cases, the pixel color of the body tag of your html page).
What you have to do:
use a temporaty canvas to get image data is the good way
modifiy the imageData as you need
don't try to put this imageData back in the conetext with a putImageData, it won't behave as you wish
but create a new Image object and give it the imageData as source (yes, it works :))
use drawImage to draw back the image
example of code:
var tempCanvas = document.createElement('canvas');
var tempContext = tempCanvas.getContext('2d');
tempContext.drawImage(image, 0, 0);
var imageData = tempContext.getImageData(0, 0, image.width, image.height);
//modify here the imageData as you need
var img = new Image();
img.src = imageData;
context.drawImage(img, 0, 0); //the true context of the canvas
It should works.
Related
This question already has answers here:
Load image from url and draw to HTML5 Canvas
(3 answers)
Closed 4 years ago.
I want to get an image from my database, and show it in a canvas and draw shapes on it. Is there a way to draw image on canvas using image as byte array etc..
A <canvas> is like a regular <img> image with the difference that the Javascript code of the page can actually control the values of the pixels.
You can decide what is the content of the canvas by drawing primitives like lines, polygons, arcs or even other images. You can also set or alter the content by processing the actual red, green, blue and transparency values of every single pixel (using getImageData and putImageData). You can resize the canvas as you wish and drawing on a canvas is quite fast... fast enough to be able to do complex animations with just plain Javascript code.
For example the code to load an image and draw it in a canvas after changing it to black and white and adding a red grid could be:
function canvasTest(img) {
let canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
let ctx = canvas.getContext("2d");
// Copy image pixels to the canvas
ctx.drawImage(img, 0, 0);
// Now let's set R and B channels equal to G
let idata = ctx.getImageData(0, 0, canvas.width, canvas.height);
for (let i=0,n=img.width*img.height*4; i<n; i+=4) {
idata.data[i] = idata.data[i+2] = idata.data[i+1];
}
ctx.putImageData(idata, 0, 0);
// Add a red grid
ctx.beginPath();
for (let y=0; y<img.height; y+=50) {
ctx.moveTo(0, y+0.5); ctx.lineTo(img.width, y+0.5);
}
for (let x=0; x<img.width; x+=50) {
ctx.moveTo(x+0.5, 0); ctx.lineTo(x+0.5, img.height);
}
ctx.strokeStyle = "#F00";
ctx.lineWidth = 1;
ctx.stroke();
// add the final result to page
document.body.appendChild(canvas);
}
The only annoyance is that if you draw an image on a canvas and the image is coming from a different origin from where the page comes from, then the canvas becomes in the general case "tainted" and you cannot access the pixel values any more (getImageData is forbidden). The reason for this limit is security (and the sad fact that security in web application is on the client). In your case since the image database is yours there should be no problem.
var img, imageData,width,height;
var c = canvasEle.getContext("2d");
width = canvasEle.width;
height = canvasEle.height;
img = document.getElementById("id");
c.drawImage(img,0,0);
imageData = c.createImageData(width, height);
After I draw the image onto the context, then create an imageData array, the values of the array are all 0.
I have been struggling with this for hours and couldn't find any solution. The image is shown on the canvas after I draw it, but the imageData of the context says all the pixels are white. This doesn't make any sense to me.
With createImageData you are creating new image data for an empty image. Please use getImageData to get the image data from an already existing canvas
I have two canvases that are different sizes. My goal is copy the user's drawing from the main canvas to a second canvas as a scaled down version. So far the drawImage() and scale appear to be working, but the second canvas keeps the old version of the main drawing along with the new copy. I tried clearing it each time before calling drawImage(), but that doesn't appear to do anything. How can I copy just the current image to my secondary canvas each time the function runs?
$('#hand').dblclick(function(){
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
//var imageData = context.getImageData(0, 0, 100, 100);
var newCanvas = document.getElementById('scaledCanvas');
var destCtx = newCanvas.getContext('2d');
destCtx.clearRect(0, 0, newCanvas.width, newCanvas.height);
destCtx.scale(.5,.5);
destCtx.drawImage(canvas, 0, 0);
});
I can include more code if necessary. I also just realized that scale keeps getting called; this explains why the new copied image would get smaller each time as well, so that might be another problem.
It's quite simple actually, you're using what's called a transform (translate, rotate, or scale).
In order to use them "freshly" each time you must save and restore the canvas state each time.
$('#hand').dblclick(function(){
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
//var imageData = context.getImageData(0, 0, 100, 100);
var newCanvas = document.getElementById('scaledCanvas');
var destCtx = newCanvas.getContext('2d');
destCtx.clearRect(0, 0, newCanvas.width, newCanvas.height);
//save the current state of this canvas' drawing mode
destCtx.save();
destCtx.scale(.5,.5);
destCtx.drawImage(canvas, 0, 0);
//restore destCtx to a 1,1 scale (and also 0,0 origin and 0 rotation)
destCtx.restore();
});
It's also important to note you can push several times before calling restore, in order to perform many cool geometric tricks using recursive functions etc...
Take a look at this explanation of states and transformations:
https://developer.mozilla.org/en-US/docs/HTML/Canvas/Tutorial/Transformations
Hope this helps you understand canvas transforms a bit better.
Is there any way to create a deep copy of a canvas element with all drawn content?
Actually the correct way to copy the canvas data is to pass the old canvas to the new blank canvas. Try this function.
function cloneCanvas(oldCanvas) {
//create a new canvas
var newCanvas = document.createElement('canvas');
var context = newCanvas.getContext('2d');
//set dimensions
newCanvas.width = oldCanvas.width;
newCanvas.height = oldCanvas.height;
//apply the old canvas to the new one
context.drawImage(oldCanvas, 0, 0);
//return the new canvas
return newCanvas;
}
Using getImageData is for pixel data access, not for copying canvases. Copying with it is very slow and hard on the browser. It should be avoided.
You can call
context.getImageData(0, 0, context.canvas.width, context.canvas.height);
which will return an ImageData object. This has a property named data of type CanvasPixelArray which contains the rgb and transparency values of all the pixels. These values are not references to the canvas so can be changed without affecting the canvas.
If you also want a copy of the element, you could create a new canvas element and then copy all attributes to the new canvas element. After that you can use the
context.putImageData(imageData, 0, 0);
method to draw the ImageData object onto the new canvas element.
See this answer for more detail getPixel from HTML Canvas? on manipulating the pixels.
You might find this mozilla article useful as well https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Drawing_shapes
I want to do pixel-true rendering of some images on my Canvas. Right now, I obtain the images through Javascript, so my images are HTMLImageElement instances. I can draw these on the Canvas' rendering context with drawImage. However, this performs anti-aliasing on the image, which I don't want.
There appears to be a lower-level image manipulation method named putImageData, operating on ImageData objects. Does this method perform any anti-aliasing? If not, it's a fine candidate for what I'm looking for, but I haven't found out how I can convert or blit an HTMLImageElement to an ImageData instance.
Any advice would be welcome!
Edit: my original problem was solved, I accidentally had a coordinate that was fractional, which forces anti-aliasing. The conversion-to-image-data question still stands though.
The only way to convert an image into an ImageData object is to draw it to a canvas first, so you'll need to create a temporary canvas, draw the image on it, and get the image data from there.
function imageToImageData(image) {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0);
return ctx.getImageData(0, 0, canvas.width, canvas.height);
}
Note though, that the same-origin policy prevents you from calling getImageData if you draw an image from a different domain to the canvas, so this will only work on images from the same domain as the document. If you need to draw images from other domains, your only option is to call drawImage on the context for you main canvas directly, making sure there are no transformations that will affect the accuracy.