RazrFalcon / tiny-skia

A tiny Skia subset ported to Rust
BSD 3-Clause "New" or "Revised" License
1.05k stars 67 forks source link

Add another Image format to reduce rounding errors at low alpha #90

Closed Pr0methean closed 1 year ago

Pr0methean commented 1 year ago

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.

RazrFalcon commented 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.

Pr0methean commented 1 year ago

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:

  1. The pipeline consists entirely of orthogonal rectangles aligned to pixel boundaries, so only explicitly-specified colors will appear in the output.
  2. The layers that may be blended by antialiasing are solid colors that are close enough together that the number of possible blended colors is manageable.

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.

RazrFalcon commented 1 year ago

Sorry, but this is out of scope. You either have to do this on your side or fork tiny-skia.