@ -7,6 +7,7 @@ using ImageMagick.Formats;
using SixLabors.ImageSharp.Formats ;
using SixLabors.ImageSharp.Formats ;
using SixLabors.ImageSharp.Formats.Bmp ;
using SixLabors.ImageSharp.Formats.Bmp ;
using SixLabors.ImageSharp.Formats.Exr ;
using SixLabors.ImageSharp.Formats.Exr ;
using SixLabors.ImageSharp.Formats.Heif ;
using SixLabors.ImageSharp.Formats.Jpeg ;
using SixLabors.ImageSharp.Formats.Jpeg ;
using SixLabors.ImageSharp.Formats.Png ;
using SixLabors.ImageSharp.Formats.Png ;
using SixLabors.ImageSharp.Formats.Tiff ;
using SixLabors.ImageSharp.Formats.Tiff ;
@ -45,6 +46,8 @@ public class MagickReferenceDecoder : ImageDecoder
public static MagickReferenceDecoder Exr { get ; } = new ( ExrFormat . Instance ) ;
public static MagickReferenceDecoder Exr { get ; } = new ( ExrFormat . Instance ) ;
public static MagickReferenceDecoder Heif { get ; } = new ( HeifFormat . Instance ) ;
protected override Image < TPixel > Decode < TPixel > ( DecoderOptions options , Stream stream , CancellationToken cancellationToken )
protected override Image < TPixel > Decode < TPixel > ( DecoderOptions options , Stream stream , CancellationToken cancellationToken )
{
{
ImageMetadata metadata = new ( ) ;
ImageMetadata metadata = new ( ) ;
@ -83,13 +86,13 @@ public class MagickReferenceDecoder : ImageDecoder
( int ) magicFrame . Height ) ;
( int ) magicFrame . Height ) ;
using IUnsafePixelCollection < ushort > pixels = magicFrame . GetPixelsUnsafe ( ) ;
using IUnsafePixelCollection < ushort > pixels = magicFrame . GetPixelsUnsafe ( ) ;
if ( magicFrame . Depth is 1 2 or 1 0 or 8 or 6 or 5 or 4 or 3 or 2 or 1 )
if ( magicFrame . Depth is 8 or 6 or 5 or 4 or 3 or 2 or 1 )
{
{
byte [ ] data = pixels . ToByteArray ( PixelMapping . RGBA ) ;
byte [ ] data = pixels . ToByteArray ( PixelMapping . RGBA ) ;
FromRgba32Bytes ( configuration , data , buffer ) ;
FromRgba32Bytes ( configuration , data , buffer ) ;
}
}
else if ( magicFrame . Depth is 1 4 or 1 6 or 3 2 )
else if ( magicFrame . Depth is 1 0 or 1 2 or 1 4 or 1 6 or 3 2 )
{
{
if ( this . imageFormat is PngFormat png )
if ( this . imageFormat is PngFormat png )
{
{
@ -97,6 +100,21 @@ public class MagickReferenceDecoder : ImageDecoder
}
}
ushort [ ] data = pixels . ToShortArray ( PixelMapping . RGBA ) ;
ushort [ ] data = pixels . ToShortArray ( PixelMapping . RGBA ) ;
if ( this . imageFormat is HeifFormat & & magicFrame . Depth is 1 0 or 1 2 )
{
// The HEIF reader left-aligns native samples in its 16-bit channels. Recover the declared
// sample values before expanding their full range to Rgba64; a shift alone leaves white
// below 65535 and changes every nonzero component's normalized value.
int depth = ( int ) magicFrame . Depth ;
int shift = 1 6 - depth ;
int maximum = ( 1 < < depth ) - 1 ;
for ( int i = 0 ; i < data . Length ; i + + )
{
int sample = data [ i ] > > shift ;
data [ i ] = ( ushort ) ( ( ( sample * 6 5 5 3 5 ) + ( maximum / 2 ) ) / maximum ) ;
}
}
Span < byte > bytes = MemoryMarshal . Cast < ushort , byte > ( data . AsSpan ( ) ) ;
Span < byte > bytes = MemoryMarshal . Cast < ushort , byte > ( data . AsSpan ( ) ) ;
FromRgba64Bytes ( configuration , bytes , buffer ) ;
FromRgba64Bytes ( configuration , bytes , buffer ) ;
}
}