Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create colored svg in c++ code. #5

Merged
merged 10 commits into from
Feb 2, 2022
Merged

Create colored svg in c++ code. #5

merged 10 commits into from
Feb 2, 2022

Conversation

sylmroz
Copy link
Contributor

@sylmroz sylmroz commented Jan 29, 2022

  • Create colored svg in c++ code. Basically it is simillar algoritm from repo https://github.com/tomayac/SVGcode
    The porpouse was to speedup colored svg by using c++ code.
  • Create building scripts for windows platform
  • Use em++ compiler to use c++ language

@tomayac
Copy link
Owner

tomayac commented Jan 29, 2022

Wow, this looks amazing. Thanks <3 so much for contributing this improvement! I’ll review this after the weekend and merge it hopefully on Monday!

@tomayac
Copy link
Owner

tomayac commented Jan 29, 2022

Addendum: since your build script also appends the export manually, I wonder if you manage to get the proper way of doing this via -s "MODULARIZE=1" -s "EXPORT_ES6=1" to work? See my poor attempt in #1, which fails. I have no idea what I’m doing when it comes to emscripten (and C or C++), but you are obviously a master of both. Maybe you succeed in outputting a proper ES module directly from emscripten?

@sylmroz
Copy link
Contributor Author

sylmroz commented Jan 30, 2022

Thanks! That sounds great. :) Could You first check does it not cause any problems with Your existing SVG code? If Yes I will fix it asap.

I guess it is not as simple as we think to just modularize. I think, following documentation and examples from StackOverflow it seems like a modularization creates a module that needs to be instantiated and used like is in src/potrace.js file.
The potrace.js shouldn't be bundled into one module because it just hides the required implementation. You can see that in index.js file when You will use -gsource-map flag in the build script.
Following that example https://github.com/imxood/emcc-typescript-example and that one emscripten-core/emscripten#10271 I see that it can be done also combining with a typescript.
I can do that in the next PR when I find a time next weekend. It will be much more code refactoring but seems reasonable to change it. Now in my typescript project, I need to define my own types which is annoying :)

@tomayac
Copy link
Owner

tomayac commented Jan 31, 2022

I have played a bit with this, but fail to get super convincing results:

Your PR:

  • Quant level 1:
    Screen Shot 2022-01-31 at 13 50 23
  • Quant level 75 (I don't understand the "flipping over" of colors as in the second example.):
    Screen Shot 2022-01-31 at 13 51 30
  • Quant level 100:
    Screen Shot 2022-01-31 at 13 51 00

Current client-side implementation:

The current SVGcode output with the default settings is this:

Screen Shot 2022-01-31 at 13 53 30

Posterization in SVGcode

When you paste $('label[hidden]').hidden = false into the DevTools console, you can toggle debug mode:

Screen Shot 2022-01-31 at 14 02 55

This allows you to see what the app is doing internally (top: input image, bottom: posterized input image):

Screen Shot 2022-01-31 at 14 03 26

Posterization happens on all four channels (r, g, b, a) independently, essentially as in this CodePen demo.

Do the results of the demo look entirely different for you? Maybe it's a problem on my side?

@sylmroz
Copy link
Contributor Author

sylmroz commented Jan 31, 2022

Thanks for the tests!
Yeah, I made one mistake in code. It should be fixed now. In c++ You must be careful about variables size :)
Your algorithm works fine.

The best results (visual and speed) I get now when I used canvas with posterization filter - from Your code - and quant level = 255 so it means - no quantization, and results I pushed to the c++ code. It just needs 55ms on my machine to generate that result:
image
which looks really similar to your result.

Without posterization and quant level = 5 I get that result:
image
Which is close to the original

@sylmroz
Copy link
Contributor Author

sylmroz commented Jan 31, 2022

And to get that black color You need to use
<svg id="div1" style="background-color:black"></svg> indstead of div.

@sylmroz
Copy link
Contributor Author

sylmroz commented Jan 31, 2022

Now quant level has the same behavior as the step value from SVGcode, but it is one value for all channels. The value should be between <1;255>

@sylmroz
Copy link
Contributor Author

sylmroz commented Jan 31, 2022

I added a swith to choose between simple ( 0 ) and interpolated ( 1 ) posterization
First is faster but second has beetter results.
image

@tomayac
Copy link
Owner

tomayac commented Feb 1, 2022

I cannot really reproduce the results from your screenshots. If I run the following code from the demo, I get the image below, which has a lot more white holes than your screenshots:

potrace(blob, {
    turdsize: 2,
    turnpolicy: 4,
    alphamax: 1,
    opticurve: 1,
    opttolerance: 0.2,
    pathonly: false,
    extractColors: true,
    posterizeLevel: 6,
    posterizationAlgorithm: 0, // 0 - simple, 1 - interpolation
}

Screen Shot 2022-02-01 at 13 51 11

A couple of review remarks:

  • Potrace exposes all settings as lower case, please do so as well for consistency: posterizationAlgorithm → posterizationalgorithm for all parameters.
  • What do you want to expose: quantlevel or posterizelevel? So far the code uses both.

A meta level remark:

  • Maybe you want to contribute these changes upstream to the core Potrace project and we can then work here on creating a Wasm version of that? Sorry, I realized this only a bit late, but it would actually make more sense directly upstream.

@sylmroz
Copy link
Contributor Author

sylmroz commented Feb 1, 2022

I can feel Your confusion.
It is simple to change this line in demo/index.html
Just change that

<div id="div1"></div>

To <svg id="div1" style="background-color:black"></svg>
On div is white background so transparent is white there :)
Please try with parameters posterizationAlgorithm = 1 and posterizeLevel = 5
Algorithm 0:
It is just simple quantization method - floor(color/level)*level+ level/2
Algorithm 1:
It is also simple algorithm but require more instruction

  1. getRanges(5) - 0, 0.2, 0.4, 0.6, 0.8, 1.0
  2. Normallize collor from 0 - 255 to 0 - 1
  3. check which number from rages the color channel is closer and choose that one

I have both because sometimes I do not need great visualization effect - example when trying to vecorize text and do not need to care about clear white or black color but speed is required.

For first.
Yes I will change that to lower case. I would to expose posterizelevel. quantlevel must be mistake which I missed.

For second.
Most of changes which I made is for potrace.h and potrace.c files which are not part of potrace library. There been created by author to wrap potrace. Only one thing I do not understand why he first encode color to one bit (in js file) and next decode in potrace.c file. Passing image.data to wasm function where it is changed to char[] array is just passing pointer to the memory so it cost nothing - it just one number.
The code in that respository is behind potrace core so I think to update it in the future.
But yeah, it is great idea to contribute directly to potrace and extend basic functionally. Also porace library allow to export to not only svg. Whole code from potrace can extend esm-potrace-wasm possibilities. I will ask them but it will require much more work and I am not sure when it can be done.

@tomayac tomayac merged commit 5e874f1 into tomayac:main Feb 2, 2022
@tomayac
Copy link
Owner

tomayac commented Feb 2, 2022

Thank you very much for this contribution! <3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants