Creating thumbnail from existing base64 image - javascript

This is my first time using HTML canvas. I have been given a working camera that returns images as a base64 string. I am trying to pass this string to a new function that handles the image resizing(the actual dimensions aren't important right now as I am just testing the resizing).
Right now I am getting a blank image from my generateThumbnail function. Below I have attached an image of the output in the application, as well as an image of the console output.
For the first attached image, you will see 2 photos. The photo on the left is the original which is working correctly (it is all black because my webcam is covered). The photo on the right is the blank output when I attempt to resize.
generateThumbnail(imageData) {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let img = new Image();
img.onload = () => {
ctx.drawImage(img, 0, 0, 300, 300);
}
img.src = imageData;
let dataUrl = canvas.toDataURL("image/png");
console.log(imageData);
console.log(dataUrl);
return dataUrl;
}
image of taken photos
image of console output from thumbnail base64

Although your code is not working on the embedded fiddle, I think your problem is because the image has not loaded yet as you're returning dataUrl as soon as you execute your method.
dataUrl
should be returning inside img.onload method , maybe something like this will work?
** EDIT **
Make sure you set width and height of your canvas as well.
const generateThumbnail = (imageData) => {
let canvas = document.createElement("canvas");
canvas.width = 300;
canvas.height = 300;
document.querySelector(".canvas").appendChild(canvas);
let ctx = canvas.getContext("2d");
let img = new Image();
img.onload = () => {
ctx.drawImage(img, 0 , 0, 300, 300);
console.log(imageData);
console.log(dataUrl);
return dataUrl;
}
img.src = imageData;
let dataUrl = canvas.toDataURL("image/png");
document.querySelector(".image").appendChild(img);
}
window.onload = () => {
generateThumbnail(window.image_base64);
}
.canvas, .image {
position: absolute;
top: 0;
left: 0;
width: 300px;
height: 300px;
color: white;
}
.image { border: solid 1px white; }
.canvas {
left: 310px;
top: 0;
width: 300px;
height: 300px;
}
body {
background: purple;
}
<div class="image"></div>
<div class="canvas"></div>
<script>
window.image_base64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAMAAABOo35HAAAFU2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChNYWNpbnRvc2gpIgogICB4bXA6Q3JlYXRlRGF0ZT0iMjAxOC0xMC0yNFQxNjo0NTowNiswMTowMCIKICAgeG1wOk1vZGlmeURhdGU9IjIwMTgtMTAtMjRUMTY6NTE6MTUrMDE6MDAiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMTgtMTAtMjRUMTY6NTE6MTUrMDE6MDAiCiAgIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIgogICBwaG90b3Nob3A6Q29sb3JNb2RlPSIyIgogICBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiCiAgIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6N2Q3MTU5YWYtYzM3Ni00YWVhLWFkNTYtYzNlYWFiZTUw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";
</script>

Related

Why can't I draw a picture in canvas?

I tried to put a picture in the canvas, but it just doesn't appear. I've Googled it to find out what's wrong, unfortunately I still can't solve it.
Here's my code:
window.onload = function() {
var cnvs = document.getElementById("gc");
var ctx = cnvs.getContext("2d");
var img = new Image();
img.src = "/img/road.jpg";
ctx.drawImage(img, 0, 0);
};
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
.game-border {
display: flex;
justify-content: center;
justify-items: center;
}
#gc {
width: 100vmin;
height: 100vmin;
background-color: coral;
}
<div class="game-border">
<canvas id="gc"></canvas>
</div>
If you try to call drawImage() before the image has finished loading, it won't do anything. So you need to be sure to use the load event so you don't try this before the image has loaded:
var img = new Image(); // Create new img element
img.addEventListener('load', function() {
// execute drawImage statements here
ctx.drawImage(img,0,0);
}, false);
img.src = 'myImage.png'; // Set source path
Source: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images

Generation of Base64 string from JPG/PNG/... image returns plain white image after canvas resize operation

