Capture HTML Canvas as gif/jpg/png/pdf?
Solution 1
Original answer was specific to a similar question. This has been revised:
const canvas = document.getElementById('mycanvas')
const img = canvas.toDataURL('image/png')
with the value in IMG you can write it out as a new Image like so:
document.getElementById('existing-image-id').src = img
or
document.write('<img src="'+img+'"/>');
Solution 2
HTML5 provides Canvas.toDataURL(mimetype) which is implemented in Opera, Firefox, and Safari 4 beta. There are a number of security restrictions, however (mostly to do with drawing content from another origin onto the canvas).
So you don't need an additional library.
e.g.
<canvas id=canvas width=200 height=200></canvas>
<script>
window.onload = function() {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.fillStyle = "green";
context.fillRect(50, 50, 100, 100);
// no argument defaults to image/png; image/jpeg, etc also work on some
// implementations -- image/png is the only one that must be supported per spec.
window.location = canvas.toDataURL("image/png");
}
</script>
Theoretically this should create and then navigate to an image with a green square in the middle of it, but I haven't tested.
Solution 3
I thought I'd extend the scope of this question a bit, with some useful tidbits on the matter.
In order to get the canvas as an image, you should do the following:
var canvas = document.getElementById("mycanvas");
var image = canvas.toDataURL("image/png");
You can use this to write the image to the page:
document.write('<img src="'+image+'"/>');
Where "image/png" is a mime type (png is the only one that must be supported). If you would like an array of the supported types you can do something along the lines of this:
var imageMimes = ['image/png', 'image/bmp', 'image/gif', 'image/jpeg', 'image/tiff']; //Extend as necessary
var acceptedMimes = new Array();
for(i = 0; i < imageMimes.length; i++) {
if(canvas.toDataURL(imageMimes[i]).search(imageMimes[i])>=0) {
acceptedMimes[acceptedMimes.length] = imageMimes[i];
}
}
You only need to run this once per page - it should never change through a page's lifecycle.
If you wish to make the user download the file as it is saved you can do the following:
var canvas = document.getElementById("mycanvas");
var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"); //Convert image to 'octet-stream' (Just a download, really)
window.location.href = image;
If you're using that with different mime types, be sure to change both instances of image/png, but not the image/octet-stream. It is also worth mentioning that if you use any cross-domain resources in rendering your canvas, you will encounter a security error when you try to use the toDataUrl method.
Solution 4
function exportCanvasAsPNG(id, fileName) {
var canvasElement = document.getElementById(id);
var MIME_TYPE = "image/png";
var imgURL = canvasElement.toDataURL(MIME_TYPE);
var dlLink = document.createElement('a');
dlLink.download = fileName;
dlLink.href = imgURL;
dlLink.dataset.downloadurl = [MIME_TYPE, dlLink.download, dlLink.href].join(':');
document.body.appendChild(dlLink);
dlLink.click();
document.body.removeChild(dlLink);
}
Solution 5
I would use "wkhtmltopdf". It just work great. It uses webkit engine (used in Chrome, Safari, etc.), and it is very easy to use:
wkhtmltopdf stackoverflow.com/questions/923885/ this_question.pdf
That's it!
Comments
-
nosid almost 2 years
Is it possible to capture or print what's displayed in an html canvas as an image or pdf?
I'd like to generate an image via canvas, and be able to generate a png from that image.
-
nosid over 13 yearsThanks michael, looks like getContext together with toDataURL would do it
-
Surya almost 13 yearsone more question, how can I save the image I got in this tag to server. Any guess??
-
Erik Karulf almost 13 years@Surya - In the example above, I would use AJAX to POST the img variable to the server. Alternatively, you could set the value of a hidden field in a form.
-
alemomo about 12 yearsI'm in the wkhtmltopdf camp, too. We've been using it for archiving and its AMAZING.
-
jnthnclrk over 11 yearsIs this technique suitable for making a screenshot of a web page?
-
llamerr over 11 years@jnthnclrk I don't think so, since it's only saving canvas (until all your page is a canvas)
-
llamerr over 11 years@jnthnclrk you can take a look for screenshot making at screengrab addon for firefox sources (and seems for chrome too?) - code.google.com/p/screengrab/source/browse/trunk/src/chrome/… maybe it will help
-
chinna_82 almost 11 yearsWhere the image will be saved. Location in my local?
-
johndodo over 10 years+1: PhantomJS is simple, well documented and well thought-out system, perfect for this job. It allows much more than just grabbing a canvas too - for instance, you can modify the page or part of it (through JS) before grabbing so make it look just the way you want it. Perfect!
-
So4ne over 10 yearsWith your solution for downloading the file, I must choose the software I want to use, it's a bit unconvenient... Is there a way to re-replace the mime as png once downloaded?
-
gauti over 10 yearsBut if i use var img = canvas.toDataURL("image/jpeg"); am getting the background as complete black. How to rectify that
-
donohoe over 10 years@Gauti Likely a browser issue. JPEG isn't supported by all (should work on Chrome/Firefox though)
-
meiamsome over 10 years@So4ne I don't think so, it has to be an image/octet-stream to prompt the user for a download. If you get rid of that line, you'll end up with the page redirecting to the image. I would love to know if someone else knows a way to do this nicely, though.
-
meiamsome over 10 years@Gauti It's likely your background is the RGBA colour (0,0,0,0) i.e. completely transparent black. JPEG does not support transparency and so this is converted to just be black I think.
-
Kai Carver about 10 yearsthe image will be displayed as an image in your browser. You can then save it to disk or whatever. Here's a quick and dirty generic "Canvas2PNG" bookmarklet that converts the first canvas in the page to PNG and displays it in the browser in a new window:
javascript:void(window.open().location = document.getElementsByTagName("canvas")[0].toDataURL("image/png"))
-
confile almost 10 years@donohoe This is not working on IOS7 when the canvas contains an SVG image.
-
donohoe almost 10 yearsOh come on. I answered this in 2009. What do you expect?
-
Alan Wells almost 10 yearsInstead of using
document.write()
you can use:document.getElementById('theID_of_a_DIV_to_Wrap_IMG_In').innerHTML = "<img src='" + img + "'>";
-
j6m8 almost 10 yearsDo note that the only usage of jQuery here is the selection of the canvas.
.toDataURL
is native JS. -
Ramesh S over 9 yearsI have save issue some one can help me see this link :stackoverflow.com/questions/25131763/…
-
Ax3l over 9 yearsusing target="_blank" on <a> link and .click() it should work, too to trigger the download (tested with FF data-urls and download="filename" for text/csv and text/plain)
-
jahu about 9 yearsIf the image is a few MB in size, prepare to crash your browser (I did that a while back in FireFox).
-
Naeel Maqsudov about 9 yearsPure (100%) jQuery solution is the following:
$('<img>').attr('src',$('#mycanvas')[0].toDataURL('image/png')).appendTo($('#element-to-write-to').empty());
Exactly one line. -
ElectroBit about 9 yearsWorks for me right now, but somehow not a year ago or so. I knew about this before, but it didn't work before.
-
msciwoj about 9 yearsdoesn't work for me - for
png
I get transparent box image (no visible data), forjpeg
the same as reported above - all black. Any ideas? -
nick almost 9 years@donohoe actually you answered it in August 2010 :)
-
Chief Alchemist almost 9 yearsThis is great. Thanks! But what if I want to save to server and not local? Will a form file input accept the img src as something that is uploadable?
-
Chief Alchemist almost 9 yearsOops. Just found the answer. Leaving the previous question in case someone else is looking as well stackoverflow.com/questions/13198131/…
-
Razi Syed over 8 yearsThis works except on Mac Safari when there is an embedded <image> tag. Safari ignores the image, whether the image is base64 or a link. Has anyone got in to this issue and resolved it? Would really like to know.
-
Greg0ry over 8 yearsI would only add this: be careful when you scale your image. If you let user manipulate scaled image (i.e. you only show small tile when dropping on google map) you probably want to keep original (usually much bigger) image in hidden img and use this as source you feed to canvas. Othervise you will get qyality of your image reduced since drawing img on canvas will take whatever size of your img.
-
Mentalist over 8 yearsHow can this be used to download multiple images?
-
Mentalist over 8 yearsHow could this be modified to render multiple images?
-
Oki Erie Rinaldi over 8 yearswhat about saving image from svg (not canvas)?
-
nullpointer about 8 yearsThe saved file stays in .svg format. How to save it as png?
-
khaled Dehia over 7 yearsHow to use WKHTMLtoPDF in page that required login info ? I am using Jsreport to convert to PDF but I capture my content with HTML2Canvas ,I have issue with sending the Canvas as parameter to JSreport
-
lepe over 7 years@khaledDehia check: stackoverflow.com/questions/10287386/…
-
gman over 7 yearsIt would use a lot less memory to do something like
var img = new Image(); img.src = canvas.toDataURL(); document.body.appendChild(img);
. Thedocument.write
code is making the data URL, them making a HTML string, then putting a copy of that string in the DOM, the browser then has to parse that HTML string, put another copy on the image element, then parse it again to turn the data URL into image data, then finally it can show the image. For a screen size image that's a huge amount of memory/copying/parsing. Just a suggestion -
Jose Cherian almost 7 yearsThis is a nice solution except that it may not work on IE. Getting error "The data area passed to a system call is too small"
-
Ecker00 over 6 yearsIn Chrome it says "Network error", while in Firefox it works great. (On Linux)
-
Merc almost 6 yearsPhantomJs is now obsolete
-
Juha Syrjälä almost 6 yearsData URIs have max length, so there is upper limit on the size of an image that you can put to a data url.
-
JED over 5 years@DilaGurung you need to do
var img = canvas[0].toDataURL("image/png");
. See: stackoverflow.com/questions/8667458/todataurl-not-a-function -
M. D. P over 5 yearsif "/home/Desktop/dataset/" is my path and i want to save image as " image_1.jpg" , what changes i need to do --> ('<img src="'+img+'"/>'); ?? @donohoe
-
Umesh Patadiya over 5 yearsis it possible to export canvas as video in format like mp4?
-
sc0ttj almost 4 yearsPhantomJS is not "obsolete" - it is unmaintained.... It still supports most ES6 stuff, and is still the only modern/decent headless browser that works on x86 and does not need compiling. Therefore it still the only [proper] headless browser that works on various embedded or lightweight distros/systems.
-
ClownCoder over 3 yearsThis answer must be marked as the correct one and need to be upvoted. Thanks!
-
Vesper over 3 years@OkiErieRinaldi just make a canvas, draw that SVG over the canvas aaand... use this to grab the image just drawn.