svgo icon indicating copy to clipboard operation
svgo copied to clipboard

Simplify curves like Paper.js or vectorscribes "smart remove brush tool" does.

Open Quentie opened this issue 10 years ago • 13 comments

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

Quentie avatar Aug 03 '15 21:08 Quentie

Yep, I was thinking about it, but haven't got to it yet. Many plans, but very little time.

GreLI avatar Aug 03 '15 22:08 GreLI

I suppose this is at least related to Inkscape's "simplify", right?

waldyrious avatar Aug 03 '15 22:08 waldyrious

@waldyrious Yes this looks like what I was thinking off ...

Quentie avatar Aug 03 '15 22:08 Quentie

May be you were meant Illustrator? Inkscape is quite bad here.

GreLI avatar Aug 04 '15 13:08 GreLI

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

Quentie avatar Aug 04 '15 13:08 Quentie

You have http://bost.ocks.org/mike/simplify/ which has some witty js code for line simplification.

hugolpz avatar Dec 24 '15 14:12 hugolpz

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.

GreLI avatar Dec 25 '15 06:12 GreLI

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.

behdad avatar Feb 10 '16 03:02 behdad

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

waldyrious avatar Sep 14 '16 11:09 waldyrious

for reference, this module seem to also approximate a linestring with bezier curves - https://www.npmjs.com/package/turf-bezier

jeromew avatar Mar 08 '17 16:03 jeromew

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

jeromew avatar Mar 09 '17 11:03 jeromew

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!

twardoch avatar Aug 31 '17 18:08 twardoch

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:

MarcelRobitaille avatar Oct 13 '22 16:10 MarcelRobitaille