Skip to content

Image.Load() throws InvalidImageContentException: CRC Error. PNG IDAT chunk is corrupt! #2570

Description

@oskarlindman

Prerequisites

  • I have written a descriptive issue title
  • I have verified that I am running the latest version of ImageSharp
  • I have verified if the problem exist in both DEBUG and RELEASE mode
  • I have searched open and closed issues to ensure it has not already been reported

ImageSharp version

3.0.2

Other ImageSharp packages and versions

None

Environment (Operating system, version and so on)

Windows 11 Version 22H2

.NET Framework version

.net 7

Description

I have two png images that opens fine with System.Drawing.Common, but that fails to open with ImageSharp, and instead throw an InvalidImageContentException: CRC Error. PNG IDAT chunk is corrupt! Both files can be viewed in windows.

Steps to Reproduce

Just point to the filePath with Image.Open(filePath) and it should throw the exception when running the code.

 at SixLabors.ImageSharp.Formats.Png.PngThrowHelper.ThrowInvalidChunkCrc(String chunkTypeName)
   at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.ValidateChunk(PngChunk& chunk)
   at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.TryReadChunk(PngChunk& chunk)
   at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.Decode[TPixel](BufferedReadStream stream, CancellationToken cancellationToken)
   at SixLabors.ImageSharp.Formats.ImageDecoderUtilities.Decode[TPixel](IImageDecoderInternals decoder, Configuration configuration, Stream stream, Func`3 largeImageExceptionFactory, CancellationToken cancellationToken)
   at SixLabors.ImageSharp.Formats.ImageDecoderUtilities.Decode[TPixel](IImageDecoderInternals decoder, Configuration configuration, Stream stream, CancellationToken cancellationToken)
   at SixLabors.ImageSharp.Formats.Png.PngDecoder.Decode[TPixel](DecoderOptions options, Stream stream, CancellationToken cancellationToken)
   at SixLabors.ImageSharp.Formats.Png.PngDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
   at SixLabors.ImageSharp.Formats.ImageDecoder.<>c__DisplayClass1_0.<Decode>b__0(Stream s)
   at SixLabors.ImageSharp.Formats.ImageDecoder.<WithSeekableStream>g__PeformActionAndResetPosition|11_0[T](Stream s, Int64 position, <>c__DisplayClass11_0`1& )
   at SixLabors.ImageSharp.Formats.ImageDecoder.WithSeekableStream[T](DecoderOptions options, Stream stream, Func`2 action)
   at SixLabors.ImageSharp.Formats.ImageDecoder.Decode(DecoderOptions options, Stream stream)
   at SixLabors.ImageSharp.Image.Decode(DecoderOptions options, Stream stream)
   at SixLabors.ImageSharp.Image.<>c__DisplayClass80_0.<Load>b__0(Stream s)
   at SixLabors.ImageSharp.Image.WithSeekableStream[T](DecoderOptions options, Stream stream, Func`2 action)
   at SixLabors.ImageSharp.Image.Load(DecoderOptions options, Stream stream)
   at SixLabors.ImageSharp.Image.Load(DecoderOptions options, String path)
   at SixLabors.ImageSharp.Image.Load(String path)

Images

transparent_png_without_extension_2
transparent_png_without_extension_1

