Trying to determine whether canvas is blank or not with javascript - javascript

I'm using the solution from: How to check if a canvas is blank? but it's not working. My blank canvas URL does not match the newly created canvas URL and I cannot figure out why. They are the same dimensions and everything but their .toDataURL return different things so there is no way for me to tell if it has been drawn in. Below is an example of what happens when I do .toDataURL on my blank canvas and .toDataURL on the newly created canvas, as you can see they differ as you continue along.
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA0sAAACUCAYAAABCxLIRAAAKfUlEQVR4Xu3ZIRKAQAwEQfj/ow9NgRi/jY5J58wU9znnXD4CBAgQIECAAAECBAgQeAncYsmLIECAAAECBAgQIECAwFdALHkVBAgQIECAAAECBAgQ+BEQS54FAQIECBAgQIAAAQIExJI3QIAAAQIECBAgQIAAgSbgz1JzMkWAAAECBAgQIECAwJiAWBo7uHUJECBAgAABAgQIEGgCYqk5mSJAgAABAgQIECBAYExALI0d3LoECBAgQIAAAQIECDQBsdScTBEgQIAAAQIECBAgMCYglsYObl0CBAgQIECAAAECBJqAWGpOpggQIECAAAECBAgQGBMQS2MHty4BAgQIECBAgAABAk1ALDUnUwQIECBAgAABAgQIjAmIpbGDW5cAAQIECBAgQIAAgSYglpqTKQIECBAgQIAAAQIExgTE0tjBrUuAAAECBAgQIECAQBMQS83JFAECBAgQIECAAAECYwJiaezg1iVAgAABAgQIECBAoAmIpeZkigABAgQIECBAgACBMQGxNHZw6xIgQIAAAQIECBAg0ATEUnMyRYAAAQIECBAgQIDAmIBYGju4dQkQIECAAAECBAgQaAJiqTmZIkCAAAECBAgQIEBgTEAsjR3cugQIECBAgAABAgQINAGx1JxMESBAgAABAgQIECAwJiCWxg5uXQIECBAgQIAAAQIEmoBYak6mCBAgQIAAAQIECBAYExBLYwe3LgECBAgQIECAAAECTUAsNSdTBAgQIECAAAECBAiMCYilsYNblwABAgQIECBAgACBJiCWmpMpAgQIECBAgAABAgTGBMTS2MGtS4AAAQIECBAgQIBAExBLzckUAQIECBAgQIAAAQJjAmJp7ODWJUCAAAECBAgQIECgCYil5mSKAAECBAgQIECAAIExAbE0dnDrEiBAgAABAgQIECDQBMRSczJFgAABAgQIECBAgMCYgFgaO7h1CRAgQIAAAQIECBBoAmKpOZkiQIAAAQIECBAgQGBMQCyNHdy6BAgQIECAAAECBAg0AbHUnEwRIECAAAECBAgQIDAmIJbGDm5dAgQIECBAgAABAgSagFhqTqYIECBAgAABAgQIEBgTEEtjB7cuAQIECBAgQIAAAQJNQCw1J1MECBAgQIAAAQIECIwJiKWxg1uXAAECBAgQIECAAIEmIJaakykCBAgQIECAAAECBMYExNLYwa1LgAABAgQIECBAgEATEEvNyRQBAgQIECBAgAABAmMCYmns4NYlQIAAAQIECBAgQKAJiKXmZIoAAQIECBAgQIAAgTEBsTR2cOsSIECAAAECBAgQINAExFJzMkWAAAECBAgQIECAwJiAWBo7uHUJECBAgAABAgQIEGgCYqk5mSJAgAABAgQIECBAYExALI0d3LoECBAgQIAAAQIECDQBsdScTBEgQIAAAQIECBAgMCYglsYObl0CBAgQIECAAAECBJqAWGpOpggQIECAAAECBAgQGBMQS2MHty4BAgQIECBAgAABAk1ALDUnUwQIECBAgAABAgQIjAmIpbGDW5cAAQIECBAgQIAAgSYglpqTKQIECBAgQIAAAQIExgTE0tjBrUuAAAECBAgQIECAQBMQS83JFAECBAgQIECAAAECYwJiaezg1iVAgAABAgQIECBAoAmIpeZkigABAgQIECBAgACBMQGxNHZw6xIgQIAAAQIECBAg0ATEUnMyRYAAAQIECBAgQIDAmIBYGju4dQkQIECAAAECBAgQaAJiqTmZIkCAAAECBAgQIEBgTEAsjR3cugQIECBAgAABAgQINAGx1JxMESBAgAABAgQIECAwJiCWxg5uXQIECBAgQIAAAQIEmoBYak6mCBAgQIAAAQIECBAYExBLYwe3LgECBAgQIECAAAECTUAsNSdTBAgQIECAAAECBAiMCYilsYNblwABAgQIECBAgACBJiCWmpMpAgQIECBAgAABAgTGBMTS2MGtS4AAAQIECBAgQIBAExBLzckUAQIECBAgQIAAAQJjAmJp7ODWJUCAAAECBAgQIECgCYil5mSKAAECBAgQIECAAIExAbE0dnDrEiBAgAABAgQIECDQBMRSczJFgAABAgQIECBAgMCYgFgaO7h1CRAgQIAAAQIECBBoAmKpOZkiQIAAAQIECBAgQGBMQCyNHdy6BAgQIECAAAECBAg0AbHUnEwRIECAAAECBAgQIDAmIJbGDm5dAgQIECBAgAABAgSagFhqTqYIECBAgAABAgQIEBgTEEtjB7cuAQIECBAgQIAAAQJNQCw1J1MECBAgQIAAAQIECIwJiKWxg1uXAAECBAgQIECAAIEmIJaakykCBAgQIECAAAECBMYExNLYwa1LgAABAgQIECBAgEATEEvNyRQBAgQIECBAgAABAmMCYmns4NYlQIAAAQIECBAgQKAJiKXmZIoAAQIECBAgQIAAgTEBsTR2cOsSIECAAAECBAgQINAExFJzMkWAAAECBAgQIECAwJiAWBo7uHUJECBAgAABAgQIEGgCYqk5mSJAgAABAgQIECBAYExALI0d3LoECBAgQIAAAQIECDQBsdScTBEgQIAAAQIECBAgMCYglsYObl0CBAgQIECAAAECBJqAWGpOpggQIECAAAECBAgQGBMQS2MHty4BAgQIECBAgAABAk1ALDUnUwQIECBAgAABAgQIjAmIpbGDW5cAAQIECBAgQIAAgSYglpqTKQIECBAgQIAAAQIExgTE0tjBrUuAAAECBAgQIECAQBMQS83JFAECBAgQIECAAAECYwJiaezg1iVAgAABAgQIECBAoAmIpeZkigABAgQIECBAgACBMQGxNHZw6xIgQIAAAQIECBAg0ATEUnMyRYAAAQIECBAgQIDAmIBYGju4dQkQIECAAAECBAgQaAJiqTmZIkCAAAECBAgQIEBgTEAsjR3cugQIECBAgAABAgQINAGx1JxMESBAgAABAgQIECAwJiCWxg5uXQIECBAgQIAAAQIEmoBYak6mCBAgQIAAAQIECBAYExBLYwe3LgECBAgQIECAAAECTUAsNSdTBAgQIECAAAECBAiMCYilsYNblwABAgQIECBAgACBJiCWmpMpAgQIECBAgAABAgTGBMTS2MGtS4AAAQIECBAgQIBAExBLzckUAQIECBAgQIAAAQJjAmJp7ODWJUCAAAECBAgQIECgCYil5mSKAAECBAgQIECAAIExAbE0dnDrEiBAgAABAgQIECDQBMRSczJFgAABAgQIECBAgMCYgFgaO7h1CRAgQIAAAQIECBBoAmKpOZkiQIAAAQIECBAgQGBMQCyNHdy6BAgQIECAAAECBAg0AbHUnEwRIECAAAECBAgQIDAmIJbGDm5dAgQIECBAgAABAgSagFhqTqYIECBAgAABAgQIEBgTEEtjB7cuAQIECBAgQIAAAQJNQCw1J1MECBAgQIAAAQIECIwJiKWxg1uXAAECBAgQIECAAIEmIJaakykCBAgQIECAAAECBMYExNLYwa1LgAABAgQIECBAgEATEEvNyRQBAgQIECBAgAABAmMCYmns4NYlQIAAAQIECBAgQKAJiKXmZIoAAQIECBAgQIAAgTGBB7R+TmNlhJuwAAAAAElFTkSuQmCC
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA0sAAACUCAYAAABCxLIRAAAKeUlEQVR4Xu3ZoRHAMAwEwbj/plOADY7/BotoZXKT8/kIECBAgAABAgQIECBA4BI4TAgQIECAAAECBAgQIEDgFhBLXgUBAgQIECBAgAABAgQeAmLJsyBAgAABAgQIECBAgIBY8gYIECBAgAABAgQIECDQBPxZak6mCBAgQIAAAQIECBAYExBLYwe3LgECBAgQIECAAAECTUAsNSdTBAgQIECAAAECBAiMCYilsYNblwABAgQIECBAgACBJiCWmpMpAgQIECBAgAABAgTGBMTS2MGtS4AAAQIECBAgQIBAExBLzckUAQIECBAgQIAAAQJjAmJp7ODWJUCAAAECBAgQIECgCYil5mSKAAECBAgQIECAAIExAbE0dnDrEiBAgAABAgQIECDQBMRSczJFgAABAgQIECBAgMCYgFgaO7h1CRAgQIAAAQIECBBoAmKpOZkiQIAAAQIECBAgQGBMQCyNHdy6BAgQIECAAAECBAg0AbHUnEwRIECAAAECBAgQIDAmIJbGDm5dAgQIECBAgAABAgSagFhqTqYIECBAgAABAgQIEBgTEEtjB7cuAQIECBAgQIAAAQJNQCw1J1MECBAgQIAAAQIECIwJiKWxg1uXAAECBAgQIECAAIEmIJaakykCBAgQIECAAAECBMYExNLYwa1LgAABAgQIECBAgEATEEvNyRQBAgQIECBAgAABAmMCYmns4NYlQIAAAQIECBAgQKAJiKXmZIoAAQIECBAgQIAAgTEBsTR2cOsSIECAAAECBAgQINAExFJzMkWAAAECBAgQIECAwJiAWBo7uHUJECBAgAABAgQIEGgCYqk5mSJAgAABAgQIECBAYExALI0d3LoECBAgQIAAAQIECDQBsdScTBEgQIAAAQIECBAgMCYglsYObl0CBAgQIECAAAECBJqAWGpOpggQIECAAAECBAgQGBMQS2MHty4BAgQIECBAgAABAk1ALDUnUwQIECBAgAABAgQIjAmIpbGDW5cAAQIECBAgQIAAgSYglpqTKQIECBAgQIAAAQIExgTE0tjBrUuAAAECBAgQIECAQBMQS83JFAECBAgQIECAAAECYwJiaezg1iVAgAABAgQIECBAoAmIpeZkigABAgQIECBAgACBMQGxNHZw6xIgQIAAAQIECBAg0ATEUnMyRYAAAQIECBAgQIDAmIBYGju4dQkQIECAAAECBAgQaAJiqTmZIkCAAAECBAgQIEBgTEAsjR3cugQIECBAgAABAgQINAGx1JxMESBAgAABAgQIECAwJiCWxg5uXQIECBAgQIAAAQIEmoBYak6mCBAgQIAAAQIECBAYExBLYwe3LgECBAgQIECAAAECTUAsNSdTBAgQIECAAAECBAiMCYilsYNblwABAgQIECBAgACBJiCWmpMpAgQIECBAgAABAgTGBMTS2MGtS4AAAQIECBAgQIBAExBLzckUAQIECBAgQIAAAQJjAmJp7ODWJUCAAAECBAgQIECgCYil5mSKAAECBAgQIECAAIExAbE0dnDrEiBAgAABAgQIECDQBMRSczJFgAABAgQIECBAgMCYgFgaO7h1CRAgQIAAAQIECBBoAmKpOZkiQIAAAQIECBAgQGBMQCyNHdy6BAgQIECAAAECBAg0AbHUnEwRIECAAAECBAgQIDAmIJbGDm5dAgQIECBAgAABAgSagFhqTqYIECBAgAABAgQIEBgTEEtjB7cuAQIECBAgQIAAAQJNQCw1J1MECBAgQIAAAQIECIwJiKWxg1uXAAECBAgQIECAAIEmIJaakykCBAgQIECAAAECBMYExNLYwa1LgAABAgQIECBAgEATEEvNyRQBAgQIECBAgAABAmMCYmns4NYlQIAAAQIECBAgQKAJiKXmZIoAAQIECBAgQIAAgTEBsTR2cOsSIECAAAECBAgQINAExFJzMkWAAAECBAgQIECAwJiAWBo7uHUJECBAgAABAgQIEGgCYqk5mSJAgAABAgQIECBAYExALI0d3LoECBAgQIAAAQIECDQBsdScTBEgQIAAAQIECBAgMCYglsYObl0CBAgQIECAAAECBJqAWGpOpggQIECAAAECBAgQGBMQS2MHty4BAgQIECBAgAABAk1ALDUnUwQIECBAgAABAgQIjAmIpbGDW5cAAQIECBAgQIAAgSYglpqTKQIECBAgQIAAAQIExgTE0tjBrUuAAAECBAgQIECAQBMQS83JFAECBAgQIECAAAECYwJiaezg1iVAgAABAgQIECBAoAmIpeZkigABAgQIECBAgACBMQGxNHZw6xIgQIAAAQIECBAg0ATEUnMyRYAAAQIECBAgQIDAmIBYGju4dQkQIECAAAECBAgQaAJiqTmZIkCAAAECBAgQIEBgTEAsjR3cugQIECBAgAABAgQINAGx1JxMESBAgAABAgQIECAwJiCWxg5uXQIECBAgQIAAAQIEmoBYak6mCBAgQIAAAQIECBAYExBLYwe3LgECBAgQIECAAAECTUAsNSdTBAgQIECAAAECBAiMCYilsYNblwABAgQIECBAgACBJiCWmpMpAgQIECBAgAABAgTGBMTS2MGtS4AAAQIECBAgQIBAExBLzckUAQIECBAgQIAAAQJjAmJp7ODWJUCAAAECBAgQIECgCYil5mSKAAECBAgQIECAAIExAbE0dnDrEiBAgAABAgQIECDQBMRSczJFgAABAgQIECBAgMCYgFgaO7h1CRAgQIAAAQIECBBoAmKpOZkiQIAAAQIECBAgQGBMQCyNHdy6BAgQIECAAAECBAg0AbHUnEwRIECAAAECBAgQIDAmIJbGDm5dAgQIECBAgAABAgSagFhqTqYIECBAgAABAgQIEBgTEEtjB7cuAQIECBAgQIAAAQJNQCw1J1MECBAgQIAAAQIECIwJiKWxg1uXAAECBAgQIECAAIEmIJaakykCBAgQIECAAAECBMYExNLYwa1LgAABAgQIECBAgEATEEvNyRQBAgQIECBAgAABAmMCYmns4NYlQIAAAQIECBAgQKAJiKXmZIoAAQIECBAgQIAAgTEBsTR2cOsSIECAAAECBAgQINAExFJzMkWAAAECBAgQIECAwJiAWBo7uHUJECBAgAABAgQIEGgCYqk5mSJAgAABAgQIECBAYExALI0d3LoECBAgQIAAAQIECDQBsdScTBEgQIAAAQIECBAgMCYglsYObl0CBAgQIECAAAECBJqAWGpOpggQIECAAAECBAgQGBMQS2MHty4BAgQIECBAgAABAk1ALDUnUwQIECBAgAABAgQIjAmIpbGDW5cAAQIECBAgQIAAgSYglpqTKQIECBAgQIAAAQIExgTE0tjBrUuAAAECBAgQIECAQBMQS83JFAECBAgQIECAAAECYwJiaezg1iVAgAABAgQIECBAoAmIpeZkigABAgQIECBAgACBMQGxNHZw6xIgQIAAAQIECBAg0ATEUnMyRYAAAQIECBAgQIDAmIBYGju4dQkQIECAAAECBAgQaAJiqTmZIkCAAAECBAgQIEBgTEAsjR3cugQIECBAgAABAgQINAGx1JxMESBAgAABAgQIECAwJvADO98Ald0HVn8AAAAASUVORK5CYII=
For reference here is the function:
function isCanvasBlank(canvas) {
var blank = document.createElement('canvas');
blank.width = canvas.width;
blank.height = canvas.height;
return canvas.toDataURL() == blank.toDataURL();
}

