guys!
I'm trying to make a demo using which a user will be able to capture an image from the web camera enabled through his browser and this image will be saved in the backend by passing it to a PHP service using AJAX call.
I'm able to capture as canvas but not being to convert it into image data.
I'm getting canvas is undefined error
Setup is pretty simple.
HTML
<video id="videoElement" autoplay></video>
<button id="snap">Snap Photo</button>
<canvas id="canvas" style="display:none" ></canvas>
JAVASCRIPT
// Grab elements, create settings, etc.
var video = document.getElementById('videoElement');
// Get access to the camera!
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
// Not adding `{ audio: true }` since we only want video now
navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {
video.src = window.URL.createObjectURL(stream);
video.play();
});
}
// Elements for taking the snapshot
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var video = document.getElementById('videoElement');
// Trigger photo take
document.getElementById("snap").addEventListener("click", function() {
var cann= context.drawImage(video, 0, 0, 640, 480); //draw canvas
//then convert canvas to image so i can obtain dataurl
//and pass it to another function using AJAX
var img= convertCanvasToImage(cann);
console.log(img);
});
// Converts canvas to an image
function convertCanvasToImage(canvas)
{
var image = new Image();
image.src = canvas.toDataURL("image/png");
return image;
}
I'm pretty new to this field. I have one more question. Will this work on latest browsers?
Can anyone help me figure out the mistake I made?
FIDDLE
Reference:
https://davidwalsh.name/browser-camera
https://davidwalsh.name/convert-canvas-image
Just call this
var img= convertCanvasToImage();
function convertCanvasToImage()
{
var image = new Image();
image.src = canvas.toDataURL("image/png");
return image;
}
No need to pass canvas as you defined canvas above. But if you have convertCanvasToImage function in another file then you can use
var img= convertCanvasToImage(canvas);
This may help.
function demoFromHTML() {
html2canvas(document.getElementById("talltweets"), {
onrendered: function(canvas) {
var imageData = canvas.toDataURL('image/png',1.0);
}
});
}
Pass canvas object instead of cann
var img= convertCanvasToImage(canvas);
If you can try to avoid dataURL and use blob instead - it will save you more memory and load images faster
$canvas.toBlob(function(blob){
var url = URL.createObjectURL(blob)
var img = new Image
img.onload = function() {
URL.revokeObjecURL(this.src)
}
img.src = url
console.log(blob)
console.log(url)
})
<canvas id="$canvas">
there is polyfills you can use to support canvas#toBlob
Related
Im currently making an app hosted by flask.
Im trying to take a drawing a user does on my canvas and then save it for them, the code below is what is meant to save my canvas:
$(document).on("click", "#savepng", function(){
canvas.isDrawingMode = false;
if(!window.localStorage){alert("This function is not supported by your browser."); return;}
console.log(canvas.toDataURL())
var html="<img src='"+canvas.toDataURL()+"' alt='canvas image'/>";
var newTab=window.open();
newTab.document.write(html);
});
The when I hit save a new tab is opened and no errors show but problem is the tab is blank when its mean to show my image, I did a console log on the toDataRrl value and its just a blank png even though I drew on the canvas every time ive tested it. Heres my code for creating a simple canvas to draw on:
<canvas id="sheet" width="400" height="400"></canvas>
<button id="savepng">Save as PNG</button>
var canvas = new fabric.Canvas('sheet', { isDrawingMode: true });
window.onload=function(){
var canvas = new fabric.Canvas('sheet');
canvas.isDrawingMode = true;
canvas.freeDrawingBrush.width = 5;
canvas.freeDrawingBrush.color = "#ff0000";
}
$(document).on("click", "#savepng", function() {
canvas.isDrawingMode = false;
var newTab = window.open();
var img = new Image();
img.onload = function() {
newTab.document.body.append(img);
}
img.src = canvas.toDataURL({
format: 'image/png'
});
});
You can make an image() element and onload event you append that image element to body. Here is jsFiddle Demo.
I'm converting images to base64 using canvas. What i need to do is convert those images and then show the result to the user (original image and base64 version). Everything works as expected with small images, but when i try to convert large images (>3MB) and the conversion time increases, the base64 version is empty.
This might be is caused because the result is shown before the toDataURL() function is completed.
I need to show the result after all the needed processing has ended, for testing purposes.
Here's my code:
var convertToBase64 = function(url, callback)
{
var image = new Image();
image.onload = function ()
{
//create canvas and draw image...
var imageData = canvas.toDataURL('image/png');
callback(imageData);
};
image.src = url;
};
convertToBase64('img/circle.png', function(imageData)
{
window.open(imageData);
});
Even though i'm using image.onload() with a callback, i'm unable to show the result after the toDataURL() has been processed.
What am i doing wrong?
UPDATE: I tried both the solutions below and they didn't work. I'm using AngularJS and Electron in this project. Any way i can force the code to be synchronous? Or maybe some solution using Promises?
UPDATE #2: #Kaiido pointed out that toDataURL() is in fact synchronous and this issue is more likely due to maximum URI length. Since i'm using Electron and the image preview was for testing purposes only, i'm going to save the file in a folder and analise it from there.
Your code seems absolutely fine. Not sure why isn't working you. Maybe, there are some issues with your browser. Perhaps try using a different one. Also you could use a custom event, which gets triggered when the image conversion is competed.
// using jQuery for custom event
function convertToBase64(url) {
var image = new Image();
image.src = url;
image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
var imageData = canvas.toDataURL();
$(document).trigger('conversionCompleted', imageData);
};
};
convertToBase64('4mb.jpg');
$(document).on('conversionCompleted', function(e, d) {
window.open(d);
});
This approach might work for you. It shows the image onscreen using the native html element, then draws it to a canvas, then converts the canvas to Base64, then clears the canvas and draws the converted image onto the canvas. You can then scroll between the top image (original) and the bottom image (converted). I tried it on large images and it takes a second or two for the second image to draw but it seems to work...
Html is here:
<img id="imageID">
<canvas id="myCanvas" style="width:400;height:400;">
</canvas>
Script is here:
var ctx;
function convertToBase64(url, callback)
{
var image = document.getElementById("imageID");
image.onload = function() {
var canvas = document.getElementById("myCanvas");
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
ctx = canvas.getContext("2d");
ctx.drawImage(image,0,0);
var imageData = canvas.toDataURL('image/png');
ctx.fillStyle ="#FFFFFF";
ctx.fillRect(0,0,canvas.width,canvas.height);
callback(imageData);
};
image.src = url;
};
var imagename = 'images/bigfiletest.jpg';
window.onload = function () {
convertToBase64(imagename, function(imageData) {
var myImage = new Image();
myImage.src = imageData;
ctx.drawImage(myImage,0,0);
});
}
Note that I also tried it without the callback and it worked fine as well...
I have an html canvas that shows a preview of an image when the image is selected in an input. This works in Chrome, but I can't seem to get it to work in Safari. Specifically - in Safari - the onchange="previewFile()" does not seem to call the previewFile function.
<canvas id="canvas" width="0" height="0"></canvas>
<h2>Upload a photo </h2>
<input type="file" onchange="previewFile()"><br>
<script type="text/javascript">
// setup the canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// grab the photo and display in canvas
var photo = new Image();
function previewFile() {
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.addEventListener("load", function () {
photo.src = reader.result;
canvas.height = photo.height;
canvas.width = photo.width;
ctx.drawImage(photo,0,0);
}, false);
if (file) {
reader.readAsDataURL(file);
}
}
</script>
Your problem is certainly due to the fact that you are not waiting for the image has loaded before you try to draw it on the canvas.
Even wen the source is a dataURI, the loading of the image is asynchronous, so you need to wrap your drawing operations in the image's onload event.
var photo = new Image();
photo.onload = function(){
canvas.height = photo.height;
...
}
...
reader.onload = function(){
// this will eventually trigger the image's onload event
photo.src = this.result;
}
But if all you need is to draw your image on the canvas, don't even use a FileReader, actually, the readAsDataURL() method should trigger a I'm doing something wrong error in your brain. Almost all you can do with a dataURI version of a Blob, you can also do it with the Blob itself, without computing it nor polluting the browser's memory.
For example, to display an image for user input, you can use URL.createObjectURL(blob) method.
// setup the canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// grab the photo and display in canvas
var photo = new Image();
// drawing operations should be in the mage's load event
photo.onload = function() {
// if you don't need to display this image elsewhere
URL.revokeObjectURL(this.src);
canvas.height = this.height;
canvas.width = this.width;
ctx.drawImage(this, 0, 0);
}
photo.onerror = function(e) {
console.warn('file format not recognised as a supported image');
}
file_input.onchange = function() {
// prefer 'this' over DOM selection
var file = this.files[0];
var url = URL.createObjectURL(file);
photo.src = url;
};
<canvas id="canvas" width="0" height="0"></canvas>
<h2>Upload a photo </h2>
<input type="file" id="file_input">
<br>
And for those who need to send this file to their server, use a FormData to send directly the Blob. If you really need a dataURI version, then convert it server-side.
Using JavaScript, I want to convert an img tag like this:
<img width="11" height="14" src="http://mysite/file.gif" alt="File Icon">
Into one with a dataurl like this:
<img width="11" height="14" src="data:image/gif;base64,R0lGODlhCwAOAMQfAP////7+/vj4+Hh4eHd3d/v7+/Dw8HV1dfLy8ubm5vX19e3t7fr6+nl5edra2nZ2dnx8fMHBwYODg/b29np6eujo6JGRkeHh4eTk5LCwsN3d3dfX13Jycp2dnevr6////yH5BAEAAB8ALAAAAAALAA4AAAVq4NFw1DNAX/o9imAsBtKpxKRd1+YEWUoIiUoiEWEAApIDMLGoRCyWiKThenkwDgeGMiggDLEXQkDoThCKNLpQDgjeAsY7MHgECgx8YR8oHwNHfwADBACGh4EDA4iGAYAEBAcQIg0Dk gcEIQA7" alt="File Icon">
Is this possible?
Here's how to get the data url of an image with fetch:
(async function() {
let blob = await fetch("https://example.com/image.png").then(r => r.blob());
let dataUrl = await new Promise(resolve => {
let reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.readAsDataURL(blob);
});
// now do something with `dataUrl`
})();
First, load the image into a canvas
var canvas = document.createElement("canvas");
context = canvas.getContext('2d');
make_base();
function make_base()
{
base_image = new Image();
base_image.src = 'img/base.png';
base_image.onload = function(){
context.drawImage(base_image, 100, 100);
}
}
Make sure to update the context.drawImage(base_image, 100, 100); to values appropriate for your application.
Source: https://stackoverflow.com/a/6011402/3969707
Then convert the canvas to data.
var jpegUrl = canvas.toDataURL("image/jpeg");
var pngUrl = canvas.toDataURL(); // PNG is the default
Source: https://stackoverflow.com/a/15685877/3969707
I'd solve this problem with a temporary canvas element with the same size of the image loaded:
function imageToUri(url, callback) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
var base_image = new Image();
base_image.src = url;
base_image.onload = function() {
canvas.width = base_image.width;
canvas.height = base_image.height;
ctx.drawImage(base_image, 0, 0);
callback(canvas.toDataURL('image/png'));
canvas.remove();
}
}
imageToUri('./assets/some_image.png', function(uri) {
console.log(uri);
});
This really isn't something you may want to do in JavaScript as it requires the image be parsed in JavaScript which is very slow. You would be loading the image and then putting the output of the function into the img tag, which doesn't save bandwidth, decrease complexity, or improve security.
Your best bet is to do this server-side. I've used this to great success in the past for generating pages which need to have absolutely no linked/referenced external resources. You can, for jsPDF, then use raw JavaScript or jQuery to get the data of an image to pass into the PDF creation process.
This will work everywhere and not rely on resorting to canvas which doesn't have full mobile browser support.
I have the following code :
function createImage(source) {
var pastedImage = new Image();
pastedImage.onload = function() {
document.write('<br><br><br>Image: <img src="'+pastedImage.src+'" height="700" width="700"/>');
}
pastedImage.src = source;
}
Here I am displaying the image through html image tag which I wrote in document.write and provide appropriate height and width to image.
My question is can it possible to displaying image into the canvas instead of html img tag? So that I can drag and crop that image as I want?
But how can I display it in canvas?
Further I want to implement save that image using PHP but for now let me know about previous issue.
Try This
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image(); // Create new img element
img.onload = function(){
// execute drawImage statements here This is essential as it waits till image is loaded before drawing it.
ctx.drawImage(img , 0, 0);
};
img.src = 'myImage.png'; // Set source path
Make sure the image is hosted in same domain as your site. Read this for Javascript Security Restrictions Same Origin Policy.
E.g. If your site is http://example.com/
then the Image should be hosted on http://example.com/../myImage.png
if you try http://facebook.com/..image/ or something then it will throw security error.
Use
CanvasRenderingContext2D.drawImage.
function createImage(source) {
var ctx = document.getElementById('canvas').getContext('2d');
var pastedImage = new Image();
pastedImage.onload = function(){
ctx.drawImage(pastedImage, 0, 0);
};
pastedImage = source;
}
Also MDN seems to be have nice examples.