How to save a canvas image with a specific filename - javascript

I have a web page that can show a live stream and then be able to snap shot the live stream.
I need to have a button that can save the image in the canvas with a specific file name of my own (it can be the date for today).
Badly need it. Thanks to those who will respond! :)
Here's the code:
<!DOCTYPE html>
<html>
<head>
<title>Video Live Stream</title>
<link rel="stylesheet" type="text/css" href="demo'.css"/>
</head>
<body>
<center>
<style>
<p>
video { border: 20px solid #ccc; display: block; margin: 0 0 -5px 0; }
#canvas { margin-top: 20px; border: 1px solid #ccc; display: block; }
</p>
</style>
</br>
<h3>Live Stream with Snap Shot</h3>
<div align="center">
<video style="position:relative;top:-75px;" id="video" width="600" height="600" autoplay="">
</video>
</div>
<div align="center">
<button style="position:relative;top:-60px;" id="snap" class="sexyButton">Snap Photo</button>
<canvas style="position:relative;top:-60px;" class="input" id="canvas" width="640" height="480"></canvas>
</div>
Download!
<script>
// Put event listeners into place
window.addEventListener("DOMContentLoaded", function() {
// Grab elements, create settings, etc.
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
video = document.getElementById("video"),
videoObj = { "video": true },
errBack = function(error) {
console.log("Video capture error: ", error.code);
};
// Put video listeners into place
if(navigator.getUserMedia) { // Standard
navigator.getUserMedia(videoObj, function(stream) {
video.src = stream;
video.play();
}, errBack);
} else if(navigator.webkitGetUserMedia) { // WebKit-prefixed
navigator.webkitGetUserMedia(videoObj, function(stream){
video.src = window.webkitURL.createObjectURL(stream);
video.play();
}, errBack);
} else if(navigator.mozGetUserMedia) { // WebKit-prefixed
navigator.mozGetUserMedia(videoObj, function(stream){
video.src = window.URL.createObjectURL(stream);
video.play();
}, errBack);
}
// Trigger photo take
document.getElementById("snap").addEventListener("click", function() {
context.drawImage(video, 0, 0, 640, 480);
});
}, false);
</script>
</center>
</body>
</html>

Automatic file Download
You can not guarantee a filename but you can suggest a filename. The client may override the filename as it is just a download request and subject to the clients download policies. Event if the user allows the file to save with the name given the browser may still change the name if the file exist in the download directory by appending to the filename (or other stuff depending on the browser).
Here is a simple download image function. It will attempt to save (via download) to the client's file system the image as a PNG with the given filename. Will take an image or canvas image.
Update
As pointed out by markE the download attribute that I use to set the filename is not supported on all browsers. So only browser that support the attribute will let you set the download name.
Further the function given will also not download if the MouseEvent object is not supported. I have added a legacy method fireEvent for older browsers namely IE otherwise the function will not download.
function saveAsPNG(image, filename){ // No IE <11 support. Chrome URL bug for large images may crash
var anchorElement, event, blob;
function image2Canvas(image){ // converts an image to canvas
function createCanvas(width, height){ // creates a canvas of width height
var can = document.createElement("canvas");
can.width = width;
can.height = height;
return can;
};
var newImage = createCanvas(img.width, img.height); // create new image
newImage.ctx = newImage.getContext("2d"); // get image context
newImage.ctx.drawImage(image, 0, 0); // draw the image onto the canvas
return newImage; // return the new image
}
if(image.toDataURL === undefined){ // does the image have the toDataURL function
image = image2Canvas(image); // No then convert to canvas
}
// if msToBlob and msSaveBlob then use them to save. IE >= 10
if(image.msToBlob !== undefined && navigator.msSaveBlob !== undefined){
blob = image.msToBlob();
navigator.msSaveBlob(blob, filename + ".png");
return;
}
anchorElement = document.createElement('a'); // Create a download link
anchorElement.href = image.toDataURL(); // attach the image data URL
// check for download attribute
if ( anchorElement.download !== undefined ) {
anchorElement.download = filename + ".png"; // set the download filename
if (typeof MouseEvent === "function") { // does the browser support the object MouseEvent
event = new MouseEvent( // yes create a new mouse click event
"click", {
view : window,
bubbles : true,
cancelable : true,
ctrlKey : false,
altKey : false,
shiftKey : false,
metaKey : false,
button : 0,
buttons : 1,
}
);
anchorElement.dispatchEvent(event); // simulate a click on the download link.
} else
if (anchorElement.fireEvent) { // if no MouseEvent object try fireEvent
anchorElement.fireEvent("onclick");
}
}
}
To use the function
saveAsPNG(canvas,"MyTest"); // Will attempt to save the canvas as "MyTest.png"
This does not guarantee that the file will be saved or that the filename will be what you want. If you want to guarantee a filename you must then save the file inside a zip file. This is a lot of work and still does not guarantee that the file will be saved. Security dictates that the client must have the right to accept or reject any download request. There is no way to side step this.

I just found a way to save the canvas image with the filename of your own. You can find it at
http://eligrey.com/demos/FileSaver.js/
edit the canvas part:
<section id="image-demo">
<form id="canvas-options">
<label>Filename: <input type="text" class="filename" id="canvas-filename" placeholder="filename"/>.png</label>
<input type="submit" value="Save"/>
<input type="button" id="canvas-clear" value="Clear"/>
</form>
and insert the following scripts:
<script type="application/ecmascript" async="" src="Blob.js"/>
<script type="application/ecmascript" async="" src="canvas-toBlob.js"/>
<script type="application/ecmascript" async="" src="FileSaver.js"/>
<script type="application/ecmascript">
It worked!

Related

Download a div as an image [duplicate]

This is the code which I am using to convert div into image and download that using html2canvas.js
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://html2canvas.hertzen.com/build/html2canvas.js"></script>
<style>
#download{
margin:10% 40%;
}
.download-btn{
padding:10px;
font-size:20px;
margin:0 20px;
}
#test{
background:#3399cc;
padding:50px;
}
.x2{
transform: scale(2,2);
}
</style>
<div id="download">
<h1 id="test">Testing Download</h1>
</div>
<center>
<button id="download-window" class="download-btn">New Window</button>
<button id="download-png" class="download-btn">Download png</button>
<button id="download-jpg" class="download-btn">Download jpg</button>
<button id="download-pngx2" class="download-btn">Download pngx2</button>
</center>
<script>
$('#download-window').click(function(){
html2canvas($('#download'),
{
onrendered: function (canvas) {
var img = canvas.toDataURL("image/png");
window.open(img);
}
});
});
$('#download-png').click(function(){
html2canvas($('#download'),
{
onrendered: function (canvas) {
var a = document.createElement('a');
a.href = canvas.toDataURL("image/png");
a.download = 'image.png';
a.click();
}
});
});
$('#download-pngx2').click(function(){
$('#download').addClass('x2');
html2canvas($('#download'),
{
onrendered: function (canvas) {
var a = document.createElement('a');
a.href = canvas.toDataURL("image/png");
a.download = 'image.png';
a.click();
}
});
});
$('#download-jpg').click(function(){
html2canvas($('#download'),
{
onrendered: function (canvas) {
var a = document.createElement('a');
// toDataURL defaults to png, so we need to request a jpeg, then convert for file download.
a.href = canvas.toDataURL("image/jpeg").replace("image/jpeg", "image/octet-stream");
a.download = 'image.jpg';
a.click();
}
});
});
</script>
Here image generated is not having good resolution.
Is there any other way to generate image with good resolution?
Can php function be used for doing this task?
Here is a simple way to do this.
<div id="my-node">
You will get a image downloaded.
</div>
<button id="foo">download img</button>
<script>
var node = document.getElementById('my-node');
var btn = document.getElementById('foo');
btn.onclick = function() {
node.innerHTML = "I'm an image now."
domtoimage.toBlob(document.getElementById('my-node'))
.then(function(blob) {
window.saveAs(blob, 'my-node.png');
});
}
</script>
Here is a demo: this JSFiddle.
In this fiddle, two libraries are used:
dom-to-image: https://github.com/tsayen/dom-to-image
FileSaver.js: https://github.com/eligrey/FileSaver.js/
First one is used to turn dom into image, second one is used to download the image.
Update:
If you want to get a img of base64 instead of just downloading img as the blob format. You can do as below:
domToImage
.toBlob(document.getElementById("my-node"))
.then(function(blob) {
saveBlobAsFile(blob, "XX.png");
});
// this function is to convert blob to base64 img
function saveBlobAsFile(blob, fileName) {
var reader = new FileReader();
reader.onloadend = function() {
var base64 = reader.result;
var img = document.createElement("img");
img.classList.add("me-img");
img.setAttribute("src", base64);
// insert the img to dom
document.getElementById("bar").appendChild(img);
};
reader.readAsDataURL(blob);
}
Here FileSaver.js is not needed, we use html5 api FileReader to do the trick.
Increase resolution by making more pixels
Resolution kind of equals pixel density. If you want greater resolution then one attempt to create more pixels is to create a second canvas with a proportionally larger width & height and then use secondaryContext.scale & secondaryContext.drawImage(mainCanvas,0,0) to enlarge & draw the main canvas content onto the second canvas. Use this larger canvas, for example, on a printer.
Here's an example that increases the pixel density at the cost of some clarity. You don't state why you desire more resolution, but this example is useful, for example if you're outputting the image to a printer. Note: The printed page will be clearer than the density-increased image you feed to the printer because the printer prints at higher density (maybe 300dpi printer resolution vs maybe 72/96ppi).
var divX2=document.createElement('canvas');
divAt2X('#download',1.5);
$('#go').on('click',function(){
// save
var a = document.createElement('a');
a.href = divX2.toDataURL("image/png");
a.download = 'image.png';
a.click();
});
function divAt2X(id,upscale){
var w=$(id).width();
var h=$(id).height();
html2canvas($(id),{
onrendered:
function(canvasDiv){
// scale up
ctx=divX2.getContext('2d');
divX2.width=w*upscale;
divX2.height=h*upscale;
ctx.scale(upscale,upscale);
ctx.drawImage(canvasDiv,0,0);
}
}
);
}
#download{
margin:10% 20%;
}
.download-btn{
padding:10px;
font-size:20px;
margin:0 20px;
}
#test{
background:#3399cc;
padding:50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src='https://html2canvas.hertzen.com/build/html2canvas.js'></script>
<button id='go'>Download 1.5X</button><span>(IE/Edge don't support download)</span>
<div id="download"><h1 id="test">Testing Download</h1></div>
If you have already dismissed html2Canvas, then your way forward is more difficult because html2Canvas is one (perhaps the only one) tool we have to read html+css and draw them to the canvas element.
Increase resolution with an image manipulation library
You can use the ImageMagick library. In particular, the ImageMagick resize method will change the embedded resolution of a .png image using resampling for better quality.
Use a headless-browser on the server to capture the Div
If you need cross-browser compatibility, then you can use a server-size headless browser like PhantomJS.
The captureJS extension to PhantomJS allows you to specify a target div using standard CSS selectors. CaptureJS lets you specify the viewport size -- effectively letting you increase the pixel density.
One good approach that we've used at work in a production system for 1M+ daily users is to do this completely on the server side - spawn a browser (Chrome); then take a screenshot of it; then stream it to the client. The results are very clear / not pixelated at all - all of the other options turned out quite pixelated.

HTML canvas not producing image from web cam

I want to capture image every time socket.on('takePic') gets triggered. It works fine for the first time. but when the socket.on('takePic') gets triggered second time,the canvas div is just blank and so the img tag.
I have copied the takePicture() function from somewhere and added the setInterval() and localstream variable to stop camera.
how can I fix this?
here is my js code.
const socket = io('http://localhost:3001');
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
let roomId = params.roomId;
socket.emit('joinRoom',roomId);
var takePicture = function () {
// The width and height of the captured photo. We will set the
// width to the value defined here, but the height will be
// calculated based on the aspect ratio of the input stream.
var width = 320; // We will scale the photo width to this
var height = 0; // This will be computed based on the input stream
// |streaming| indicates whether or not we're currently streaming
// video from the camera. Obviously, we start at false.
var streaming = false;
var localstream;
// The various HTML elements we need to configure or control. These
// will be set by the startup() function.
var video = null;
var canvas = null;
var photo = null;
var startbutton = null;
function showViewLiveResultButton() {
if (window.self !== window.top) {
// Ensure that if our document is in a frame, we get the user
// to first open it in its own tab or window. Otherwise, it
// won't be able to request permission for camera access.
document.querySelector(".contentarea").remove();
const button = document.createElement("button");
button.textContent = "View live result of the example code above";
document.body.append(button);
button.addEventListener('click', () => window.open(location.href));
return true;
}
return false;
}
function startup() {
if (showViewLiveResultButton()) { return; }
video = document.getElementById('video');
canvas = document.getElementById('canvas');
photo = document.getElementById('photo');
startbutton = document.getElementById('startbutton');
navigator.mediaDevices.getUserMedia({video: true, audio: false})
.then(function(stream) {
video.srcObject = stream;
localstream = stream;
video.play();
})
.catch(function(err) {
console.log("An error occurred: " + err);
});
video.addEventListener('canplay', function(ev){
if (!streaming) {
height = video.videoHeight / (video.videoWidth/width);
// Firefox currently has a bug where the height can't be read from
// the video, so we will make assumptions if this happens.
if (isNaN(height)) {
height = width / (4/3);
}
video.setAttribute('width', width);
video.setAttribute('height', height);
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
streaming = true;
}
}, false);
startbutton.addEventListener('click', function(ev){
takepicture();
ev.preventDefault();
clearInterval(picInterval);
$('#heading').css('display','none')
video.pause();
video.src = "";
localstream.getTracks()[0].stop();
}, false);
clearphoto();
}
// Fill the photo with an indication that none has been
// captured.
function clearphoto() {
var context = canvas.getContext('2d');
context.fillStyle = "#AAA";
context.fillRect(0, 0, canvas.width, canvas.height);
var data = canvas.toDataURL('image/png');
photo.setAttribute('src', data);
}
// Capture a photo by fetching the current contents of the video
// and drawing it into a canvas, then converting that to a PNG
// format data URL. By drawing it on an offscreen canvas and then
// drawing that to the screen, we can change its size and/or apply
// other changes before drawing it.
function takepicture() {
var context = canvas.getContext('2d');
if (width && height) {
canvas.width = width;
canvas.height = height;
context.drawImage(video, 0, 0, width, height);
var data = canvas.toDataURL('image/png');
photo.setAttribute('src', data);
} else {
clearphoto();
}
}
// Set up our event listener to run the startup process
// once loading is complete.
startup();
var i = 10;
let picInterval = setInterval(()=>{
i -= 1;
$('#heading').html(`taking picture in ${i}`);
if(i==0){
$('#startbutton').click()
}
}, 1000)
}
socket.on('takePic',()=>{
takePicture()
})
and this is the html code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>StudentVideo</title>
<link rel="stylesheet" href="css/studentVideo.css">
</head>
<body>
<div class="contentarea">
<h1 id="heading">
</h1>
<p>
This example demonstrates how to set up a media stream using your built-in webcam, fetch an image from that stream, and create a PNG using that image.
</p>
<div class="camera">
<video id="video" width="320" height="240">Video stream not available.</video>
<button id="startbutton">Take photo</button>
</div>
<canvas id="canvas" width="320" height="240">
</canvas>
<div class="output">
<img id="photo" alt="The screen capture will appear in this box." src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAACWCAYAAABkW7XSAAAAAXNSR0IArs4c6QAABGlJREFUeF7t1AEJADAMA8HVv5Oa3GAuHq4KwqVkdvceR4AAgYDAGKxASyISIPAFDJZHIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRB46/vA5AUJNVYAAAAASUVORK5CYII=">
</div>
<p>
Visit our article Taking still photos with WebRTC to learn more about the technologies used here.
</p>
</div>
</body>
<script src="https://cdn.socket.io/socket.io-3.0.1.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="js/video.js"></script>
</html>
In the click handler of #startbutton your code calls takepicture and then it goes on to remove the video's src and stop the MediaStream.
So the next time this handler is called, there is no source affected to the video element and thus nothing to be drawn on the canvas anymore.
It's quire unclear why you clear the video in this click handler, so you might want to remove this part of the code, or to move it to a "stop" button instead, but anyway, you would probably be better calling takepicture from your interval directly rather than relying on the event handler.

how to Add a watermark to a pic already cropped?

basically people take a pic with their phone and I should crop the pic and add a watermark.
how can I add a watermark to my picture?
my code below
function takeSnapshot(){
// Here we're using a trick that involves a hidden canvas element.
var hidden_canvas = document.querySelector('canvas'),
context = hidden_canvas.getContext('2d');
var width = 480,
height = 480;
hidden_canvas.width = width;
hidden_canvas.height = height;
// Make a copy of the current frame in the video on the canvas.
context.drawImage(video, 100, 0, 480, 480, 0, 0, hidden_canvas.width, hidden_canvas.width);
// Turn the canvas image into a dataURL that can be used as a src for our photo.
return hidden_canvas.toDataURL('image/png');
}
html
<div class="container">
<div class="app">
Touch here to start the app.
<video id="camera-stream" width="640" height="480"></video>
<img id="snap">
<img src="http://localhost/selfie/face-pic.png" style="z-index:100;position:absolute; top:0;left:0;"/>
<p id="error-message"></p>
<div class="controls" style="z-index:200;">
<i class="material-icons">delete</i>
<i class="material-icons">camera_alt</i>
<i class="material-icons">file_download</i>
</div>
<!-- Hidden canvas element. Used for taking snapshot of video. -->
<canvas>
</canvas>
</div>
</div>
js
document.addEventListener('DOMContentLoaded', function () {
// References to all the element we will need.
var video = document.querySelector('#camera-stream'),
image = document.querySelector('#snap'),
start_camera = document.querySelector('#start-camera'),
controls = document.querySelector('.controls'),
take_photo_btn = document.querySelector('#take-photo'),
delete_photo_btn = document.querySelector('#delete-photo'),
download_photo_btn = document.querySelector('#download-photo'),
error_message = document.querySelector('#error-message');
// The getUserMedia interface is used for handling camera input.
// Some browsers need a prefix so here we're covering all the options
navigator.getMedia = ( navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
if(!navigator.getMedia){
displayErrorMessage("Your browser doesn't have support for the navigator.getUserMedia interface.");
}
else{
// Request the camera.
navigator.getMedia(
{
video: true
},
// Success Callback
function(stream){
// Create an object URL for the video stream and
// set it as src of our HTLM video element.
video.srcObject=stream;
// Play the video element to start the stream.
video.play();
video.onplay = function() {
showVideo();
};
},
// Error Callback
function(err){
displayErrorMessage("There was an error with accessing the camera stream: " + err.name, err);
}
);
}
// Mobile browsers cannot play video without user input,
// so here we're using a button to start it manually.
start_camera.addEventListener("click", function(e){
e.preventDefault();
// Start video playback manually.
video.play();
showVideo();
});
take_photo_btn.addEventListener("click", function(e){
e.preventDefault();
var snap = takeSnapshot();
// Show image.
image.setAttribute('src', snap);
image.classList.add("visible");
// Enable delete and save buttons
delete_photo_btn.classList.remove("disabled");
download_photo_btn.classList.remove("disabled");
// Set the href attribute of the download button to the snap url.
download_photo_btn.href = snap;
// Pause video playback of stream.
video.pause();
});
delete_photo_btn.addEventListener("click", function(e){
e.preventDefault();
// Hide image.
image.setAttribute('src', "");
image.classList.remove("visible");
// Disable delete and save buttons
delete_photo_btn.classList.add("disabled");
download_photo_btn.classList.add("disabled");
// Resume playback of stream.
video.play();
});
function showVideo(){
// Display the video stream and the controls.
hideUI();
video.classList.add("visible");
controls.classList.add("visible");
}
function takeSnapshot(){
// Here we're using a trick that involves a hidden canvas element.
var hidden_canvas = document.querySelector('canvas'),
context = hidden_canvas.getContext('2d');
var width = 480,
height = 480;
hidden_canvas.width = width;
hidden_canvas.height = height;
// Make a copy of the current frame in the video on the canvas.
context.drawImage(video, 100, 0, 480, 480, 0, 0, hidden_canvas.width, hidden_canvas.width);
// Turn the canvas image into a dataURL that can be used as a src for our photo.
return hidden_canvas.toDataURL('image/png');
}
function displayErrorMessage(error_msg, error){
error = error || "";
if(error){
console.error(error);
}
error_message.innerText = error_msg;
hideUI();
error_message.classList.add("visible");
}
function hideUI(){
// Helper function for clearing the app UI.
controls.classList.remove("visible");
start_camera.classList.remove("visible");
video.classList.remove("visible");
snap.classList.remove("visible");
error_message.classList.remove("visible");
}
});

bad output of canvas generated image

SO the code below is simply meant to allow users upload a video and then when the press the button 'choose thumbnail' an image is generated from a canvas which represents the current image which was showing when the video was playing...that is,the image becomes the thumbnail of the video which the user chooses by seeking a particular video time,pauses the video and creates the thumbnail which is an image of the video when it was paused.
Everything is going fine except that the image is too long..in a way...the image is created in the dimensions that I want BUT some a lot of extra white space is still counted as the image....that is a lot of white space round it is the image.
This screenshots may help...
var _CANVAS = document.querySelector("#myCanvas"),
_CTX = _CANVAS.getContext("2d"),
_VIDEO = document.querySelector("#main-video");
document.getElementById("image").src = _CANVAS.toDataURL();
function showit() {
document.getElementById("other").style.display = 'block';
}
// Upon click this should should trigger click on the #file-to-upload file input element
// This is better than showing the not-good-looking file input element
document.querySelector("#diver").addEventListener('click', function() {
document.querySelector("#file-to-upload").click();
});
// When user chooses a MP4 file
document.querySelector("#file-to-upload").addEventListener('change', function() {
// Validate whether MP4
if (['video/mp4'].indexOf(document.querySelector("#file-to-upload").files[0].type) == -1) {
alert('Error : Only MP4 format allowed');
return;
}
// Hide upload button
document.querySelector("#upload-button").style.display = 'none';
// Object Url as the video source
document.querySelector("#main-video source").setAttribute('src', URL.createObjectURL(document.querySelector("#file-to-upload").files[0]));
// Load the video and show it
_VIDEO.load();
_VIDEO.style.display = 'inline';
// Load metadata of the video to get video duration and dimensions
_VIDEO.addEventListener('loadedmetadata', function() {
console.log(_VIDEO.duration);
var video_duration = _VIDEO.duration,
duration_options_html = '';
// Set options in dropdown at 4 second interval
for (var i = 0; i < Math.floor(video_duration); i = i + 2) {
duration_options_html += '<option value="' + i + '">' + i + '</option>';
}
document.querySelector("#set-video-seconds").innerHTML = duration_options_html;
// Show the dropdown container
document.querySelector("#thumbnail-container").style.display = 'block';
// Set canvas dimensions same as video dimensions
_CANVAS.width = _VIDEO.videoWidth;
_CANVAS.height = _VIDEO.videoHeight;
});
});
// On changing the duration dropdown, seek the video to that duration
document.querySelector("#set-video-seconds").addEventListener('change', function() {
_VIDEO.currentTime = document.querySelector("#set-video-seconds").value;
// Seeking might take a few milliseconds, so disable the dropdown and hide download link
});
// Seeking video to the specified duration is complete
document.querySelector("#main-video").addEventListener('timeupdate', function() {
// Re-enable the dropdown and show the Download link
document.querySelector("#set-video-seconds").disabled = false;
document.querySelector("#get-thumbnail").style.display = 'inline';
});
// On clicking the Download button set the video in the canvas and download the base-64 encoded image data
document.querySelector("#get-thumbnail").addEventListener('click', function() {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.drawImage(_VIDEO, 1, 1, _VIDEO.videoWidth / 8, _VIDEO.videoHeight / 8);
document.getElementById("image").src = c.toDataURL();
});
document.querySelector("#get-thumbnail").setAttribute('href', c.toDataURL());
document.querySelector("#get-thumbnail").setAttribute('download', 'thumbnai.png');
body {
margin: 0;
}
#video-demo-container {
width: 400px;
margin: 40px auto;
}
#main-video {
display: none;
max-width: 400px;
}
#thumbnail-container {
display: none;
}
#get-thumbnail {
display: none;
}
#video-canvas {
display: block;
}
#upload-button {
width: 150px;
display: block;
margin: 20px auto;
}
#file-to-upload {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale = 1.0, maximum-scale = 1.0, user-scalable=no">
</head>
<body>
<div style="border:2px dashed blue;" id="diver">
<div id="video-demo-container">
<button id="upload-button">Select MP4 Video</button>
<input type="file" id="file-to-upload" accept="video/mp4" />
<video id="main-video" controls>
<source type="video/mp4">
</video>
<p id="yes"></p>
</div>
</div>
<p id="thumbnail-container"><button onclick="showit()">Confirm</button> <button>Undo</button></p>
<br>
<!-- other content to choose -->
<div style="border:2px solid green;display:none" id="other">
<br>
<div style="margin-left:10%;">
<p style="font-size:160%">
<font style="font-weight:bolder">(1)</font>Choose thumbnail</p>
<font style="font-weight:bolder;margin-left:3%;">(a)Choose from video clip:</font><br><br>
<div id="allfloat">
<div style="margin-left:5%;">
Seek to
<select id="set-video-seconds"></select> seconds <br><br>
<button id="get-thumbnail" href="#" style="text-decoration:none;background-color:blue;padding-left,padding-right:2%;color:white;">Create Thumbnail</button>
</div>
<p style="font-weight:bolder;margin-left:5%;">Thumbnail:</p>
<img id="image" src width="200%" height="200%" style="margin-left:5%">
</div>
</div>
</div>
<canvas id="myCanvas" style="display:none;">
Your browser does not support the HTML5 canvas tag.
</canvas>
u see what I'm talking about.the image is somehow so large but I can't see the 'large part' of the image.
Also,I don't know what they mean as 'c is undefined'
Thanks in advance...
(1) Fix c is undefined error :
Cut the var c and var ctx declarations from //On clicking the Download button section and paste them with your other var declarations. This will give it global access (not just local access for only that specific function) :
// when you do this part
var _CANVAS = document.querySelector("#myCanvas");
var _CTX = _CANVAS.getContext("2d");
var _VIDEO = document.querySelector("#main-video");
// also add this part below it
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
(2) Fix scale or quality :
When drawing the thumbnail with ctx.drawImage, use values of c.width and c.height. Example:
// On clicking the Download button set the video in the canvas and download the base-64 encoded image data
document.querySelector("#get-thumbnail").addEventListener('click', function() {
ctx.drawImage(_VIDEO, 1, 1, c.width, c.height); //use c.width not _VIDEO.videoWidth... etc
document.getElementById("image").src = c.toDataURL();
});
That should give a clear image at same size as video resolution.
Let me know how it goes. Thanks.

