Browse Source

Add an equivalent for System.Drawing.Image.GetPixelFormatSize() (#258)

af/merge-core
Nikita Balabaev 9 years ago
parent
commit
855ef8cf5d
  1. 11
      src/ImageSharp/Formats/Bmp/BmpDecoder.cs
  2. 11
      src/ImageSharp/Formats/Gif/GifDecoder.cs
  3. 8
      src/ImageSharp/Formats/IImageDecoder.cs
  4. 11
      src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
  5. 22
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  6. 12
      src/ImageSharp/Formats/Png/PngDecoder.cs
  7. 74
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  8. 14
      src/ImageSharp/Image/Image.Decode.cs
  9. 27
      src/ImageSharp/Image/Image.FromStream.cs
  10. 29
      tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
  11. 15
      tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
  12. 16
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  13. 18
      tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
  14. 7
      tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs
  15. 26
      tests/ImageSharp.Tests/Image/ImageLoadTests.cs
  16. 2
      tests/ImageSharp.Tests/TestFileSystem.cs
  17. 15
      tests/ImageSharp.Tests/TestFormat.cs
  18. 6
      tests/ImageSharp.Tests/TestImages.cs
  19. 3
      tests/ImageSharp.Tests/TestImages/Formats/Bmp/bpp8.bmp
  20. 3
      tests/ImageSharp.Tests/TestImages/Formats/Png/bpp1.png
  21. 3
      tests/ImageSharp.Tests/TestImages/Formats/Png/gray_4bpp.png
  22. 3
      tests/ImageSharp.Tests/TestImages/Formats/Png/palette-8bpp.png

11
src/ImageSharp/Formats/Bmp/BmpDecoder.cs

@ -37,5 +37,16 @@ namespace ImageSharp.Formats
return new BmpDecoderCore(configuration, this).Decode<TPixel>(stream);
}
/// <inheritdoc/>
public int DetectPixelSize(Configuration configuration, Stream stream)
{
Guard.NotNull(stream, "stream");
byte[] buffer = new byte[2];
stream.Skip(28);
stream.Read(buffer, 0, 2);
return BitConverter.ToInt16(buffer, 0);
}
}
}

11
src/ImageSharp/Formats/Gif/GifDecoder.cs

@ -33,5 +33,16 @@ namespace ImageSharp.Formats
var decoder = new GifDecoderCore<TPixel>(configuration, this);
return decoder.Decode(stream);
}
/// <inheritdoc/>
public int DetectPixelSize(Configuration configuration, Stream stream)
{
Guard.NotNull(stream, "stream");
byte[] buffer = new byte[1];
stream.Skip(10); // Skip the identifier and size
stream.Read(buffer, 0, 1); // Skip the identifier and size
return (buffer[0] & 0x07) + 1; // The lowest 3 bits represent the bit depth minus 1
}
}
}

8
src/ImageSharp/Formats/IImageDecoder.cs

@ -25,5 +25,13 @@ namespace ImageSharp.Formats
/// <returns>The decoded image</returns>
Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream)
where TPixel : struct, IPixel<TPixel>;
/// <summary>
/// Detects the image pixel size from the specified stream.
/// </summary>
/// <param name="configuration">The configuration for the image.</param>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <returns>The color depth, in number of bits per pixel</returns>
int DetectPixelSize(Configuration configuration, Stream stream);
}
}

11
src/ImageSharp/Formats/Jpeg/JpegDecoder.cs

@ -32,5 +32,16 @@ namespace ImageSharp.Formats
return decoder.Decode<TPixel>(stream);
}
}
/// <inheritdoc/>
public int DetectPixelSize(Configuration configuration, Stream stream)
{
Guard.NotNull(stream, "stream");
using (JpegDecoderCore decoder = new JpegDecoderCore(configuration, this))
{
return decoder.DetectPixelSize(stream);
}
}
}
}

22
src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

@ -30,6 +30,11 @@ namespace ImageSharp.Formats
/// </summary>
public const int MaxTq = 3;
/// <summary>
/// The only supported precision
/// </summary>
public const int SupportedPrecision = 8;
// Complex value type field + mutable + available to other classes = the field MUST NOT be private :P
#pragma warning disable SA1401 // FieldsMustBePrivate
@ -191,7 +196,7 @@ namespace ImageSharp.Formats
public bool IgnoreMetadata { get; private set; }
/// <summary>
/// Decodes the image from the specified <see cref="Stream"/> and sets
/// Decodes the image from the specified <see cref="Stream"/> and sets
/// the data to image.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
@ -208,6 +213,17 @@ namespace ImageSharp.Formats
return image;
}
/// <summary>
/// Detects the image pixel size from the specified stream.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <returns>The color depth, in number of bits per pixel</returns>
public int DetectPixelSize(Stream stream)
{
this.ProcessStream(new ImageMetaData(), stream, true);
return this.ComponentCount * SupportedPrecision;
}
/// <summary>
/// Dispose
/// </summary>
@ -1196,7 +1212,7 @@ namespace ImageSharp.Formats
this.InputProcessor.ReadFull(this.Temp, 0, remaining);
// We only support 8-bit precision.
if (this.Temp[0] != 8)
if (this.Temp[0] != SupportedPrecision)
{
throw new ImageFormatException("Only 8-Bit precision supported.");
}
@ -1238,7 +1254,7 @@ namespace ImageSharp.Formats
if (h == 3 || v == 3)
{
throw new ImageFormatException("Lnsupported subsampling ratio");
throw new ImageFormatException("Unsupported subsampling ratio");
}
switch (this.ComponentCount)

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

@ -56,5 +56,17 @@ namespace ImageSharp.Formats
var decoder = new PngDecoderCore(configuration, this);
return decoder.Decode<TPixel>(stream);
}
/// <summary>
/// Detects the image pixel size from the specified stream.
/// </summary>
/// <param name="configuration">The configuration for the image.</param>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <returns>The color depth, in number of bits per pixel</returns>
public int DetectPixelSize(Configuration configuration, Stream stream)
{
var decoder = new PngDecoderCore(configuration, this);
return decoder.DetectPixelSize(stream);
}
}
}

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

@ -261,6 +261,58 @@ namespace ImageSharp.Formats
}
}
/// <summary>
/// Detects the image pixel size from the specified stream.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <returns>The color depth, in number of bits per pixel</returns>
public int DetectPixelSize(Stream stream)
{
this.currentStream = stream;
this.currentStream.Skip(8);
try
{
PngChunk currentChunk;
while (!this.isEndChunkReached && (currentChunk = this.ReadChunk()) != null)
{
try
{
switch (currentChunk.Type)
{
case PngChunkTypes.Header:
this.ReadHeaderChunk(currentChunk.Data);
this.ValidateHeader();
this.isEndChunkReached = true;
break;
case PngChunkTypes.End:
this.isEndChunkReached = true;
break;
}
}
finally
{
// Data is rented in ReadChunkData()
if (currentChunk.Data != null)
{
ArrayPool<byte>.Shared.Return(currentChunk.Data);
}
}
}
}
finally
{
this.scanline?.Dispose();
this.previousScanline?.Dispose();
}
if (this.header == null)
{
throw new ImageFormatException("PNG Image hasn't header chunk");
}
return this.CalculateBitsPerPixel();
}
/// <summary>
/// Converts a byte array to a new array where each value in the original array is represented by the specified number of bits.
/// </summary>
@ -343,6 +395,28 @@ namespace ImageSharp.Formats
this.scanline = Buffer<byte>.CreateClean(this.bytesPerScanline);
}
/// <summary>
/// Calculates the correct number of bits per pixel for the given color type.
/// </summary>
/// <returns>The <see cref="int"/></returns>
private int CalculateBitsPerPixel()
{
switch (this.pngColorType)
{
case PngColorType.Grayscale:
case PngColorType.Palette:
return this.header.BitDepth;
case PngColorType.GrayscaleWithAlpha:
return this.header.BitDepth * 2;
case PngColorType.Rgb:
return this.header.BitDepth * 3;
case PngColorType.RgbWithAlpha:
return this.header.BitDepth * 4;
default:
throw new NotSupportedException("Unsupported PNG color type");
}
}
/// <summary>
/// Calculates the correct number of bytes per pixel for the given color type.
/// </summary>

14
src/ImageSharp/Image/Image.Decode.cs

@ -81,5 +81,19 @@ namespace ImageSharp
Image<TPixel> img = decoder.Decode<TPixel>(config, stream);
return (img, format);
}
/// <summary>
/// Detects the image pixel size.
/// </summary>
/// <param name="stream">The stream.</param>
/// <param name="config">the configuration.</param>
/// <returns>
/// The color depth, in number of bits per pixel or null if suitable decoder not found.
/// </returns>
private static int? InternalDetectPixelSize(Stream stream, Configuration config)
{
IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat _);
return decoder?.DetectPixelSize(config, stream);
}
}
}

27
src/ImageSharp/Image/Image.FromStream.cs

@ -39,6 +39,33 @@ namespace ImageSharp
return WithSeekableStream(stream, s => InternalDetectFormat(s, config ?? Configuration.Default));
}
/// <summary>
/// By reading the header on the provided stream this calculates the images color depth.
/// </summary>
/// <param name="stream">The image stream to read the header from.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <returns>The color depth, in number of bits per pixel or null if suitable decoder not found</returns>
public static int? DetectPixelSize(Stream stream)
{
return DetectPixelSize(null, stream);
}
/// <summary>
/// By reading the header on the provided stream this calculates the images color depth.
/// </summary>
/// <param name="config">The configuration.</param>
/// <param name="stream">The image stream to read the header from.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <returns>The color depth, in number of bits per pixel or null if suitable decoder not found</returns>
public static int? DetectPixelSize(Configuration config, Stream stream)
{
return WithSeekableStream(stream, s => InternalDetectPixelSize(s, config ?? Configuration.Default));
}
/// <summary>
/// Create a new instance of the <see cref="Image{Rgba32}"/> class from the given stream.
/// </summary>

29
tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs

@ -0,0 +1,29 @@
// <copyright file="GifDecoderTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// ReSharper disable InconsistentNaming
namespace ImageSharp.Tests
{
using System.IO;
using Xunit;
public class BmpDecoderTests
{
[Theory]
[InlineData(TestImages.Bmp.Car, 24)]
[InlineData(TestImages.Bmp.F, 24)]
[InlineData(TestImages.Bmp.NegHeight, 24)]
[InlineData(TestImages.Bmp.Bpp8, 8)]
public void DetectPixelSize(string imagePath, int expectedPixelSize)
{
TestFile testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
Assert.Equal(expectedPixelSize, Image.DetectPixelSize(stream));
}
}
}
}

15
tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs

@ -6,6 +6,7 @@
// ReSharper disable InconsistentNaming
namespace ImageSharp.Tests
{
using System.IO;
using System.Text;
using Xunit;
@ -80,5 +81,19 @@ namespace ImageSharp.Tests
Assert.Equal("浉条卥慨灲", image.MetaData.Properties[0].Value);
}
}
[Theory]
[InlineData(TestImages.Gif.Cheers, 8)]
[InlineData(TestImages.Gif.Giphy, 8)]
[InlineData(TestImages.Gif.Rings, 8)]
[InlineData(TestImages.Gif.Trans, 8)]
public void DetectPixelSize(string imagePath, int expectedPixelSize)
{
TestFile testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
Assert.Equal(expectedPixelSize, Image.DetectPixelSize(stream));
}
}
}
}

16
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

@ -152,5 +152,21 @@ namespace ImageSharp.Tests
Assert.Null(image.MetaData.ExifProfile);
}
}
[Theory]
[InlineData(TestImages.Jpeg.Progressive.Progress, 24)]
[InlineData(TestImages.Jpeg.Progressive.Fb, 24)]
[InlineData(TestImages.Jpeg.Baseline.Cmyk, 32)]
[InlineData(TestImages.Jpeg.Baseline.Ycck, 32)]
[InlineData(TestImages.Jpeg.Baseline.Jpeg400, 8)]
[InlineData(TestImages.Jpeg.Baseline.Snake, 24)]
public void DetectPixelSize(string imagePath, int expectedPixelSize)
{
TestFile testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
Assert.Equal(expectedPixelSize, Image.DetectPixelSize(stream));
}
}
}
}

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

@ -5,6 +5,7 @@
namespace ImageSharp.Tests
{
using System.IO;
using System.Text;
using Xunit;
@ -82,5 +83,22 @@ namespace ImageSharp.Tests
Assert.Equal("潓瑦慷敲", image.MetaData.Properties[0].Name);
}
}
[Theory]
[InlineData(TestImages.Png.Bpp1, 1)]
[InlineData(TestImages.Png.Gray4Bpp, 4)]
[InlineData(TestImages.Png.Palette8Bpp, 8)]
[InlineData(TestImages.Png.Pd, 24)]
[InlineData(TestImages.Png.Blur, 32)]
[InlineData(TestImages.Png.Rgb48Bpp, 48)]
[InlineData(TestImages.Png.Rgb48BppInterlaced, 48)]
public void DetectPixelSize(string imagePath, int expectedPixelSize)
{
TestFile testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
Assert.Equal(expectedPixelSize, Image.DetectPixelSize(stream));
}
}
}
}

7
tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs

@ -41,20 +41,20 @@ namespace ImageSharp.Tests
this.fileSystem = new Mock<IFileSystem>();
this.LocalConfiguration = new Configuration()
this.LocalConfiguration = new Configuration
{
FileSystem = this.fileSystem.Object
};
this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector.Object);
TestFormat.RegisterGloablTestFormat();
TestFormat.RegisterGlobalTestFormat();
this.Marker = Guid.NewGuid().ToByteArray();
this.DataStream = TestFormat.GlobalTestFormat.CreateStream(this.Marker);
this.FilePath = Guid.NewGuid().ToString();
this.fileSystem.Setup(x => x.OpenRead(this.FilePath)).Returns(this.DataStream);
TestFileSystem.RegisterGloablTestFormat();
TestFileSystem.RegisterGlobalTestFormat();
TestFileSystem.Global.AddFile(this.FilePath, this.DataStream);
}
@ -86,7 +86,6 @@ namespace ImageSharp.Tests
Assert.Equal(localImageFormat, type);
}
[Fact]
public void DiscoverImageFormatStream()
{

26
tests/ImageSharp.Tests/Image/ImageLoadTests.cs

@ -55,28 +55,28 @@ namespace ImageSharp.Tests
this.fileSystem = new Mock<IFileSystem>();
this.LocalConfiguration = new Configuration()
this.LocalConfiguration = new Configuration
{
FileSystem = this.fileSystem.Object
};
this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector.Object);
this.LocalConfiguration.SetDecoder(localImageFormatMock.Object, this.localDecoder.Object);
TestFormat.RegisterGloablTestFormat();
TestFormat.RegisterGlobalTestFormat();
this.Marker = Guid.NewGuid().ToByteArray();
this.DataStream = TestFormat.GlobalTestFormat.CreateStream(this.Marker);
this.FilePath = Guid.NewGuid().ToString();
this.fileSystem.Setup(x => x.OpenRead(this.FilePath)).Returns(this.DataStream);
TestFileSystem.RegisterGloablTestFormat();
TestFileSystem.RegisterGlobalTestFormat();
TestFileSystem.Global.AddFile(this.FilePath, this.DataStream);
}
[Fact]
public void LoadFromStream()
{
Image<Rgba32> img = Image.Load<Rgba32>(this.DataStream);
Image<Rgba32> img = Image.Load<Rgba32>(this.DataStream);
Assert.NotNull(img);
@ -87,7 +87,7 @@ namespace ImageSharp.Tests
public void LoadFromNoneSeekableStream()
{
NoneSeekableStream stream = new NoneSeekableStream(this.DataStream);
Image<Rgba32> img = Image.Load<Rgba32>(stream);
Image<Rgba32> img = Image.Load<Rgba32>(stream);
Assert.NotNull(img);
@ -112,7 +112,7 @@ namespace ImageSharp.Tests
public void LoadFromStreamWithConfig()
{
Stream stream = new MemoryStream();
Image<Rgba32> img = Image.Load<Rgba32>(this.LocalConfiguration, stream);
Image<Rgba32> img = Image.Load<Rgba32>(this.LocalConfiguration, stream);
Assert.NotNull(img);
@ -138,7 +138,7 @@ namespace ImageSharp.Tests
public void LoadFromStreamWithDecoder()
{
Stream stream = new MemoryStream();
Image<Rgba32> img = Image.Load<Rgba32>(stream, this.localDecoder.Object);
Image<Rgba32> img = Image.Load<Rgba32>(stream, this.localDecoder.Object);
Assert.NotNull(img);
this.localDecoder.Verify(x => x.Decode<Rgba32>(Configuration.Default, stream));
@ -158,7 +158,7 @@ namespace ImageSharp.Tests
[Fact]
public void LoadFromBytes()
{
Image<Rgba32> img = Image.Load<Rgba32>(this.DataStream.ToArray());
Image<Rgba32> img = Image.Load<Rgba32>(this.DataStream.ToArray());
Assert.NotNull(img);
@ -182,7 +182,7 @@ namespace ImageSharp.Tests
[Fact]
public void LoadFromBytesWithConfig()
{
Image<Rgba32> img = Image.Load<Rgba32>(this.LocalConfiguration, this.DataStream.ToArray());
Image<Rgba32> img = Image.Load<Rgba32>(this.LocalConfiguration, this.DataStream.ToArray());
Assert.NotNull(img);
@ -207,7 +207,7 @@ namespace ImageSharp.Tests
[Fact]
public void LoadFromBytesWithDecoder()
{
Image<Rgba32> img = Image.Load<Rgba32>(this.DataStream.ToArray(), this.localDecoder.Object);
Image<Rgba32> img = Image.Load<Rgba32>(this.DataStream.ToArray(), this.localDecoder.Object);
Assert.NotNull(img);
this.localDecoder.Verify(x => x.Decode<Rgba32>(Configuration.Default, It.IsAny<Stream>()));
@ -228,7 +228,7 @@ namespace ImageSharp.Tests
[Fact]
public void LoadFromFile()
{
Image<Rgba32> img = Image.Load<Rgba32>(this.DataStream);
Image<Rgba32> img = Image.Load<Rgba32>(this.DataStream);
Assert.NotNull(img);
@ -251,7 +251,7 @@ namespace ImageSharp.Tests
[Fact]
public void LoadFromFileWithConfig()
{
Image<Rgba32> img = Image.Load<Rgba32>(this.LocalConfiguration, this.FilePath);
Image<Rgba32> img = Image.Load<Rgba32>(this.LocalConfiguration, this.FilePath);
Assert.NotNull(img);
@ -273,7 +273,7 @@ namespace ImageSharp.Tests
[Fact]
public void LoadFromFileWithDecoder()
{
Image<Rgba32> img = Image.Load<Rgba32>(this.FilePath, this.localDecoder.Object);
Image<Rgba32> img = Image.Load<Rgba32>(this.FilePath, this.localDecoder.Object);
Assert.NotNull(img);
this.localDecoder.Verify(x => x.Decode<Rgba32>(Configuration.Default, this.DataStream));

2
tests/ImageSharp.Tests/TestFileSystem.cs

@ -22,7 +22,7 @@ namespace ImageSharp.Tests
public static TestFileSystem Global { get; } = new TestFileSystem();
public static void RegisterGloablTestFormat()
public static void RegisterGlobalTestFormat()
{
Configuration.Default.FileSystem = Global;
}

15
tests/ImageSharp.Tests/TestFormat.cs

@ -23,15 +23,15 @@ namespace ImageSharp.Tests
{
public static TestFormat GlobalTestFormat { get; } = new TestFormat();
public static void RegisterGloablTestFormat()
public static void RegisterGlobalTestFormat()
{
Configuration.Default.Configure(GlobalTestFormat);
}
public TestFormat()
{
this.Encoder = new TestEncoder(this); ;
this.Decoder = new TestDecoder(this); ;
this.Encoder = new TestEncoder(this);
this.Decoder = new TestDecoder(this);
}
public List<DecodeOperation> DecodeCalls { get; } = new List<DecodeOperation>();
@ -200,10 +200,15 @@ namespace ImageSharp.Tests
config = config
});
// TODO record this happend so we an verify it.
// TODO record this happend so we can verify it.
return this.testFormat.Sample<TPixel>();
}
public int DetectPixelSize(Configuration configuration, Stream stream)
{
throw new NotImplementedException();
}
public bool IsSupportedFileFormat(Span<byte> header) => testFormat.IsSupportedFileFormat(header);
}
@ -222,7 +227,7 @@ namespace ImageSharp.Tests
public void Encode<TPixel>(Image<TPixel> image, Stream stream) where TPixel : struct, IPixel<TPixel>
{
// TODO record this happend so we an verify it.
// TODO record this happend so we can verify it.
}
}
}

6
tests/ImageSharp.Tests/TestImages.cs

@ -25,6 +25,9 @@ namespace ImageSharp.Tests
public const string Powerpoint = "Png/pp.png";
public const string SplashInterlaced = "Png/splash-interlaced.png";
public const string Interlaced = "Png/interlaced.png";
public const string Palette8Bpp = "Png/Palette-8bpp.png";
public const string Bpp1 = "Png/bpp1.png";
public const string Gray4Bpp = "Png/gray_4bpp.png";
public const string Rgb48Bpp = "Png/rgb-48bpp.png";
public const string Rgb48BppInterlaced = "Png/rgb-48bpp-interlaced.png";
@ -108,8 +111,9 @@ namespace ImageSharp.Tests
{
public const string Car = "Bmp/Car.bmp";
public const string F = "Bmp/F.bmp";
public const string Bpp8 = "Bmp/bpp8.bmp";
public const string NegHeight = "Bmp/neg_height.bmp";
public static readonly string[] All = { Car, F, NegHeight };
public static readonly string[] All = { Car, F, NegHeight, Bpp8 };
}
public static class Gif

3
tests/ImageSharp.Tests/TestImages/Formats/Bmp/bpp8.bmp

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bf34f4498dfe2a983771d0ff07ef87230de59fea3db8096212b5ad562dfb1011
size 65002

3
tests/ImageSharp.Tests/TestImages/Formats/Png/bpp1.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:364e9fac6467570afe2f23e432d4f7df10dd2dd53920d4f2c743ac0f8519f1e0
size 4403

3
tests/ImageSharp.Tests/TestImages/Formats/Png/gray_4bpp.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e7c6d6cbd959e84001e559702c31e313d065c9cc25808c190c4d4a1f564d4357
size 7396

3
tests/ImageSharp.Tests/TestImages/Formats/Png/palette-8bpp.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7bfbc244f4b0672d6a12a1f73ec062bcf762f229268b99aa4b9ffd8447512471
size 9171
Loading…
Cancel
Save