Chlumsky / msdfgen

Multi-channel signed distance field generator
MIT License
3.9k stars 404 forks source link

Add an option to dump colored edges as an SVG file. #152

Closed shi-yan closed 2 years ago

shi-yan commented 2 years ago

I had a hard time understanding the paper. I'm now trying to debug the code to understand it. In particular, I don't quite get the logic of switchColor().

And for example, what are those hardcoded values:

for (int i = 0; i < m; ++i)
                    contour->edges[(corner+i)%m]->color = (colors+1)[int(3+2.875*i/(m-1)-1.4375+.5)-3];

I hope to add a new option: dumping colored edges as an SVG file. So we can visualize them.

-outputedgecolor <filename.svg> <width> <height> <scale>
Chlumsky commented 2 years ago

Thanks for the contribution, I hope it helped you understand the edge coloring logic, but I won't be merging this because it's more of a personal experiment than an official feature, and the coloring can already be dumped with -exportshape. If somebody needs it specifically in SVG format, it can be converted e.g. with a very short Python script.

As for the code you asked about, this is for a case where a sequence of smoothly connected edge segments needs to be split into three groups of roughly the same size with different colors. The formula simply produces the following symmetrical sequences to facilitate it:

-1 0 1
-1 0 0 1
-1 -1 0 1 1
-1 -1 0 0 1 1
-1 -1 0 0 0 1 1
-1 -1 -1 0 0 1 1 1
-1 -1 -1 0 0 0 1 1 1
-1 -1 -1 0 0 0 0 1 1 1
-1 -1 -1 -1 0 0 0 1 1 1 1
-1 -1 -1 -1 0 0 0 0 1 1 1 1
-1 -1 -1 -1 0 0 0 0 0 1 1 1 1
-1 -1 -1 -1 -1 0 0 0 0 1 1 1 1 1
-1 -1 -1 -1 -1 0 0 0 0 0 1 1 1 1 1
shi-yan commented 2 years ago

Thank you for replying.

I see, so you basically want an even distribution within the range of [-0.9,1.9]

shi-yan commented 2 years ago

May I ask another question?

Why do we want to scale the pixel value by pxRange? and why is pxRange related to image sizes?

 pxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height);
distVal(median(sd[0], sd[1], sd[2]), pxRange, midValue);
Chlumsky commented 2 years ago

I believe this code is from the software SDF renderer that evaluates an SDF to an anti-aliased image. The first line simply converts "pixel range" from SDF pixels to output pixels which can be different size. Multiplication by pxRange within distVal ("distance to value") facilitates anti-aliasing - it scales the signed distance gradient so that the transition between 0 (black) and 1 (white) is one pixel wide. You can actually set pxRange to 0 and it would still work but without anti-aliasing.