|
|
|
@ -3,7 +3,6 @@ |
|
|
|
|
|
|
|
using System.IO; |
|
|
|
using System.Threading; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using SixLabors.ImageSharp.PixelFormats; |
|
|
|
|
|
|
|
namespace SixLabors.ImageSharp.Formats.Png |
|
|
|
@ -17,18 +16,18 @@ namespace SixLabors.ImageSharp.Formats.Png |
|
|
|
public bool IgnoreMetadata { get; set; } |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) |
|
|
|
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) |
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
{ |
|
|
|
PngDecoderCore decoder = new(configuration, this); |
|
|
|
return decoder.Decode<TPixel>(configuration, stream); |
|
|
|
return decoder.Decode<TPixel>(configuration, stream, cancellationToken); |
|
|
|
} |
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
public Image Decode(Configuration configuration, Stream stream) |
|
|
|
public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) |
|
|
|
{ |
|
|
|
PngDecoderCore decoder = new(configuration, true); |
|
|
|
IImageInfo info = decoder.Identify(configuration, stream); |
|
|
|
IImageInfo info = decoder.Identify(configuration, stream, cancellationToken); |
|
|
|
stream.Position = 0; |
|
|
|
|
|
|
|
PngMetadata meta = info.Metadata.GetPngMetadata(); |
|
|
|
@ -40,118 +39,49 @@ namespace SixLabors.ImageSharp.Formats.Png |
|
|
|
if (bits == PngBitDepth.Bit16) |
|
|
|
{ |
|
|
|
return !meta.HasTransparency |
|
|
|
? this.Decode<L16>(configuration, stream) |
|
|
|
: this.Decode<La32>(configuration, stream); |
|
|
|
? this.Decode<L16>(configuration, stream, cancellationToken) |
|
|
|
: this.Decode<La32>(configuration, stream, cancellationToken); |
|
|
|
} |
|
|
|
|
|
|
|
return !meta.HasTransparency |
|
|
|
? this.Decode<L8>(configuration, stream) |
|
|
|
: this.Decode<La16>(configuration, stream); |
|
|
|
? this.Decode<L8>(configuration, stream, cancellationToken) |
|
|
|
: this.Decode<La16>(configuration, stream, cancellationToken); |
|
|
|
|
|
|
|
case PngColorType.Rgb: |
|
|
|
if (bits == PngBitDepth.Bit16) |
|
|
|
{ |
|
|
|
return !meta.HasTransparency |
|
|
|
? this.Decode<Rgb48>(configuration, stream) |
|
|
|
: this.Decode<Rgba64>(configuration, stream); |
|
|
|
? this.Decode<Rgb48>(configuration, stream, cancellationToken) |
|
|
|
: this.Decode<Rgba64>(configuration, stream, cancellationToken); |
|
|
|
} |
|
|
|
|
|
|
|
return !meta.HasTransparency |
|
|
|
? this.Decode<Rgb24>(configuration, stream) |
|
|
|
: this.Decode<Rgba32>(configuration, stream); |
|
|
|
? this.Decode<Rgb24>(configuration, stream, cancellationToken) |
|
|
|
: this.Decode<Rgba32>(configuration, stream, cancellationToken); |
|
|
|
|
|
|
|
case PngColorType.Palette: |
|
|
|
return this.Decode<Rgba32>(configuration, stream); |
|
|
|
return this.Decode<Rgba32>(configuration, stream, cancellationToken); |
|
|
|
|
|
|
|
case PngColorType.GrayscaleWithAlpha: |
|
|
|
return (bits == PngBitDepth.Bit16) |
|
|
|
? this.Decode<La32>(configuration, stream) |
|
|
|
: this.Decode<La16>(configuration, stream); |
|
|
|
? this.Decode<La32>(configuration, stream, cancellationToken) |
|
|
|
: this.Decode<La16>(configuration, stream, cancellationToken); |
|
|
|
|
|
|
|
case PngColorType.RgbWithAlpha: |
|
|
|
return (bits == PngBitDepth.Bit16) |
|
|
|
? this.Decode<Rgba64>(configuration, stream) |
|
|
|
: this.Decode<Rgba32>(configuration, stream); |
|
|
|
? this.Decode<Rgba64>(configuration, stream, cancellationToken) |
|
|
|
: this.Decode<Rgba32>(configuration, stream, cancellationToken); |
|
|
|
|
|
|
|
default: |
|
|
|
return this.Decode<Rgba32>(configuration, stream); |
|
|
|
return this.Decode<Rgba32>(configuration, stream, cancellationToken); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken) |
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
{ |
|
|
|
PngDecoderCore decoder = new(configuration, this); |
|
|
|
return decoder.DecodeAsync<TPixel>(configuration, stream, cancellationToken); |
|
|
|
} |
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) |
|
|
|
{ |
|
|
|
PngDecoderCore decoder = new(configuration, true); |
|
|
|
IImageInfo info = await decoder.IdentifyAsync(configuration, stream, cancellationToken).ConfigureAwait(false); |
|
|
|
stream.Position = 0; |
|
|
|
|
|
|
|
PngMetadata meta = info.Metadata.GetPngMetadata(); |
|
|
|
PngColorType color = meta.ColorType.GetValueOrDefault(); |
|
|
|
PngBitDepth bits = meta.BitDepth.GetValueOrDefault(); |
|
|
|
switch (color) |
|
|
|
{ |
|
|
|
case PngColorType.Grayscale: |
|
|
|
if (bits == PngBitDepth.Bit16) |
|
|
|
{ |
|
|
|
return !meta.HasTransparency |
|
|
|
? await this.DecodeAsync<L16>(configuration, stream, cancellationToken).ConfigureAwait(false) |
|
|
|
: await this.DecodeAsync<La32>(configuration, stream, cancellationToken).ConfigureAwait(false); |
|
|
|
} |
|
|
|
|
|
|
|
return !meta.HasTransparency |
|
|
|
? await this.DecodeAsync<L8>(configuration, stream, cancellationToken).ConfigureAwait(false) |
|
|
|
: await this.DecodeAsync<La16>(configuration, stream, cancellationToken).ConfigureAwait(false); |
|
|
|
|
|
|
|
case PngColorType.Rgb: |
|
|
|
if (bits == PngBitDepth.Bit16) |
|
|
|
{ |
|
|
|
return !meta.HasTransparency |
|
|
|
? await this.DecodeAsync<Rgb48>(configuration, stream, cancellationToken).ConfigureAwait(false) |
|
|
|
: await this.DecodeAsync<Rgba64>(configuration, stream, cancellationToken).ConfigureAwait(false); |
|
|
|
} |
|
|
|
|
|
|
|
return !meta.HasTransparency |
|
|
|
? await this.DecodeAsync<Rgb24>(configuration, stream, cancellationToken).ConfigureAwait(false) |
|
|
|
: await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false); |
|
|
|
|
|
|
|
case PngColorType.Palette: |
|
|
|
return await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false); |
|
|
|
|
|
|
|
case PngColorType.GrayscaleWithAlpha: |
|
|
|
return (bits == PngBitDepth.Bit16) |
|
|
|
? await this.DecodeAsync<La32>(configuration, stream, cancellationToken).ConfigureAwait(false) |
|
|
|
: await this.DecodeAsync<La16>(configuration, stream, cancellationToken).ConfigureAwait(false); |
|
|
|
|
|
|
|
case PngColorType.RgbWithAlpha: |
|
|
|
return (bits == PngBitDepth.Bit16) |
|
|
|
? await this.DecodeAsync<Rgba64>(configuration, stream, cancellationToken).ConfigureAwait(false) |
|
|
|
: await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false); |
|
|
|
|
|
|
|
default: |
|
|
|
return await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken).ConfigureAwait(false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public IImageInfo Identify(Configuration configuration, Stream stream) |
|
|
|
{ |
|
|
|
PngDecoderCore decoder = new(configuration, this); |
|
|
|
return decoder.Identify(configuration, stream); |
|
|
|
} |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public Task<IImageInfo> IdentifyAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) |
|
|
|
public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken) |
|
|
|
{ |
|
|
|
PngDecoderCore decoder = new(configuration, this); |
|
|
|
return decoder.IdentifyAsync(configuration, stream, cancellationToken); |
|
|
|
return decoder.Identify(configuration, stream, cancellationToken); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|