Merging multiple previous drawn canvases - javascript

In my current code I have different functions to draw different canvases, these work perfectly. The draw function will be called a number of times and store the result to be called later, once the image is finalised.
I cannot get the two images to merge together. I can redraw them individually in mergeCanvas(), by calling 'testbor1.url' but when I try to draw them onto a new canvas, the result is blank.
Can anyone tell me why I cannot draw these onto one canvas?
Following: How can I put multiple canvas elements in to one canvas element?
function draw()
{
var can3 = document.getElementById('RugCanvas3');
can3.offset = 0;
can3.width = namespacetest.getCanvasWidth();
can3.height = namespacetest.getCanvasHeight();
var ctx3 = can3.getContext('2d');
ctx3.drawImage(drawBorder(70,size,img, borderwidth), 0, 0);
ctx3.drawImage(drawOverlay(borderwidth, 70), 0, 0);
var img = new Image();
img.src = can3.toDataURL("image/png");
namespacetest.dataURLs['img1'] = img.src;
}
namespacetest.mergeCanvas = function()
{
var testbor1 = new Image();
var testbor2 = new Image();
testbor1.src = namespacetest.dataURLs['img1'];
testbor2.src = namespacetest.dataURLs['img2'];
var bor = document.getElementById('Canvas5');
var ctx = bor.getContext("2d");
ctx.drawImage(testbor1, 0, 0, 400, 400);
ctx.drawImage(testbor2, 0, 0, 400, 400);
var buffer_img = new Image();
buffer_img.src = bor.toDataURL("image/png");
var output = document.getElementById('RugCanvas6');
output.innerHTML = '<img src="' + buffer_img.src + '" alt="Canvas Image" />';
}

Related

Merge images together in canvas using JS

