Repository navigation
Error block in image result after saving after loading some files #2866
Description
Activity
What do you mean by compressed gifs?
The encoder only encodes the difference because otherwise you end up with massive gifs. There’s no way to turn that off.
Sorry for the long delay in replying.
What do you mean by compressed gifs?
The encoder only encodes the difference because otherwise you end up with massive gifs. There’s no way to turn that off.
I'm referring to gifs that only keep a record of the changed pixels.
Since the images themselves do not originate from me, I cannot confirm exactly what was used for gif optimization.After I ran a lot of tests, I figured out why I was asking the question. Using CloneFrame itself gives me the results I want, and the reason I'm asking is because I usually save as a png or gif, so it's getting the wrong results, and leading me to think that what this method gets would be the difference pixel map (instead of the full frame image)
This gif if I export it using CloneFrame and save it as a png, it will all show up as a pure empty image.
using var image = await Image.LoadAsync<Rgba32>("1.gif"); for (var i = 0; i < image.Frames.Count; i++) { using var frameImage = image.Frames.CloneFrame(i); frameImage.Save($"frame-{i}.png"); }
And if I store it in jpg format, it's correct, this image is the result I want.
using var image = await Image.LoadAsync<Rgba32>("1.gif"); for (var i = 0; i < image.Frames.Count; i++) { using var frameImage = image.Frames.CloneFrame(i); frameImage.Save($"frame-{i}.jpg"); }
- changed the title
[-]The specific Gif file is loaded and saved as the wrong style.[/-][+]Error block in image result after saving after loading some files[/+]on Jan 26, 2025 A similar phenomenon occurs in webp. For example, these two images.
using var image = await Image.LoadAsync<Rgba32>("1.webp"); await image.SaveAsync("2.webp");
I changed the title of the issue because of this.
@BAKAOLC I think your issue is this.
From the spec:
- The background color MAY contain a non-opaque alpha value, even if the Alpha flag in the 'VP8X' Chunk is unset.
- Viewer applications SHOULD treat the background color value as a hint and are not required to use it.
https://developers.google.com/speed/webp/docs/riff_container#animation
ImageSharp has a dedicated decoder option when dealing with this ambiguity but requires explicit usage of the decoder to use it.
using FileStream stream = File.OpenRead("1.webp"); WebpDecoderOptions decoderOptions = new() { GeneralOptions = this.options, BackgroundColorHandling = BackgroundColorHandling.Ignore }; using WebpDecoderCore decoder = new(decoderOptions); using Image<Rgb32> image = decoder.Decode<Rgb32>(decoderOptions.GeneralOptions.Configuration, stream, cancellationToken); image.Save("2.webp");
This gives you your output without the blocks.
I'm almost tempted to use
Ignoreas the default because that's what browsers seem to do.However, I have found something odd in the output. There's some ghosting on frame 16 where there are remnants of an ear that shouldn't be there.
If I compare that frame to one extracted using EazyGif you will see that the BGR components are the same however the alpha component has a value. That value is coming straight out of the
AlphaDecoder.Is it a bug.... I don't know, is there some unspecified magic that is performed by other decoders.... I don't know. The
AlphaDecoderis complex as all hell. @brianpopow I'll need your help here...Reacted by OLCImageSharp has a dedicated decoder option when dealing with this ambiguity but requires explicit usage of the decoder to use it.
Thank you very much for your answer, it solves part of my problem.
This gif if I export it using CloneFrame and save it as a png, it will all show up as a pure empty image.
After additional experimentation, I confirmed that the gif will export the png image correctly using the following code. This issue is still one of the more confusing points for me at the moment.
var image = await Image.LoadAsync<Rgba32>("1.gif").ConfigureAwait(false); for (var i = 0; i < image.Frames.Count; i++) { using var frameImage = image.Frames.CloneFrame(i); frameImage.Metadata.GetGifMetadata().GlobalColorTable = null; await frameImage.SaveAsync($"frame-{i}.png").ConfigureAwait(false); }
This doesn't happen with all gif files extracting png frames. And by outputting a version of the empty file, does that mean it tries to store it as APNG?
Also I don't think extracted frames should have this particular discrepancy when stored directly as a single frame image, should this behavior be handled away by default?
var image = await Image.LoadAsync<Rgba32>("1.gif").ConfigureAwait(false); image.Metadata.GetGifMetadata().GlobalColorTable = null; await image.SaveAsync("2.gif").ConfigureAwait(false);
Again, no unusual black blocks will appear when using this method when saving immediately after a direct read. But this should mean that there is something wrong with the GlobalColorTable data, because as I thought, without any editing of the image, the generated result should not be noticeably different from the original.
OK... So I had a good look at the GIF. It's an odd one.
It has a global color table but only two entries within that table. None of the frames actually use that table.
ImageSharp assumes that the table use both valid so when converting between formats will attempt to use it. It also attempts to use it for the first frame when reencoding the GIF. I'm going to have to revisit the logic to handle such oddities.
Reacted by OLCFigured out the WebP ghosting issue! We were disposing of the background restore area based on the current frame's disposal mode not the previous one! (@brianpopow crisis averted).
Saved output attached (GitHub does not allow WebP)
WebpDecoder_CanDecode_Issue2866_Rgba32_Issue2866.zip@BAKAOLC I'll open a PR tomorrow.
Reacted by OLC and Brian Popow@JimBobSquarePants I am glad you found this issue, this was hard to spot!
Fixed via #2882






Prerequisites
DEBUGandRELEASEmodeImageSharp version
3.1.6
Other ImageSharp packages and versions
SixLabors.ImageSharp.Drawing 2.1.5
Environment (Operating system, version and so on)
macOS Sequoia 15.2
.NET Framework version
.net 9.0
Description
There are some specific compressed Gif files that are saved after being loaded that lose their differential rendering properties, resulting in black blocks in the image. But the original image renders fine without ImageSharp. However the image works fine in ImageSharp after it has been re-encoded by other software.
The result of the error looks like this:

As well, how do I get the full frame image of the compressed Gif correctly in the code instead of the difference?
Steps to Reproduce
just load and save it.
Images