Context
I'm trying to generate a Base64 string of a JPG/PNG/... image after resizing it. For some reason, the resulting Base64 string is that of a plain white image.
Assumption
My assumption of what is causing this, is the following: <canvas width="X" height="Y"></canvas> does not seem to contain innerHTML, where I would expect it to contain <img src="https://static.wixstatic.com/media/6068b5_b0d5df4c3d094694bb5d348eac41128d~mv2.jpg" crossorigin="anonymous"> However, I cannot figure out why ctx.drawImage() does not handle this.
Related issues
Several other people have brought up this issue, but unfortunately, the proposed solutions didn't seem to resolve my issue. See:
Rendering a base64 image, currently comes back as blank
How can I convert an image into Base64 string using JavaScript?
How to display Base64 images in HTML?
Minimal Working Example
async function init(){
//getDataUrl
var dataUrl = await getDataUrl("https://static.wixstatic.com/media/6068b5_5888cb03ab9643febc221f3e6788d656~mv2.jpg");
console.log(dataUrl); //returns string, but white image?
//Create new image on body tag with dataurl
addBase64Image(dataUrl);
}
function getImageDimensions(file) {
return new Promise (function (resolved, rejected) {
var i = new Image()
i.onload = function(){
resolved({w: i.width, h: i.height})
};
i.src = file
})
}
async function getDataUrl(img_url) {
// Create canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
var dimensions = await getImageDimensions(img_url);
console.log(dimensions);
// Set width and height
canvas.width = dimensions.w; //img_url.width
canvas.height = dimensions.h; //img_url.height
var res = await loadImage(ctx, img_url, dimensions.w, dimensions.h);
console.log(res);
res.setAttribute('crossorigin', 'anonymous');
ctx.drawImage(res, dimensions.w, dimensions.h); //issue: <canvas width="2075" height="3112"></canvas> has no innerHTML e.g. <img src="https://static.wixstatic.com/media/6068b5_b0d5df4c3d094694bb5d348eac41128d~mv2.jpg" crossorigin="anonymous">
console.log(canvas);
console.log(ctx);
dataurl = canvas.toDataURL('image/png');
return dataurl;
}
function loadImage(context, path, dimx, dimy){
return new Promise(function(resolve, reject){
var img=new Image();
img.onload = function() {
resolve.call(null, img);
};
img.src=path;
});
}
function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
return { width: srcWidth*ratio, height: srcHeight*ratio };
}
async function addBase64Image(img_dataurl){
var dimensions = await getImageDimensions(img_dataurl);
console.log(dimensions);
var res = calculateAspectRatioFit(dimensions.w, dimensions.h, 512, 512);
console.log(res);
var image = document.createElement("img");
var imageParent = document.querySelector('body');
image.id = "user_upload";
image.width = res.width;
image.height = res.height;
image.src = img_dataurl;
imageParent.appendChild(image);
}
body {
margin: 0px;
}
#user_upload {
display: block;
margin-left: auto;
margin-right: auto;
border: 2.5px solid;
}
<body onload="init()">
</body>
To be able to draw an image hosted on a different domain onto a canvas
a) the webserver needs to permit it and send the appropriate headers
b) you need to set the crossOrigin property of the image to "anonymous"
Obviously you already figured this out yourself, as you already have the line
res.setAttribute('crossorigin', 'anonymous');
in your code.
The problem is that it happens too late. It needs to be set before assigning an URL to the src property of the image.
So simply move the above line inside the loadImage() function, just before the call to
img.src=path;
Here's an example:
async function init() {
//getDataUrl
var dataUrl = await getDataUrl("https://static.wixstatic.com/media/6068b5_5888cb03ab9643febc221f3e6788d656~mv2.jpg");
console.log(dataUrl); //returns string, but white image?
//Create new image on body tag with dataurl
addBase64Image(dataUrl);
}
function getImageDimensions(file) {
return new Promise(function(resolved, rejected) {
var i = new Image()
i.onload = function() {
resolved({
w: i.width,
h: i.height
})
};
i.src = file
})
}
async function getDataUrl(img_url) {
// Create canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
var dimensions = await getImageDimensions(img_url);
console.log(dimensions);
// Set width and height
canvas.width = dimensions.w; //img_url.width
canvas.height = dimensions.h; //img_url.height
var res = await loadImage(ctx, img_url, dimensions.w, dimensions.h);
console.log("asd ", res);
ctx.drawImage(res, 0, 0); //issue: <canvas width="2075" height="3112"></canvas> has no innerHTML e.g. <img src="https://static.wixstatic.com/media/6068b5_b0d5df4c3d094694bb5d348eac41128d~mv2.jpg" crossorigin="anonymous">
console.log(canvas);
console.log(ctx);
dataurl = canvas.toDataURL('image/png');
return dataurl;
}
function loadImage(context, path, dimx, dimy) {
return new Promise(function(resolve, reject) {
var img = new Image();
img.onload = function() {
resolve.call(null, img);
};
img.setAttribute('crossorigin', 'anonymous');
img.src = path;
});
}
function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
return {
width: srcWidth * ratio,
height: srcHeight * ratio
};
}
async function addBase64Image(img_dataurl) {
var dimensions = await getImageDimensions(img_dataurl);
console.log(dimensions);
var res = calculateAspectRatioFit(dimensions.w, dimensions.h, 512, 512);
console.log(res);
var image = document.createElement("img");
var imageParent = document.querySelector('body');
image.id = "user_upload";
image.width = res.width;
image.height = res.height;
image.src = img_dataurl;
imageParent.appendChild(image);
}
init();
body {
margin: 0px;
}
#user_upload {
display: block;
margin-left: auto;
margin-right: auto;
border: 2.5px solid;
}

