image onload not triggering inside of promise - javascript

Hello I created a promise and call it recursively from a loop to fill an array but the onload never triggers thus never resolving the promise.
Can anyone see anything I'm doing wrong?
function imageResizeToDataUriPromise(url, width, height) {
return new Promise(function (resolve, reject) {
var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.onload = function () {
var imgWidth = img.naturalWidth;
var imgHeight = img.naturalHeight;
var result = _scaleImage(imgWidth, imgHeight, width, height, true);
//create an off-screen canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = result.width;
canvas.height = result.height;
//draw source image into the off-screen canvas:
ctx.drawImage(img, 0, 0, result.width, result.height);
resolve(canvas.toDataURL());
};
img.src = url;
});
}

this is my basic calling block but its in a loop
caller(logo, 150, 150).then
(function (response) {
console.log("Success!", response);
base64Urls.push(response);
});

It works after I use that promise to get an URL and set it to an image element... not sure how you would use the return Data URL. One possible issue is: can you check whether your image source is serving you the image. (double check the network tab in developer tool).
function imageResizeToDataUriPromise(url, width, height) {
return new Promise(function(resolve, reject) {
var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.onload = function() {
console.log("IMG ONLOAD handler invoked");
var imgWidth = img.naturalWidth;
var imgHeight = img.naturalHeight;
var result = img;
//create an off-screen canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = result.width;
canvas.height = result.height;
//draw source image into the off-screen canvas:
ctx.drawImage(img, 0, 0, result.width, result.height);
ctx.fillStyle = "white";
ctx.font = '21px sans-serif';
ctx.fillText('Hello world', 21, 51);
resolve(canvas.toDataURL());
};
img.src = url;
});
}
imageResizeToDataUriPromise("https://i.imgur.com/j7Ie7pg.jpg", 100, 100)
.then(url => document.querySelector("#an-image").src = url);
console.log("Promise obtained");
<img id="an-image">

Related

Uncaught Error: Incomplete or corrupt PNG file

I am trying to add a couple of images to a pdf. I am using the jspdf plugin for this. My code is as following:
document.getElementById("help").addEventListener("click",function(){
var base1="";
var base2="";
var base3="";
var doc = new jsPDF();
var img=new Image();
var img1=new Image();
var img2=new Image();
img.onload = function() {
var canvas = document.createElement("canvas");
ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
base1 = canvas.toDataURL();
}
img.src='/Screenshot (1).png';
img1.onload = function() {
var canvas = document.createElement("canvas");
ctx = canvas.getContext('2d');
ctx.drawImage(img1, 0, 0);
base2 = canvas.toDataURL();
}
img1.src='/Screenshot (2).png';
img2.onload = function() {
var canvas = document.createElement("canvas");
ctx = canvas.getContext('2d');
ctx.drawImage(img2, 0, 0);
base3 = canvas.toDataURL();
}
img2.src='/Screenshot (3).png';
doc.addImage(base1,'PNG',20,36,100,120);
doc.addImage(base2,'PNG',20,158,100,120);
doc.addImage(base3,'PNG',20,281,100,120);
doc.save("example.pdf");
})
But when I execute the code, I get the following error in addImage():
Uncaught Error: Incomplete or corrupt PNG file
How do I fix this?
EDIT: After implementing #AKX's solution, the code works in the local machine. But when tested live, it throws this error:
Uncaught (in promise) Event {isTrusted: true, type: 'error', target:
null, currentTarget: null, eventPhase: 0, …}
You're not waiting for all the images to load. You can refactor things to use a promisified function to load an image and turn it into a data URI (though according to the docs for jspdf, a HTMLImageElement would also do, so you could skip the canvas bit), and then turn your handler into an async function to make it easy to just await for all the loads.
function loadImageAsDataURL(url) {
return new Promise((resolve, reject) => {
var img = new Image();
img.onload = function () {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
resolve(canvas.toDataURL());
}
img.onerror = reject;
img.src = url;
});
}
document.getElementById('help').addEventListener('click', async function () {
// Load all images first...
var base1 = await loadImageAsDataURL("/Screenshot (1).png");
var base2 = await loadImageAsDataURL("/Screenshot (2).png");
var base3 = await loadImageAsDataURL("/Screenshot (3).png");
// ... and then generate the PDF.
var doc = new jsPDF();
doc.addImage(base1, 'PNG', 20, 36, 100, 120);
doc.addImage(base2, 'PNG', 20, 158, 100, 120);
doc.addImage(base3, 'PNG', 20, 281, 100, 120);
doc.save('example.pdf');
})