the resulting images you have are different. The first one has a white background and the other is transparent.
This is causing the difference.
this is a quick way to fill the new canvas.
function isCanvasBlank(canvas) {
var blank = document.createElement('canvas');
blank.width = canvas.width;
blank.height = canvas.height;
var ctx = blank.getContext("2d");
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0, 0, blank .width, blank .height);
return canvas.toDataURL() == blank.toDataURL();
}
or use same function as the fiddle. blank.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
function isCanvasBlank(canvas) {
var blank = document.createElement('canvas');
blank.width = canvas.width;
blank.height = canvas.height;
blank.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
return canvas.toDataURL() == blank.toDataURL();
}

Related

Can't seem to get an old image off the canvas

I'm importing an image (that has to come in portrait) onto a canvas object, rotating it (because it's actually landscape) and running some OCR on the base64 from the canvas. That all works fine. However when I put a new image onto the canvas, the old one is retained and never replaced. I've tried clearRect, even gone to the extent of creating a new dom element each time and destroying it when I have everything I need (which is still in the code below) but I just cannot get the first image to clear.
Here's the relevant bit of the code
function onSuccess(imageURI) {
//CREATE NEW CANVAS ELEMENT
g = document.createElement('canvas');
g.setAttribute("id", "thePic");
g.style.overflow = "visible";
document.body.appendChild(g);
const canvas = document.getElementById('thePic'),
context = canvas.getContext('2d');
make_base();
function make_base()
{
base_image = new Image();
base_image.src = imageURI;
base_image.onload = function(){
const uriheight = base_image.naturalHeight;
const uriwidth = base_image.naturalWidth;
console.log(uriwidth + " " + uriheight);
context.canvas.width = uriheight;
context.canvas.height = uriheight;
context.drawImage(base_image, 0, 0);
//ROTATE THE IMAGE 90
context.clearRect(0,0,canvas.width,canvas.height);
context.save();
context.translate(canvas.width/2,canvas.height/2);
context.rotate(90*Math.PI/180);
context.drawImage(base_image,-base_image.width/1.2,-base_image.width/1.2);
context.restore();
var theCanvas = document.getElementById('thePic');
var rotImg = theCanvas.toDataURL();
var rotImg = rotImg.substring(21);
textocr.recText(4, rotImg, onSuccess, onFail);
function onSuccess(recognizedText) {
var recdata = recognizedText.lines.linetext;
var blockData = recognizedText.blocks.blocktext;
context.clearRect(0, 0, 10000,10000);
base_image = "";
rotImg = "";
document.getElementById('thePic').outerHTML = "";
document.getElementById('cgh').innerHTML = "";
}
}
}
Any advice much appreciated.
So it turned out to not be the canvas at all, it was image caching in a previous function that give the image to the canvas.
Thanks to everyone who took the time to have a squiz.

How to change window level of an image on canvas using javascript

I have an image on canvas or a set of images that i draw on the canvas. I can draw them fine but I want to change the window level of the image on canvas by dragging the mouse over it. I've seen a lot of external javascript api's but they're quite huge and i don't want to use them for this purpose.
here's my JSFIDDLE that is basically drawing an image on the canvas
this is how my code looks
// Grab the Canvas and Drawing Context
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
// Create an image element
var img = document.createElement('IMG');
// When the image is loaded, draw it
img.onload = function () {
ctx.drawImage(img, 0, 0);
}
// Specify the src to load the image
img.src = "http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/sample5_l.jpg";
i need something with basic JS or JQuery. it would be great if you can point me in the right direction using a sample code.
Thanks in advance.
If you want to use JavaScript, try something like:
<script>
var c = document.getElementById("drawingboard");
var ctx = c.getContext("2d");
var mouseDown = 0;
document.body.ontouchstart = function() {
mouseDown+=1;
}
document.body.ontouchend = function() {
mouseDown-=1;
}
function draw(event){
ctx.color='gold';
ctx.fillStyle = "lime";
ctx.drawImage(img,event.clientX,event.clientY);}
</script>
This is what I gained after some research:
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const rangeMin = level - window / 2;
const rangeMax = level + window / 2;
const totalSize = canvas.width * canvas.height;
for (let idx = 0; idx < totalSize; idx++) {
if (imageData.data[idx] < rangeMin) {
imageData.data[idx] = 0;
} else if (imageData.data[idx] > rangeMax) {
imageData.data[idx] = 255;
}
}
ctx.putImageData(imageData, 0, 0);

Drawing another image to canvas

So I am creating a cordova app where I take a photo from the iphone library, draw it to canvas and add another image to it in order to save it as one photo. So far the photo I draw from the iphone photo library gets drawn without problems to the canvas, however the second image doesn't.
When I load the second image, it first gets added to a div with absolute positioning in order to move it to wherever I want. After that I get the actual image it's source and it's positions and try to draw it to canvas. The drawing of the second image happens when I call a method that also performs the canvas2ImagePlugin it's functions. In the end only the first photo without the second image gets saved.
The draw image to canvas function:
function drawImage(image_source, dx, dy)
{
var canvas = document.getElementById('Photo');
var image = new Image();
image.src = image_source;
image.onload = function() {
c=canvas.getContext("2d");
c.canvas.width = window.innerWidth;
c.canvas.height = window.innerHeight;
c.drawImage(image,dx,dy, window.innerWidth, window.innerHeight);
}
}
The method for drawing the second image and saving it:
function saveImage()
{
var img = $('.ObjectImage').attr('src', $('img:first').attr('src'));
var imagePosition = $('.ObjectImage').find('img:first').position();
drawImage(img, imgPosition.left, imgPosition.top);
window.canvas2ImagePlugin.saveImageDataToLibrary(
function(msg){
console.log(msg);
},
function(err){
console.log(err);
},
document.getElementById('Photo')
);
alert("Image saved");
}
The window.innerWidth, window.innerHeight on the canvas is done to get the canvas in full screen of the parent div.
EDIT to the comment:
function drawImage(image_source, dx, dy)
{
var canvas = document.getElementById('Photo');
var image = new Image();
image.onload = function() {
c=canvas.getContext("2d");
c.canvas.width = window.innerWidth;
c.canvas.height = window.innerHeight;
c.drawImage(image,dx,dy, window.innerWidth, window.innerHeight);
}
image.src = image_source;
}
Still not working
The drawImage function works asynchronously, it starts loading an image and exits immediately. Then, when the image loads, the canvas is updated. If you run something like:
drawImage('test.jpg',0,0);
drawImage('test2.jpg',0,0);
you will get both images updating the canvas at approximately the same time and only one will appear.
Also, what wolfhammer said is correct. If you set the size of the canvas, you clear it, so drawing one image after the other, even if they are smaller sizes and should both appear, will only show the last one. Check this link on how to solve it: Preventing Canvas Clear when Resizing Window
Further more, you are drawing all images with the width and height of the window, which doesn't make sense. Probably you want to use the width and height of the image (so this.width instead of window.innerWidth)
When you set the width and height of the canvas the data on "Photo" is cleared. I've provide a resize function if resizing is really needed.
function drawImage(image_source, dx, dy)
{
var canvas = document.getElementById('Photo');
var image = new Image();
image.src = image_source;
image.onload = function() {
c=canvas.getContext("2d");
//c.canvas.width = window.innerWidth;
//c.canvas.height = window.innerHeight;
c.drawImage(image,dx,dy, window.innerWidth, window.innerHeight);
}
}
var can = document.getElementById('can');
var ctx = can.getContext('2d');
ctx.fillStyle = "red";
ctx.beginPath();
ctx.moveTo(20, 90);
ctx.lineTo(50, 10);
ctx.lineTo(80, 90);
ctx.lineTo(10, 40);
ctx.lineTo(90, 40);
ctx.lineTo(20, 90);
ctx.fill();
var btn = document.getElementById('btnResize');
btn.addEventListener('click', function() {
resize(can, can.width * 2, can.height * 2);
});
function resize(can, w, h) {
var ctx = can.getContext('2d');
// copy
var can2 = document.createElement('canvas');
var ctx2 = can2.getContext('2d');
can2.width = can.width;
can2.height = can.height;
ctx2.drawImage(can, 0, 0);
// resize
can.width = w;
can.height = h;
ctx.drawImage(can2, 0, 0, can2.width, can2.height, 0, 0, w, h);
}
#can {
border:1px solid red;
}
<button id='btnResize'>Size x 2</button><br/>
<canvas id="can" width="100" height="100"></canvas>

