Is there a way to render html to image like PNG? I know that it is possible with canvas but I would like to render standard html element like div for example.
I know this is quite an old question which already has a lot of answers, yet I still spent hours trying to actually do what I wanted:
Using Chrome headless (version 74.0.3729.157 as of this response), it is actually easy:
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --headless --screenshot --window-size=256,256 --default-background-color=0 button.html
Explanation of the command:
--headless
runs Chrome without opening it and exits after the command completes--screenshot
will capture a screenshot (note that it generates a file called screenshot.png
in the folder where the command is run)--window-size
allow to only capture a portion of the screen (format is --window-size=width,height
)--default-background-color=0
is the magic trick that tells Chrome to use a transparent background, not the default white colorYes. HTML2Canvas exists to render HTML onto <canvas>
(which you can then use as an image).
NOTE: There is a known issue, that this will not work with SVG
May I recommend dom-to-image library, that was written solely to address this problem (I'm the maintainer).
Here is how you use it (some more here):
var node = document.getElementById('my-node');
domtoimage.toPng(node)
.then (function (dataUrl) {
var img = new Image();
img.src = dataUrl;
document.appendChild(img);
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});
There is a lot of options and they all have their pro and cons.
Pros
Cons
Pros
Cons
Pros
Cons
Pros
Cons
Disclosure: I'm the founder of ApiFlash. I did my best to provide an honest and useful answer.
All the answers here use third party libraries while rendering HTML to an image can be relatively simple in pure Javascript. There is was even an article about it on the canvas section on MDN.
The trick is this:
drawImage
onto the canvasconst {body} = document
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = canvas.height = 100
const tempImg = document.createElement('img')
tempImg.addEventListener('load', onTempImageLoad)
tempImg.src = 'data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml"><style>em{color:red;}</style><em>I</em> lick <span>cheese</span></div></foreignObject></svg>')
const targetImg = document.createElement('img')
body.appendChild(targetImg)
function onTempImageLoad(e){
ctx.drawImage(e.target, 0, 0)
targetImg.src = canvas.toDataURL()
}
Some things to note
You could use PhantomJS, which is a headless webkit (the rendering engine in safari and (up until recently) chrome) driver. You can learn how to do screen capture of pages here. Hope that helps!
You can use an HTML to PDF tool like wkhtmltopdf. And then you can use a PDF to image tool like imagemagick. Admittedly this is server side and a very convoluted process...
The only library that I got to work for Chrome, Firefox and MS Edge was rasterizeHTML. It outputs better quality that HTML2Canvas and is still supported unlike HTML2Canvas.
Getting Element and Downloading as PNG
var node= document.getElementById("elementId");
var canvas = document.createElement("canvas");
canvas.height = node.offsetHeight;
canvas.width = node.offsetWidth;
var name = "test.png"
rasterizeHTML.drawHTML(node.outerHTML, canvas)
.then(function (renderResult) {
if (navigator.msSaveBlob) {
window.navigator.msSaveBlob(canvas.msToBlob(), name);
} else {
const a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
a.href = canvas.toDataURL();
a.download = name;
a.click();
document.body.removeChild(a);
}
});
I don't expect this to be the best answer, but it seemed interesting enough to post.
Write an app that opens up your favorite browser to the desired HTML document, sizes the window properly, and takes a screen shot. Then, remove the borders of the image.
Use html2canvas just include plugin and call method to convert HTML to Canvas then download as image PNG
html2canvas(document.getElementById("image-wrap")).then(function(canvas) {
var link = document.createElement("a");
document.body.appendChild(link);
link.download = "manpower_efficiency.jpg";
link.href = canvas.toDataURL();
link.target = '_blank';
link.click();
});
Source: http://www.freakyjolly.com/convert-html-document-into-image-jpg-png-from-canvas/
Use this code, it will surely work:
<script type="text/javascript">
$(document).ready(function () {
setTimeout(function(){
downloadImage();
},1000)
});
function downloadImage(){
html2canvas(document.querySelector("#dvContainer")).then(canvas => {
a = document.createElement('a');
document.body.appendChild(a);
a.download = "test.png";
a.href = canvas.toDataURL();
a.click();
});
}
</script>
Just do not forget to include Html2CanvasJS file in your program. https://html2canvas.hertzen.com/dist/html2canvas.js
You can't do this 100% accurately with JavaScript alone.
There's a Qt Webkit tool out there, and a python version. If you want to do it yourself, I've had success with Cocoa:
[self startTraverse:pagesArray performBlock:^(int collectionIndex, int pageIndex) {
NSString *locale = [self selectedLocale];
NSRect offscreenRect = NSMakeRect(0.0, 0.0, webView.frame.size.width, webView.frame.size.height);
NSBitmapImageRep* offscreenRep = nil;
offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
pixelsWide:offscreenRect.size.width
pixelsHigh:offscreenRect.size.height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSCalibratedRGBColorSpace
bitmapFormat:0
bytesPerRow:(4 * offscreenRect.size.width)
bitsPerPixel:32];
[NSGraphicsContext saveGraphicsState];
NSGraphicsContext *bitmapContext = [NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep];
[NSGraphicsContext setCurrentContext:bitmapContext];
[webView displayRectIgnoringOpacity:offscreenRect inContext:bitmapContext];
[NSGraphicsContext restoreGraphicsState];
// Create a small + large thumbs
NSImage *smallThumbImage = [[NSImage alloc] initWithSize:thumbSizeSmall];
NSImage *largeThumbImage = [[NSImage alloc] initWithSize:thumbSizeLarge];
[smallThumbImage lockFocus];
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
[offscreenRep drawInRect:CGRectMake(0, 0, thumbSizeSmall.width, thumbSizeSmall.height)];
NSBitmapImageRep *smallThumbOutput = [[NSBitmapImageRep alloc] initWithFocusedViewRect:CGRectMake(0, 0, thumbSizeSmall.width, thumbSizeSmall.height)];
[smallThumbImage unlockFocus];
[largeThumbImage lockFocus];
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
[offscreenRep drawInRect:CGRectMake(0, 0, thumbSizeLarge.width, thumbSizeLarge.height)];
NSBitmapImageRep *largeThumbOutput = [[NSBitmapImageRep alloc] initWithFocusedViewRect:CGRectMake(0, 0, thumbSizeLarge.width, thumbSizeLarge.height)];
[largeThumbImage unlockFocus];
// Write out small
NSString *writePathSmall = [issueProvider.imageDestinationPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@-collection-%03d-page-%03d_small.png", locale, collectionIndex, pageIndex]];
NSData *dataSmall = [smallThumbOutput representationUsingType:NSPNGFileType properties: nil];
[dataSmall writeToFile:writePathSmall atomically: NO];
// Write out lage
NSString *writePathLarge = [issueProvider.imageDestinationPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@-collection-%03d-page-%03d_large.png", locale, collectionIndex, pageIndex]];
NSData *dataLarge = [largeThumbOutput representationUsingType:NSPNGFileType properties: nil];
[dataLarge writeToFile:writePathLarge atomically: NO];
}];
Hope this helps!
Install phantomjs
$ npm install phantomjs
Create a file github.js with following code
var page = require('webpage').create();
//viewportSize being the actual size of the headless browser
page.viewportSize = { width: 1024, height: 768 };
page.open('http://github.com/', function() {
page.render('github.png');
phantom.exit();
});
Pass the file as argument to phantomjs
$ phantomjs github.js
You certainly can. GrabzIt's JavaScript API allows you to capture a div from a webpage like this:
<script type="text/javascript" src="grabzit.min.js"></script>
<script type="text/javascript">
GrabzIt("Your Application Key").ConvertURL("http://www.example.com/my-page.html",
{"target": "#features", "bheight": -1, "height": -1, "width": -1}).Create();
</script>
Where #features is the ID of the div to capture. If you wanted to convert HTML to a image. You could use this technique:
GrabzIt("Your Application Key").ConvertHTML(
"<html><body><h1>Hello World!</h1></body></html>").Create();
Disclaimer I built this API!
HtmlToImage.jar will be the simplest way to convert a html into an image
You can add reference HtmlRenderer to your project and do the following,
string htmlCode ="<p>This is a sample html.</p>";
Image image = HtmlRender.RenderToImage(htmlCode ,new Size(500,300));
I read the answer by Sjeiti which I found very interesting, where you with just a few plain javascript lines can render HTML in an image. We of course have to be aware of the limitations of this method (please read about some of them in his answer). Though I think his code was a bit convoluted. Perhaps there was a need for that which I don't understand.
But here is my cleaned up, or simplified, version of his code. One thing I realized is that my code renders much better resolution than his code, which you can easily see if you zoom in.
const body = document.getElementsByTagName('BODY')[0];
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = canvas.height = 200
const img = document.createElement('img')
img.src = 'data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml"><style>em{color:red;}</style>What you see here is only an image, nothing else.<br /><br /><em>I</em> really like <span>cheese.</span><br /><br />Zoom in to check the resolution!</div></foreignObject></svg>')
body.appendChild(img);
©2020 All rights reserved.