Raster Image to SVG Image Conversion (Vectorization) — Img2Num

Summary

Hello Krita devs and community,

I’m the maintainer of Img2Num, an open-source project that started as a browser web app for converting raster images into color-by-number SVG templates. I’m refactoring the project to be library-first (C++ core with a clear API) so it can be embedded into other applications. I’d like to propose that Krita consider integrating Img2Num (or parts of it) as an optional library or plugin to add raster → SVG / vectorization features.

Why this could help Krita

  • Convert raster artwork into editable vector paths: Img2Num isolates flat regions and converts them into SVG path elements. Those paths can be converted into Krita vector layers or editable shapes, enabling fine-grained vector editing of raster artwork.

  • Layer isolation & selective editing: Each detected region becomes an independent path, which is easy to map to separate layers, masks, or groups in Krita for non-destructive editing.

  • Fast C++ core: The library is implemented in C++, which was designed to be fast and portable. It already compiles to WebAssembly for the demo; a native C++ library would be straightforward to integrate into Krita’s plugin or core codebase.

  • Useful for designers and illustrators: Vectorizing flattened scans, posterizing artwork, creating coloring templates, or producing clean assets that are easier to scale and export.

Technical overview

  • Language / build: Core vectorization module is in C++, currently built for the web via Emscripten in the demo, but structured to be library-first so native builds are supported. It won’t be long before the project is converted to a library.

  • Input / Output: Accepts raster images (PNG / JPG / etc.) → outputs SVG (paths, fills). The library can also return an intermediate path list or per-region masks if Krita prefers direct layer/mask creation instead of SVG import.

  • API ideas:

    • vectorize(image, settings) -> SVG — simple one-call API.

    • vectorize_to_regions(image, settings) -> vector<Region> — returns per-region geometry + color, useful to create Krita vector layers directly.

    • Configurable parameters: color quantization levels, smoothing, minimum area threshold, merge/split heuristics.

  • Performance: Written with performance in mind; runs in native C++ quickly. A WASM build exists for browser demos which shows the algorithm is portable - it runs well on mobile device CPUs via a browser.

Possible integration approaches for Krita

  1. Standalone plugin (recommended first step)

    • Provide a Krita plugin that calls the Img2Num native library to produce either an imported SVG or a set of Krita vector layers and masks.

    • Pros: Minimal impact to Krita core, quick to iterate.

  2. Core/shared library

    • Add Img2Num as an optional dependency in Krita’s build system and expose vectorization in the UI as Filter → Vectorize (Img2Num) or similar.

    • Pros: Tighter UX integration, more control over memory and threading.

  3. Scripted wrapper

    • Supply a Python wrapper around the native library so plugin authors can easily call it from Krita’s Python plugin system. Python support is already planned, so this is not a stretch.

    • Pros: Low friction for community-driven experimentation.

UX suggestions

  • A small dialog with sliders for: color count / quantization, smoothing radius, minimum area size, and an Advanced tab for merging heuristics.

  • A preview pane (low-res) to show the detected regions, with toggles to export as SVG vs. Krita vector layers vs. Krita vector + mask pairs.

How you can test/demo

  • The GitHub repository contains the source and build instructions. The project currently has a browser demo (WASM) for quick experimentation; I can provide native build instructions or a prebuilt binary if maintainers want to try it locally.

License & contribution

  • Img2Num is open source. I am open to aligning licensing or making adjustments needed for compatibility with Krita’s ecosystem, but I don’t think that will even be necessary.

  • I’m eager to submit a proof-of-concept plugin / PR or pair-program with someone from the Krita team to get an initial integration working.

Next steps / Call to action

If this sounds useful, I’d love to:

  1. Hear feedback from Krita devs about preferred integration approach (plugin vs. core vs. Python wrapper).

  2. Provide a small demo PR or a plugin skeleton that shows importing vectorized output directly into Krita as vector layers.

  3. Work with interested contributors on UX and edge cases (antialiasing, complex gradients, textured fills).

Thank you for reading — I’d be excited to help bring raster → SVG vectorization into Krita. If anyone on the team wants to chat or test, please reply here or reach me via the repository discussions / issues tab.


Useful links

10 Likes

:slight_smile: Hello @Ryan-Millard, and welcome to the forum!

This sounds interesting and may be good news for those who like to work with vectors in Krita.
Unfortunately, I’m out of votes, so I can not support this request.

Michelist

Thanks Michelist! I’m glad you find it interesting. :slightly_smiling_face:

Hopefully others will get a chance to support it too.

1 Like

I recommend going to krita irc chat, especially if you can make it during the meetings as many of the devs are there together.

If you don’t want to install an irc client, you can use an irc web chat: Using Our Webchat | Libera Chat

    1. Joining IRC: connect to Libera.Chat, select a unique nickname and join the #krita and ##krita-chat channels. #krita is for on-topic talk, ##krita-chat for off-topic chat.
    2. Don’t ask to ask: if you’ve got a question, just ask it.
    3. Don’t panic if several discussions happen at the same time. That’s normal in a busy channel.
    4. Talk to an individual by typing their nick and a colon.
    5. Almost every Monday, at 16:00 CET or CEST, we have a meeting where we discuss what happened in the past week, what we’re doing, and everything that’s relevant for the project. The meeting notes are kept in google docs.
    6. Activity is highest in CET or CEST daytime and evenings. US daytime and evenings are most quiet.
    7. IRC is not logged. If you close the channel, you will be gone, and you will not be able to read what happened when you join the channel again. If you ask a question, you have to stay around!
    8. It is really irritating for other users and disrupting to conversations if you keep connecting and disconnecting.

Thank you! I’ll try to be there on Monday.

Which is the most common time for meetings? CET or CEST? Could you give it to me in relation to GMT (like GMT+1 or GMT+2)?

AGPLv3 is not compatible with Krita’s GPLv3 license. The application would need to be relicensed, which probably isn’t going to happen. If you want to release a plugin, you’ll probably want to change the license (if you have copyright over the code) or ask a lawyer first. A plugin is probably the right call anyway, the use case and library are probably too obscure to integrate into Krita’s core and I don’t think a deeper integration is necessary, you should be able to do everything that’s needed from a plugin.

Otherwise, your post reads like a vacuous marketing document (or maybe it’s just AI-generated.) This gives a strongly negative, deceptive impression to me, both as a developer and as someone who has a use case for layer vectorization, which I currently solve by dumping PNGs and running them through potrace. So I’d suggest rewriting that.

The time zone for the meeting is Europe/Amsterdam, so UTC+1 in winter.

Hi. Thank you very much for your input. I appreciate the depth you went into.


AGPLv3 is not compatible with Krita’s GPLv3 license. The application would need to be relicensed, which probably isn’t going to happen.

This discussion proposes a relicensing for the part that will be converted to a library because I realised that AGPLv3 is a bad license for a library in general. I proposed MIT instead. Since there have been very few people contributing directly to the core code, it won’t be a stretch to ask everyone for permission to do so.

A plugin is probably the right call anyway, the use case and library are probably too obscure to integrate into Krita’s core and I don’t think a deeper integration is necessary, you should be able to do everything that’s needed from a plugin.

I understand that it may look obscure right now given that it is currently built into the demo app, but the core of the library is not tightly coupled to that specific implementation.

Otherwise, your post reads like a vacuous marketing document (or maybe it’s just AI-generated.)

I don’t know what seems AI-generated or like a marketing document. I posted this because someone else requested that I speak to the devs at Krita because they said you were in need of something like Img2Num. I put effort into the post because first impressions matter and a sloppy post would be disrespectful because it wastes time.

This gives a strongly negative, deceptive impression to me, both as a developer and as someone who has a use case for layer vectorization, which I currently solve by dumping PNGs and running them through potrace. So I’d suggest rewriting that. The time zone for the meeting is Europe/Amsterdam, so UTC+1 in winter.

Thank you for letting me know your feelings about it. If Potrace is sufficient and you do not see a need for my proposition - that’s okay. Img2Num is fairly new and a benefit of you guys using it could be that the project gets shaped according to Krita’s needs.


My intention wasn’t to waste your time. I’m sorry for doing that.

Relicensing as MIT would be fine, yeah. GPLv3 is fine too, as far as Krita is concerned. AGPLv3 might also be okay, since the GPL has provisions for it, but I’d consider it too scary without asking someone with legal expertise.

And like I said, I have a use case for it. Extracting PNGs and running them through potrace is pretty terrible, so I’d use a built-in vector layer conversion if it existed. I assume I’m not the only person in existence who has a use for this, so surely there’s also artists who aren’t able to write scripts to that degree that would find it useful, they don’t have the option of putting together an asset pipeline themselves. So the current situation is not “sufficient” at all.

“Obscure” also wasn’t meant as a derogatory, I mean that literally. Wanting to convert raster to vector layers is an obscure use case for a program meant primarily for painting, so even while I personally have a use for it, I don’t think I could reasonably argue to integrate it into Krita’s core over a plugin. And a relatively new library with a low bus number is obscure because it’s new and not used much (yet), so this poses stability and maintainability risks if it were integrated into the application. Hence I think a plugin is the right call.

My negative impression is just about the post. As a developer, it has a lot of fluff and little actual information. Like, you have a heading that says “language/build”, but then it doesn’t actually say what the build system is. Or you say that it runs “quickly”, but show nothing for it. It was also missing the information about the relicensing, which is a pretty important thing. And as a user interested in this feature, there’s a lot of tech speak about C++ and libraries, but it doesn’t actually show me what this thing can do, so I had to go look at it elsewhere.

Relicensing as MIT would be fine, yeah. GPLv3 is fine too, as far as Krita is concerned. AGPLv3 might also be okay, since the GPL has provisions for it, but I’d consider it too scary without asking someone with legal expertise.

That is my concern right now. MIT is compatible with your license, so it is up to me to ensure my code is compatible. I have already started asking the people who contributed to the code if they are okay with a relicensing.

And like I said, I have a use case for it. Extracting PNGs and running them through potrace is pretty terrible, so I’d use a built-in vector layer conversion if it existed. I assume I’m not the only person in existence who has a use for this, so surely there’s also artists who aren’t able to write scripts to that degree that would find it useful, they don’t have the option of putting together an asset pipeline themselves. So the current situation is not “sufficient” at all.

That’s why I came - someone else with this problem suggested that I propose the solution and it sounded like a win-win situation. By being able to customize how the SVG data is returned (e.g., a full and complete SVG vs individual components that are in their own layer), more options will be available for image editing. Specifying all of the uses that could come from this would take very long and probably become a long list because vectorization opens the door to to many new features that raster images can’t offer.

“Obscure” also wasn’t meant as a derogatory, I mean that literally. Wanting to convert raster to vector layers is an obscure use case for a program meant primarily for painting, so even while I personally have a use for it, I don’t think I could reasonably argue to integrate it into Krita’s core over a plugin. And a relatively new library with a low bus number is obscure because it’s new and not used much (yet), so this poses stability and maintainability risks if it were integrated into the application. Hence I think a plugin is the right call.

Obscure features exist everywhere. One cannot argue that the average user uses every feature Krita offers on a daily basis, so that shouldn’t be enough to dismiss this outright. You do have a good point, though - the age of Img2Num as a whole, number of users and the safer option for a plugin is probably a good motivator to steer away from it being a built-in feature.

My negative impression is just about the post. As a developer, it has a lot of fluff and little actual information. Like, you have a heading that says “language/build”, but then it doesn’t actually say what the build system is. Or you say that it runs “quickly”, but show nothing for it. It was also missing the information about the relicensing, which is a pretty important thing. And as a user interested in this feature, there’s a lot of tech speak about C++ and libraries, but it doesn’t actually show me what this thing can do, so I had to go look at it elsewhere.

This is my first time posting on this platform and I assumed that the users here aren’t just developers, so I tried to keep away from going into too much technical depth to accommodate them. Comments sections were invented to solve questions people may have - and that’s what we’re doing right now.

If you want to know more about Img2Num, I’d be happy to answer any questions you have.

I don’t think there’s other questions. I think the right thing to do would be to continue with the relicensing process, setting up the library and creating a plugin. If you have questions about the latter, you can ask here or in the IRC channel, but you don’t need to ask the developers’ permissions of course. And you’re free to join the meeting on Monday, this is just my own perspective, the other developers may think differently or have other pointers.

Thanks. I think it would be helpful for me to get other people’s perspectives as well.

Hello!!, @Ryan-Millard
I think Img2Num is a nice project,and tried the web demo.The multicolor tracing is useful.
It works fine (I hope this will be added to the parameter adjustment and save button in the demo), and it would be even better if there were some concept code running with Krita (Python or something similar).
It may take time, but I hope everything goes smoothly for your project.

Either way, it’s nice to have more options. :slightly_smiling_face:
Because I once made an Imagetracer.js(python port) plugin for Krita,but it was pretty slow with a large image.
Hope it helps. Good luck!

It works fine (I hope this will be added to the parameter adjustment and save button in the demo), and it would be even better if there were some concept code running with Krita (Python or something similar).

Yes. We plan to add an advanced setting feature that allows users to configure the processing as well as export options to export the images as an SVG, PDF, etc. It’s not our top priority right now because we have more important milestones.

Because I once made an Imagetracer.js(python port) plugin for Krita,but it was pretty slow with a large image.

That’s cool! I started using imagetracerjs when I started prototyping the project (it was an app back then) and I really liked it. I didn’t find it slow, but I found that it wasn’t very accurate - there were often holes inside the image. I would’ve rather improved that library instead of making my own, but they don’t seem to be developing it anymore. It’s still a really nice library.


Thanks for everything! I hope you have a nice day.

1 Like