Browse Source

Process first round of review comments

pull/1851/head
Ynse Hoornenborg 5 years ago
parent
commit
0c8c892647
  1. 2
      src/ImageSharp/Formats/Pbm/BinaryDecoder.cs
  2. 22
      src/ImageSharp/Formats/Pbm/BinaryEncoder.cs
  3. 2
      src/ImageSharp/Formats/Pbm/BufferedReadStreamExtensions.cs
  4. 4
      src/ImageSharp/Formats/Pbm/PbmConstants.cs
  5. 18
      src/ImageSharp/Formats/Pbm/PbmDecoder.cs
  6. 4
      src/ImageSharp/Formats/Pbm/PbmDecoderCore.cs
  7. 23
      src/ImageSharp/Formats/Pbm/PbmEncoder.cs
  8. 58
      src/ImageSharp/Formats/Pbm/PbmEncoderCore.cs
  9. 7
      src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs
  10. 129
      src/ImageSharp/Formats/Pbm/PlainEncoder.cs
  11. 19
      src/ImageSharp/Formats/Pbm/StreamExtensions.cs
  12. 55
      tests/ImageSharp.Tests/Formats/Pbm/PbmDecoderTests.cs
  13. 2
      tests/ImageSharp.Tests/TestImages.cs
  14. 3
      tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_L16_Gene-UP WebSocket RunImageMask.png
  15. 3
      tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_L8_blackandwhite_binary.png
  16. 3
      tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_L8_blackandwhite_plain.png
  17. 3
      tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_L8_grayscale_plain_normalized.png
  18. 3
      tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_L8_rings.png
  19. 3
      tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_Rgb24_00000_00000.png
  20. 3
      tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_Rgb24_rgb_plain_normalized.png
  21. 10
      tests/Images/Input/Pbm/grayscale_plain_normalized.pgm
  22. 8
      tests/Images/Input/Pbm/rgb_plain_normalized.ppm

2
src/ImageSharp/Formats/Pbm/BinaryDecoder.cs