Scaling canvas on Firefox doesn't effect SVG images

Firefox does not respect 2D canvas transformation for SVG images, however, it does for PNG pictures.
The following code snippet creates two HTML canvases with 2D drawing contexts. On both of them a simple scale transformation is applied, then a 20px sized square PNG image is drawn on the upper one, and an SVG with the same dimensions is drawn on the bottom one.
On my Chromium (v65.0.3325.162) the images are scaled up as expected. However, on Firefox (v58.0.2) the canvas at the bottom (the one with the SVG) is not scaled, unlike the one with PNG source image.
function createPng(xSize, ySize) {
var canvas = document.createElement("canvas");
canvas.width = 20;
canvas.height = 20;
var ctx = canvas.getContext("2d")
ctx.fillStyle = "000000";
ctx.fillRect(0, 0, xSize, ySize);
var img = new Image()
prom = new Promise(function(resolve, reject) {
img.onload = function() {resolve(img)}
img.onerror = function(err) {reject(err)}
})
img.src = canvas.toDataURL("image/png");
return prom
}
function createSvg() {
var img = new Image()
var prom = new Promise(function(resolve, reject) {
img.onload = function() {resolve(img)}
img.onerror = function(err) {reject(err)}
})
img.src = "https://cdn.rawgit.com/AttilaVM/4e0987aae8bc37b2067fbde591088758/raw/95dcffd67b37540d739f4bd5f33f6bead625a90f/test.svg"
return prom
}
var containerPng = document.getElementById("container-png")
var canvasPng = document.createElement("canvas")
canvasPng.width = containerPng.clientWidth;
canvasPng.height = containerPng.clientHeight;
containerPng.appendChild(canvasPng);
var ctxPng = canvasPng.getContext("2d");
createPng(20, 20)
.then(function(img) {
ctxPng.scale(5, 1);
ctxPng.drawImage(img, 0, 0)
})
.catch(function(err) {console.error(err)});
var containerSvg = document.getElementById("container-svg")
var canvasSvg = document.createElement("canvas")
canvasSvg.width = containerSvg.clientWidth;
canvasSvg.height = containerSvg.clientHeight;
containerSvg.appendChild(canvasSvg);
var ctxSvg = canvasSvg.getContext("2d");
createSvg()
.then(function(img) {
ctxSvg.scale(5, 1);
ctxSvg.drawImage(img, 0, 0)
})
.catch(function(err) {console.error(err)});
.container {
position: relative;
margin: 15px 0 0 0;
width: 100%;
height: 20px;
background-color: #aaaaaa
}
.container > canvas {
position: absolute;
top: 0;
left: 0;
}
<div id="container-png" class="container"></div>
<div id="container-svg" class="container"></div>
Screenshots
Chromium:
Firefox:
Question:
What is the best way to write code to draw scaled SVG images on HTML canvas, which gives the same result on both Firefox and Chromium?
It is not in fact a bug. In your original svg, the preserveAspectRatio attribute is missing. This means that the default value is used which is XMidYMid. That will create the problem if the viewBox aspect ratio of the svg does not match to the aspect ratio of the target viewPort (you image). To turn this off, you need to add preserveAspectRatio="none" to your svg. I went to the source of the svg, added the preserveAspectRatio="none" attribute and then did this:
var x = "data:image/svg+xml;base64,"+ btoa(ser.serializeToString(document.querySelector("svg")))
The ser above is an XMLSerializer instance. This will give me a data url which I can use:
"data:image/svg+xml;base64,PHN2ZyB4bWxuczpvc2I9Imh0dHA6Ly93d3cub3BlbnN3YXRjaGJvb2sub3JnL3VyaS8yMDA5L29zYiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMCAwIDI2LjQ1OCAyNi40NTgiIGhlaWdodD0iMjAiIHdpZHRoPSIyMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnM+PGxpbmVhckdyYWRpZW50IG9zYjpwYWludD0iZ3JhZGllbnQiIGlkPSJhIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNlMjVlNWUiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMxMjkwMzMiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCB5Mj0iMjk1LjQ4MiIgeDI9IjEyLjYxNCIgeTE9IjI3Mi4xNjQiIHgxPSIxMi4xOSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxLjExMzQ3IDAgMCAxLjExMzQ3IC0xLjUwMSAtMzIuMTk4KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGlkPSJiIiB4bGluazpocmVmPSIjYSIvPjwvZGVmcz48cGF0aCBmaWxsPSJ1cmwoI2IpIiBkPSJNMCAyNzAuNTQyaDI2LjQ1OFYyOTdIMHoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTI3MC41NDIpIi8+PC9zdmc+"
Next , I created a fiddle and modified these:
function createSvg() {
var img = new Image()
var prom = new Promise(function(resolve, reject) {
img.onload = function() {resolve(img)}
img.onerror = function(err) {reject(err)}
})
img.src = "data:image/svg+xml;base64,PHN2ZyB4bWxuczpvc2I9Imh0dHA6Ly93d3cub3BlbnN3YXRjaGJvb2sub3JnL3VyaS8yMDA5L29zYiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMCAwIDI2LjQ1OCAyNi40NTgiIGhlaWdodD0iMjAiIHdpZHRoPSIyMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnM+PGxpbmVhckdyYWRpZW50IG9zYjpwYWludD0iZ3JhZGllbnQiIGlkPSJhIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNlMjVlNWUiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMxMjkwMzMiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCB5Mj0iMjk1LjQ4MiIgeDI9IjEyLjYxNCIgeTE9IjI3Mi4xNjQiIHgxPSIxMi4xOSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxLjExMzQ3IDAgMCAxLjExMzQ3IC0xLjUwMSAtMzIuMTk4KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGlkPSJiIiB4bGluazpocmVmPSIjYSIvPjwvZGVmcz48cGF0aCBmaWxsPSJ1cmwoI2IpIiBkPSJNMCAyNzAuNTQyaDI2LjQ1OFYyOTdIMHoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTI3MC41NDIpIi8+PC9zdmc+";
return prom
}
See the fiddle here:
https://fiddle.jshell.net/ibowankenobi/4ntq2qLz/1/
Seems like it solved the problem in the firefox browser I was testing.

