ImageSharp
ImageSharp copied to clipboard
GIF Encoder: Exploit transparency
Prerequisites
- [x] I have written a descriptive issue title
- [x] I have verified that I am running the latest version of ImageSharp
- [x] I have searched open and closed issues to ensure it has not already been reported
Feature
The GIF format supports reusing pixels from previous frames by setting the Disposal Method to 1 ("Do not dispose") in the previous frame and using a transparent pixel in the current frame. This feature can be exploited to produce better quality GIFs for images where subsequent frames keep the same color values. My suggestion is to expose this as an option for the GifEncoder
. To take full advantage the disposal method for all frames should be set to 1, so maybe that should be overriden when the option is enabled.
The benefit to doing this is that we can reduce the number of colors in the ImageFrame
and get better quantization results and ultimately a better quality GIF. We can optionally also check if we only need to redraw a subarea of the entire frame. I don't think that will be often applicable for typical use-cases. Though when it can be applied it will reduce file size (and quantization cost if quantization can happen on a subset of an image -> #633).
Implementation
Below I refer to an ImageFrame
as just frame and to a frame as it will be visible in the GIF as a rendered frame.
The implementation is straightforward. Before quantizing a frame (if the previous frame is preserved) we can replace each pixel that has the same value as (or is within some distance of) the pixel at the same position in the last rendered frame with a transparent pixel. We need to allocate two frames for this process, one to keep track of the rendered frame and one to be a copy of the current frame that we can make transparent. After quantizing we can update the rendered frame by copying non-transparent pixels over from the QuantizedFrame
.
I have a WIP branch that implements this behavior in the GIF encoder (not yet as an option). The process of comparing and replacing pixels is implemented as an ImageProcessor
that takes a reference ImageFrame
(or a QuantizedFrame
or a single color), a maximum distance and a replacement color.
I can set up a PR to further discuss this and polish the implementation if this proposal is accepted :)
Thanks @Jjagg this would be a great improvement.
Just a quick note. IImageProcessor implementations should be separate from codecs so any behaviour should be written as part of the codec codebase itself.
IImageProcessor implementations should be separate from codecs so any behaviour should be written as part of the codec codebase itself.
Gotcha, I'll fix that before I set up the PR.