@ -171,7 +171,7 @@ namespace SixLabors.ImageSharp.Formats.Pbm
x++;
if (x == width)
{
startBit = (bit + 1) % 8;
startBit = (bit + 1) & 7; // Round off to below 8.
if (startBit != 0)
{
stream.Seek(-1, System.IO.SeekOrigin.Current);

22
src/ImageSharp/Formats/Pbm/BinaryEncoder.cs

@ -60,8 +60,8 @@ namespace SixLabors.ImageSharp.Formats.Pbm
private static void WriteGrayscale<TPixel>(Configuration configuration, Stream stream, ImageFrame<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{
int width = image.Size().Width;
int height = image.Size().Height;
int width = image.Width;
int height = image.Height;
MemoryAllocator allocator = configuration.MemoryAllocator;
using IMemoryOwner<byte> row = allocator.Allocate<byte>(width);
Span<byte> rowSpan = row.GetSpan();
@ -83,8 +83,8 @@ namespace SixLabors.ImageSharp.Formats.Pbm
private static void WriteWideGrayscale<TPixel>(Configuration configuration, Stream stream, ImageFrame<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{
int width = image.Size().Width;
int height = image.Size().Height;
int width = image.Width;
int height = image.Height;
int bytesPerPixel = 2;
MemoryAllocator allocator = configuration.MemoryAllocator;
using IMemoryOwner<byte> row = allocator.Allocate<byte>(width * bytesPerPixel);
@ -107,8 +107,8 @@ namespace SixLabors.ImageSharp.Formats.Pbm
private static void WriteRgb<TPixel>(Configuration configuration, Stream stream, ImageFrame<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{
int width = image.Size().Width;
int height = image.Size().Height;
int width = image.Width;
int height = image.Height;
int bytesPerPixel = 3;
MemoryAllocator allocator = configuration.MemoryAllocator;
using IMemoryOwner<byte> row = allocator.Allocate<byte>(width * bytesPerPixel);
@ -131,8 +131,8 @@ namespace SixLabors.ImageSharp.Formats.Pbm
private static void WriteWideRgb<TPixel>(Configuration configuration, Stream stream, ImageFrame<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{
int width = image.Size().Width;
int height = image.Size().Height;
int width = image.Width;
int height = image.Height;
int bytesPerPixel = 6;
MemoryAllocator allocator = configuration.MemoryAllocator;
using IMemoryOwner<byte> row = allocator.Allocate<byte>(width * bytesPerPixel);
@ -155,8 +155,8 @@ namespace SixLabors.ImageSharp.Formats.Pbm
private static void WriteBlackAndWhite<TPixel>(Configuration configuration, Stream stream, ImageFrame<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{
int width = image.Size().Width;
int height = image.Size().Height;
int width = image.Width;
int height = image.Height;
MemoryAllocator allocator = configuration.MemoryAllocator;
using IMemoryOwner<L8> row = allocator.Allocate<L8>(width);
Span<L8> rowSpan = row.GetSpan();
@ -186,7 +186,7 @@ namespace SixLabors.ImageSharp.Formats.Pbm
if (x == width)
{
previousValue = value;
startBit = (i + 1) % 8;
startBit = (i + 1) & 7; // Round off to below 8.
break;
}
}

2
src/ImageSharp/Formats/Pbm/BufferedReadStreamExtensions.cs

@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Formats.Pbm
while (true)
{
int current = stream.ReadByte() - 0x30;
if (current < 0 || current > 9)
if ((uint)current > 9)
{
break;
}

4
src/ImageSharp/Formats/Pbm/PbmConstants.cs

@ -18,11 +18,11 @@ namespace SixLabors.ImageSharp.Formats.Pbm
/// <summary>
/// The list of mimetypes that equate to a ppm.
/// </summary>
public static readonly IEnumerable<string> MimeTypes = new[] { "image/x-portable-pixmap", "image/x-portable-anymap", "image/x-portable-arbitrarymap" };
public static readonly IEnumerable<string> MimeTypes = new[] { "image/x-portable-pixmap", "image/x-portable-anymap" };
/// <summary>
/// The list of file extensions that equate to a ppm.
/// </summary>
public static readonly IEnumerable<string> FileExtensions = new[] { "ppm", "pbm", "pgm", "pam" };
public static readonly IEnumerable<string> FileExtensions = new[] { "ppm", "pbm", "pgm" };
}
}

18
src/ImageSharp/Formats/Pbm/PbmDecoder.cs

@ -9,7 +9,23 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Pbm
{
/// <summary>
/// Image decoder for generating an image out of a ppm stream.
/// Image decoder for reading PGM, PBM or PPM bitmaps from a stream. These images are from
/// the family of PNM images.
/// <list type="bullet">
/// <item>
/// <term>PBM</term>
/// <description>Black and white images.</description>
/// </item>
/// <item>
/// <term>PGM</term>
/// <description>Grayscale images.</description>
/// </item>
/// <item>
/// <term>PPM</term>
/// <description>Color images, with RGB pixels.</description>
/// </item>
/// </list>
/// The specification of these images is found at <seealso href="http://netpbm.sourceforge.net/doc/pnm.html"/>.
/// </summary>
public sealed class PbmDecoder : IImageDecoder, IImageInfoDetector
{

4
src/ImageSharp/Formats/Pbm/PbmDecoderCore.cs

@ -82,9 +82,9 @@ namespace SixLabors.ImageSharp.Formats.Pbm
/// <param name="stream">The input stream.</param>
private void ProcessHeader(BufferedReadStream stream)
{
byte[] buffer = new byte[2];
Span<byte> buffer = stackalloc byte[2];
int bytesRead = stream.Read(buffer, 0, 2);
int bytesRead = stream.Read(buffer);
if (bytesRead != 2 || buffer[0] != 'P')
{
// Empty or not an PPM image.

23
src/ImageSharp/Formats/Pbm/PbmEncoder.cs

@ -10,7 +10,28 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Pbm
{
/// <summary>
/// Image encoder for writing an image to a stream as PGM, PBM, PPM or PAM bitmap.
/// Image encoder for writing an image to a stream as PGM, PBM or PPM bitmap. These images are from
/// the family of PNM images.
/// <para>
/// The PNM formats are a faily simple image format. They share a plain text header, consisting of:
/// signature, width, height and max_pixel_value only. The pixels follow thereafter and can be in
/// plain text decimals seperated by spaces, or binary encoded.
/// <list type="bullet">
/// <item>
/// <term>PBM</term>
/// <description>Black and white images, with 1 representing black and 0 representing white.</description>
/// </item>
/// <item>
/// <term>PGM</term>
/// <description>Grayscale images, scaling from 0 to max_pixel_value, 0 representing black and max_pixel_value representing white.</description>
/// </item>
/// <item>
/// <term>PPM</term>
/// <description>Color images, with RGB pixels (in that order), with 0 representing black and 2 representing full color.</description>
/// </item>
/// </list>
/// </para>
/// The specification of these images is found at <seealso href="http://netpbm.sourceforge.net/doc/pnm.html"/>.
/// </summary>
public sealed class PbmEncoder : IImageEncoder, IPbmEncoderOptions
{

58
src/ImageSharp/Formats/Pbm/PbmEncoderCore.cs

@ -2,12 +2,10 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Buffers.Text;
using System.IO;
using System.Text;
using System.Threading;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Pbm
@ -17,7 +15,9 @@ namespace SixLabors.ImageSharp.Formats.Pbm
/// </summary>
internal sealed class PbmEncoderCore : IImageEncoderInternals
{
private const char NewLine = '\n';
private const byte NewLine = (byte)'\n';
private const byte Space = (byte)' ';
private const byte P = (byte)'P';
/// <summary>
/// The global configuration.
@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Formats.Pbm
this.DeduceOptions(image);
string signature = this.DeduceSignature();
byte signature = this.DeduceSignature();
this.WriteHeader(stream, signature, image.Size());
this.WritePixels(stream, image.Frames.RootFrame);
@ -91,29 +91,29 @@ namespace SixLabors.ImageSharp.Formats.Pbm
}
}
private string DeduceSignature()
private byte DeduceSignature()
{
string signature;
byte signature;
if (this.colorType == PbmColorType.BlackAndWhite)
{
if (this.encoding == PbmEncoding.Plain)
{
signature = "P1";
signature = (byte)'1';
}
else
{
signature = "P4";
signature = (byte)'4';
}
}
else if (this.colorType == PbmColorType.Grayscale)
{
if (this.encoding == PbmEncoding.Plain)
{
signature = "P2";
signature = (byte)'2';
}
else
{
signature = "P5";
signature = (byte)'5';
}
}
else
@ -121,35 +121,41 @@ namespace SixLabors.ImageSharp.Formats.Pbm
// RGB ColorType
if (this.encoding == PbmEncoding.Plain)
{
signature = "P3";
signature = (byte)'3';
}
else
{
signature = "P6";
signature = (byte)'6';
}
}
return signature;
}
private void WriteHeader(Stream stream, string signature, Size pixelSize)
private void WriteHeader(Stream stream, byte signature, Size pixelSize)
{
var builder = new StringBuilder(20);
builder.Append(signature);
builder.Append(NewLine);
builder.Append(pixelSize.Width.ToString());
builder.Append(NewLine);
builder.Append(pixelSize.Height.ToString());
builder.Append(NewLine);
Span<byte> buffer = stackalloc byte[128];
int written = 3;
buffer[0] = P;
buffer[1] = signature;
buffer[2] = NewLine;
Utf8Formatter.TryFormat(pixelSize.Width, buffer.Slice(written), out int bytesWritten);
written += bytesWritten;
buffer[written++] = Space;
Utf8Formatter.TryFormat(pixelSize.Height, buffer.Slice(written), out bytesWritten);
written += bytesWritten;
buffer[written++] = NewLine;
if (this.colorType != PbmColorType.BlackAndWhite)
{
builder.Append(this.maxPixelValue.ToString());
builder.Append(NewLine);
Utf8Formatter.TryFormat(this.maxPixelValue, buffer.Slice(written), out bytesWritten);
written += bytesWritten;
buffer[written++] = NewLine;
}
string headerStr = builder.ToString();
byte[] headerBytes = Encoding.ASCII.GetBytes(headerStr);
stream.Write(headerBytes, 0, headerBytes.Length);
stream.Write(buffer, 0, written);
}
/// <summary>

7
src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs

@ -22,9 +22,12 @@ namespace SixLabors.ImageSharp.Formats.Pbm
private bool IsSupportedFileFormat(ReadOnlySpan<byte> header)
{
if (header.Length >= this.HeaderSize)
#pragma warning disable SA1131 // Use readable conditions
if (1 < (uint)header.Length)
#pragma warning restore SA1131 // Use readable conditions
{
return header[0] == P && header[1] > Zero && header[1] < Seven;
// Signature should be between P1 and P6.
return header[0] == P && (uint)(header[1] - Zero - 1) < (Seven - Zero - 1);
}
return false;

129
src/ImageSharp/Formats/Pbm/PlainEncoder.cs

@ -3,6 +3,7 @@
using System;
using System.Buffers;
using System.Buffers.Text;
using System.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
@ -20,6 +21,14 @@ namespace SixLabors.ImageSharp.Formats.Pbm
private const byte Zero = 0x30;
private const byte One = 0x31;
private const int MaxCharsPerPixelBlackAndWhite = 2;
private const int MaxCharsPerPixelGrayscale = 4;
private const int MaxCharsPerPixelGrayscaleWide = 6;
private const int MaxCharsPerPixelRgb = 4 * 3;
private const int MaxCharsPerPixelRgbWide = 6 * 3;
private static readonly StandardFormat DecimalFormat = StandardFormat.Parse("D");
/// <summary>
/// Decode pixels into the PBM plain encoding.
/// </summary>
@ -63,12 +72,12 @@ namespace SixLabors.ImageSharp.Formats.Pbm
private static void WriteGrayscale<TPixel>(Configuration configuration, Stream stream, ImageFrame<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{
int width = image.Size().Width;
int height = image.Size().Height;
int bytesWritten = -1;
int width = image.Width;
int height = image.Height;
MemoryAllocator allocator = configuration.MemoryAllocator;
using IMemoryOwner<L8> row = allocator.Allocate<L8>(width);
Span<L8> rowSpan = row.GetSpan();
Span<byte> plainSpan = stackalloc byte[width * MaxCharsPerPixelGrayscale];
for (int y = 0; y < height; y++)
{
@ -78,23 +87,28 @@ namespace SixLabors.ImageSharp.Formats.Pbm
pixelSpan,
rowSpan);
int written = 0;
for (int x = 0; x < width; x++)
{
WriteWhitespace(stream, ref bytesWritten);
bytesWritten += stream.WriteDecimal(rowSpan[x].PackedValue);
Utf8Formatter.TryFormat(rowSpan[x].PackedValue, plainSpan.Slice(written), out int bytesWritten, DecimalFormat);
written += bytesWritten;
plainSpan[written++] = Space;
}
plainSpan[written - 1] = NewLine;
stream.Write(plainSpan, 0, written);
}
}
private static void WriteWideGrayscale<TPixel>(Configuration configuration, Stream stream, ImageFrame<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{
int width = image.Size().Width;
int height = image.Size().Height;
int bytesWritten = -1;
int width = image.Width;
int height = image.Height;
MemoryAllocator allocator = configuration.MemoryAllocator;
using IMemoryOwner<L16> row = allocator.Allocate<L16>(width);
Span<L16> rowSpan = row.GetSpan();
Span<byte> plainSpan = stackalloc byte[width * MaxCharsPerPixelGrayscaleWide];
for (int y = 0; y < height; y++)
{
@ -104,23 +118,28 @@ namespace SixLabors.ImageSharp.Formats.Pbm
pixelSpan,
rowSpan);
int written = 0;
for (int x = 0; x < width; x++)
{
WriteWhitespace(stream, ref bytesWritten);
bytesWritten += stream.WriteDecimal(rowSpan[x].PackedValue);
Utf8Formatter.TryFormat(rowSpan[x].PackedValue, plainSpan.Slice(written), out int bytesWritten, DecimalFormat);
written += bytesWritten;
plainSpan[written++] = Space;
}
plainSpan[written - 1] = NewLine;
stream.Write(plainSpan, 0, written);
}
}
private static void WriteRgb<TPixel>(Configuration configuration, Stream stream, ImageFrame<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{
int width = image.Size().Width;
int height = image.Size().Height;
int bytesWritten = -1;
int width = image.Width;
int height = image.Height;
MemoryAllocator allocator = configuration.MemoryAllocator;
using IMemoryOwner<Rgb24> row = allocator.Allocate<Rgb24>(width);
Span<Rgb24> rowSpan = row.GetSpan();
Span<byte> plainSpan = stackalloc byte[width * MaxCharsPerPixelRgb];
for (int y = 0; y < height; y++)
{
@ -130,27 +149,34 @@ namespace SixLabors.ImageSharp.Formats.Pbm
pixelSpan,
rowSpan);
int written = 0;
for (int x = 0; x < width; x++)
{
WriteWhitespace(stream, ref bytesWritten);
bytesWritten += stream.WriteDecimal(rowSpan[x].R);
WriteWhitespace(stream, ref bytesWritten);
bytesWritten += stream.WriteDecimal(rowSpan[x].G);
WriteWhitespace(stream, ref bytesWritten);
bytesWritten += stream.WriteDecimal(rowSpan[x].B);
Utf8Formatter.TryFormat(rowSpan[x].R, plainSpan.Slice(written), out int bytesWritten, DecimalFormat);
written += bytesWritten;
plainSpan[written++] = Space;
Utf8Formatter.TryFormat(rowSpan[x].G, plainSpan.Slice(written), out bytesWritten, DecimalFormat);
written += bytesWritten;
plainSpan[written++] = Space;
Utf8Formatter.TryFormat(rowSpan[x].B, plainSpan.Slice(written), out bytesWritten, DecimalFormat);
written += bytesWritten;
plainSpan[written++] = Space;
}
plainSpan[written - 1] = NewLine;
stream.Write(plainSpan, 0, written);
}
}
private static void WriteWideRgb<TPixel>(Configuration configuration, Stream stream, ImageFrame<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{
int width = image.Size().Width;
int height = image.Size().Height;
int bytesWritten = -1;
int width = image.Width;
int height = image.Height;
MemoryAllocator allocator = configuration.MemoryAllocator;
using IMemoryOwner<Rgb48> row = allocator.Allocate<Rgb48>(width);
Span<Rgb48> rowSpan = row.GetSpan();
Span<byte> plainSpan = stackalloc byte[width * MaxCharsPerPixelRgbWide];
for (int y = 0; y < height; y++)
{
@ -160,27 +186,34 @@ namespace SixLabors.ImageSharp.Formats.Pbm
pixelSpan,
rowSpan);
int written = 0;
for (int x = 0; x < width; x++)
{
WriteWhitespace(stream, ref bytesWritten);
bytesWritten += stream.WriteDecimal(rowSpan[x].R);
WriteWhitespace(stream, ref bytesWritten);
bytesWritten += stream.WriteDecimal(rowSpan[x].G);
WriteWhitespace(stream, ref bytesWritten);
bytesWritten += stream.WriteDecimal(rowSpan[x].B);
Utf8Formatter.TryFormat(rowSpan[x].R, plainSpan.Slice(written), out int bytesWritten, DecimalFormat);
written += bytesWritten;
plainSpan[written++] = Space;
Utf8Formatter.TryFormat(rowSpan[x].G, plainSpan.Slice(written), out bytesWritten, DecimalFormat);
written += bytesWritten;
plainSpan[written++] = Space;
Utf8Formatter.TryFormat(rowSpan[x].B, plainSpan.Slice(written), out bytesWritten, DecimalFormat);
written += bytesWritten;
plainSpan[written++] = Space;
}
plainSpan[written - 1] = NewLine;
stream.Write(plainSpan, 0, written);
}
}
private static void WriteBlackAndWhite<TPixel>(Configuration configuration, Stream stream, ImageFrame<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{
int width = image.Size().Width;
int height = image.Size().Height;
int bytesWritten = -1;
int width = image.Width;
int height = image.Height;
MemoryAllocator allocator = configuration.MemoryAllocator;
using IMemoryOwner<L8> row = allocator.Allocate<L8>(width);
Span<L8> rowSpan = row.GetSpan();
Span<byte> plainSpan = stackalloc byte[width * MaxCharsPerPixelBlackAndWhite];
for (int y = 0; y < height; y++)
{
@ -190,38 +223,16 @@ namespace SixLabors.ImageSharp.Formats.Pbm
pixelSpan,
rowSpan);
int written = 0;
for (int x = 0; x < width; x++)
{
WriteWhitespace(stream, ref bytesWritten);
if (rowSpan[x].PackedValue > 127)
{
stream.WriteByte(Zero);
}
else
{
stream.WriteByte(One);
}
bytesWritten++;
byte value = (rowSpan[x].PackedValue > 127) ? Zero : One;
plainSpan[written++] = value;
plainSpan[written++] = Space;
}
}
}
private static void WriteWhitespace(Stream stream, ref int bytesWritten)
{
if (bytesWritten > MaxLineLength)
{
stream.WriteByte(NewLine);
bytesWritten = 1;
}
else if (bytesWritten == -1)
{
bytesWritten = 0;
}
else
{
stream.WriteByte(Space);
bytesWritten++;
plainSpan[written - 1] = NewLine;
stream.Write(plainSpan, 0, written);
}
}
}

19
src/ImageSharp/Formats/Pbm/StreamExtensions.cs

@ -1,19 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.IO;
using System.Text;
namespace SixLabors.ImageSharp.Formats.Pbm
{
internal static class StreamExtensions
{
public static int WriteDecimal(this Stream stream, int value)
{
string str = value.ToString();
byte[] bytes = Encoding.ASCII.GetBytes(str);
stream.Write(bytes);
return bytes.Length;
}
}
}

55
tests/ImageSharp.Tests/Formats/Pbm/PbmDecoderTests.cs

@ -3,7 +3,8 @@
using System.IO;
using SixLabors.ImageSharp.Formats.Pbm;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Xunit;
using static SixLabors.ImageSharp.Tests.TestImages.Pbm;
@ -21,7 +22,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Pbm
[InlineData(GrayscaleBinaryWide, PbmColorType.Grayscale)]
[InlineData(RgbPlain, PbmColorType.Rgb)]
[InlineData(RgbBinary, PbmColorType.Rgb)]
public void PpmDecoder_CanDecode(string imagePath, PbmColorType expectedColorType)
public void ImageLoadCanDecode(string imagePath, PbmColorType expectedColorType)
{
// Arrange
var testFile = TestFile.Create(imagePath);
@ -36,5 +37,55 @@ namespace SixLabors.ImageSharp.Tests.Formats.Pbm
Assert.NotNull(bitmapMetadata);
Assert.Equal(expectedColorType, bitmapMetadata.ColorType);
}
[Theory]
[InlineData(BlackAndWhitePlain)]
[InlineData(BlackAndWhiteBinary)]
[InlineData(GrayscalePlain)]
[InlineData(GrayscaleBinary)]
[InlineData(GrayscaleBinaryWide)]
public void ImageLoadL8CanDecode(string imagePath)
{
// Arrange
var testFile = TestFile.Create(imagePath);
using var stream = new MemoryStream(testFile.Bytes, false);
// Act
using var image = Image.Load<L8>(stream);
// Assert
Assert.NotNull(image);
}
[Theory]
[InlineData(RgbPlain)]
[InlineData(RgbBinary)]
public void ImageLoadRgb24CanDecode(string imagePath)
{
// Arrange
var testFile = TestFile.Create(imagePath);
using var stream = new MemoryStream(testFile.Bytes, false);
// Act
using var image = Image.Load<Rgb24>(stream);
// Assert
Assert.NotNull(image);
}
[Theory]
[WithFile(BlackAndWhiteBinary, PixelTypes.L8, true)]
[WithFile(GrayscalePlainNormalized, PixelTypes.L8, true)]
[WithFile(GrayscaleBinary, PixelTypes.L8, true)]
[WithFile(GrayscaleBinaryWide, PixelTypes.L16, true)]
[WithFile(RgbPlainNormalized, PixelTypes.Rgb24, false)]
[WithFile(RgbBinary, PixelTypes.Rgb24, false)]
public void DecodeReferenceImage<TPixel>(TestImageProvider<TPixel> provider, bool isGrayscale)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage();
image.CompareToReferenceOutput(provider, grayscale: isGrayscale);
}
}
}

2
tests/ImageSharp.Tests/TestImages.cs

@ -874,8 +874,10 @@ namespace SixLabors.ImageSharp.Tests
public const string GrayscaleBinary = "Pbm/rings.pgm";
public const string GrayscaleBinaryWide = "Pbm/Gene-UP WebSocket RunImageMask.pgm";
public const string GrayscalePlain = "Pbm/grayscale_plain.pgm";
public const string GrayscalePlainNormalized = "Pbm/grayscale_plain_normalized.pgm";
public const string RgbBinary = "Pbm/00000_00000.ppm";
public const string RgbPlain = "Pbm/rgb_plain.ppm";
public const string RgbPlainNormalized = "Pbm/rgb_plain_normalized.ppm";
}
}
}

3
tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_L16_Gene-UP WebSocket RunImageMask.png

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

3
tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_L8_blackandwhite_binary.png

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

3
tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_L8_blackandwhite_plain.png

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

3
tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_L8_grayscale_plain_normalized.png

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

3
tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_L8_rings.png

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

3
tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_Rgb24_00000_00000.png

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

3
tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_Rgb24_rgb_plain_normalized.png

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

10
tests/Images/Input/Pbm/grayscale_plain_normalized.pgm

@ -0,0 +1,10 @@
P2
24 7
255
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 51 51 51 51 0 0 119 119 119 119 0 0 187 187 187 187 0 0 255 255 255 255 0
0 51 0 0 0 0 0 119 0 0 0 0 0 187 0 0 0 0 0 255 0 0 255 0
0 51 51 51 0 0 0 119 119 119 0 0 0 187 187 187 0 0 0 255 255 255 255 0
0 51 0 0 0 0 0 119 0 0 0 0 0 187 0 0 0 0 0 255 0 0 0 0
0 51 0 0 0 0 0 119 119 119 119 0 0 187 187 187 187 0 0 255 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

8
tests/Images/Input/Pbm/rgb_plain_normalized.ppm

@ -0,0 +1,8 @@
P3
# example from the man page
4 4
255
0 0 0 0 0 0 0 0 0 255 0 255
0 0 0 0 255 119 0 0 0 0 0 0
0 0 0 0 0 0 0 255 119 0 0 0
255 0 255 0 0 0 0 0 0 0 0 0
Loading…
Cancel
Save