I'm currently trying to add watermark to an image, and I'm using this script:
function mixImages(){
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var imageObj1 = new Image();
var imageObj2 = new Image();
var marginTop = 10;
var marginLeft = 10;
imageObj1.src = "http://localhost:8080/sisop/storage/app/public/files/16522147787.png"
imageObj1.onload = function() {
ctx.drawImage(imageObj1, 0, 0, 328, 526);
imageObj2.src = "http://localhost:8080/sisop/storage/app/public/files/165221397618.png";
imageObj2.onload = function() {
ctx.drawImage(imageObj2, marginLeft, marginTop, 100, 100);
var img = c.toDataURL("image/png");
}
};
}
Which works fine if I'm only doing it with 1 canvas. But I'm trying to do this dynamically to every image that is loaded in my PHP code. so I'm trying to do this:
foreach($collection as $file){
echo "
<div class='posts-cards'>
<canvas id='myCanvas$file->id' width='300' height='300'></canvas>
</div>
<script>
var c=document.getElementById('myCanvas$file->id');
var ctx=c.getContext('2d');
var imageObj1 = new Image();
var imageObj2 = new Image();
var marginTop = 10;
var marginLeft = 10;
imageObj1.src = 'http://localhost:8080/sisop/storage/app/public/files/16522147787.png'
imageObj1.onload = function() {
ctx.drawImage(imageObj1, 0, 0, 328, 526);
imageObj2.src = 'http://localhost:8080/sisop/storage/app/public/files/165221397618.png';
imageObj2.onload = function() {
ctx.drawImage(imageObj2, marginLeft, marginTop, 100, 100);
var img = c.toDataURL('image/png');
}
};
</script>
But for some reason, the result is this:
I have "display: flex; flex-flow: wrap; " in my css (it's supposed to be 2 rows of 4 items in each), so, for some reason, only the 5th and 8th image are being generated.. And as you can see, only the last image has actually "merged" with the other image. I'm pretty stuck in here and don't quite understand what is going on here..

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.

Images not loading and not displaying on HTML canvas

I am working on a website that, when loaded, it displays the compiled image from an HTML canvas element. My problem is that I can't tell when an image is loaded to draw it to the canvas or how to force an image to be loaded before I proceed to the next step. I have been looking through previous posts about the subject and have tried a lot of different solutions but nothing is working for me.
I am using web2py so I do use some Python helpers which are run on the server side.
When I use this:
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
image1 = new Image();
image1.src = '{{=URL('static', 'images/image-wrap-border-land.png')}}'; //resolves to: '/SNotes/static/images/image-wrap-border-land.png'
image1.onload = function() {
context.drawImage(image1, 0, 0, canvas.width, canvas.height);
};
Since the image isn't loaded, the onload function doesn't do anything and it skips over it. I have also tried putting the onload function before I set the source but the image still isn't drawn.
I have tried:
//code from above
if(image1.completed) {
context.drawImage(image1, 0, 0, canvas.width, canvas.height);
}
But have faced the same problem.
I have also looked at the possibility that the image is producing an error as it is loaded. To catch this I wrote:
//code from above
image1.onerror = function() {
console.log('error');
}
But the image source is fine, and the image isn't producing an error, it is just taking a long time to load.
Is there a way to wait for an image to load before it is drawn to the canvas?
Edit to add specificity:
My HTML looks like this:
<div id="profile-container" class="container-fluid">
<h1>My Notes</h1>
<div id="empty-orders" class="column-wrapper disable" style="padding-top: 5px; margin: 0 38%;">
<h3>Create a Note and it will appear here</h3>
<button class="btn btn-lg btn-outline">{{=A('GET STARTED', _href=URL('default', 'canvas_board_print'))}}</button>
</div>
<div id="loading" class="column-wrapper">
<i class="fa fa-cog fa-spin fa-3x fa-fw"></i>
</div>
<div id="row1" class="row">
</div>
</div>
My javascript looks like this:
function showOrders(note_orders) {
var orders = note_orders;
//console.log(orders);
var row_num = 1;
var node_num = 1;
if(orders.length > 0) {
for (var i = 0; i != orders.length; i++) {
orders[i].border = JSON.parse(orders[i].border);
orders[i].image_retouching = JSON.parse(orders[i].image_retouching);
orders[i].shipping_info = JSON.parse(orders[i].shipping_info);
var new_node = $("<div>", {id: "node" + node_num, "class": "col-xs-3 node-wrapper"});
var new_canvas = $('<canvas>', {id: "canvas" + node_num, style: 'display: none'});
var new_image = $('<img>', {id: "note_prev" + node_num, 'class': 'img-responsive'});
$('#row' + row_num).append(new_node);
$('#node'+ node_num).append(new_canvas).append(new_image).append(processOrders(orders[i], node_num));
node_num++;
if (i != 0 && (i + 1) % 4 == 0) {
row_num++;
var new_row = $("<div>", {id: "row" + row_num, "class": "row"});
$(' #profile-container ').append(new_row);
}
}
$(' #loading ').addClass('disable');
} else {
$(' #loading ').addClass('disable');
$(' #empty-orders ').removeClass('disable');
}
}
function processOrders(curr_order, node_num) {
var canvas = document.getElementById('canvas' + node_num);
var context = canvas.getContext('2d');
var image1 = new Image();
image1.src = curr_order.image_url;
canvas.width = image1.naturalWidth;
canvas.height = image1.naturalHeight;
if(image1.complete) {
context.drawImage(image1, 0, 0, canvas.width, canvas.height);
if(curr_order.border.style == 'color_wrap') {
document.getElementById('note_prev' + node_num).style.border = "10px solid " + curr_order.border.color;
} else if(curr_order.border.style == 'image_wrap') {
var image_wrap = new Image();
if(canvas.width > canvas.height) {
image_wrap.src = '{{=URL('static', 'images/image-wrap-border-land.png')}}';
} else {
image_wrap.src = '{{=URL('static', 'images/image-wrap-border-port.png')}}';
}
console.log(image_wrap);
image_wrap.onload = function() {
context.drawImage(image_wrap, 0, 0, canvas.width, canvas.height);
};
image_wrap.onerror = function() {
console.log('errors');
}
}
}
document.getElementById('note_prev' + node_num).src = canvas.toDataURL('image/png');
var node_div = document.createElement('div');
//Other non-image informantion is appended to node_div
return node_div;
}
My problem is when drawing image_wrap, not image1 from my above example. Image1 from my code draws fine, but image_wrap won't appear when it is drawn to the canvas.
I FIXED IT!!!
I moved the creation of image_Wrap variable up with the creation of the image1 variable.
function processOrders(curr_order, node_num) {
var canvas = document.getElementById('canvas' + node_num);
var context = canvas.getContext('2d');
var image1 = new Image();
var image_wrap = new Image();
image1.src = curr_order.image_url;
canvas.width = image1.naturalWidth;
canvas.height = image1.naturalHeight;
if(image1.complete) {
context.drawImage(image
I thought this wouldn't be a good idea because I didn't want to create extra variables even if they weren't going to get used, but I guess it fixed it.
I was able to load the image using your code.
Can you confirm you are not getting an error while loading the image?
(Seeking clarification: posted as an answer to demo the running code snippet)
Update: added a hackish way to wait a second after loading image and before drawing it to canvas
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var image1 = new Image();
image1.src = 'http://lorempixel.com/400/200/sports/1/';
image1.onload = function() {
// you could draw the image right away
// ctx.drawImage(image1, 0, 0, canvas.width, canvas.height);
// OR
// You could wait for an extra second before drawing the image (hackish, I know)
setTimeout(function() {
ctx.drawImage(image1, 0, 0, canvas.width, canvas.height);
}, 1 * 1000); // 1 second (in milliseconds)
};
<h2>canvas</h2>
<canvas id='canvas'>
</canvas>
<hr/>
Set the onload function BEFORE you set the src. It's likely that the image is loading before the onload function is being set.
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
image1 = new Image();
image1.onload = function() {
context.drawImage(image1, 0, 0, canvas.width, canvas.height);
};
image1.src = '{{=URL('static', 'images/image-wrap-border-land.png')}}'; //resolves to: '/SNotes/static/images/image-wrap-border-land.png'
The first parameter for context.drawImage is the image you want to draw, the second two are the position on the context....
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
The remaining parameters allow you to scale the image.
Suggest you try..
image1.onload = function() { context.drawImage(image1,0,0); }

Resize the canvas output image to a specific size (width/height)

I have a big canvas (5000x5000) and I want to take a picture of it and create a thumbnail on client side. I can capture the image using canvas.toDataURL but how do i re-size it? Do i have to create an new $("<canvas></canvas>") element and then put that image inside and run the canvas2.toDataURL(); Can anyone help me with this? I can't get my head around it how to do it.
var canvas = document.getElementById("main");
var ctx = canvas.getContext("2d");
var tumbnail64 = null;
var image = new Image();
image.src = canvas.toDataURL();
image.onload = function() {
$c2 = $("<canvas></canvas>");
$c2[0].width=100;
$c2[0].height=100;
$c2[0].getContext("2d");
$c2[0].drawImage(image, 0, 0,100,100);
tumbnail64 = $c2[0].toDataURL();
};
Something like this should work, given you don't have security restrictions on the original canvas element:
var resizedCanvas = document.createElement("canvas");
var resizedContext = resizedCanvas.getContext("2d");
resizedCanvas.height = "100";
resizedCanvas.width = "200";
var canvas = document.getElementById("original-canvas");
resizedContext.drawImage(canvas, 0, 0, 200, 100);
var myResizedData = resizedCanvas.toDataURL();

HTML5 canvas how to draw one picture on top of another

I want to draw two images on the same canvas. The first image is background.jpg and the second is photo.jpg. I want the photo.jpg always on top of the other:
var ctx = document.getElementById("main").getContext("2d");
var background = new Image();
var photo = new Image();
background.onload = function() {
ctx.drawImage(background, 0, 0);
}
photo.onload = function() {
ctx.drawImage(photo, 0, 0);
}
background.src = "background.jpg";
photo.src = "photo.jpg"
My question is how can I make sure the photo is always on the top. Because the onload are callbacks, I cannot make any assumptions about the calling order. Thanks!
Store your images in an array instead. That will makes sure the order is kept no matter which image finish loading first:
var ctx = document.getElementById("main").getContext("2d");
var background = new Image();
var photo = new Image();
var images = [background, photo]; /// the key
var count = images.length;
background.onload = photo.onload = counter;
background.src = "background.jpg";
photo.src = "photo.jpg"
/// common loader keeping track if loads
function counter() {
count--;
if (count === 0) drawImages();
}
/// is called when all images are loaded
function drawImages() {
for(i = 0; i < images.length; i++)
ctx.drawImage(images[i], 0, 0);
}
(the draw method assumes all being drawn at position 0,0 - of course, change this to meet your criteria).
The foreground could be loaded in the callback for the background
var ctx = document.getElementById("main").getContext("2d");
var background = new Image();
var photo = new Image();
background.onload = function() {
ctx.drawImage(background, 0, 0);
photo.src = "photo.jpg" // after background is loaded, load foreground
}
photo.onload = function() {
ctx.drawImage(photo, 0, 0);
}
background.src = "background.jpg";

Categories

Resources