mirror of https://github.com/SixLabors/ImageSharp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
219 lines
7.8 KiB
219 lines
7.8 KiB
// Copyright (c) Six Labors.
|
|
// Licensed under the Six Labors Split License.
|
|
|
|
using System.Text;
|
|
using SixLabors.ImageSharp.Formats;
|
|
using SixLabors.ImageSharp.Formats.Pbm;
|
|
using SixLabors.ImageSharp.PixelFormats;
|
|
using SixLabors.ImageSharp.Tests.TestUtilities;
|
|
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
|
|
using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs;
|
|
using static SixLabors.ImageSharp.Tests.TestImages.Pbm;
|
|
|
|
// ReSharper disable InconsistentNaming
|
|
namespace SixLabors.ImageSharp.Tests.Formats.Pbm;
|
|
|
|
[Trait("Format", "Pbm")]
|
|
[ValidateDisposedMemoryAllocations]
|
|
public class PbmDecoderTests
|
|
{
|
|
[Theory]
|
|
[InlineData(BlackAndWhitePlain, PbmColorType.BlackAndWhite, PbmComponentType.Bit)]
|
|
[InlineData(BlackAndWhiteBinary, PbmColorType.BlackAndWhite, PbmComponentType.Bit)]
|
|
[InlineData(GrayscalePlain, PbmColorType.Grayscale, PbmComponentType.Byte)]
|
|
[InlineData(GrayscalePlainMagick, PbmColorType.Grayscale, PbmComponentType.Byte)]
|
|
[InlineData(GrayscaleBinary, PbmColorType.Grayscale, PbmComponentType.Byte)]
|
|
[InlineData(GrayscaleBinaryWide, PbmColorType.Grayscale, PbmComponentType.Short)]
|
|
[InlineData(RgbPlain, PbmColorType.Rgb, PbmComponentType.Byte)]
|
|
[InlineData(RgbPlainMagick, PbmColorType.Rgb, PbmComponentType.Byte)]
|
|
[InlineData(RgbBinary, PbmColorType.Rgb, PbmComponentType.Byte)]
|
|
[InlineData(RgbBinaryWide, PbmColorType.Rgb, PbmComponentType.Short)]
|
|
public void ImageLoadCanDecode(string imagePath, PbmColorType expectedColorType, PbmComponentType expectedComponentType)
|
|
{
|
|
// Arrange
|
|
TestFile testFile = TestFile.Create(imagePath);
|
|
using MemoryStream stream = new(testFile.Bytes, false);
|
|
|
|
// Act
|
|
using Image image = Image.Load(stream);
|
|
|
|
// Assert
|
|
Assert.NotNull(image);
|
|
PbmMetadata metadata = image.Metadata.GetPbmMetadata();
|
|
Assert.NotNull(metadata);
|
|
Assert.Equal(expectedColorType, metadata.ColorType);
|
|
Assert.Equal(expectedComponentType, metadata.ComponentType);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(BlackAndWhitePlain)]
|
|
[InlineData(BlackAndWhiteBinary)]
|
|
[InlineData(GrayscalePlain)]
|
|
[InlineData(GrayscalePlainMagick)]
|
|
[InlineData(GrayscaleBinary)]
|
|
[InlineData(GrayscaleBinaryWide)]
|
|
public void ImageLoadL8CanDecode(string imagePath)
|
|
{
|
|
// Arrange
|
|
TestFile testFile = TestFile.Create(imagePath);
|
|
using MemoryStream stream = new(testFile.Bytes, false);
|
|
|
|
// Act
|
|
using Image<L8> image = Image.Load<L8>(stream);
|
|
|
|
// Assert
|
|
Assert.NotNull(image);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(RgbPlain)]
|
|
[InlineData(RgbPlainMagick)]
|
|
[InlineData(RgbBinary)]
|
|
public void ImageLoadRgb24CanDecode(string imagePath)
|
|
{
|
|
// Arrange
|
|
TestFile testFile = TestFile.Create(imagePath);
|
|
using MemoryStream stream = new(testFile.Bytes, false);
|
|
|
|
// Act
|
|
using Image<Rgb24> image = Image.Load<Rgb24>(stream);
|
|
|
|
// Assert
|
|
Assert.NotNull(image);
|
|
}
|
|
|
|
[Theory]
|
|
[WithFile(BlackAndWhitePlain, PixelTypes.L8, "pbm")]
|
|
[WithFile(BlackAndWhiteBinary, PixelTypes.L8, "pbm")]
|
|
[WithFile(Issue2477, PixelTypes.L8, "pbm")]
|
|
[WithFile(GrayscalePlain, PixelTypes.L8, "pgm")]
|
|
[WithFile(GrayscalePlainNormalized, PixelTypes.L8, "pgm")]
|
|
[WithFile(GrayscaleBinary, PixelTypes.L8, "pgm")]
|
|
[WithFile(GrayscaleBinaryWide, PixelTypes.L16, "pgm")]
|
|
[WithFile(RgbPlain, PixelTypes.Rgb24, "ppm")]
|
|
[WithFile(RgbPlainNormalized, PixelTypes.Rgb24, "ppm")]
|
|
[WithFile(RgbBinary, PixelTypes.Rgb24, "ppm")]
|
|
[WithFile(RgbBinaryWide, PixelTypes.Rgb48, "ppm")]
|
|
public void DecodeReferenceImage<TPixel>(TestImageProvider<TPixel> provider, string extension)
|
|
where TPixel : unmanaged, IPixel<TPixel>
|
|
{
|
|
using Image<TPixel> image = provider.GetImage();
|
|
image.DebugSave(provider, extension: extension);
|
|
|
|
bool isGrayscale = extension is "pgm" or "pbm";
|
|
image.CompareToReferenceOutput(provider, grayscale: isGrayscale);
|
|
}
|
|
|
|
[Theory]
|
|
[WithFile(GrayscaleBinaryWide, PixelTypes.Rgb48)]
|
|
[WithFile(RgbBinaryWide, PixelTypes.Rgb48)]
|
|
public void Decode_WideBinary_MatchesReferenceDecoder<TPixel>(TestImageProvider<TPixel> provider)
|
|
where TPixel : unmanaged, IPixel<TPixel>
|
|
{
|
|
using Image<TPixel> image = provider.GetImage(PbmDecoder.Instance);
|
|
image.CompareToOriginal(provider, ImageComparer.Exact, new MagickReferenceDecoder(PbmFormat.Instance));
|
|
}
|
|
|
|
[Fact]
|
|
public void Decode_WideBinaryGrayscale_SamplesAreBigEndian()
|
|
{
|
|
// Per the Netpbm specification, 16-bit samples store the most significant byte first.
|
|
byte[] header = Encoding.ASCII.GetBytes("P5\n2 1\n65535\n");
|
|
byte[] samples = [0x80, 0x00, 0x00, 0x80];
|
|
byte[] data = [.. header, .. samples];
|
|
|
|
using Image<L16> image = Image.Load<L16>(data);
|
|
|
|
Assert.Equal(0x8000, image[0, 0].PackedValue);
|
|
Assert.Equal(0x0080, image[1, 0].PackedValue);
|
|
}
|
|
|
|
[Fact]
|
|
public void Decode_WideBinaryRgb_SamplesAreBigEndian()
|
|
{
|
|
// Per the Netpbm specification, 16-bit samples store the most significant byte first.
|
|
byte[] header = Encoding.ASCII.GetBytes("P6\n1 1\n65535\n");
|
|
byte[] samples = [0x81, 0xB5, 0x84, 0x91, 0x86, 0x71];
|
|
byte[] data = [.. header, .. samples];
|
|
|
|
using Image<Rgb48> image = Image.Load<Rgb48>(data);
|
|
|
|
Assert.Equal(new Rgb48(0x81B5, 0x8491, 0x8671), image[0, 0]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Decode_NonStandardByteMaxPixelValue_UpscalesToFullRange()
|
|
{
|
|
byte[] data = Encoding.ASCII.GetBytes("P2\n1 1\n100\n100");
|
|
|
|
using Image<L8> image = Image.Load<L8>(data);
|
|
|
|
Assert.Equal(255, image[0, 0].PackedValue);
|
|
}
|
|
|
|
[Fact]
|
|
public void Decode_NonStandardShortMaxPixelValue_UpscalesToFullRange()
|
|
{
|
|
byte[] header = Encoding.ASCII.GetBytes("P5\n1 1\n1000\n");
|
|
byte[] samples = [0x03, 0xE8];
|
|
byte[] data = [.. header, .. samples];
|
|
|
|
using Image<L16> image = Image.Load<L16>(data);
|
|
|
|
Assert.Equal(65535, image[0, 0].PackedValue);
|
|
}
|
|
|
|
[Theory]
|
|
[WithFile(RgbPlain, PixelTypes.Rgb24)]
|
|
public void PbmDecoder_Decode_Resize<TPixel>(TestImageProvider<TPixel> provider)
|
|
where TPixel : unmanaged, IPixel<TPixel>
|
|
{
|
|
DecoderOptions options = new()
|
|
{
|
|
TargetSize = new Size { Width = 150, Height = 150 }
|
|
};
|
|
|
|
using Image<TPixel> image = provider.GetImage(PbmDecoder.Instance, options);
|
|
|
|
FormattableString details = $"{options.TargetSize.Value.Width}_{options.TargetSize.Value.Height}";
|
|
|
|
image.DebugSave(provider, testOutputDetails: details, appendPixelTypeToFileName: false);
|
|
image.CompareToReferenceOutput(
|
|
ImageComparer.Exact,
|
|
provider,
|
|
testOutputDetails: details,
|
|
appendPixelTypeToFileName: false);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("P2")]
|
|
[InlineData("P3")]
|
|
[InlineData("P5")]
|
|
[InlineData("P6")]
|
|
public void Decode_MaxPixelValueZero_ThrowsInvalidImageContentException(string magic)
|
|
{
|
|
byte[] bytes = Encoding.ASCII.GetBytes($"{magic} 1 1 0\n0");
|
|
using MemoryStream stream = new(bytes);
|
|
|
|
Assert.Throws<InvalidImageContentException>(() => Image.Load<Rgba32>(stream));
|
|
}
|
|
|
|
[Fact]
|
|
public void PlainText_PrematureEof()
|
|
{
|
|
byte[] bytes = Encoding.ASCII.GetBytes($"P1\n100 100\n1 0 1 0 1 0");
|
|
using EofHitCounter eofHitCounter = EofHitCounter.RunDecoder(bytes);
|
|
|
|
Assert.True(eofHitCounter.EofHitCount <= 2);
|
|
Assert.Equal(new Size(100, 100), eofHitCounter.Image.Size);
|
|
}
|
|
|
|
[Fact]
|
|
public void Binary_PrematureEof()
|
|
{
|
|
using EofHitCounter eofHitCounter = EofHitCounter.RunDecoder(RgbBinaryPrematureEof);
|
|
|
|
Assert.True(eofHitCounter.EofHitCount <= 2);
|
|
Assert.Equal(new Size(29, 30), eofHitCounter.Image.Size);
|
|
}
|
|
}
|
|
|