how to make my webcam streaming full screen with WebRTC using javascript

I have tested many css properties to make my webcam streaming full screen but i am not getting proper results.
Sometimes the height gets overflow.
I tried object-fit also, but did not get proper result.
Sharing my code here .https://jsfiddle.net/jn6payn6/#&togetherjs=Sc8JuHsSfU
CSS-code
video{
width: 100%;
min-height: 100%;
margin:0 auto;
transform: rotateY(180deg);
}
img{
position: relative;
top: 50%;
transform: rotateY(180deg);
}
HTML code:
<video autoplay></video>
Javascript code:
(function() {
'use strict';
var video = document.querySelector('video')
, canvas;
/**
* generates a still frame image from the stream in the <video>
* appends the image to the <body>
*/
function takeSnapshot() {
var img = document.querySelector('img') || document.createElement('img');
var context;
var width = video.offsetWidth
, height = video.offsetHeight;
canvas = canvas || document.createElement('canvas');
canvas.width = width;
canvas.height = height;
context = canvas.getContext('2d');
context.drawImage(video, 0, 0, width, height);
img.src = canvas.toDataURL('image/png');
document.body.appendChild(img);
}
// use MediaDevices API
// docs: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
if (navigator.mediaDevices) {
// access the web cam
navigator.mediaDevices.getUserMedia({video: true})
// permission granted:
.then(function(stream) {
video.srcObject = stream;
video.addEventListener('click', takeSnapshot);
})
// permission denied:
.catch(function(error) {
document.body.textContent = 'Could not access the camera. Error: ' + error.name;
});
}
})();
Need help!

