saucecontrol / PhotoSauce

MagicScaler high-performance, high-quality image processing pipeline for .NET
http://photosauce.net/
MIT License
569 stars 49 forks source link

Image format not supported exception with test heic file #89

Closed cvdsoftware closed 1 year ago

cvdsoftware commented 2 years ago

I'm trying to convert sample1.heic from https://filesamples.com/formats/heic (image1.zip) using the latest version from nuget (PhotoSauce.MagicScaler 0.13.0 and PhotoSauce.NativeCodecs.Libheif 1.12.0-Preview2) on .NET 6.0:

CodecManager.Configure(codecs => {
    var wicheif = codecs.OfType<IImageDecoderInfo>().FirstOrDefault(c => c.MimeTypes.Any(m => m == ImageMimeTypes.Heic));
    if (wicheif != null)
        codecs.Remove(wicheif);

    codecs.UseLibheif();
});

MagicImageProcessor.ProcessImage(@"c:\temp\heic\image1.heic", @"c:\temp\heic\image1.jpg", new ProcessImageSettings { Width = 240, Height = 240, ResizeMode = CropScaleMode.Max, EncoderOptions = new JpegEncoderOptions() { Quality = 80 } });

But I receive a exception: System.IO.InvalidDataException: 'Image format not supported. Please ensure the input file is an image and that a codec capable of reading the image is registered.' Other test heic files works fine with the test code.

If I disable the Libheif native codec it works on Windows 10 (but Windows Server doesn't have the codec), also the Windows Photo app can show the file: image

I don't now if this is just a coincidence or a bug in the native codec.

Btw, thanks for your great lib!

saucecontrol commented 2 years ago

Hey, thanks for the report.

That sample image has an unusual signature that's not recognized by the plugin. Normal HEIC BMFF box type is ftypheic but that image has ftypmif1. It appears that's a valid (if uncommon) structure, and libheif does support it, so we'll just have to update the patterns the plugin registers.

In the meantime, if you need to decode files with that signature, you can update the patterns matched by the codec just after you register it, like this:

CodecManager.Configure(codecs => {
    // remove WIC HEIF
    var wicheif = codecs.OfType<IImageDecoderInfo>().FirstOrDefault(c => c.MimeTypes.Any(m => m == ImageMimeTypes.Heic));
    if (wicheif != null)
        codecs.Remove(wicheif);

    // register libheif
    codecs.UseLibheif();

    // remove libheif and re-add with updated patterns
    var libheif = codecs.OfType<DecoderInfo>().Single(c => c.MimeTypes.Any(m => m == ImageMimeTypes.Heic));
    codecs.Remove(libheif);

    var mif1 = new ContainerPattern {
        Offset = 0,
        Pattern = new byte[] { 0, 0, 0, 0, (byte)'f', (byte)'t', (byte)'y', (byte)'p', (byte)'m', (byte)'i', (byte)'f', (byte)'1' },
        Mask = new byte[] { 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
    };
    var patterns = libheif.Patterns.Append(mif1);

    codecs.Add(libheif with { Patterns = patterns });
});
cvdsoftware commented 2 years ago

Sorry for my late response, was on vacation.

Your fix works perfectly, thanks for the quick response!

saucecontrol commented 1 year ago

Thanks for confirming. I've published a new package with the additional signature (and which no longer requires manually removing the Windows HEIF codec before registering the plugin) https://www.nuget.org/packages/PhotoSauce.NativeCodecs.Libheif