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.
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);
});
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));
HtmlToImage.jar will be the simplest way to convert a html into an image
Converting HTML to image using java
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).
Here I have taken his code a couple of steps further.
An SVG-image has in principle infinite resolution, since it is vector graphics. But you might have noticed that the image that Sjeiti's code generated did not have a high resolution. This can be fixed by scaling the SVG-image before transferring it to the canvas-element, which I have done in the last one of the two (runnable) example codes i give below. The other thing I have implemented in that code is the last step, namely saving it as a PNG-file. Just to complete the whole thing.
So, I give two runnable snippets of code:
The first one demonstrates the infinite resolution of an SVG. Run it and zoom in with your browser to see that the resolution does not diminish as you zoom in.
In the snippet that you can run I have used backticks to specify a so called template string with line breaks so that you can more clearly see the HTML that is rendered. But otherwise, if that HTML is within one line, then the code will be very short, like this.
const body = document.getElementsByTagName('BODY')[0];
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="border:1px solid red;padding:20px;"><style>em {color:red;}.test {color:blue;}</style>What you see here is only an image, nothing else.<br /><br /><em>I</em> really like <span class="test">cheese.</span><br /><br />Zoom in to check the resolution!</div></foreignObject></svg>`);
body.appendChild(img);
Here it comes as a runnable snippet.
const body = document.getElementsByTagName('BODY')[0];
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="border:1px solid red;padding:20px;">
<style>
em {
color:red;
}
.test {
color:blue;
}
</style>
What you see here is only an image, nothing
else.<br />
<br />
<em>I</em> really like <span class="test">cheese.</span><br />
<br />
Zoom in to check the resolution!
</div>
</foreignObject>
</svg>
`);
body.appendChild(img);
Zoom in and check the infinite resolution of the SVG.
The next runnable, below, is the one that implements the two extra steps which I mentioned above, namely improving resolution by first scaling the SVG, and then the saving as a PNG-image.
window.addEventListener("load", doit, false)
var canvas;
var ctx;
var tempImg;
function doit() {
const body = document.getElementsByTagName('BODY')[0];
const scale = document.getElementById('scale').value;
let trans = document.getElementById('trans').checked;
if (trans) {
trans = '';
} else {
trans = 'background-color:white;';
}
let source = `
<div xmlns="http://www.w3.org/1999/xhtml" style="border:1px solid red;padding:20px;${trans}">
<style>
em {
color:red;
}
.test {
color:blue;
}
</style>
What you see here is only an image, nothing
else.<br />
<br />
<em>I</em> really like <span class="test">cheese.</span><br />
<br />
<div style="text-align:center;">
Scaling:
<br />
${scale} times!
</div>
</div>`
document.getElementById('source').innerHTML = source;
canvas = document.createElement('canvas');
ctx = canvas.getContext('2d');
canvas.width = 200*scale;
canvas.height = 200*scale;
tempImg = document.createElement('img');
tempImg.src = 'data:image/svg+xml,' + encodeURIComponent(`
<svg xmlns="http://www.w3.org/2000/svg" width="${200*scale}" height="${200*scale}">
<foreignObject
style="
width:200px;
height:200px;
transform:scale(${scale});
"
>` + source + `
</foreignObject>
</svg>
`);
}
function saveAsPng(){
ctx.drawImage(tempImg, 0, 0);
var a = document.createElement('a');
a.href = canvas.toDataURL('image/png');
a.download = 'image.png';
a.click();
}
<table border="0">
<tr>
<td colspan="2">
The claims in the HTML-text is only true for the image created when you click the button.
</td>
</tr>
<tr>
<td width="250">
<div id="source" style="width:200px;height:200px;">
</div>
</td>
<td valign="top">
<div>
In this example the PNG-image will be squarish even if the HTML here on the left is not exactly squarish. That can be fixed.<br>
To increase the resolution of the image you can change the scaling with this slider.
<div style="text-align:right;margin:5px 0px;">
<label style="background-color:#FDD;border:1px solid #F77;padding:0px 10px;"><input id="trans" type="checkbox" onchange="doit();" /> Make it transparent</label>
</div>
<span style="white-space:nowrap;">1<input id="scale" type="range" min="1" max="10" step="0.25" value="2" oninput="doit();" style="width:150px;vertical-align:-8px;" />10 <button onclick="saveAsPng();">Save as PNG-image</button></span>
</div>
</td>
</tr>
</table>
Try with different scalings. If you for example set scaling to 10, then you get a very good resolution in the generated PNG-image. And I added a little extra feature: a checkbox so that you can make the PNG-image transparent if you like.
The Save-button does not work in Chrome and Edge when this script is run here at Stack Overflow. The reason is this https://www.chromestatus.com/feature/5706745674465280 .
Therefore I have also put this snippet on https://jsfiddle.net/7gozdq5v/ where it works for those browsers.
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
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.