saucecontrol / PhotoSauce

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

`ArgumentOutOfRangeException` reading JPEG XL image from their test page #142

Closed MaceWindu closed 4 months ago

MaceWindu commented 6 months ago

not sure if it is issue in this project or in libjxl

CodecManager.Configure(codecs =>
{
    codecs.UseLibjxl();
    codecs.UseLibpng();
});

// test animation from https://jpegxl.info/test-page/
var input = await new HttpClient().GetByteArrayAsync("https://jpegxl.info/test-page/dice.jxl");
var output = new MemoryStream();
var result = MagicImageProcessor.ProcessImage(input, output, new ProcessImageSettings()
{
    EncoderOptions = PngEncoderOptions.Default,
});
System.ArgumentOutOfRangeException
  Message=Specified argument was out of the range of valid values.
  Source=System.Private.CoreLib
  StackTrace:
   at System.ThrowHelper.ThrowArgumentOutOfRangeException() in System\ThrowHelper.cs:line 44
   at System.ReadOnlySpan`1..ctor(T[] array, Int32 start, Int32 length) in System\ReadOnlySpan.cs:line 117
   at PhotoSauce.MagicScaler.PixelBuffer`1.PrepareRead(Int32 first, Int32 lines) in /_/src/MagicScaler/Core/PixelBuffer.cs:line 190
   at PhotoSauce.NativeCodecs.Libjxl.JxlContainer.JxlPixelSource.CopyPixelsInternal(PixelArea& prc, Int32 cbStride, Int32 cbBufferSize, Byte* pbBuffer) in /_/src/NativeCodecs/Libjxl/JxlDecoder.cs:line 421
   at PhotoSauce.MagicScaler.PixelSource.CopyPixels(PixelArea& prc, Int32 cbStride, Int32 cbBufferSize, Byte* pbBuffer) in /_/src/MagicScaler/Magic/PixelSource.cs:line 51
   at PhotoSauce.MagicScaler.Transforms.ConversionTransform.copyPixelsDirect(PixelArea& prc, Int32 cbStride, Byte* pbBuffer) in /_/src/MagicScaler/Magic/ConversionTransform.cs:line 191
   at PhotoSauce.MagicScaler.Transforms.ConversionTransform.CopyPixelsInternal(PixelArea& prc, Int32 cbStride, Int32 cbBufferSize, Byte* pbBuffer) in /_/src/MagicScaler/Magic/ConversionTransform.cs:line 156
   at PhotoSauce.MagicScaler.PixelSource.CopyPixels(PixelArea& prc, Int32 cbStride, Int32 cbBufferSize, Byte* pbBuffer) in /_/src/MagicScaler/Magic/PixelSource.cs:line 51
   at PhotoSauce.MagicScaler.Transforms.ConversionTransform.copyPixelsDirect(PixelArea& prc, Int32 cbStride, Byte* pbBuffer) in /_/src/MagicScaler/Magic/ConversionTransform.cs:line 191
   at PhotoSauce.MagicScaler.Transforms.ConversionTransform.CopyPixelsInternal(PixelArea& prc, Int32 cbStride, Int32 cbBufferSize, Byte* pbBuffer) in /_/src/MagicScaler/Magic/ConversionTransform.cs:line 156
   at PhotoSauce.MagicScaler.PixelSource.CopyPixels(PixelArea& prc, Int32 cbStride, Int32 cbBufferSize, Byte* pbBuffer) in /_/src/MagicScaler/Magic/PixelSource.cs:line 51
   at PhotoSauce.MagicScaler.PixelSource.PhotoSauce.MagicScaler.IPixelSource.CopyPixels(Rectangle sourceArea, Int32 cbStride, Span`1 buffer) in /_/src/MagicScaler/Magic/PixelSource.cs:line 71
   at PhotoSauce.NativeCodecs.Libpng.PngEncoder.writePixels(IPixelSource src, PixelArea area) in /_/src/NativeCodecs/Libpng/PngEncoder.cs:line 218
   at PhotoSauce.NativeCodecs.Libpng.PngEncoder.WriteFrame(IPixelSource source, IMetadataSource metadata, Rectangle sourceArea) in /_/src/NativeCodecs/Libpng/PngEncoder.cs:line 93
   at PhotoSauce.MagicScaler.MagicImageProcessor.WriteOutput(PipelineContext ctx, Stream ostm) in /_/src/MagicScaler/Magic/MagicImageProcessor.cs:line 268
   at PhotoSauce.MagicScaler.MagicImageProcessor.ProcessImage(ReadOnlySpan`1 imgBuffer, Stream outStream, ProcessImageSettings settings) in /_/src/MagicScaler/Magic/MagicImageProcessor.cs:line 72
   at ConsoleApp123.Program.<Main>d__0.MoveNext() in ConsoleApp123\Program.cs:line 20
   at ConsoleApp123.Program.<Main>(String[] args)
saucecontrol commented 6 months ago

Thanks for logging this.

There is a new libjxl release, but I'm assuming this one is something on my end. I haven't seen too many test images for JXL, so there are bound to be some holes.

saucecontrol commented 6 months ago

Looks like this is related to libjxl returning pixels out of order when using its decoder in push mode. I wasn't able to locate good samples of out-of-order progressive images when writing the codec wrapper initially, so the plugin bails when it encounters such images, leaving the buffer rows undefined. Should be fairly easy to fix now that there are sample images to work with.

saucecontrol commented 4 months ago

All samples now decode in the latest build on the CI feed. I'll be publishing new versions to nuget.org soon™