Browse Source

Merge pull request #1861 from SixLabors/js/png-decode-to-type

Png - Preserve Pixel Format for Non-generic decode.
pull/1898/head
James Jackson-South 4 years ago
committed by GitHub
parent
commit
ecd3db2271
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 114
      src/ImageSharp/Formats/Png/PngDecoder.cs
  2. 144
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  3. 225
      tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs

114
src/ImageSharp/Formats/Png/PngDecoder.cs

@ -20,37 +20,137 @@ namespace SixLabors.ImageSharp.Formats.Png
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
{
var decoder = new PngDecoderCore(configuration, this);
PngDecoderCore decoder = new(configuration, this);
return decoder.Decode<TPixel>(configuration, stream);
}
/// <inheritdoc />
public Image Decode(Configuration configuration, Stream stream) => this.Decode<Rgba32>(configuration, stream);
public Image Decode(Configuration configuration, Stream stream)
{
PngDecoderCore decoder = new(configuration, true);
IImageInfo info = decoder.Identify(configuration, stream);
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
? this.Decode<L16>(configuration, stream)
: this.Decode<La32>(configuration, stream);
}
return !meta.HasTransparency
? this.Decode<L8>(configuration, stream)
: this.Decode<La16>(configuration, stream);
case PngColorType.Rgb:
if (bits == PngBitDepth.Bit16)
{
return !meta.HasTransparency
? this.Decode<Rgb48>(configuration, stream)
: this.Decode<Rgba64>(configuration, stream);
}
return !meta.HasTransparency
? this.Decode<Rgb24>(configuration, stream)
: this.Decode<Rgba32>(configuration, stream);
case PngColorType.Palette:
return this.Decode<Rgba32>(configuration, stream);
case PngColorType.GrayscaleWithAlpha:
return (bits == PngBitDepth.Bit16)
? this.Decode<La32>(configuration, stream)
: this.Decode<La16>(configuration, stream);
case PngColorType.RgbWithAlpha:
return (bits == PngBitDepth.Bit16)
? this.Decode<Rgba64>(configuration, stream)
: this.Decode<Rgba32>(configuration, stream);
default:
return this.Decode<Rgba32>(configuration, stream);
}
}
/// <inheritdoc/>
public Task<Image<TPixel>> DecodeAsync<TPixel>(Configuration configuration, Stream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
var decoder = new PngDecoderCore(configuration, this);
PngDecoderCore decoder = new(configuration, this);
return decoder.DecodeAsync<TPixel>(configuration, stream, cancellationToken);
}
/// <inheritdoc />
public async Task<Image> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
=> await this.DecodeAsync<Rgba32>(configuration, stream, cancellationToken)
.ConfigureAwait(false);
{
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)
{
var decoder = new PngDecoderCore(configuration, this);
PngDecoderCore decoder = new(configuration, this);
return decoder.Identify(configuration, stream);
}
/// <inheritdoc/>
public Task<IImageInfo> IdentifyAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken)
{
var decoder = new PngDecoderCore(configuration, this);
PngDecoderCore decoder = new(configuration, this);
return decoder.IdentifyAsync(configuration, stream, cancellationToken);
}
}

144
src/ImageSharp/Formats/Png/PngDecoderCore.cs

