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.

+3


source to share


3 answers


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).

+1


source


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?



0


source


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.

0


source







All Articles