Convert div into downloadable Image

This is the code which I am using to convert div into image and download that using html2canvas.js
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://html2canvas.hertzen.com/build/html2canvas.js"></script>
<style>
#download{
margin:10% 40%;
}
.download-btn{
padding:10px;
font-size:20px;
margin:0 20px;
}
#test{
background:#3399cc;
padding:50px;
}
.x2{
transform: scale(2,2);
}
</style>
<div id="download">
<h1 id="test">Testing Download</h1>
</div>
<center>
<button id="download-window" class="download-btn">New Window</button>
<button id="download-png" class="download-btn">Download png</button>
<button id="download-jpg" class="download-btn">Download jpg</button>
<button id="download-pngx2" class="download-btn">Download pngx2</button>
</center>
<script>
$('#download-window').click(function(){
html2canvas($('#download'),
{
onrendered: function (canvas) {
var img = canvas.toDataURL("image/png");
window.open(img);
}
});
});
$('#download-png').click(function(){
html2canvas($('#download'),
{
onrendered: function (canvas) {
var a = document.createElement('a');
a.href = canvas.toDataURL("image/png");
a.download = 'image.png';
a.click();
}
});
});
$('#download-pngx2').click(function(){
$('#download').addClass('x2');
html2canvas($('#download'),
{
onrendered: function (canvas) {
var a = document.createElement('a');
a.href = canvas.toDataURL("image/png");
a.download = 'image.png';
a.click();
}
});
});
$('#download-jpg').click(function(){
html2canvas($('#download'),
{
onrendered: function (canvas) {
var a = document.createElement('a');
// toDataURL defaults to png, so we need to request a jpeg, then convert for file download.
a.href = canvas.toDataURL("image/jpeg").replace("image/jpeg", "image/octet-stream");
a.download = 'image.jpg';
a.click();
}
});
});
</script>
Here image generated is not having good resolution.
Is there any other way to generate image with good resolution?
Can php function be used for doing this task?
Here is a simple way to do this.
<div id="my-node">
You will get a image downloaded.
</div>
<button id="foo">download img</button>
<script>
var node = document.getElementById('my-node');
var btn = document.getElementById('foo');
btn.onclick = function() {
node.innerHTML = "I'm an image now."
domtoimage.toBlob(document.getElementById('my-node'))
.then(function(blob) {
window.saveAs(blob, 'my-node.png');
});
}
</script>
Here is a demo: this JSFiddle.
In this fiddle, two libraries are used:
dom-to-image: https://github.com/tsayen/dom-to-image
FileSaver.js: https://github.com/eligrey/FileSaver.js/
First one is used to turn dom into image, second one is used to download the image.
Update:
If you want to get a img of base64 instead of just downloading img as the blob format. You can do as below:
domToImage
.toBlob(document.getElementById("my-node"))
.then(function(blob) {
saveBlobAsFile(blob, "XX.png");
});
// this function is to convert blob to base64 img
function saveBlobAsFile(blob, fileName) {
var reader = new FileReader();
reader.onloadend = function() {
var base64 = reader.result;
var img = document.createElement("img");
img.classList.add("me-img");
img.setAttribute("src", base64);
// insert the img to dom
document.getElementById("bar").appendChild(img);
};
reader.readAsDataURL(blob);
}
Here FileSaver.js is not needed, we use html5 api FileReader to do the trick.
Increase resolution by making more pixels
Resolution kind of equals pixel density. If you want greater resolution then one attempt to create more pixels is to create a second canvas with a proportionally larger width & height and then use secondaryContext.scale & secondaryContext.drawImage(mainCanvas,0,0) to enlarge & draw the main canvas content onto the second canvas. Use this larger canvas, for example, on a printer.
Here's an example that increases the pixel density at the cost of some clarity. You don't state why you desire more resolution, but this example is useful, for example if you're outputting the image to a printer. Note: The printed page will be clearer than the density-increased image you feed to the printer because the printer prints at higher density (maybe 300dpi printer resolution vs maybe 72/96ppi).
var divX2=document.createElement('canvas');
divAt2X('#download',1.5);
$('#go').on('click',function(){
// save
var a = document.createElement('a');
a.href = divX2.toDataURL("image/png");
a.download = 'image.png';
a.click();
});
function divAt2X(id,upscale){
var w=$(id).width();
var h=$(id).height();
html2canvas($(id),{
onrendered:
function(canvasDiv){
// scale up
ctx=divX2.getContext('2d');
divX2.width=w*upscale;
divX2.height=h*upscale;
ctx.scale(upscale,upscale);
ctx.drawImage(canvasDiv,0,0);
}
}
);
}
#download{
margin:10% 20%;
}
.download-btn{
padding:10px;
font-size:20px;
margin:0 20px;
}
#test{
background:#3399cc;
padding:50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src='https://html2canvas.hertzen.com/build/html2canvas.js'></script>
<button id='go'>Download 1.5X</button><span>(IE/Edge don't support download)</span>
<div id="download"><h1 id="test">Testing Download</h1></div>
If you have already dismissed html2Canvas, then your way forward is more difficult because html2Canvas is one (perhaps the only one) tool we have to read html+css and draw them to the canvas element.
Increase resolution with an image manipulation library
You can use the ImageMagick library. In particular, the ImageMagick resize method will change the embedded resolution of a .png image using resampling for better quality.
Use a headless-browser on the server to capture the Div
If you need cross-browser compatibility, then you can use a server-size headless browser like PhantomJS.
The captureJS extension to PhantomJS allows you to specify a target div using standard CSS selectors. CaptureJS lets you specify the viewport size -- effectively letting you increase the pixel density.
One good approach that we've used at work in a production system for 1M+ daily users is to do this completely on the server side - spawn a browser (Chrome); then take a screenshot of it; then stream it to the client. The results are very clear / not pixelated at all - all of the other options turned out quite pixelated.

Categories