Activity

  1. JimBobSquarePants commented on Oct 26, 2023

    @JimBobSquarePants
    Member

    The IDAT is indeed corrupt.

    image

    We'll need to have a look at libpng to see if they have some special handling of this.

    https://www.nayuki.io/page/png-file-chunk-inspector

  2. dlemstra commented on Oct 26, 2023

    @dlemstra
    Member

    Libpng also "throws an exceptions":

    C:\Users\Dirk\Desktop>magick 277674454-e24cc769-3dbd-420b-977f-7f7b6dbec05c.png info:
    magick: Expected 4 bytes; found 0 bytes `277674454-e24cc769-3dbd-420b-977f-7f7b6dbec05c.png' @ warning/png.c/MagickPNGWarningHandler/1526.
    magick: Read Exception `277674454-e24cc769-3dbd-420b-977f-7f7b6dbec05c.png' @ error/png.c/MagickPNGErrorHandler/1492.
    
  3. svenclaesson commented on Nov 6, 2023

    @svenclaesson
    Contributor

    corrupt
    This file, and the two above can be partially displayed by chrome, that uses libpng

  4. JimBobSquarePants commented on Nov 6, 2023

    @JimBobSquarePants
    Member

    Can they be opened by other imaging libraries? Chrome looks to have turned of the safety checks. (There’s a compiler option in libpng)

  5. svenclaesson commented on Nov 7, 2023

    @svenclaesson
    Contributor

    MagicScalar uses libpng and can handle the last image that i posted

    MagicScalar uses vcpkg precompiled version of libpng. What is the compiler option called can't seam to find it here?

  6. JimBobSquarePants commented on Nov 7, 2023

    @JimBobSquarePants
    Member

    Ah not a compiler option it seems. Look for png_set_crc_action

    http://www.libpng.org/pub/png/libpng-manual.txt

  7. svenclaesson commented on Nov 7, 2023

    @svenclaesson
    Contributor

    So this explains why it works in MagicScalar then.

    Would it be possible to consider this for ImageSharp?

  8. svenclaesson commented on Nov 8, 2023

    @svenclaesson
    Contributor

    After further investigation into MagicScaler, it turns out that using default settings on windows will result in native WIC codecs being used. This png codec is forgiving.
    Instead when libpng is used with "codecs.UseLibpng()" no CRC error is thrown but the resulting image is all black.
    nevermind. this works as expected.

    Any input?

  9. JimBobSquarePants commented on Nov 9, 2023

    @JimBobSquarePants
    Member

    This is precisely the kind of thing I designed ISpecializedDecoderOptions for. There's no reason we cannot define rules for handling Crc and Adler validation on decode.

    Would you be interested in creating a PR?

  10. svenclaesson commented on Nov 10, 2023

    @svenclaesson
    Contributor

    Tried it a bit but got stuck by the fact that IDAT and IEND is considered critical chunks and found no way of ignoring that fact if the file is truncated, IDAT is cut off and IEND is missing.

    Maybe you have some pointers for me here
    PR not yet posted to here because it is work in progress still.

  11. JimBobSquarePants commented on Nov 24, 2023

    @JimBobSquarePants
    Member

    Sorry for the slow reply @svenclaesson I've been off the boil for the last few weeks with sickness.

    If you actually open a PR I can commit directly to your fork to help finish it off.

  12. 3 remaining items

  13. Erik-White commented on Mar 5, 2024

    @Erik-White
    Contributor

    @JimBobSquarePants What is the easiest way to make use of the new options? Ideally I would like to be able to pass something through via Image.Identify or Image.Load, but they only take a basic DecoderOptions.

    Would it be reasonable to add overloads that take ISpecializedDecoderOptions since that already contains a DecoderOptions property? Or maybe some other concept of aggregated specialized decoder options?

  14. JimBobSquarePants commented on Mar 5, 2024

    @JimBobSquarePants
    Member

    @JimBobSquarePants What is the easiest way to make use of the new options? Ideally I would like to be able to pass something through via Image.Identify or Image.Load, but they only take a basic DecoderOptions.

    Would it be reasonable to add overloads that take ISpecializedDecoderOptions since that already contains a DecoderOptions property? Or maybe some other concept of aggregated specialized decoder options?

    Ideally, we'd add a general equivalent to DecoderOptions but we're stuck with the problem of what to choose... The specialized, or general version of the enum. Implementing it would require a breaking change to either remove or make nullable the specialized enum.

  15. Erik-White commented on Mar 6, 2024

    @Erik-White
    Contributor

    Just so I understand, you would like to add a new property to DecoderOptions, a new enum e.g. CrcChunkHandling.
    This could then be used in place of PngCrcChunkHandling, and maybe also in other decoders?

    Maybe the new one could be added and mapped to the specialized enum to save a breaking change? If I get time I could make an attempt at that.

  16. ADSAU-vestas commented on May 19, 2026

    @ADSAU-vestas

    So this issue is still pending, right? And no workaround in sight?

  17. ADSAU-vestas commented on May 19, 2026

    @ADSAU-vestas

    Possibly its not, there is a PR merged for it as I see now.
    I do get the same exception on .Identify() not on .Load(), guess its fixed on one path only.

  18. JimBobSquarePants commented on May 20, 2026

    @JimBobSquarePants
    Member

    Feel free to PR a fix for Identify

  19. ADSAU-vestas commented on May 20, 2026

    @ADSAU-vestas

    Ouch, I am working full time employed plus on 3 Github projects on my "spare" time already. Hard to find time for another one.

  20. svenclaesson commented on May 20, 2026

    @svenclaesson
    Contributor

    Then you wait and hope for the best

  21. ADSAU-vestas commented on May 20, 2026

    @ADSAU-vestas

    Possibly its not, there is a PR merged for it as I see now. I do get the same exception on .Identify() not on .Load(), guess its fixed on one path only.

    Done some more investigation here and it seems to be an deeper issue.

    The images where we can see the issue are actually saved with ImageSharp as PNG.
    We do receive the image, using var loaded = Image.Load(imageStream).Clone(i => i.AutoOrient());
    Then we determine the format from var format = loaded.MetaData.DecodedImageFormat, if it is an acceptable format we then store it into a memory stream from where we save it to cloud storage loaded.Save(targetStream, format);

    So the issue happens somewhere between those lines. Will have to try and run an .Identify() after each step to get to the bottom of it.

  22. Erik-White commented on May 20, 2026

    @Erik-White
    Contributor

    As far as I can see, this is fixed. However it does require passing SegmentIntegrityHandling.IgnoreImageData

    The default options throws InvalidImageContentException("CRC Error. PNG IDAT chunk is corrupt!"):

    using var image = Image.Load("Issue_2589.png");
    ImageInfo info = Image.Identify("Issue_2589.png");
    

    Passing decoder options avoids the throw:

    DecoderOptions options = new() { SegmentIntegrityHandling = SegmentIntegrityHandling.IgnoreImageData };
    using var image = Image.Load(options, "Issue_2589.png");
    ImageInfo info = Image.Identify(options, "Issue_2589.png");
    

    Output:
    Image

  23. ADSAU-vestas commented on May 21, 2026

    @ADSAU-vestas

    I will try that out, but it does not explain how come that the image gets saved by ImageSharp with a corrupt IDAT block. As mentioned -> Load()->Clone(AutoOrient())->Save and the incoming image has no defects.

  24. Erik-White commented on May 21, 2026

    @Erik-White
    Contributor

    Ok, it wasn't clear to me that you were starting with a good image that was maybe getting a corrupt IDAT during the ImageSharp processing.

    When exactly do you get the exceptions? Do you do an Identify() after loaded.Save(targetStream, format);? Is the input image definitely well formed?

  25. ADSAU-vestas commented on May 21, 2026

    @ADSAU-vestas

    Yes, input images are definitely good. Created a console app to read a bunch of the ones that are saved with IDAT errors, all fine.

    The Identify() is separate from the load/clone/save cycle, different modules even, same ImageSharp library ( we are still on the latest 3.x version though)

  26. JimBobSquarePants commented on May 21, 2026

    @JimBobSquarePants
    Member

    we are still on the latest 3.x version though

    Stop wasting everyone’s time then

  27. ADSAU-vestas commented on May 21, 2026

    @ADSAU-vestas

    Stop wasting everyone’s time then

    So its already fixed in the 4.x version? Great. Then its just a license question.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions