Browse Source

Fix webp bpp parsing, normalize property naming.

pull/2751/head
James Jackson-South 2 years ago
parent
commit
0e54081232
  1. 14
      src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs
  2. 24
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  3. 30
      src/ImageSharp/Formats/Bmp/BmpMetadata.cs
  4. 4
      src/ImageSharp/Formats/Jpeg/JpegMetadata.cs
  5. 8
      src/ImageSharp/Formats/Tga/TgaBitsPerPixel.cs
  6. 2
      src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
  7. 22
      src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
  8. 18
      src/ImageSharp/Formats/Tga/TgaMetadata.cs
  9. 4
      src/ImageSharp/Formats/Webp/WebpBitsPerPixel.cs
  10. 37
      src/ImageSharp/Formats/Webp/WebpChunkParsingUtils.cs
  11. 25
      src/ImageSharp/Formats/Webp/WebpColorType.cs
  12. 21
      src/ImageSharp/Formats/Webp/WebpDecoderCore.cs
  13. 6
      src/ImageSharp/Formats/Webp/WebpImageInfo.cs
  14. 33
      src/ImageSharp/Formats/Webp/WebpMetadata.cs
  15. 90
      tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs
  16. 4
      tests/ImageSharp.Tests/Formats/Bmp/BmpMetadataTests.cs
  17. 32
      tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs
  18. 8
      tests/ImageSharp.Tests/Formats/Tga/TgaFileHeaderTests.cs
  19. 4
      tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs

14
src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs

@ -11,35 +11,35 @@ public enum BmpBitsPerPixel : short
/// <summary>
/// 1 bit per pixel.
/// </summary>
Pixel1 = 1,
Bit1 = 1,
/// <summary>
/// 2 bits per pixel.
/// </summary>
Pixel2 = 2,
Bit2 = 2,
/// <summary>
/// 4 bits per pixel.
/// </summary>
Pixel4 = 4,
Bit4 = 4,
/// <summary>
/// 8 bits per pixel. Each pixel consists of 1 byte.
/// </summary>
Pixel8 = 8,
Bit8 = 8,
/// <summary>
/// 16 bits per pixel. Each pixel consists of 2 bytes.
/// </summary>
Pixel16 = 16,
Bit16 = 16,
/// <summary>
/// 24 bits per pixel. Each pixel consists of 3 bytes.
/// </summary>
Pixel24 = 24,
Bit24 = 24,
/// <summary>
/// 32 bits per pixel. Each pixel consists of 4 bytes.
/// </summary>
Pixel32 = 32
Bit32 = 32
}

24
src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs

@ -130,10 +130,10 @@ internal sealed class BmpEncoderCore : IImageEncoderInternals
int colorPaletteSize = this.bitsPerPixel switch
{
BmpBitsPerPixel.Pixel8 => ColorPaletteSize8Bit,
BmpBitsPerPixel.Pixel4 => ColorPaletteSize4Bit,
BmpBitsPerPixel.Pixel2 => ColorPaletteSize2Bit,
BmpBitsPerPixel.Pixel1 => ColorPaletteSize1Bit,
BmpBitsPerPixel.Bit8 => ColorPaletteSize8Bit,
BmpBitsPerPixel.Bit4 => ColorPaletteSize4Bit,
BmpBitsPerPixel.Bit2 => ColorPaletteSize2Bit,
BmpBitsPerPixel.Bit1 => ColorPaletteSize1Bit,
_ => 0
};
@ -220,7 +220,7 @@ internal sealed class BmpEncoderCore : IImageEncoderInternals
clrUsed: 0,
clrImportant: 0);
if ((this.infoHeaderType is BmpInfoHeaderType.WinVersion4 or BmpInfoHeaderType.WinVersion5) && this.bitsPerPixel == BmpBitsPerPixel.Pixel32)
if ((this.infoHeaderType is BmpInfoHeaderType.WinVersion4 or BmpInfoHeaderType.WinVersion5) && this.bitsPerPixel == BmpBitsPerPixel.Bit32)
{
infoHeader.AlphaMask = Rgba32AlphaMask;
infoHeader.RedMask = Rgba32RedMask;
@ -319,31 +319,31 @@ internal sealed class BmpEncoderCore : IImageEncoderInternals
Buffer2D<TPixel> pixels = image.Frames.RootFrame.PixelBuffer;
switch (this.bitsPerPixel)
{
case BmpBitsPerPixel.Pixel32:
case BmpBitsPerPixel.Bit32:
this.Write32BitPixelData(configuration, stream, pixels);
break;
case BmpBitsPerPixel.Pixel24:
case BmpBitsPerPixel.Bit24:
this.Write24BitPixelData(configuration, stream, pixels);
break;
case BmpBitsPerPixel.Pixel16:
case BmpBitsPerPixel.Bit16:
this.Write16BitPixelData(configuration, stream, pixels);
break;
case BmpBitsPerPixel.Pixel8:
case BmpBitsPerPixel.Bit8:
this.Write8BitPixelData(configuration, stream, image);
break;
case BmpBitsPerPixel.Pixel4:
case BmpBitsPerPixel.Bit4:
this.Write4BitPixelData(configuration, stream, image);
break;
case BmpBitsPerPixel.Pixel2:
case BmpBitsPerPixel.Bit2:
this.Write2BitPixelData(configuration, stream, image);
break;
case BmpBitsPerPixel.Pixel1:
case BmpBitsPerPixel.Bit1:
this.Write1BitPixelData(configuration, stream, image);
break;
}

30
src/ImageSharp/Formats/Bmp/BmpMetadata.cs

@ -36,7 +36,7 @@ public class BmpMetadata : IFormatMetadata<BmpMetadata>, IFormatFrameMetadata<Bm
/// <summary>
/// Gets or sets the number of bits per pixel.
/// </summary>
public BmpBitsPerPixel BitsPerPixel { get; set; } = BmpBitsPerPixel.Pixel24;
public BmpBitsPerPixel BitsPerPixel { get; set; } = BmpBitsPerPixel.Bit24;
/// <inheritdoc/>
public static BmpMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata)
@ -44,23 +44,23 @@ public class BmpMetadata : IFormatMetadata<BmpMetadata>, IFormatFrameMetadata<Bm
int bpp = metadata.PixelTypeInfo.BitsPerPixel;
return bpp switch
{
1 => new BmpMetadata { BitsPerPixel = BmpBitsPerPixel.Pixel1 },
2 => new BmpMetadata { BitsPerPixel = BmpBitsPerPixel.Pixel2 },
<= 4 => new BmpMetadata { BitsPerPixel = BmpBitsPerPixel.Pixel4 },
<= 8 => new BmpMetadata { BitsPerPixel = BmpBitsPerPixel.Pixel8 },
1 => new BmpMetadata { BitsPerPixel = BmpBitsPerPixel.Bit1 },
2 => new BmpMetadata { BitsPerPixel = BmpBitsPerPixel.Bit2 },
<= 4 => new BmpMetadata { BitsPerPixel = BmpBitsPerPixel.Bit4 },
<= 8 => new BmpMetadata { BitsPerPixel = BmpBitsPerPixel.Bit8 },
<= 16 => new BmpMetadata
{
BitsPerPixel = BmpBitsPerPixel.Pixel16,
BitsPerPixel = BmpBitsPerPixel.Bit16,
InfoHeaderType = BmpInfoHeaderType.WinVersion3
},
<= 24 => new BmpMetadata
{
BitsPerPixel = BmpBitsPerPixel.Pixel24,
BitsPerPixel = BmpBitsPerPixel.Bit24,
InfoHeaderType = BmpInfoHeaderType.WinVersion4
},
_ => new BmpMetadata
{
BitsPerPixel = BmpBitsPerPixel.Pixel32,
BitsPerPixel = BmpBitsPerPixel.Bit32,
InfoHeaderType = BmpInfoHeaderType.WinVersion5
}
};
@ -92,34 +92,34 @@ public class BmpMetadata : IFormatMetadata<BmpMetadata>, IFormatFrameMetadata<Bm
PixelColorType color;
switch (this.BitsPerPixel)
{
case BmpBitsPerPixel.Pixel1:
case BmpBitsPerPixel.Bit1:
info = PixelComponentInfo.Create(1, bpp, 1);
color = PixelColorType.Indexed;
break;
case BmpBitsPerPixel.Pixel2:
case BmpBitsPerPixel.Bit2:
info = PixelComponentInfo.Create(1, bpp, 2);
color = PixelColorType.Indexed;
break;
case BmpBitsPerPixel.Pixel4:
case BmpBitsPerPixel.Bit4:
info = PixelComponentInfo.Create(1, bpp, 4);
color = PixelColorType.Indexed;
break;
case BmpBitsPerPixel.Pixel8:
case BmpBitsPerPixel.Bit8:
info = PixelComponentInfo.Create(1, bpp, 8);
color = PixelColorType.Indexed;
break;
// Could be 555 with padding but 565 is more common in newer bitmaps and offers
// greater accuracy due to extra green precision.
case BmpBitsPerPixel.Pixel16:
case BmpBitsPerPixel.Bit16:
info = PixelComponentInfo.Create(3, bpp, 5, 6, 5);
color = PixelColorType.RGB;
break;
case BmpBitsPerPixel.Pixel24:
case BmpBitsPerPixel.Bit24:
info = PixelComponentInfo.Create(3, bpp, 8, 8, 8);
color = PixelColorType.RGB;
break;
case BmpBitsPerPixel.Pixel32 or _:
case BmpBitsPerPixel.Bit32 or _:
info = PixelComponentInfo.Create(4, bpp, 8, 8, 8, 8);
color = PixelColorType.RGB | PixelColorType.Alpha;
break;

4
src/ImageSharp/Formats/Jpeg/JpegMetadata.cs

@ -14,7 +14,9 @@ public class JpegMetadata : IFormatMetadata<JpegMetadata>
/// <summary>
/// Initializes a new instance of the <see cref="JpegMetadata"/> class.
/// </summary>
public JpegMetadata() => this.Comments = [];
public JpegMetadata()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JpegMetadata"/> class.

8
src/ImageSharp/Formats/Tga/TgaBitsPerPixel.cs

@ -11,20 +11,20 @@ public enum TgaBitsPerPixel : byte
/// <summary>
/// 8 bits per pixel. Each pixel consists of 1 byte.
/// </summary>
Pixel8 = 8,
Bit8 = 8,
/// <summary>
/// 16 bits per pixel. Each pixel consists of 2 bytes.
/// </summary>
Pixel16 = 16,
Bit16 = 16,
/// <summary>
/// 24 bits per pixel. Each pixel consists of 3 bytes.
/// </summary>
Pixel24 = 24,
Bit24 = 24,
/// <summary>
/// 32 bits per pixel. Each pixel consists of 4 bytes.
/// </summary>
Pixel32 = 32
Bit32 = 32
}

2
src/ImageSharp/Formats/Tga/TgaDecoderCore.cs

@ -934,7 +934,7 @@ internal sealed class TgaDecoderCore : IImageDecoderInternals
return (TgaImageOrigin)((this.fileHeader.ImageDescriptor & 0x30) >> 4);
}
private bool IsTrueColor32BitPerPixel(TgaBitsPerPixel bitsPerPixel) => bitsPerPixel == TgaBitsPerPixel.Pixel32 &&
private bool IsTrueColor32BitPerPixel(TgaBitsPerPixel bitsPerPixel) => bitsPerPixel == TgaBitsPerPixel.Bit32 &&
(this.fileHeader.ImageType == TgaImageType.TrueColor ||
this.fileHeader.ImageType == TgaImageType.RleTrueColor);
}