How to step back in HTML5 Canvas history

I have an image cropper using Imgly HTML5 Canvas plugin. I need to be able to setup a history stack for the cropper to be able to undo a crop operation. Currently, I can clear the canvas on button click, but I need to be able to retain the original image, and just move back through a history of changes of the image in the canvas, in the event that a cropping step is done incorrectly.
I have the following which simply clears the canvas:
$("#renderButton").click(function() {
var elem = $(".imgly-canvas");
var canvas = elem.get(0);
var context = canvas.getContext("2d");
$('#file').val('');
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
});
The plugin creates the canvas element on image load with:
Utils.getImageDataForImage = function(image) {
var canvas, context;
canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
context = canvas.getContext("2d");
context.drawImage(image, 0, 0);
return context.getImageData(0, 0, image.width, image.height);
};
And this is used on resize:
Utils.cloneImageData = function(imageData) {
var i, newImageData, _i, _ref;
newImageData = this.sharedContext.createImageData(imageData.width, imageData.height);
for (i = _i = 0, _ref = imageData.data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
newImageData.data[i] = imageData.data[i];
}
return newImageData;
};
/*
#param {Object} dimensions
#param {Integer} dimensions.width
#param {Integer} dimensions.height
#returns {HTMLCanvasElement}
*/
Utils.newCanvasWithDimensions = function(dimensions) {
var canvas;
canvas = document.createElement("canvas");
canvas.width = dimensions.width;
canvas.height = dimensions.height;
return canvas;
};
/*
#param {imageData} imageData
#returns {HTMLCanvasElement}
*/
Utils.newCanvasFromImageData = function(imageData) {
var canvas, context;
canvas = document.createElement("canvas");
canvas.width = imageData.width;
canvas.height = imageData.height;
context = canvas.getContext("2d");
context.putImageData(imageData, 0, 0);
return canvas;
};
So I'm not sure how to build a call stack to reference each change and move back through a history of modifications to an image in the canvas.
The HTML5 canvas nicely converts to JSON which can then be used to reload the canvas. You can store this in a global object.
var myObj = window.myObj || {};
myObj = {
history: [],
canvas: null
};
Get the canvas data:
myObj.canvas = document.getElementById('canvas-id');
var ctx = myObj.canvas.getContext('2d');
var data = JSON.stringify(ctx.getImageData(0, 0, myObj.canvas.width, myObj.canvas.height));
myObj.history.push(data);
Reload data:
var reloadData = JSON.parse(myObj.history[someIndex]);
var ctx = myObj.canvas.getContext('2d');
ctx.putImageData(reloadData, 0, 0);
Once you can store/load data the tricky part is managing the myObj.history array.
You should look at the command pattern. Basically, you need to write a function for every action that the user can do. When they click a button or load an image, don't call the function right away. Instead, create a command object with all the information needed to execute the command plus the information needed to undo it.
Commands are applied to a data model (the image and the crop marks). A command "load image" needs to record the new and the previous image URL so you can load the correct image when you move through the history.
For crop commands, you need to store the old and new crop rectangles - if you keep a copy of the original image around. When the command is executed, you apply the new crop rectangle on the original and draw that on the canvas.
For undo, you use the original image and the previous crop rectangle.
So the trick is to define a data model which contains all the information how the UI looks like (which is often hard to get from the UI directly - you can't get crop information after rendering the cropped image to the canvas). The commands then manipulate this state (so the next command can save it for undo) and update the UI.

Canvas Image trouble

I am having issues with JavaScript and Canvas particularly in Firefox. I am trying to create an canvas image viewer that will run when canvas is enabled in a browser in place of standard img tag. Javascript changes the image from an array of src paths when an arrow is clicked. For some reason Firefox is always one img out of sync. When I test it in chrome the imgs are in sync but the first one is not displayed.
here is the image object
var image = new Image();
image.src = myImage.src[0];
here is my initial canvas intialization
if(canvas()){ //canvas stuff
var myc = document.createElement('canvas');
myc.id='mycanvasx';
mycanvas = document.getElementById('mycanvasx');
myc.width = image.width;
myc.height = image.height;
//viewer.replaceChild(myc, scroller);
viewer.appendChild(myc);
var context = myc.getContext("2d");
dw = image.width;
dh = image.height;
context.clearRect(0, 0, myc.width, myc.height);
context.drawImage(image, 0, 0, dw, dh);
}
and when the arrow is pressed a function like this is called
function update(){
if(canvas()){
context.clearRect(0,0,myc.width, myc.height) //maybe bloat
myc.width = image.width;
myc.height = image.height;
dw = image.width;
dh = image.height;
context.drawImage(image, 0, 0, dw, dh);
}
}
function left(){ //these move the image through the source array
if(myImage.num > 0){myImage.num--;}else{
myImage.num = (myImage.src.length-1)}
image.src = myImage.src[myImage.num];
scroller.src = image.src;
update();
x=0;
}
I know I must be missing something simple here. I'm using firefox 4.0.1 and chrome 11
You're setting the src of the image and then immediately painting it into the canvas. But image loads are async. So you're painting it before the new src you set has loaded; since you keep reusing the same image it's still showing the previous image at that point.
You want to run update() off an onload listener on image.

Categories

Resources