@ -37,6 +37,11 @@ namespace SixLabors.ImageSharp.Formats.Png
/// </summary>
private readonly bool ignoreMetadata;
/// <summary>
/// Gets or sets a value indicating whether to read the IHDR and tRNS chunks only.
/// </summary>
private readonly bool colorMetadataOnly;
/// <summary>
/// Used the manage memory allocations.
/// </summary>
@ -77,11 +82,6 @@ namespace SixLabors.ImageSharp.Formats.Png
/// </summary>
private byte[] paletteAlpha;
/// <summary>
/// A value indicating whether the end chunk has been reached.
/// </summary>
private bool isEndChunkReached;
/// <summary>
/// Previous scanline processed.
/// </summary>
@ -124,13 +124,21 @@ namespace SixLabors.ImageSharp.Formats.Png
this.ignoreMetadata = options.IgnoreMetadata;
}
internal PngDecoderCore(Configuration configuration, bool colorMetadataOnly)
{
this.Configuration = configuration ?? Configuration.Default;
this.memoryAllocator = this.Configuration.MemoryAllocator;
this.colorMetadataOnly = colorMetadataOnly;
this.ignoreMetadata = true;
}
/// <inheritdoc/>
public Configuration Configuration { get; }
/// <summary>
/// Gets the dimensions of the image.
/// </summary>
public Size Dimensions => new Size(this.header.Width, this.header.Height);
public Size Dimensions => new(this.header.Width, this.header.Height);
/// <inheritdoc/>
public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken cancellationToken)
@ -143,7 +151,7 @@ namespace SixLabors.ImageSharp.Formats.Png
Image<TPixel> image = null;
try
{
while (!this.isEndChunkReached && this.TryReadChunk(out PngChunk chunk))
while (this.TryReadChunk(out PngChunk chunk))
{
try
{
@ -168,12 +176,12 @@ namespace SixLabors.ImageSharp.Formats.Png
break;
case PngChunkType.Palette:
var pal = new byte[chunk.Length];
byte[] pal = new byte[chunk.Length];
chunk.Data.GetSpan().CopyTo(pal);
this.palette = pal;
break;
case PngChunkType.Transparency:
var alpha = new byte[chunk.Length];
byte[] alpha = new byte[chunk.Length];
chunk.Data.GetSpan().CopyTo(alpha);
this.paletteAlpha = alpha;
this.AssignTransparentMarkers(alpha, pngMetadata);
@ -190,15 +198,14 @@ namespace SixLabors.ImageSharp.Formats.Png
case PngChunkType.Exif:
if (!this.ignoreMetadata)
{
var exifData = new byte[chunk.Length];
byte[] exifData = new byte[chunk.Length];
chunk.Data.GetSpan().CopyTo(exifData);
metadata.ExifProfile = new ExifProfile(exifData);
}
break;
case PngChunkType.End:
this.isEndChunkReached = true;
break;
goto EOF;
case PngChunkType.ProprietaryApple:
PngThrowHelper.ThrowInvalidChunkType("Proprietary Apple PNG detected! This PNG file is not conform to the specification and cannot be decoded.");
break;
@ -210,6 +217,7 @@ namespace SixLabors.ImageSharp.Formats.Png
}
}
EOF:
if (image is null)
{
PngThrowHelper.ThrowNoData();
@ -233,7 +241,7 @@ namespace SixLabors.ImageSharp.Formats.Png
this.currentStream.Skip(8);
try
{
while (!this.isEndChunkReached && this.TryReadChunk(out PngChunk chunk))
while (this.TryReadChunk(out PngChunk chunk))
{
try
{
@ -243,35 +251,89 @@ namespace SixLabors.ImageSharp.Formats.Png
this.ReadHeaderChunk(pngMetadata, chunk.Data.GetSpan());
break;
case PngChunkType.Physical:
if (this.colorMetadataOnly)
{
this.SkipChunkDataAndCrc(chunk);
break;
}
this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan());
break;
case PngChunkType.Gamma:
if (this.colorMetadataOnly)
{
this.SkipChunkDataAndCrc(chunk);
break;
}
this.ReadGammaChunk(pngMetadata, chunk.Data.GetSpan());
break;
case PngChunkType.Data:
// Spec says tRNS must be before IDAT so safe to exit.
if (this.colorMetadataOnly)
{
goto EOF;
}
this.SkipChunkDataAndCrc(chunk);
break;
case PngChunkType.Transparency:
byte[] alpha = new byte[chunk.Length];
chunk.Data.GetSpan().CopyTo(alpha);
this.paletteAlpha = alpha;
this.AssignTransparentMarkers(alpha, pngMetadata);
if (this.colorMetadataOnly)
{
goto EOF;
}
break;
case PngChunkType.Text:
if (this.colorMetadataOnly)
{
this.SkipChunkDataAndCrc(chunk);
break;
}
this.ReadTextChunk(pngMetadata, chunk.Data.GetSpan());
break;
case PngChunkType.CompressedText:
if (this.colorMetadataOnly)
{
this.SkipChunkDataAndCrc(chunk);
break;
}
this.ReadCompressedTextChunk(pngMetadata, chunk.Data.GetSpan());
break;
case PngChunkType.InternationalText:
if (this.colorMetadataOnly)
{
this.SkipChunkDataAndCrc(chunk);
break;
}
this.ReadInternationalTextChunk(pngMetadata, chunk.Data.GetSpan());
break;
case PngChunkType.Exif:
if (this.colorMetadataOnly)
{
this.SkipChunkDataAndCrc(chunk);
break;
}
if (!this.ignoreMetadata)
{
var exifData = new byte[chunk.Length];
byte[] exifData = new byte[chunk.Length];
chunk.Data.GetSpan().CopyTo(exifData);
metadata.ExifProfile = new ExifProfile(exifData);
}
break;
case PngChunkType.End:
this.isEndChunkReached = true;
break;
goto EOF;
}
}
finally
@ -279,19 +341,20 @@ namespace SixLabors.ImageSharp.Formats.Png
chunk.Data?.Dispose(); // Data is rented in ReadChunkData()
}
}
EOF:
if (this.header.Width == 0 && this.header.Height == 0)
{
PngThrowHelper.ThrowNoHeader();
}
return new ImageInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), this.header.Width, this.header.Height, metadata);
}
finally
{
this.scanline?.Dispose();
this.previousScanline?.Dispose();
}
if (this.header.Width == 0 && this.header.Height == 0)
{
PngThrowHelper.ThrowNoHeader();
}
return new ImageInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), this.header.Width, this.header.Height, metadata);
}
/// <summary>
@ -364,11 +427,10 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <param name="pngMetadata">The metadata to read to.</param>
/// <param name="data">The data containing physical data.</param>
private void ReadGammaChunk(PngMetadata pngMetadata, ReadOnlySpan<byte> data)
{
// The value is encoded as a 4-byte unsigned integer, representing gamma times 100000.
// For example, a gamma of 1/2.2 would be stored as 45455.
pngMetadata.Gamma = BinaryPrimitives.ReadUInt32BigEndian(data) / 100_000F;
}
=> pngMetadata.Gamma = BinaryPrimitives.ReadUInt32BigEndian(data) * 1e-5F;
/// <summary>
/// Initializes the image and various buffers needed for processing
@ -477,19 +539,17 @@ namespace SixLabors.ImageSharp.Formats.Png
private void ReadScanlines<TPixel>(PngChunk chunk, ImageFrame<TPixel> image, PngMetadata pngMetadata)
where TPixel : unmanaged, IPixel<TPixel>
{
using (var deframeStream = new ZlibInflateStream(this.currentStream, this.ReadNextDataChunk))
{
deframeStream.AllocateNewBytes(chunk.Length, true);
DeflateStream dataStream = deframeStream.CompressedStream;
using var deframeStream = new ZlibInflateStream(this.currentStream, this.ReadNextDataChunk);
deframeStream.AllocateNewBytes(chunk.Length, true);
DeflateStream dataStream = deframeStream.CompressedStream;
if (this.header.InterlaceMethod == PngInterlaceMode.Adam7)
{
this.DecodeInterlacedPixelData(dataStream, image, pngMetadata);
}
else
{
this.DecodePixelData(dataStream, image, pngMetadata);
}
if (this.header.InterlaceMethod == PngInterlaceMode.Adam7)
{
this.DecodeInterlacedPixelData(dataStream, image, pngMetadata);
}
else
{
this.DecodePixelData(dataStream, image, pngMetadata);
}
}
@ -919,7 +979,7 @@ namespace SixLabors.ImageSharp.Formats.Png
int zeroIndex = data.IndexOf((byte)0);
// Keywords are restricted to 1 to 79 bytes in length.
if (zeroIndex < PngConstants.MinTextKeywordLength || zeroIndex > PngConstants.MaxTextKeywordLength)
if (zeroIndex is < PngConstants.MinTextKeywordLength or > PngConstants.MaxTextKeywordLength)
{
return;
}
@ -1146,8 +1206,10 @@ namespace SixLabors.ImageSharp.Formats.Png
PngChunkType type = this.ReadChunkType();
// NOTE: Reading the chunk data is the responsible of the caller
if (type == PngChunkType.Data)
// NOTE: Reading the Data chunk is the responsible of the caller
// If we're reading color metadata only we're only interested in the IHDR and tRNS chunks.
// We can skip all other chunk data in the stream for better performance.
if (type == PngChunkType.Data || (this.colorMetadataOnly && type != PngChunkType.Header && type != PngChunkType.Transparency))
{
chunk = new PngChunk(length, type);

225
tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs

@ -1,7 +1,9 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.DotNet.RemoteExecutor;
using SixLabors.ImageSharp.Formats.Png;
@ -19,7 +21,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
[Trait("Format", "Png")]
public partial class PngDecoderTests
{
private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32 | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32;
private const PixelTypes TestPixelTypes = PixelTypes.Rgba32 | PixelTypes.RgbaVector | PixelTypes.Argb32;
private static PngDecoder PngDecoder => new();
@ -62,16 +64,51 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
TestImages.Png.Bad.ZlibZtxtBadHeader,
};
public static readonly TheoryData<string, Type> PixelFormatRange = new()
{
{ TestImages.Png.Gray4Bpp, typeof(Image<L8>) },
{ TestImages.Png.L16Bit, typeof(Image<L16>) },
{ TestImages.Png.Gray1BitTrans, typeof(Image<La16>) },
{ TestImages.Png.Gray2BitTrans, typeof(Image<La16>) },
{ TestImages.Png.Gray4BitTrans, typeof(Image<La16>) },
{ TestImages.Png.GrayA8Bit, typeof(Image<La16>) },
{ TestImages.Png.GrayAlpha16Bit, typeof(Image<La32>) },
{ TestImages.Png.Palette8Bpp, typeof(Image<Rgba32>) },
{ TestImages.Png.PalettedTwoColor, typeof(Image<Rgba32>) },
{ TestImages.Png.Rainbow, typeof(Image<Rgb24>) },
{ TestImages.Png.Rgb24BppTrans, typeof(Image<Rgba32>) },
{ TestImages.Png.Kaboom, typeof(Image<Rgba32>) },
{ TestImages.Png.Rgb48Bpp, typeof(Image<Rgb48>) },
{ TestImages.Png.Rgb48BppTrans, typeof(Image<Rgba64>) },
{ TestImages.Png.Rgba64Bpp, typeof(Image<Rgba64>) },
};
[Theory]
[MemberData(nameof(PixelFormatRange))]
public void Decode_NonGeneric_CreatesCorrectImageType(string path, Type type)
{
string file = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, path);
using var image = Image.Load(file);
Assert.IsType(type, image);
}
[Theory]
[MemberData(nameof(PixelFormatRange))]
public async Task DecodeAsync_NonGeneric_CreatesCorrectImageType(string path, Type type)
{
string file = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, path);
using Image image = await Image.LoadAsync(file);
Assert.IsType(type, image);
}
[Theory]
[WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32)]
public void Decode<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
[Theory]
@ -80,11 +117,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decode_GrayWithAlpha<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
[Theory]
@ -94,11 +129,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decode_Interlaced<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
[Theory]
@ -111,11 +144,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decode_Indexed<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
[Theory]
@ -124,11 +155,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decode_48Bpp<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
[Theory]
@ -137,11 +166,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decode_64Bpp<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
[Theory]
@ -152,11 +179,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decoder_L8bitInterlaced<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
[Theory]
@ -164,11 +189,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decode_L16Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
[Theory]
@ -177,23 +200,19 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decode_GrayAlpha16Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
[Theory]
[WithFile(TestImages.Png.GrayA8BitInterlaced, PixelTypes)]
[WithFile(TestImages.Png.GrayA8BitInterlaced, TestPixelTypes)]
public void Decoder_CanDecode_Grey8bitInterlaced_WithAlpha<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
[Theory]
@ -201,23 +220,19 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Decoder_CanDecode_CorruptedImages<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
[Theory]
[WithFile(TestImages.Png.Splash, PixelTypes)]
[WithFile(TestImages.Png.Splash, TestPixelTypes)]
public void Decoder_IsNotBoundToSinglePixelType<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
[Theory]
@ -231,10 +246,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
public void Identify(string imagePath, int expectedPixelSize)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
Assert.Equal(expectedPixelSize, Image.Identify(stream)?.PixelType?.BitsPerPixel);
}
using var stream = new MemoryStream(testFile.Bytes, false);
Assert.Equal(expectedPixelSize, Image.Identify(stream)?.PixelType?.BitsPerPixel);
}
[Theory]
@ -245,10 +258,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
System.Exception ex = Record.Exception(
() =>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
});
Assert.NotNull(ex);
Assert.Contains("PNG Image does not contain a data chunk", ex.Message);
@ -263,10 +274,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
System.Exception ex = Record.Exception(
() =>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
});
Assert.NotNull(ex);
Assert.Contains("Invalid or unsupported bit depth", ex.Message);
@ -281,10 +290,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
System.Exception ex = Record.Exception(
() =>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
});
Assert.NotNull(ex);
Assert.Contains("Invalid or unsupported color type", ex.Message);
@ -299,11 +306,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
System.Exception ex = Record.Exception(
() =>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
});
Assert.Null(ex);
}
@ -317,11 +322,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
System.Exception ex = Record.Exception(
() =>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
});
Assert.Null(ex);
}
@ -335,11 +338,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
System.Exception ex = Record.Exception(
() =>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
});
Assert.Null(ex);
}
@ -353,15 +354,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
System.Exception ex = Record.Exception(
() =>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
// We don't have another x-plat reference decoder that can be compared for this image.
if (TestEnvironment.IsWindows)
{
image.CompareToOriginal(provider, ImageComparer.Exact, SystemDrawingReferenceDecoder.Instance);
}
// We don't have another x-plat reference decoder that can be compared for this image.
if (TestEnvironment.IsWindows)
{
image.CompareToOriginal(provider, ImageComparer.Exact, SystemDrawingReferenceDecoder.Instance);
}
});
Assert.Null(ex);
@ -376,11 +375,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
System.Exception ex = Record.Exception(
() =>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
});
Assert.Null(ex);
}
@ -394,15 +391,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
System.Exception ex = Record.Exception(
() =>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
using Image<TPixel> image = provider.GetImage(PngDecoder);
image.DebugSave(provider);
// We don't have another x-plat reference decoder that can be compared for this image.
if (TestEnvironment.IsWindows)
{
image.CompareToOriginal(provider, ImageComparer.Exact, SystemDrawingReferenceDecoder.Instance);
}
// We don't have another x-plat reference decoder that can be compared for this image.
if (TestEnvironment.IsWindows)
{
image.CompareToOriginal(provider, ImageComparer.Exact, SystemDrawingReferenceDecoder.Instance);
}
});
Assert.NotNull(ex);

Loading…
Cancel
Save