Create static png from svg without anti-aliasing, with or without canvas
What I want
I want to take a vector SVG image and create a raster png from it without anti-aliasing. The svg will be dynamically generated based on user input (text, bold, font family). png is preferred, but other bitmap formats can be accepted.
What i try
var svg = '<svg><g><text>Hello World</text></g></svg>';
var img = document.createElement('img');
img.setAttribute('src','data:image/svg+xml;base64,' + btoa(svg_static_data) );
img.onload = function() {
ctx.drawImage(img, 0, 0);
ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false;
ctx.msImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false;
static_image = canvas.toDataURL('image/png');
};
svg is very simple here for demonstration. Here I turn the svg into a canvas and turn the canvas into an image. When this resulted in anti-aliasing, the only configuration I found that could help was imageSmoothingEnabled
, however I still get Anti-aliasing, probably because this configuration is for elements drawn with the canvas itself. I also tried to post this config above drawImage
but no luck.
What I need
A function to turn a dynamic, non-animated SVG, which can contain many elements and attributes, including curved text, into a bitmap that is at least mostly identical.
source to share
imageSmoothingEnabled
apply only to images, but only when the image source is scaled.
However, the problem in this case is that the SVG image is anti-aliased internally when rasterized before your handler is onload
fired, so when you draw it to the canvas, it is already anti-aliased - you can't do anything about that other than manually parsing and SVG rendering (which is not a small project).
source to share
I believe this slightly different question explains why you can't use the drawImage method for SVG. Hope you find it helpful: Is there a canvas equivalent toDataURL for SVG?
source to share
Using the smart alpha filter technique ( found here ), you can "un-alias" all elements in your SVG before rendering it to the canvas. Just paste this at the beginning of the element <svg>
:
<defs>
<filter id="crispify">
<feComponentTransfer>
<feFuncA type="discrete" tableValues="0 1"/>
</feComponentTransfer>
</filter>
</defs>
<style>
svg * {
filter: url('#crispify');
}
</style>
JSFiddle: https://jsfiddle.net/uqfgs477/1
Works in Chrome and Edge, not Firefox.
source to share