Simplify curves like Paper.js or vectorscribes "smart remove brush tool" does.
Maybe a curve could be approximated (so that optionally you loose some detail?).
svgo already did an amazing job minimizing a test svg of mine (170kb => 22kb), but hey you can always ask for more ;)
Yep, I was thinking about it, but haven't got to it yet. Many plans, but very little time.
I suppose this is at least related to Inkscape's "simplify", right?
@waldyrious Yes this looks like what I was thinking off ...
May be you were meant Illustrator? Inkscape is quite bad here.
I have not tested inkscape's 'simplify' (just had a look at their user manual to see what waldyrious was talking about...). Just wanted to say that this is generally what I was thinking about (no clue, if it is implemented in a good or bad way).
You have http://bost.ocks.org/mike/simplify/ which has some witty js code for line simplification.
Line simplification isn't an issue, actually. Lines takes only 1 pair coordinates, while curves takes 3. Sometimes, it only takes one number (horizontal or vertical line). So one curve is 3 times larger. And there are rarely images which actually needs line simplification, while there are image that may have too many curves and can be simplified without a notable loss.
Here's paper.js's curve simplify in action:
http://paperjs.org/examples/path-simplification/ https://github.com/paperjs/paper.js/blob/develop/src/path/PathFitter.js http://paperjs.org/reference/path/#simplify
Should be rather trivial to integrate into a plugin.
@GreLI a single curve is 3 times larger than a single line, but to get even an approximation to such a curve, one would need multiple lines, not 1. So for similar geometry, whether it's represented as curves or lines, actually the lines version occupies much more space.
Of course, simplifying curves (which can at least make a reasonable attempt at preserving the shape of the curve while using less nodes) will generally produce more visually appealing results than simplifying the equivalent sequence of lines into a sequence with less nodes. The ideal approach would be to simplify sequences of lines into curves, which can then try to trace the original path by clever usage of the curve parameters.
for reference, this module seem to also approximate a linestring with bezier curves - https://www.npmjs.com/package/turf-bezier
I post this in case someone wants to work on this for svgo (I only discovered svgo via this github issue).
Here is the smallest (server-side + canvas-less) sequence I could find to use the PathFitter of paper.js mentioned by @behdad in order to approximate a path with curves. The compression results are indeed impressive even for complex linestrings and high tolerance.
var paper = require('paper');
paper.setup();
var parser = require('html-attribute-parser')
var tolerance = 0.01;
var d_source = "M20,20L80,80L140,20Z";
var path = new paper.Path({pathData: d_source })
path.simplify(tolerance);
var svg = path.exportSVG({ asString: true});
var d_target = parser(svg).attributes.d
I looks like a very low-hanging fruit to use the model of the convertPathData plugin and to incorporate the above minimal example that uses paper. The convertPathData plugin already has the code that allows you to isolate any given d string, and then the above example does the rest. The tolerance could be in the plugin parameters.
I’m not a JS dev at all, but for anyone familiar with JS, it’d be a 10-minute job to create a simplifyPaths.js plugin for svgo that simply relies on paper.js and does just that!
I opened a pull request that adds this feature based on the code that @jeromew proposed. Definitely took a lot longer than 10 minutes though :face_with_spiral_eyes: