Closed Pr0methean closed 1 year ago
This is not about storage, but about the pipeline. tiny-skia/Skia pipeline is always premultiplied. There are no options. Maybe there is a rounding bug somewhere and the original Skia is able to avoid this. Who knows.
There are plans on adding u16/f32 pixmaps, but it would require some work and it's a low priority.
One possible workaround is that the pipeline's full palette of ideal output colors can be calculated ahead of time, and then pixels can be coerced to that palette when they're demultiplied for PNG output, in two scenarios:
I've implemented that in my own code at https://github.com/Pr0methean/OcHd-RustBuild/blob/main/main/src/image_tasks/png_output.rs#L316, although the main purpose of that was to produce smaller files (hence, it isn't used for more than 256 discrete colors, which is the limit of PNG's indexed-color mode) -- that was how I started to notice the rounding errors in the first place. That makes this a rare example of compression bringing a digital signal closer to the analog ideal.
Sorry, but this is out of scope. You either have to do this on your side or fork tiny-skia.
When a color with low alpha is converted to a PremultipliedColorU8, it inevitably loses some precision, and can't get it back when demultiplied to save to a PNG. To fix this, I'd suggest offering a second Pixmap format where each pixel is either a demultiplied ColorU8 or a struct with u16 channels.