Image dimensions not reflected correctly

I am trying to get the base64 of some images in Javascript and was using this function:
function getBase64Image(img) {
return new Promise((data) => {
var canvas = document.createElement("canvas");
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
data(canvas.toDataURL("image/png").replace(/^data:image\/(png|jpg|jpeg);base64,/, ""))
})
}
Then I call the function to load in the image using:
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function () {
getBase64Image(this).then(data => {})
}
img.src = wha[1][0]
If I look at the naturalWidth of the image (96px), it is different from the actual image itself (640px). I had been looking at other methods of getting base64 from an image but they also return the same results.

Get canvas toDataUrl() after processing Javascript

I have a Javascript function that create a canvas, write a image and a text on it. At the and I need the base64 dataUrl but what I get is only a blank canvas.
This is my function:
function createBreadCrumb(label) {
var canvas = document.createElement('canvas');
canvas.width = 25;
canvas.height = 30;
var img = new Image;
img.src = 'map-pin-breadcrumb.png';
var ctx=canvas.getContext("2d");
img.onload = function(){
ctx.drawImage(img, 0, 0);
ctx.font = "11px Arial";
ctx.textAlign="center";
ctx.fillText(label, 12, 16);
};
return canvas.toDataURL();
}
You are calling toDataURL before the image is loaded. As a result, none of your canvas instructions have run yet. Because the image is loaded asynchronously, you cannot get the resulting canvas synchronously and must use a callback or a promise.
Try this.
function createBreadCrumb(label, callback) {
var canvas = document.createElement('canvas');
canvas.width = 25;
canvas.height = 30;
var img = new Image;
var ctx = canvas.getContext("2d");
img.onload = function(){
ctx.drawImage(img, 0, 0);
ctx.font = "11px Arial";
ctx.textAlign="center";
ctx.fillText(label, 12, 16);
callback(canvas.toDataURL());
};
img.src = 'map-pin-breadcrumb.png';
}
createBreadCrumb("hello", function(crumb){
// do your stuff
});

Drawing ends up all black

I'm trying to resize an image via HTML canvas, but when I display it, it displays all black.
My code
function onSuccess(imageData) {
var img = new Image();
img.src = imageData;
window.setTimeout(function() {
var maxSize = 200;
var canvas = document.createElement("canvas");
canvas.width = maxSize;
canvas.height = maxSize;
var ctx = canvas.getContext("2d");
ctx.drawImage(img.src, 0, 0, maxSize, maxSize);
dataurl = canvas.toDataURL("image/jpeg");
alert(dataurl);
}, 1000);
}
I'm not exactly sure what it is I'm doing incorrectly. Thanks for the help!

Missing image when saving image from canvas

I use this code to save images in Javascript :
function saveImage() {
var canvas = document.getElementById('myPicture');
var ctx = canvas.getContext('2d');
var img = new Image();
ctx.rect(0, 0, 460, 600);
ctx.fillStyle = 'white';
img = new Image();
img.crossOrigin = 'anonymous';
img.src = "http://localhost/upload/abc.jpg";
ctx.drawImage(img,0,0,_item.width(),_item.height());
return canvas.toDataURL("image/jpeg");
}
When i click button save image:
$("#save").on('click', function () {
var rawImageData = saveImage();
$(this).attr('download', 'your_pic_name.jpeg').attr('href', rawImageData);
});
However the result I get is white image.
And I click on the save button again (ie 2 times) then is now right result. how do I can just click one time only?
Thank you.
It is because the first time you click, anchor doesn't have image data url... You may set the url and forget about the click event.
//$("#save").on('click', function () {
var rawImageData = saveImage();
$(this).attr('download', 'your_pic_name.jpeg')
.attr('href', rawImageData);
//});
OR
$("#save").on('click', function () {
var rawImageData = saveImage();
/*$(this).attr('download', 'your_pic_name.jpeg')
.attr('href', rawImageData);*/
window.location=rawImageData;
});
OR alternatively, you need this file to use following code
var canvas = document.getElementById('myPicture');
function saveImage() {
var ctx = canvas.getContext('2d');
var img = new Image();
ctx.rect(0, 0, 460, 600);
ctx.fillStyle = 'white';
img = new Image();
img.crossOrigin = 'anonymous';
img.src = "http://localhost/upload/abc.jpg";
// ctx.fill...
return canvas.toDataURL("image/jpeg");
}
$("#save").on('click', function () {
var rawImageData = saveImage();
var png= Canvas2Image.saveAsPNG(canvas , true);
});
PS: I don't see where you feel canvas with the image...int the saveImage function

Categories