I would like to combine two images (one uploaded from the device and another from the website) and export them as one image. The image uploaded from the device would be the background image and the one from the website is a logo to make in to a watermark in the bottom corner.
Is this possible and if so where should I start?
Thank you
I have been able to add an image on top of another image using the Javascript code below:
function watermarkLogo(elemImage) {
var canvas = document.getElementById("canvas");
canvas.width = elemImage.naturalWidth;
canvas.height = elemImage.naturalHeight;
var myVar = canvas.getContext("2d");
var img1 = loadImage(elemImage.src, myFunction);
var img2 = loadImage('icon.png', myFunction);
var numberOfImages = 0;
function myFunction() {
numberOfImages += 1;
if(numberOfImages == 2) {
myVar.drawImage(img1, 0, 0);
myVar.globalAlpha = 0.5;
var widthOffset = (canvas.width/3)*2;
var heightOffset = (canvas.height/3)*2;
myVar.drawImage(img2, widthOffset-50, heightOffset-50, 100, 100);
}
}
function loadImage(src, onload) {
var img = new Image();
img.onload = onload;
img.src = src;
return img;
}
}
Related
This question already has answers here:
Callback/scope understanding
(3 answers)
Closed 1 year ago.
I am having trouble drawing an image with CSS filters onto a canvas. I want to apply the CSS filters with sliders/range inputs that I have. The image that the filters will be applied to is an image that you upload from your files. This image is put into a variable in a function I have that will upload the image. The function for the slider is separate, and therefore I can't apply the filters and draw the image again in the function that is activated when the sliders are being dragged.
I need it to be drawn instead of just putting the filters on the canvas itself so that I can download the image with filters.
Here is the javascript code:
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);
var canvas = document.getElementById('imageCanvas');
var ctx = canvas.getContext('2d');
function handleImage(e) {
var reader = new FileReader();
reader.onload = function(event) {
var img = new Image();
img.onload = function() {
var ratio = this.height / this.width;
canvas.height = canvas.width * ratio;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
}
img.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
var container = document.getElementById("container")
var download = document.getElementById("download")
var adjustments = document.getElementById("adjustments")
download.addEventListener("click", function() {
var link = document.createElement('a');
link.download = 'filename.png';
link.href = canvas.toDataURL();
link.click();
});
var prop1 = document.getElementById("prop1");
var open = true;
adjustments.addEventListener("click", function() {
if (open === true) {
prop1.style = "margin-left: -240px;";
adjustments.classList.remove("line");
open = false;
} else if (open === false) {
prop1.style = "margin-left: 50px;";
adjustments.classList.add("line");
open = true;
}
});
var contrast = document.getElementById("contrast");
var brightness = document.getElementById("brightness");
var slider1 = contrast.value;
var slider2 = brightness.value;
function effect() {
slider1 = contrast.value;
slider2 = brightness.value;
ctx.filter = "contrast(" + slider1 + ") brightness(" + slider2 + ")";
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
}
contrast.oninput = function() {
effect()
};
brightness.oninput = function() {
effect()
};
You could try clearing the canvas with ctx.clearRect() then redraw everything on the canvas. I'd also recommend creating a function to redraw the items just for easier reading.
Can i change image format? i want save as jpg, not png.
var canvas = document.getElementById("canvas_final");
var ctx = canvas.getContext("2d");
var img1 = loadImage(imageData, main);
var img2 = loadImage('imagens/mask.png', main);
var imagesLoaded = 0;
function main() {
imagesLoaded += 1;
if(imagesLoaded == 2) {
ctx.drawImage(img1, 0, 0);
//ctx.globalAlpha = 0.5;
ctx.drawImage(img2, 0, 400);
}
}
function loadImage(src, onload) {
var img = new Image();
img.onload = onload;
img.src = src;
return img;
}
After display using img.src i want change file format to (jpeg) and not (png)
You can convert the canvas to a Data URI using HTMLCanvasElement.toDataURL. Depending on your requirement, you could have an export button that would request the following:
ctx.toDataURL("image/jpeg");
To fill a canvas with several images i am using the following code:
<canvas id="myCanvas"></canvas>
<script>
function loadImages(sources, callback) {
var images = {};
var loadedImages = 0;
var numImages = 0;
// get num of sources
for ( var src in sources) {
numImages++;
}
for ( var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if (++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
fitToContainer(canvas);
var sources = {
darthVader : 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg',
yoda : 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg'
};
loadImages(sources, function(images) {
context.drawImage(images.darthVader, 0,0);
context.drawImage(images.yoda, 0, 0);
});
function fitToContainer(canvas) {
canvas.style.width = '100%';
canvas.style.height = '100%';
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
}
</script>
Although this is in fact filling the canvas with images, i am not able to position the images in order not to overlap them. I dont know ahead of time the sizes of pictures. Is there any library or framework than can easily do this for me or what direction can i go?
And the canvas has a limited size since it is inside a parent html element.
Just keep track of the accumulated width of your images.
Then draw the next image to the right of that accumulated width
loadImages(sources, function(images) {
var nextX=0;
context.drawImage(images.darthVader, nextX,0);
nextX+=images.darthVader.width;
context.drawImage(images.yoda, nextX, 0);
nextX+=images.yoda.width;
// ...and so on...
});
I am trying to figure out how to switch images on a canvas without a small time of blankness in between.
To make my point here is an extreme example of this. In this program, when your spacebar is held down it redraws the image circle.png every milisecond. Because this is so fast the image dissappears.
I did try to preload my image but it didn't help.
Here is my full code:
// Access Canvas
var canvas = document.getElementById("gameBoard");
var ctx = canvas.getContext("2d");
// preload image
var circleReady = false;
var circleImage = new Image();
circleImage.onload = function () {
circleReady = true;
};
circleImage.src = "images/Circle.png";
// Game objects
var circle = {
};
// circle location
circle.x = canvas.width / 2;
circle.y = canvas.height / 2;
// Keyboard events
var keysDown = {};
addEventListener("keydown", function (e) {
keysDown[e.keyCode] = true;
}, false);
addEventListener("keyup", function (e) {
delete keysDown[e.keyCode];
}, false);
// Update Objects
var update = function () {
if (32 in keysDown) { // Player space pressed
circleImage.src = "images/Circle.png"; //re-draws image
}
};
// Draws Everything
var render = function () {
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0,0,600,609);
if (circleReady) {
ctx.drawImage(circleImage, circle.x, circle.y);
}
};
// The main loop
var main = function () {
update();
render();
};
// Starts Function
var then = Date.now();
setInterval(main, 1); // Execute as fast as possible
You are reloading the image in the update function which is causing your delay:
circleImage.src = "images/Circle.png"; //re-draws image
All you have to do is drawImage without reloading the image:
ctx.drawImage(circleImage, circle.x, circle.y);
Here is an example of an image loader that loads all your images before execution begins:
var imageURLs=[]; // put the paths to your images here
var imagesOK=0;
var imgs=[];
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house1.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house2.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house3.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house4.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house5.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house6.jpg");
loadAllImages(start);
function loadAllImages(callback){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
imgs.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK>=imageURLs.length ) {
callback();
}
};
img.onerror=function(){alert("image load failed");}
img.crossOrigin="anonymous";
img.src = imageURLs[i];
}
}
function start(){
// all your images are fully loaded so begin your app
}
You can have two canvases, one for each image. When you want to switch. Remove or hide the one in the front, leaving (instantly) the one in the back.
Per your comment, here is an example of 26 letters of the alphabet. We only keep two canvases at a time. Each time the user clicks whe add a new only, and make the hidden one visible, with no delay.
function createCanvas(letter) {
var canvas = document.createElement('canvas');
canvas.id = letter;
canvas.style.display = 'none';
document.getElementById('container').appendChild(canvas);
var image = new Image();
image.src = 'http://icons.iconarchive.com/icons/iconicon/alpha-magnets/128/Letter-'+letter+'-icon.png';
image.onload = function() {
canvas.getContext('2d').drawImage(this, 0, 0);
};
return canvas;
}
createCanvas('a').style.display = '';
createCanvas('b');
var prevCharCode = 'a'.charCodeAt(0);
var charCode = 'b'.charCodeAt(0);
document.addEventListener('click', function() {
document.getElementById(String.fromCharCode(charCode)).style.display = '';
document.getElementById('container').removeChild(
document.getElementById(String.fromCharCode(prevCharCode))
);
prevCharCode = charCode;
if(++charCode > 'z'.charCodeAt(0)) {
charCode = 'a'.charCodeAt(0);
}
createCanvas(String.fromCharCode(charCode));
});
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";