html5 canvas toDataURL returns blank image

i am using following code to draw canvas and save it as png image using toDataUrl.
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
#myCanvas {
border: 1px solid #9C9898;
}
</style>
<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];
}
}
window.onload = function(images) {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var sources = {
darthVader: "http://a1.sphotos.ak.fbcdn.net/hphotos-ak-snc6/228564_449431448422343_1996991887_n.jpg",
yoda: "http://a4.sphotos.ak.fbcdn.net/hphotos-ak-snc7/427489_449423165089838_503188418_n.jpg"
};
loadImages(sources, function(images) {
context.drawImage(images.darthVader, 250, 30, 250, 250);
context.drawImage(images.yoda, 530, 30, 250, 250);
});
// save canvas image as data url (png format by default)
var dataURL = canvas.toDataURL();
// set canvasImg image src to dataURL
// so it can be saved as an image
document.getElementById("canvasImg").src = dataURL;
};
</script>
</head>
<body>
<canvas id="myCanvas" width="850" height="315"></canvas>
<img id="canvasImg" alt="Right click to save me!">
</body>
</html>
But my png image is shown as blank image. i see only a blank white image.
i searched for this but found nothing on this.
i am using php and chrome browser.
what is wrong here?
You are first calling loadImages, then getting the data URL right after that loadImages call. However, as your loadImages implementation shows, calling it merely starts the loading process; the callback is called when all images have been loaded, which is some time in the future.
Currently you're getting a blank image because the images have not been loaded yet, so your callback is not called yet, and as a result your canvas is still empty.
In short, everything that relies on the images having being loaded (e.g. your expected toDataURL result) should be executed when those images are actually loaded - thus in the callback.
loadImages(sources, function(images) {
context.drawImage(images.darthVader, 250, 30, 250, 250);
context.drawImage(images.yoda, 530, 30, 250, 250);
var dataURL = canvas.toDataURL();
document.getElementById("canvasImg").src = dataURL;
});

Categories

Resources