22
src/ImageSharp/Formats/Tga/TgaEncoderCore.cs

@ -59,7 +59,7 @@ internal sealed class TgaEncoderCore : IImageEncoderInternals
this.bitsPerPixel ??= tgaMetadata.BitsPerPixel;
TgaImageType imageType = this.compression is TgaCompression.RunLength ? TgaImageType.RleTrueColor : TgaImageType.TrueColor;
if (this.bitsPerPixel == TgaBitsPerPixel.Pixel8)
if (this.bitsPerPixel == TgaBitsPerPixel.Bit8)
{
imageType = this.compression is TgaCompression.RunLength ? TgaImageType.RleBlackAndWhite : TgaImageType.BlackAndWhite;
}
@ -71,13 +71,13 @@ internal sealed class TgaEncoderCore : IImageEncoderInternals
imageDescriptor |= 0x20;
}
if (this.bitsPerPixel is TgaBitsPerPixel.Pixel32)
if (this.bitsPerPixel is TgaBitsPerPixel.Bit32)
{
// Indicate, that 8 bit are used for the alpha channel.
imageDescriptor |= 0x8;
}
if (this.bitsPerPixel is TgaBitsPerPixel.Pixel16)
if (this.bitsPerPixel is TgaBitsPerPixel.Bit16)
{
// Indicate, that 1 bit is used for the alpha channel.
imageDescriptor |= 0x1;
@ -130,19 +130,19 @@ internal sealed class TgaEncoderCore : IImageEncoderInternals
Buffer2D<TPixel> pixels = image.PixelBuffer;
switch (this.bitsPerPixel)
{
case TgaBitsPerPixel.Pixel8:
case TgaBitsPerPixel.Bit8:
this.Write8Bit(configuration, stream, pixels);
break;
case TgaBitsPerPixel.Pixel16:
case TgaBitsPerPixel.Bit16:
this.Write16Bit(configuration, stream, pixels);
break;
case TgaBitsPerPixel.Pixel24:
case TgaBitsPerPixel.Bit24:
this.Write24Bit(configuration, stream, pixels);
break;
case TgaBitsPerPixel.Pixel32:
case TgaBitsPerPixel.Bit32:
this.Write32Bit(configuration, stream, pixels);
break;
}
@ -208,12 +208,12 @@ internal sealed class TgaEncoderCore : IImageEncoderInternals
{
switch (this.bitsPerPixel)
{
case TgaBitsPerPixel.Pixel8:
case TgaBitsPerPixel.Bit8:
L8 l8 = L8.FromRgba32(color);
stream.WriteByte(l8.PackedValue);
break;
case TgaBitsPerPixel.Pixel16:
case TgaBitsPerPixel.Bit16:
Bgra5551 bgra5551 = Bgra5551.FromRgba32(color);
Span<byte> buffer = stackalloc byte[2];
BinaryPrimitives.WriteInt16LittleEndian(buffer, (short)bgra5551.PackedValue);
@ -222,13 +222,13 @@ internal sealed class TgaEncoderCore : IImageEncoderInternals
break;
case TgaBitsPerPixel.Pixel24:
case TgaBitsPerPixel.Bit24:
stream.WriteByte(color.B);
stream.WriteByte(color.G);
stream.WriteByte(color.R);
break;
case TgaBitsPerPixel.Pixel32:
case TgaBitsPerPixel.Bit32:
stream.WriteByte(color.B);
stream.WriteByte(color.G);
stream.WriteByte(color.R);

18
src/ImageSharp/Formats/Tga/TgaMetadata.cs

@ -27,7 +27,7 @@ public class TgaMetadata : IFormatMetadata<TgaMetadata>
/// <summary>
/// Gets or sets the number of bits per pixel.
/// </summary>
public TgaBitsPerPixel BitsPerPixel { get; set; } = TgaBitsPerPixel.Pixel24;
public TgaBitsPerPixel BitsPerPixel { get; set; } = TgaBitsPerPixel.Bit24;
/// <summary>
/// Gets or sets the number of alpha bits per pixel.
@ -41,10 +41,10 @@ public class TgaMetadata : IFormatMetadata<TgaMetadata>
int bpp = metadata.PixelTypeInfo.BitsPerPixel;
return bpp switch
{
<= 8 => new TgaMetadata { BitsPerPixel = TgaBitsPerPixel.Pixel8 },
<= 16 => new TgaMetadata { BitsPerPixel = TgaBitsPerPixel.Pixel16 },
<= 24 => new TgaMetadata { BitsPerPixel = TgaBitsPerPixel.Pixel24 },
_ => new TgaMetadata { BitsPerPixel = TgaBitsPerPixel.Pixel32 }
<= 8 => new TgaMetadata { BitsPerPixel = TgaBitsPerPixel.Bit8 },
<= 16 => new TgaMetadata { BitsPerPixel = TgaBitsPerPixel.Bit16 },
<= 24 => new TgaMetadata { BitsPerPixel = TgaBitsPerPixel.Bit24 },
_ => new TgaMetadata { BitsPerPixel = TgaBitsPerPixel.Bit32 }
};
}
@ -57,22 +57,22 @@ public class TgaMetadata : IFormatMetadata<TgaMetadata>
PixelAlphaRepresentation alpha;
switch (this.BitsPerPixel)
{
case TgaBitsPerPixel.Pixel8:
case TgaBitsPerPixel.Bit8:
info = PixelComponentInfo.Create(1, bpp, 8);
color = PixelColorType.Luminance;
alpha = PixelAlphaRepresentation.None;
break;
case TgaBitsPerPixel.Pixel16:
case TgaBitsPerPixel.Bit16:
info = PixelComponentInfo.Create(1, bpp, 5, 5, 5, 1);
color = PixelColorType.BGR | PixelColorType.Alpha;
alpha = PixelAlphaRepresentation.Unassociated;
break;
case TgaBitsPerPixel.Pixel24:
case TgaBitsPerPixel.Bit24:
info = PixelComponentInfo.Create(3, bpp, 8, 8, 8);
color = PixelColorType.RGB;
alpha = PixelAlphaRepresentation.None;
break;
case TgaBitsPerPixel.Pixel32 or _:
case TgaBitsPerPixel.Bit32 or _:
info = PixelComponentInfo.Create(4, bpp, 8, 8, 8, 8);
color = PixelColorType.RGB | PixelColorType.Alpha;
alpha = PixelAlphaRepresentation.Unassociated;

4
src/ImageSharp/Formats/Webp/WebpBitsPerPixel.cs

@ -11,10 +11,10 @@ public enum WebpBitsPerPixel : short
/// <summary>
/// 24 bits per pixel. Each pixel consists of 3 bytes.
/// </summary>
Pixel24 = 24,
Bit24 = 24,
/// <summary>
/// 32 bits per pixel. Each pixel consists of 4 bytes (an alpha channel is present).
/// </summary>
Pixel32 = 32
Bit32 = 32
}

37
src/ImageSharp/Formats/Webp/WebpChunkParsingUtils.cs

@ -17,6 +17,10 @@ internal static class WebpChunkParsingUtils
/// <summary>
/// Reads the header of a lossy webp image.
/// </summary>
/// <param name="memoryAllocator">The memory allocator.</param>
/// <param name="stream">The buffered read stream.</param>
/// <param name="buffer">The scratch buffer to use while reading.</param>
/// <param name="features">The webp features to parse.</param>
/// <returns>Information about this webp image.</returns>
public static WebpImageInfo ReadVp8Header(MemoryAllocator memoryAllocator, BufferedReadStream stream, Span<byte> buffer, WebpFeatures features)
{
@ -114,13 +118,15 @@ internal static class WebpChunkParsingUtils
Vp8BitReader bitReader = new(stream, remaining, memoryAllocator, partitionLength) { Remaining = remaining };
return new WebpImageInfo
return new()
{
Width = width,
Height = height,
XScale = xScale,
YScale = yScale,
BitsPerPixel = features?.Alpha == true ? WebpBitsPerPixel.Pixel32 : WebpBitsPerPixel.Pixel24,
// Vp8 header can be parsed during the processing of the Vp8X header.
BitsPerPixel = features?.Alpha == true ? WebpBitsPerPixel.Bit32 : WebpBitsPerPixel.Bit24,
IsLossless = false,
Features = features,
Vp8Profile = (sbyte)version,
@ -132,7 +138,10 @@ internal static class WebpChunkParsingUtils
/// <summary>
/// Reads the header of a lossless webp image.
/// </summary>
/// <returns>Information about this image.</returns>
/// <param name="memoryAllocator">The memory allocator.</param>
/// <param name="stream">The buffered read stream.</param>
/// <param name="buffer">The scratch buffer to use while reading.</param>
/// <param name="features">The webp features to parse.</param>
public static WebpImageInfo ReadVp8LHeader(MemoryAllocator memoryAllocator, BufferedReadStream stream, Span<byte> buffer, WebpFeatures features)
{
// VP8 data size.
@ -156,8 +165,8 @@ internal static class WebpChunkParsingUtils
}
// The alphaIsUsed flag should be set to 0 when all alpha values are 255 in the picture, and 1 otherwise.
// TODO: this flag value is not used yet
bool alphaIsUsed = bitReader.ReadBit();
// Alpha may have already been set by the VP8X chunk.
features.Alpha |= bitReader.ReadBit();
// The next 3 bits are the version. The version number is a 3 bit code that must be set to 0.
// Any other value should be treated as an error.
@ -167,11 +176,11 @@ internal static class WebpChunkParsingUtils
WebpThrowHelper.ThrowNotSupportedException($"Unexpected version number {version} found in VP8L header");
}
return new WebpImageInfo
return new()
{
Width = width,
Height = height,
BitsPerPixel = WebpBitsPerPixel.Pixel32,
BitsPerPixel = features.Alpha ? WebpBitsPerPixel.Bit32 : WebpBitsPerPixel.Bit24,
IsLossless = true,
Features = features,
Vp8LBitReader = bitReader
@ -187,6 +196,9 @@ internal static class WebpChunkParsingUtils
/// - An optional 'ALPH' chunk with alpha channel data.
/// After the image header, image data will follow. After that optional image metadata chunks (EXIF and XMP) can follow.
/// </summary>
/// <param name="stream">The buffered read stream.</param>
/// <param name="buffer">The scratch buffer to use while reading.</param>
/// <param name="features">The webp features to parse.</param>
/// <returns>Information about this webp image.</returns>
public static WebpImageInfo ReadVp8XHeader(BufferedReadStream stream, Span<byte> buffer, WebpFeatures features)
{
@ -217,11 +229,8 @@ internal static class WebpChunkParsingUtils
features.Animation = (imageFeatures & (1 << 1)) != 0;
// 3 reserved bytes should follow which are supposed to be zero.
// No other decoder actually checks this though.
stream.Read(buffer, 0, 3);
if (buffer[0] != 0 || buffer[1] != 0 || buffer[2] != 0)
{
WebpThrowHelper.ThrowImageFormatException("reserved bytes should be zero");
}
// 3 bytes for the width.
uint width = ReadUInt24LittleEndian(stream, buffer) + 1;
@ -230,14 +239,14 @@ internal static class WebpChunkParsingUtils
uint height = ReadUInt24LittleEndian(stream, buffer) + 1;
// Read all the chunks in the order they occur.
WebpImageInfo info = new()
return new()
{
Width = width,
Height = height,
Features = features
};
return info;
// Additional properties are set during the parsing of the VP8 or VP8L headers.
};
}
/// <summary>

25
src/ImageSharp/Formats/Webp/WebpColorType.cs

@ -0,0 +1,25 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Formats.Webp;
/// <summary>
/// Provides enumeration of the various webp color types.
/// </summary>
public enum WebpColorType
{
/// <summary>
/// Yuv (luminance, blue chroma, red chroma) as defined in the ITU-R Rec. BT.709 specification.
/// </summary>
Yuv,
/// <summary>
/// Rgb color space.
/// </summary>
Rgb,
/// <summary>
/// Rgba color space.
/// </summary>
Rgba
}

21
src/ImageSharp/Formats/Webp/WebpDecoderCore.cs

@ -186,36 +186,43 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable
Span<byte> buffer = stackalloc byte[4];
WebpChunkType chunkType = WebpChunkParsingUtils.ReadChunkType(stream, buffer);
WebpImageInfo? info = null;
WebpFeatures features = new();
switch (chunkType)
{
case WebpChunkType.Vp8:
info = WebpChunkParsingUtils.ReadVp8Header(this.memoryAllocator, stream, buffer, features);
webpMetadata.FileFormat = WebpFileFormatType.Lossy;
return WebpChunkParsingUtils.ReadVp8Header(this.memoryAllocator, stream, buffer, features);
webpMetadata.ColorType = WebpColorType.Yuv;
return info;
case WebpChunkType.Vp8L:
info = WebpChunkParsingUtils.ReadVp8LHeader(this.memoryAllocator, stream, buffer, features);
webpMetadata.FileFormat = WebpFileFormatType.Lossless;
return WebpChunkParsingUtils.ReadVp8LHeader(this.memoryAllocator, stream, buffer, features);
webpMetadata.ColorType = info.Features?.Alpha == true ? WebpColorType.Rgba : WebpColorType.Rgb;
return info;
case WebpChunkType.Vp8X:
WebpImageInfo webpInfos = WebpChunkParsingUtils.ReadVp8XHeader(stream, buffer, features);
info = WebpChunkParsingUtils.ReadVp8XHeader(stream, buffer, features);
while (stream.Position < stream.Length)
{
chunkType = WebpChunkParsingUtils.ReadChunkType(stream, buffer);
if (chunkType == WebpChunkType.Vp8)
{
info = WebpChunkParsingUtils.ReadVp8Header(this.memoryAllocator, stream, buffer, features);
webpMetadata.FileFormat = WebpFileFormatType.Lossy;
webpInfos = WebpChunkParsingUtils.ReadVp8Header(this.memoryAllocator, stream, buffer, features);
webpMetadata.ColorType = info.Features?.Alpha == true ? WebpColorType.Rgba : WebpColorType.Rgb;
}
else if (chunkType == WebpChunkType.Vp8L)
{
info = WebpChunkParsingUtils.ReadVp8LHeader(this.memoryAllocator, stream, buffer, features);
webpMetadata.FileFormat = WebpFileFormatType.Lossless;
webpInfos = WebpChunkParsingUtils.ReadVp8LHeader(this.memoryAllocator, stream, buffer, features);
webpMetadata.ColorType = info.Features?.Alpha == true ? WebpColorType.Rgba : WebpColorType.Rgb;
}
else if (WebpChunkParsingUtils.IsOptionalVp8XChunk(chunkType))
{
bool isAnimationChunk = this.ParseOptionalExtendedChunks(stream, metadata, chunkType, features, ignoreAlpha, buffer);
if (isAnimationChunk)
{
return webpInfos;
return info;
}
}
else
@ -226,7 +233,7 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable
}
}
return webpInfos;
return info;
default:
WebpThrowHelper.ThrowImageFormatException("Unrecognized VP8 header");
return

6
src/ImageSharp/Formats/Webp/WebpImageInfo.cs

@ -18,8 +18,14 @@ internal class WebpImageInfo : IDisposable
/// </summary>
public uint Height { get; set; }
/// <summary>
/// Gets or sets the horizontal scale.
/// </summary>
public sbyte XScale { get; set; }
/// <summary>
/// Gets or sets the vertical scale.
/// </summary>
public sbyte YScale { get; set; }
/// <summary>

33
src/ImageSharp/Formats/Webp/WebpMetadata.cs

@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.Webp;
/// <summary>
/// Provides Webp specific metadata information for the image.
/// </summary>
public class WebpMetadata : IDeepCloneable
public class WebpMetadata : IFormatFrameMetadata<WebpMetadata>
{
/// <summary>
/// Initializes a new instance of the <see cref="WebpMetadata"/> class.
@ -21,15 +21,27 @@ public class WebpMetadata : IDeepCloneable
/// <param name="other">The metadata to create an instance from.</param>
private WebpMetadata(WebpMetadata other)
{
this.BitsPerPixel = other.BitsPerPixel;
this.ColorType = other.ColorType;
this.FileFormat = other.FileFormat;
this.RepeatCount = other.RepeatCount;
this.BackgroundColor = other.BackgroundColor;
}
/// <summary>
/// Gets or sets the number of bits per pixel.
/// </summary>
public WebpBitsPerPixel BitsPerPixel { get; set; } = WebpBitsPerPixel.Bit32;
/// <summary>
/// Gets or sets the color type.
/// </summary>
public WebpColorType ColorType { get; set; } = WebpColorType.Rgba;
/// <summary>
/// Gets or sets the webp file format used. Either lossless or lossy.
/// </summary>
public WebpFileFormatType? FileFormat { get; set; }
public WebpFileFormatType FileFormat { get; set; } = WebpFileFormatType.Lossless;
/// <summary>
/// Gets or sets the loop count. The number of times to loop the animation. 0 means infinitely.
@ -44,9 +56,6 @@ public class WebpMetadata : IDeepCloneable
/// </summary>
public Color BackgroundColor { get; set; }
/// <inheritdoc/>
public IDeepCloneable DeepClone() => new WebpMetadata(this);
internal static WebpMetadata FromAnimatedMetadata(AnimatedImageMetadata metadata)
=> new()
{
@ -54,4 +63,18 @@ public class WebpMetadata : IDeepCloneable
BackgroundColor = metadata.BackgroundColor,
RepeatCount = metadata.RepeatCount
};
/// <inheritdoc/>
public static WebpMetadata FromFormatConnectingFrameMetadata(FormatConnectingFrameMetadata metadata)
=> throw new NotImplementedException();
/// <inheritdoc/>
public FormatConnectingFrameMetadata ToFormatConnectingFrameMetadata()
=> throw new NotImplementedException();
/// <inheritdoc/>
IDeepCloneable IDeepCloneable.DeepClone() => this.DeepClone();
/// <inheritdoc/>
public WebpMetadata DeepClone() => new(this);
}

90
tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs

@ -22,8 +22,8 @@ public class BmpEncoderTests
public static readonly TheoryData<BmpBitsPerPixel> BitsPerPixel =
new()
{
BmpBitsPerPixel.Pixel24,
BmpBitsPerPixel.Pixel32
BmpBitsPerPixel.Bit24,
BmpBitsPerPixel.Bit32
};
public static readonly TheoryData<string, int, int, PixelResolutionUnit> RatioFiles =
@ -37,13 +37,13 @@ public class BmpEncoderTests
public static readonly TheoryData<string, BmpBitsPerPixel> BmpBitsPerPixelFiles =
new()
{
{ Bit1, BmpBitsPerPixel.Pixel1 },
{ Bit2, BmpBitsPerPixel.Pixel2 },
{ Bit4, BmpBitsPerPixel.Pixel4 },
{ Bit8, BmpBitsPerPixel.Pixel8 },
{ Rgb16, BmpBitsPerPixel.Pixel16 },
{ Car, BmpBitsPerPixel.Pixel24 },
{ Bit32Rgb, BmpBitsPerPixel.Pixel32 }
{ Bit1, BmpBitsPerPixel.Bit1 },
{ Bit2, BmpBitsPerPixel.Bit2 },
{ Bit4, BmpBitsPerPixel.Bit4 },
{ Bit8, BmpBitsPerPixel.Bit8 },
{ Rgb16, BmpBitsPerPixel.Bit16 },
{ Car, BmpBitsPerPixel.Bit24 },
{ Bit32Rgb, BmpBitsPerPixel.Bit32 }
};
[Fact]
@ -97,61 +97,61 @@ public class BmpEncoderTests
where TPixel : unmanaged, IPixel<TPixel> => TestBmpEncoderCore(provider, bitsPerPixel);
[Theory]
[WithFile(Bit32Rgb, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)]
[WithFile(Bit32Rgba, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)]
[WithFile(WinBmpv4, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)]
[WithFile(WinBmpv5, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)]
[WithFile(Bit32Rgb, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Bit32)]
[WithFile(Bit32Rgba, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Bit32)]
[WithFile(WinBmpv4, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Bit32)]
[WithFile(WinBmpv5, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Bit32)]
public void Encode_32Bit_WithV3Header_Works<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
// If supportTransparency is false, a v3 bitmap header will be written.
where TPixel : unmanaged, IPixel<TPixel> => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false);
[Theory]
[WithFile(Bit32Rgb, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)]
[WithFile(Bit32Rgba, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)]
[WithFile(WinBmpv4, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)]
[WithFile(WinBmpv5, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)]
[WithFile(Bit32Rgb, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Bit32)]
[WithFile(Bit32Rgba, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Bit32)]
[WithFile(WinBmpv4, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Bit32)]
[WithFile(WinBmpv5, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Bit32)]
public void Encode_32Bit_WithV4Header_Works<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel> => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true);
[Theory]
[WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] // WinBmpv3 is a 24 bits per pixel image.
[WithFile(F, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)]
[WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Bit24)] // WinBmpv3 is a 24 bits per pixel image.
[WithFile(F, PixelTypes.Rgb24, BmpBitsPerPixel.Bit24)]
public void Encode_24Bit_WithV3Header_Works<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel> => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false);
[Theory]
[WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)]
[WithFile(F, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)]
[WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Bit24)]
[WithFile(F, PixelTypes.Rgb24, BmpBitsPerPixel.Bit24)]
public void Encode_24Bit_WithV4Header_Works<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel> => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true);
[Theory]
[WithFile(Rgb16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)]
[WithFile(Bit16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)]
[WithFile(Rgb16, PixelTypes.Bgra5551, BmpBitsPerPixel.Bit16)]
[WithFile(Bit16, PixelTypes.Bgra5551, BmpBitsPerPixel.Bit16)]
public void Encode_16Bit_WithV3Header_Works<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel> => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false);
[Theory]
[WithFile(Rgb16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)]
[WithFile(Bit16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)]
[WithFile(Rgb16, PixelTypes.Bgra5551, BmpBitsPerPixel.Bit16)]
[WithFile(Bit16, PixelTypes.Bgra5551, BmpBitsPerPixel.Bit16)]
public void Encode_16Bit_WithV4Header_Works<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel> => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true);
[Theory]
[WithFile(WinBmpv5, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)]
[WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)]
[WithFile(WinBmpv5, PixelTypes.Rgba32, BmpBitsPerPixel.Bit8)]
[WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Bit8)]
public void Encode_8Bit_WithV3Header_Works<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel> => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false);
[Theory]
[WithFile(WinBmpv5, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)]
[WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)]
[WithFile(WinBmpv5, PixelTypes.Rgba32, BmpBitsPerPixel.Bit8)]
[WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Bit8)]
public void Encode_8Bit_WithV4Header_Works<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel> => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true);
[Theory]
[WithFile(Bit8Gs, PixelTypes.L8, BmpBitsPerPixel.Pixel8)]
[WithFile(Bit8Gs, PixelTypes.L8, BmpBitsPerPixel.Bit8)]
public void Encode_8BitGray_WithV3Header_Works<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel> =>
TestBmpEncoderCore(
@ -160,7 +160,7 @@ public class BmpEncoderTests
supportTransparency: false);
[Theory]
[WithFile(Bit4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel4)]
[WithFile(Bit4, PixelTypes.Rgba32, BmpBitsPerPixel.Bit4)]
public void Encode_4Bit_WithV3Header_Works<TPixel>(
TestImageProvider<TPixel> provider,
BmpBitsPerPixel bitsPerPixel)
@ -176,7 +176,7 @@ public class BmpEncoderTests
}
[Theory]
[WithFile(Bit4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel4)]
[WithFile(Bit4, PixelTypes.Rgba32, BmpBitsPerPixel.Bit4)]
public void Encode_4Bit_WithV4Header_Works<TPixel>(
TestImageProvider<TPixel> provider,
BmpBitsPerPixel bitsPerPixel)
@ -192,7 +192,7 @@ public class BmpEncoderTests
}
[Theory]
[WithFile(Bit2, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel2)]
[WithFile(Bit2, PixelTypes.Rgba32, BmpBitsPerPixel.Bit2)]
public void Encode_2Bit_WithV3Header_Works<TPixel>(
TestImageProvider<TPixel> provider,
BmpBitsPerPixel bitsPerPixel)
@ -214,7 +214,7 @@ public class BmpEncoderTests
}
[Theory]
[WithFile(Bit2, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel2)]
[WithFile(Bit2, PixelTypes.Rgba32, BmpBitsPerPixel.Bit2)]
public void Encode_2Bit_WithV4Header_Works<TPixel>(
TestImageProvider<TPixel> provider,
BmpBitsPerPixel bitsPerPixel)
@ -236,21 +236,21 @@ public class BmpEncoderTests
}
[Theory]
[WithFile(Bit1, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel1)]
[WithFile(Bit1, PixelTypes.Rgba32, BmpBitsPerPixel.Bit1)]
public void Encode_1Bit_WithV3Header_Works<TPixel>(
TestImageProvider<TPixel> provider,
BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel> => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false);
[Theory]
[WithFile(Bit1, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel1)]
[WithFile(Bit1, PixelTypes.Rgba32, BmpBitsPerPixel.Bit1)]
public void Encode_1Bit_WithV4Header_Works<TPixel>(
TestImageProvider<TPixel> provider,
BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel> => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true);
[Theory]
[WithFile(Bit8Gs, PixelTypes.L8, BmpBitsPerPixel.Pixel8)]
[WithFile(Bit8Gs, PixelTypes.L8, BmpBitsPerPixel.Bit8)]
public void Encode_8BitGray_WithV4Header_Works<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel> =>
TestBmpEncoderCore(
@ -271,7 +271,7 @@ public class BmpEncoderTests
using Image<TPixel> image = provider.GetImage();
BmpEncoder encoder = new()
{
BitsPerPixel = BmpBitsPerPixel.Pixel8,
BitsPerPixel = BmpBitsPerPixel.Bit8,
Quantizer = new WuQuantizer()
};
@ -303,7 +303,7 @@ public class BmpEncoderTests
using Image<TPixel> image = provider.GetImage();
BmpEncoder encoder = new()
{
BitsPerPixel = BmpBitsPerPixel.Pixel8,
BitsPerPixel = BmpBitsPerPixel.Bit8,
Quantizer = new OctreeQuantizer()
};
string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false);
@ -322,8 +322,8 @@ public class BmpEncoderTests
}
[Theory]
[WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)]
[WithFile(Bit32Rgba, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)]
[WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Bit32)]
[WithFile(Bit32Rgba, PixelTypes.Rgba32, BmpBitsPerPixel.Bit32)]
public void Encode_PreservesAlpha<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel> => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true);
@ -364,8 +364,8 @@ public class BmpEncoderTests
}
[Theory]
[WithFile(Car, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)]
[WithFile(V5Header, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)]
[WithFile(Car, PixelTypes.Rgba32, BmpBitsPerPixel.Bit32)]
[WithFile(V5Header, PixelTypes.Rgba32, BmpBitsPerPixel.Bit32)]
public void Encode_WorksWithDiscontiguousBuffers<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel>
{
@ -374,7 +374,7 @@ public class BmpEncoderTests
}
[Theory]
[WithFile(BlackWhitePalletDataMatrix, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel1)]
[WithFile(BlackWhitePalletDataMatrix, PixelTypes.Rgb24, BmpBitsPerPixel.Bit1)]
public void Encode_Issue2467<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel>
{
@ -409,7 +409,7 @@ public class BmpEncoderTests
using Image<TPixel> image = provider.GetImage();
// There is no alpha in bmp with less then 32 bits per pixels, so the reference image will be made opaque.
if (bitsPerPixel != BmpBitsPerPixel.Pixel32)
if (bitsPerPixel != BmpBitsPerPixel.Bit32)
{
image.Mutate(c => c.MakeOpaque());
}

4
tests/ImageSharp.Tests/Formats/Bmp/BmpMetadataTests.cs

@ -15,10 +15,10 @@ public class BmpMetadataTests
public void CloneIsDeep()
{
BmpMetadata meta = new()
{ BitsPerPixel = BmpBitsPerPixel.Pixel24, InfoHeaderType = BmpInfoHeaderType.Os2Version2 };
{ BitsPerPixel = BmpBitsPerPixel.Bit24, InfoHeaderType = BmpInfoHeaderType.Os2Version2 };
BmpMetadata clone = (BmpMetadata)meta.DeepClone();
clone.BitsPerPixel = BmpBitsPerPixel.Pixel32;
clone.BitsPerPixel = BmpBitsPerPixel.Bit32;
clone.InfoHeaderType = BmpInfoHeaderType.WinVersion2;
Assert.False(meta.BitsPerPixel.Equals(clone.BitsPerPixel));

32
tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs

@ -15,17 +15,17 @@ public class TgaEncoderTests
public static readonly TheoryData<TgaBitsPerPixel> BitsPerPixel =
new()
{
TgaBitsPerPixel.Pixel24,
TgaBitsPerPixel.Pixel32
TgaBitsPerPixel.Bit24,
TgaBitsPerPixel.Bit32
};
public static readonly TheoryData<string, TgaBitsPerPixel> TgaBitsPerPixelFiles =
new()
{
{ Gray8BitBottomLeft, TgaBitsPerPixel.Pixel8 },
{ Bit16BottomLeft, TgaBitsPerPixel.Pixel16 },
{ Bit24BottomLeft, TgaBitsPerPixel.Pixel24 },
{ Bit32BottomLeft, TgaBitsPerPixel.Pixel32 },
{ Gray8BitBottomLeft, TgaBitsPerPixel.Bit8 },
{ Bit16BottomLeft, TgaBitsPerPixel.Bit16 },
{ Bit24BottomLeft, TgaBitsPerPixel.Bit24 },
{ Bit32BottomLeft, TgaBitsPerPixel.Bit32 },
};
[Theory]
@ -73,46 +73,46 @@ public class TgaEncoderTests
[Theory]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit8_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel8)
public void TgaEncoder_Bit8_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Bit8)
// Using tolerant comparer here. The results from magick differ slightly. Maybe a different ToGrey method is used. The image looks otherwise ok.
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.None, useExactComparer: false, compareTolerance: 0.03f);
[Theory]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit16_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel16)
public void TgaEncoder_Bit16_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Bit16)
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.None, useExactComparer: false);
[Theory]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit24_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel24)
public void TgaEncoder_Bit24_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Bit24)
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.None);
[Theory]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit32_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel32)
public void TgaEncoder_Bit32_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Bit32)
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.None);
[Theory]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit8_WithRunLengthEncoding_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel8)
public void TgaEncoder_Bit8_WithRunLengthEncoding_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Bit8)
// Using tolerant comparer here. The results from magick differ slightly. Maybe a different ToGrey method is used. The image looks otherwise ok.
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.RunLength, useExactComparer: false, compareTolerance: 0.03f);
[Theory]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit16_WithRunLengthEncoding_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel16)
public void TgaEncoder_Bit16_WithRunLengthEncoding_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Bit16)
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.RunLength, useExactComparer: false);
[Theory]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit24_WithRunLengthEncoding_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel24)
public void TgaEncoder_Bit24_WithRunLengthEncoding_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Bit24)
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.RunLength);
[Theory]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit32_WithRunLengthEncoding_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel32)
public void TgaEncoder_Bit32_WithRunLengthEncoding_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Bit32)
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.RunLength);
[Theory]
@ -152,8 +152,8 @@ public class TgaEncoderTests
}
[Theory]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32, TgaBitsPerPixel.Pixel32)]
[WithFile(Bit24BottomLeft, PixelTypes.Rgba32, TgaBitsPerPixel.Pixel24)]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32, TgaBitsPerPixel.Bit32)]
[WithFile(Bit24BottomLeft, PixelTypes.Rgba32, TgaBitsPerPixel.Bit24)]
public void TgaEncoder_WorksWithDiscontiguousBuffers<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel>
{

8
tests/ImageSharp.Tests/Formats/Tga/TgaFileHeaderTests.cs

@ -33,10 +33,10 @@ public class TgaFileHeaderTests
}
[Theory]
[InlineData(new byte[] { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 0, 195, 0, 32, 8 }, 250, 195, TgaBitsPerPixel.Pixel32)]
[InlineData(new byte[] { 26, 1, 9, 0, 0, 0, 1, 16, 0, 0, 0, 0, 128, 0, 128, 0, 8, 0 }, 128, 128, TgaBitsPerPixel.Pixel8)]
[InlineData(new byte[] { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 220, 0, 16, 0 }, 220, 220, TgaBitsPerPixel.Pixel16)]
[InlineData(new byte[] { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 0, 124, 0, 24, 32 }, 124, 124, TgaBitsPerPixel.Pixel24)]
[InlineData(new byte[] { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 0, 195, 0, 32, 8 }, 250, 195, TgaBitsPerPixel.Bit32)]
[InlineData(new byte[] { 26, 1, 9, 0, 0, 0, 1, 16, 0, 0, 0, 0, 128, 0, 128, 0, 8, 0 }, 128, 128, TgaBitsPerPixel.Bit8)]
[InlineData(new byte[] { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 220, 0, 16, 0 }, 220, 220, TgaBitsPerPixel.Bit16)]
[InlineData(new byte[] { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 0, 124, 0, 24, 32 }, 124, 124, TgaBitsPerPixel.Bit24)]
public void Identify_WithValidData_Works(byte[] data, int width, int height, TgaBitsPerPixel bitsPerPixel)
{
using MemoryStream stream = new(data);

4
tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs

@ -30,8 +30,8 @@ public class WebpDecoderTests
[Theory]
[InlineData(Lossless.GreenTransform1, 1000, 307, 32)]
[InlineData(Lossless.BikeThreeTransforms, 250, 195, 32)]
[InlineData(Lossless.NoTransform2, 128, 128, 32)]
[InlineData(Lossless.BikeThreeTransforms, 250, 195, 24)]
[InlineData(Lossless.NoTransform2, 128, 128, 24)]
[InlineData(Lossy.Alpha1, 1000, 307, 32)]
[InlineData(Lossy.Alpha2, 1000, 307, 32)]
[InlineData(Lossy.BikeWithExif, 250, 195, 24)]

Loading…
Cancel
Save