Browse Source

Merge branch 'main' into main

qoi
Luis Alfredo Figueroa Bracamontes 3 years ago
committed by GitHub
parent
commit
4a494c7dcf
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  2. 16
      src/ImageSharp/Formats/Pbm/BinaryDecoder.cs
  3. 40
      src/ImageSharp/Formats/Pbm/BinaryEncoder.cs
  4. 20
      src/ImageSharp/Formats/Tiff/Compression/Decompressors/T6BitReader.cs
  5. 1
      src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs
  6. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs
  7. 10
      src/ImageSharp/Primitives/LongRational.cs
  8. 162
      src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs
  9. 59
      src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs
  10. 132
      src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
  11. 4
      src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs
  12. 2
      tests/Directory.Build.targets
  13. 20
      tests/ImageSharp.Tests/Drawing/DrawImageExtensionsTests.cs
  14. 67
      tests/ImageSharp.Tests/Drawing/DrawImageTests.cs
  15. 24
      tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs
  16. 1
      tests/ImageSharp.Tests/Formats/Pbm/PbmDecoderTests.cs
  17. 6
      tests/ImageSharp.Tests/Formats/Pbm/PbmEncoderTests.cs
  18. 2
      tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
  19. 64
      tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs
  20. 1
      tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
  21. 8
      tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedMemoryPoolTests.Trim.cs
  22. 45
      tests/ImageSharp.Tests/Numerics/RationalTests.cs
  23. 12
      tests/ImageSharp.Tests/TestImages.cs
  24. 4
      tests/Images/External/ReferenceOutput/DitherTests/ApplyDitherFilterInBox_Rgba32_CalliphoraPartial.png
  25. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer16x16.png
  26. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer2x2.png
  27. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer4x4.png
  28. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer8x8.png
  29. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Ordered3x3.png
  30. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer16x16.png
  31. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer2x2.png
  32. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer4x4.png
  33. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer8x8.png
  34. 4
      tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Ordered3x3.png
  35. 3
      tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/Issue2447_A.png
  36. 3
      tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/Issue2447_B.png
  37. 3
      tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/Issue2447_C.png
  38. 3
      tests/Images/External/ReferenceOutput/PbmDecoderTests/DecodeReferenceImage_L8_issue2477.png
  39. 3
      tests/Images/External/ReferenceOutput/PngEncoderTests/Issue2469_Quantized_Encode_Artifacts_Rgba32_issue_2469.png
  40. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.25.png
  41. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.5.png
  42. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.75.png
  43. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.png
  44. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_1.png
  45. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.25.png
  46. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.5.png
  47. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.75.png
  48. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.png
  49. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_1.png
  50. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.25.png
  51. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.5.png
  52. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.75.png
  53. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.png
  54. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_1.png
  55. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.25.png
  56. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.5.png
  57. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.75.png
  58. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.png
  59. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_1.png
  60. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.25.png
  61. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.5.png
  62. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.75.png
  63. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.png
  64. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_1.png
  65. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.25.png
  66. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.5.png
  67. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.75.png
  68. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.png
  69. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_1.png
  70. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.25.png
  71. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.5.png
  72. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.75.png
  73. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.png
  74. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_1.png
  75. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.25.png
  76. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.5.png
  77. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.75.png
  78. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.png
  79. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_1.png
  80. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_ErrorDither.png
  81. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_NoDither.png
  82. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_OrderedDither.png
  83. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_ErrorDither.png
  84. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_NoDither.png
  85. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_OrderedDither.png
  86. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_ErrorDither.png
  87. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_NoDither.png
  88. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_OrderedDither.png
  89. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_ErrorDither.png
  90. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_NoDither.png
  91. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_OrderedDither.png
  92. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_ErrorDither.png
  93. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_NoDither.png
  94. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_OrderedDither.png
  95. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_ErrorDither.png
  96. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_NoDither.png
  97. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png
  98. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_ErrorDither.png
  99. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_NoDither.png
  100. 4
      tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png

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

@ -668,7 +668,7 @@ internal sealed class BmpEncoderCore : IImageEncoderInternals
if (quantizedPixelRow.Length % 8 != 0)
{
int startIdx = quantizedPixelRow.Length - 7;
int startIdx = quantizedPixelRow.Length - (quantizedPixelRow.Length % 8);
endIdx = quantizedPixelRow.Length;
Write1BitPalette(stream, startIdx, endIdx, quantizedPixelRow);
}

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

@ -152,7 +152,6 @@ internal class BinaryDecoder
{
int width = pixels.Width;
int height = pixels.Height;
int startBit = 0;
MemoryAllocator allocator = configuration.MemoryAllocator;
using IMemoryOwner<L8> row = allocator.Allocate<L8>(width);
Span<L8> rowSpan = row.GetSpan();
@ -162,23 +161,12 @@ internal class BinaryDecoder
for (int x = 0; x < width;)
{
int raw = stream.ReadByte();
int bit = startBit;
startBit = 0;
for (; bit < 8; bit++)
int stopBit = Math.Min(8, width - x);
for (int bit = 0; bit < stopBit; bit++)
{
bool bitValue = (raw & (0x80 >> bit)) != 0;
rowSpan[x] = bitValue ? black : white;
x++;
if (x == width)
{
startBit = (bit + 1) & 7; // Round off to below 8.
if (startBit != 0)
{
stream.Seek(-1, System.IO.SeekOrigin.Current);
}
break;
}
}
}

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

@ -33,10 +33,14 @@ internal class BinaryEncoder
{
WriteGrayscale(configuration, stream, image);
}
else
else if (componentType == PbmComponentType.Short)
{
WriteWideGrayscale(configuration, stream, image);
}
else
{
throw new ImageFormatException("Component type not supported for Grayscale PBM.");
}
}
else if (colorType == PbmColorType.Rgb)
{
@ -44,14 +48,25 @@ internal class BinaryEncoder
{
WriteRgb(configuration, stream, image);
}
else
else if (componentType == PbmComponentType.Short)
{
WriteWideRgb(configuration, stream, image);
}
else
{
throw new ImageFormatException("Component type not supported for Color PBM.");
}
}
else
{
WriteBlackAndWhite(configuration, stream, image);
if (componentType == PbmComponentType.Bit)
{
WriteBlackAndWhite(configuration, stream, image);
}
else
{
throw new ImageFormatException("Component type not supported for Black & White PBM.");
}
}
}
@ -164,8 +179,6 @@ internal class BinaryEncoder
using IMemoryOwner<L8> row = allocator.Allocate<L8>(width);
Span<L8> rowSpan = row.GetSpan();
int previousValue = 0;
int startBit = 0;
for (int y = 0; y < height; y++)
{
Span<TPixel> pixelSpan = pixelBuffer.DangerousGetRowSpan(y);
@ -177,8 +190,9 @@ internal class BinaryEncoder
for (int x = 0; x < width;)
{
int value = previousValue;
for (int i = startBit; i < 8; i++)
int value = 0;
int stopBit = Math.Min(8, width - x);
for (int i = 0; i < stopBit; i++)
{
if (rowSpan[x].PackedValue < 128)
{
@ -186,19 +200,9 @@ internal class BinaryEncoder
}
x++;
if (x == width)
{
previousValue = value;
startBit = (i + 1) & 7; // Round off to below 8.
break;
}
}
if (startBit == 0)
{
stream.WriteByte((byte)value);
previousValue = 0;
}
stream.WriteByte((byte)value);
}
}
}

20
src/ImageSharp/Formats/Tiff/Compression/Decompressors/T6BitReader.cs

@ -125,13 +125,29 @@ internal sealed class T6BitReader : T4BitReader
if (value == Len7Code0000000.Code)
{
this.Code = Len7Code0000000;
return false;
// We do not support Extensions1D codes, but some encoders (scanner from epson) write a premature EOL code,
// which at this point cannot be distinguished from the marker, because we read the data bit by bit.
// Read the next 5 bit, if its a EOL code return true, indicating its the end of the image.
if (this.ReadValue(5) == 1)
{
return true;
}
throw new NotSupportedException("ccitt extensions 1D codes are not supported.");
}
if (value == Len7Code0000001.Code)
{
this.Code = Len7Code0000001;
return false;
// Same as above, we do not support Extensions2D codes, but it could be a EOL instead.
if (this.ReadValue(5) == 1)
{
return true;
}
throw new NotSupportedException("ccitt extensions 2D codes are not supported.");
}
if (value == Len7Code0000011.Code)

1
src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs

@ -44,6 +44,7 @@ internal static class HorizontalPredictor
UndoRgb24Bit(pixelBytes, width);
break;
case TiffColorType.Rgba8888:
case TiffColorType.Cmyk:
UndoRgba32Bit(pixelBytes, width);
break;
case TiffColorType.Rgb161616:

2
src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs

@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.PixelFormats;
/// <summary>
/// Packed pixel type containing three 16-bit unsigned normalized values ranging from 0 to 635535.
/// Packed pixel type containing three 16-bit unsigned normalized values ranging from 0 to 65535.
/// <para>
/// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form.
/// </para>

10
src/ImageSharp/Primitives/LongRational.cs

@ -131,6 +131,11 @@ internal readonly struct LongRational : IEquatable<LongRational>
/// <param name="bestPrecision">Whether to use the best possible precision when parsing the value.</param>
public static LongRational FromDouble(double value, bool bestPrecision)
{
if (value == 0.0)
{
return new LongRational(0, 1);
}
if (double.IsNaN(value))
{
return new LongRational(0, 0);
@ -201,11 +206,6 @@ internal readonly struct LongRational : IEquatable<LongRational>
return this;
}
if (this.Numerator == 0)
{
return new LongRational(0, 0);
}
if (this.Numerator == this.Denominator)
{
return new LongRational(1, 1);

162
src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs

@ -15,277 +15,277 @@ public static class DrawImageExtensions
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Image foreground,
float opacity)
{
GraphicsOptions options = source.GetGraphicsOptions();
return DrawImage(source, image, options.ColorBlendingMode, options.AlphaCompositionMode, opacity);
return DrawImage(source, foreground, options.ColorBlendingMode, options.AlphaCompositionMode, opacity);
}
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="foregroundRectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Rectangle rectangle,
Image foreground,
Rectangle foregroundRectangle,
float opacity)
{
GraphicsOptions options = source.GetGraphicsOptions();
return DrawImage(source, image, rectangle, options.ColorBlendingMode, options.AlphaCompositionMode, opacity);
return DrawImage(source, foreground, foregroundRectangle, options.ColorBlendingMode, options.AlphaCompositionMode, opacity);
}
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="colorBlending">The color blending mode.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Image foreground,
PixelColorBlendingMode colorBlending,
float opacity)
=> DrawImage(source, image, Point.Empty, colorBlending, opacity);
=> DrawImage(source, foreground, Point.Empty, colorBlending, opacity);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="foregroundRectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="colorBlending">The color blending mode.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Rectangle rectangle,
Image foreground,
Rectangle foregroundRectangle,
PixelColorBlendingMode colorBlending,
float opacity)
=> DrawImage(source, image, rectangle, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity);
=> DrawImage(source, foreground, foregroundRectangle, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="colorBlending">The color blending mode.</param>
/// <param name="alphaComposition">The alpha composition mode.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Image foreground,
PixelColorBlendingMode colorBlending,
PixelAlphaCompositionMode alphaComposition,
float opacity)
=> DrawImage(source, image, Point.Empty, colorBlending, alphaComposition, opacity);
=> DrawImage(source, foreground, Point.Empty, colorBlending, alphaComposition, opacity);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="foregroundRectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="colorBlending">The color blending mode.</param>
/// <param name="alphaComposition">The alpha composition mode.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Rectangle rectangle,
Image foreground,
Rectangle foregroundRectangle,
PixelColorBlendingMode colorBlending,
PixelAlphaCompositionMode alphaComposition,
float opacity)
=> DrawImage(source, image, Point.Empty, rectangle, colorBlending, alphaComposition, opacity);
=> DrawImage(source, foreground, Point.Empty, foregroundRectangle, colorBlending, alphaComposition, opacity);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="options">The options, including the blending type and blending amount.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Image foreground,
GraphicsOptions options)
=> DrawImage(source, image, Point.Empty, options);
=> DrawImage(source, foreground, Point.Empty, options);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="foregroundRectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="options">The options, including the blending type and blending amount.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Rectangle rectangle,
Image foreground,
Rectangle foregroundRectangle,
GraphicsOptions options)
=> DrawImage(source, image, Point.Empty, rectangle, options);
=> DrawImage(source, foreground, Point.Empty, foregroundRectangle, options);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="backgroundLocation">The location on the currently processing image at which to draw.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Point location,
Image foreground,
Point backgroundLocation,
float opacity)
{
GraphicsOptions options = source.GetGraphicsOptions();
return DrawImage(source, image, location, options.ColorBlendingMode, options.AlphaCompositionMode, opacity);
return DrawImage(source, foreground, backgroundLocation, options.ColorBlendingMode, options.AlphaCompositionMode, opacity);
}
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="backgroundLocation">The location on the currently processing image at which to draw.</param>
/// <param name="foregroundRectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Point location,
Rectangle rectangle,
Image foreground,
Point backgroundLocation,
Rectangle foregroundRectangle,
float opacity)
{
GraphicsOptions options = source.GetGraphicsOptions();
return DrawImage(source, image, location, rectangle, options.ColorBlendingMode, options.AlphaCompositionMode, opacity);
return DrawImage(source, foreground, backgroundLocation, foregroundRectangle, options.ColorBlendingMode, options.AlphaCompositionMode, opacity);
}
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="backgroundLocation">The location on the currently processing image at which to draw.</param>
/// <param name="colorBlending">The color blending to apply.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Point location,
Image foreground,
Point backgroundLocation,
PixelColorBlendingMode colorBlending,
float opacity)
=> DrawImage(source, image, location, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity);
=> DrawImage(source, foreground, backgroundLocation, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="backgroundLocation">The location on the currently processing image at which to draw.</param>
/// <param name="foregroundRectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="colorBlending">The color blending to apply.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Point location,
Rectangle rectangle,
Image foreground,
Point backgroundLocation,
Rectangle foregroundRectangle,
PixelColorBlendingMode colorBlending,
float opacity)
=> DrawImage(source, image, location, rectangle, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity);
=> DrawImage(source, foreground, backgroundLocation, foregroundRectangle, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="backgroundLocation">The location on the currently processing image at which to draw.</param>
/// <param name="options">The options containing the blend mode and opacity.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Point location,
Image foreground,
Point backgroundLocation,
GraphicsOptions options)
=> DrawImage(source, image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage);
=> DrawImage(source, foreground, backgroundLocation, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="backgroundLocation">The location on the currently processing image at which to draw.</param>
/// <param name="foregroundRectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="options">The options containing the blend mode and opacity.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Point location,
Rectangle rectangle,
Image foreground,
Point backgroundLocation,
Rectangle foregroundRectangle,
GraphicsOptions options)
=> DrawImage(source, image, location, rectangle, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage);
=> DrawImage(source, foreground, backgroundLocation, foregroundRectangle, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage);
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="backgroundLocation">The location on the currently processing image at which to draw.</param>
/// <param name="colorBlending">The color blending to apply.</param>
/// <param name="alphaComposition">The alpha composition mode.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Point location,
Image foreground,
Point backgroundLocation,
PixelColorBlendingMode colorBlending,
PixelAlphaCompositionMode alphaComposition,
float opacity)
=> source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity));
=> source.ApplyProcessor(new DrawImageProcessor(foreground, backgroundLocation, foreground.Bounds, colorBlending, alphaComposition, opacity));
/// <summary>
/// Draws the given image together with the currently processing image by blending their pixels.
/// </summary>
/// <param name="source">The current image processing context.</param>
/// <param name="image">The image to draw on the currently processing image.</param>
/// <param name="location">The location on the currenty processing image at which to draw.</param>
/// <param name="rectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="foreground">The image to draw on the currently processing image.</param>
/// <param name="backgroundLocation">The location on the currently processing image at which to draw.</param>
/// <param name="foregroundRectangle">The rectangle structure that specifies the portion of the image to draw.</param>
/// <param name="colorBlending">The color blending to apply.</param>
/// <param name="alphaComposition">The alpha composition mode.</param>
/// <param name="opacity">The opacity of the image to draw. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/>.</returns>
public static IImageProcessingContext DrawImage(
this IImageProcessingContext source,
Image image,
Point location,
Rectangle rectangle,
Image foreground,
Point backgroundLocation,
Rectangle foregroundRectangle,
PixelColorBlendingMode colorBlending,
PixelAlphaCompositionMode alphaComposition,
float opacity) =>
source.ApplyProcessor(
new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity),
rectangle);
new DrawImageProcessor(foreground, backgroundLocation, foregroundRectangle, colorBlending, alphaComposition, opacity),
foregroundRectangle);
}

59
src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs

@ -14,20 +14,41 @@ public class DrawImageProcessor : IImageProcessor
/// <summary>
/// Initializes a new instance of the <see cref="DrawImageProcessor"/> class.
/// </summary>
/// <param name="image">The image to blend.</param>
/// <param name="location">The location to draw the blended image.</param>
/// <param name="foreground">The image to blend.</param>
/// <param name="backgroundLocation">The location to draw the foreground image on the background.</param>
/// <param name="colorBlendingMode">The blending mode to use when drawing the image.</param>
/// <param name="alphaCompositionMode">The Alpha blending mode to use when drawing the image.</param>
/// <param name="opacity">The opacity of the image to blend.</param>
public DrawImageProcessor(
Image image,
Point location,
Image foreground,
Point backgroundLocation,
PixelColorBlendingMode colorBlendingMode,
PixelAlphaCompositionMode alphaCompositionMode,
float opacity)
: this(foreground, backgroundLocation, foreground.Bounds, colorBlendingMode, alphaCompositionMode, opacity)
{
this.Image = image;
this.Location = location;
}
/// <summary>
/// Initializes a new instance of the <see cref="DrawImageProcessor"/> class.
/// </summary>
/// <param name="foreground">The image to blend.</param>
/// <param name="backgroundLocation">The location to draw the foreground image on the background.</param>
/// <param name="foregroundRectangle">The rectangular portion of the foreground image to draw.</param>
/// <param name="colorBlendingMode">The blending mode to use when drawing the image.</param>
/// <param name="alphaCompositionMode">The Alpha blending mode to use when drawing the image.</param>
/// <param name="opacity">The opacity of the image to blend.</param>
public DrawImageProcessor(
Image foreground,
Point backgroundLocation,
Rectangle foregroundRectangle,
PixelColorBlendingMode colorBlendingMode,
PixelAlphaCompositionMode alphaCompositionMode,
float opacity)
{
this.ForeGround = foreground;
this.BackgroundLocation = backgroundLocation;
this.ForegroundRectangle = foregroundRectangle;
this.ColorBlendingMode = colorBlendingMode;
this.AlphaCompositionMode = alphaCompositionMode;
this.Opacity = opacity;
@ -36,12 +57,17 @@ public class DrawImageProcessor : IImageProcessor
/// <summary>
/// Gets the image to blend.
/// </summary>
public Image Image { get; }
public Image ForeGround { get; }
/// <summary>
/// Gets the location to draw the foreground image on the background.
/// </summary>
public Point BackgroundLocation { get; }
/// <summary>
/// Gets the location to draw the blended image.
/// Gets the rectangular portion of the foreground image to draw.
/// </summary>
public Point Location { get; }
public Rectangle ForegroundRectangle { get; }
/// <summary>
/// Gets the blending mode to use when drawing the image.
@ -62,8 +88,8 @@ public class DrawImageProcessor : IImageProcessor
public IImageProcessor<TPixelBg> CreatePixelSpecificProcessor<TPixelBg>(Configuration configuration, Image<TPixelBg> source, Rectangle sourceRectangle)
where TPixelBg : unmanaged, IPixel<TPixelBg>
{
ProcessorFactoryVisitor<TPixelBg> visitor = new(configuration, this, source, sourceRectangle);
this.Image.AcceptVisitor(visitor);
ProcessorFactoryVisitor<TPixelBg> visitor = new(configuration, this, source);
this.ForeGround.AcceptVisitor(visitor);
return visitor.Result!;
}
@ -73,14 +99,15 @@ public class DrawImageProcessor : IImageProcessor
private readonly Configuration configuration;
private readonly DrawImageProcessor definition;
private readonly Image<TPixelBg> source;
private readonly Rectangle sourceRectangle;
public ProcessorFactoryVisitor(Configuration configuration, DrawImageProcessor definition, Image<TPixelBg> source, Rectangle sourceRectangle)
public ProcessorFactoryVisitor(
Configuration configuration,
DrawImageProcessor definition,
Image<TPixelBg> source)
{
this.configuration = configuration;
this.definition = definition;
this.source = source;
this.sourceRectangle = sourceRectangle;
}
public IImageProcessor<TPixelBg>? Result { get; private set; }
@ -91,8 +118,8 @@ public class DrawImageProcessor : IImageProcessor
this.configuration,
image,
this.source,
this.sourceRectangle,
this.definition.Location,
this.definition.BackgroundLocation,
this.definition.ForegroundRectangle,
this.definition.ColorBlendingMode,
this.definition.AlphaCompositionMode,
this.definition.Opacity);

132
src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs

@ -21,36 +21,42 @@ internal class DrawImageProcessor<TPixelBg, TPixelFg> : ImageProcessor<TPixelBg>
/// Initializes a new instance of the <see cref="DrawImageProcessor{TPixelBg, TPixelFg}"/> class.
/// </summary>
/// <param name="configuration">The configuration which allows altering default behaviour or extending the library.</param>
/// <param name="image">The foreground <see cref="Image{TPixelFg}"/> to blend with the currently processing image.</param>
/// <param name="source">The source <see cref="Image{TPixelBg}"/> for the current processor instance.</param>
/// <param name="sourceRectangle">The source area to process for the current processor instance.</param>
/// <param name="location">The location to draw the blended image.</param>
/// <param name="foregroundImage">The foreground <see cref="Image{TPixelFg}"/> to blend with the currently processing image.</param>
/// <param name="backgroundImage">The source <see cref="Image{TPixelBg}"/> for the current processor instance.</param>
/// <param name="backgroundLocation">The location to draw the blended image.</param>
/// <param name="foregroundRectangle">The source area to process for the current processor instance.</param>
/// <param name="colorBlendingMode">The blending mode to use when drawing the image.</param>
/// <param name="alphaCompositionMode">The Alpha blending mode to use when drawing the image.</param>
/// <param name="alphaCompositionMode">The alpha blending mode to use when drawing the image.</param>
/// <param name="opacity">The opacity of the image to blend. Must be between 0 and 1.</param>
public DrawImageProcessor(
Configuration configuration,
Image<TPixelFg> image,
Image<TPixelBg> source,
Rectangle sourceRectangle,
Point location,
Image<TPixelFg> foregroundImage,
Image<TPixelBg> backgroundImage,
Point backgroundLocation,
Rectangle foregroundRectangle,
PixelColorBlendingMode colorBlendingMode,
PixelAlphaCompositionMode alphaCompositionMode,
float opacity)
: base(configuration, source, sourceRectangle)
: base(configuration, backgroundImage, backgroundImage.Bounds)
{
Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity));
this.Image = image;
this.ForegroundImage = foregroundImage;
this.ForegroundRectangle = foregroundRectangle;
this.Opacity = opacity;
this.Blender = PixelOperations<TPixelBg>.Instance.GetPixelBlender(colorBlendingMode, alphaCompositionMode);
this.Location = location;
this.BackgroundLocation = backgroundLocation;
}
/// <summary>
/// Gets the image to blend
/// </summary>
public Image<TPixelFg> Image { get; }
public Image<TPixelFg> ForegroundImage { get; }
/// <summary>
/// Gets the rectangular portion of the foreground image to draw.
/// </summary>
public Rectangle ForegroundRectangle { get; }
/// <summary>
/// Gets the opacity of the image to blend
@ -65,43 +71,57 @@ internal class DrawImageProcessor<TPixelBg, TPixelFg> : ImageProcessor<TPixelBg>
/// <summary>
/// Gets the location to draw the blended image
/// </summary>
public Point Location { get; }
public Point BackgroundLocation { get; }
/// <inheritdoc/>
protected override void OnFrameApply(ImageFrame<TPixelBg> source)
{
Rectangle sourceRectangle = this.SourceRectangle;
Configuration configuration = this.Configuration;
Image<TPixelFg> targetImage = this.Image;
PixelBlender<TPixelBg> blender = this.Blender;
int locationY = this.Location.Y;
// Align the bounds so that both the source and targets are the same width and height for blending.
// We ensure that negative locations are subtracted from both bounds so that foreground images can partially overlap.
Rectangle foregroundRectangle = this.ForegroundRectangle;
// Align start/end positions.
Rectangle bounds = targetImage.Bounds;
// Sanitize the location so that we don't try and sample outside the image.
int left = this.BackgroundLocation.X;
int top = this.BackgroundLocation.Y;
int minX = Math.Max(this.Location.X, sourceRectangle.X);
int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Right);
int targetX = minX - this.Location.X;
int minY = Math.Max(this.Location.Y, sourceRectangle.Y);
int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom);
int width = maxX - minX;
if (this.BackgroundLocation.X < 0)
{
foregroundRectangle.Width += this.BackgroundLocation.X;
left = 0;
}
Rectangle workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);
if (this.BackgroundLocation.Y < 0)
{
foregroundRectangle.Height += this.BackgroundLocation.Y;
top = 0;
}
// Not a valid operation because rectangle does not overlap with this image.
if (workingRect.Width <= 0 || workingRect.Height <= 0)
int width = foregroundRectangle.Width;
int height = foregroundRectangle.Height;
if (width <= 0 || height <= 0)
{
throw new ImageProcessingException(
"Cannot draw image because the source image does not overlap the target image.");
// Nothing to do, return.
return;
}
DrawImageProcessor<TPixelBg, TPixelFg>.RowOperation operation = new(source.PixelBuffer, targetImage.Frames.RootFrame.PixelBuffer, blender, configuration, minX, width, locationY, targetX, this.Opacity);
// Sanitize the dimensions so that we don't try and sample outside the image.
foregroundRectangle = Rectangle.Intersect(foregroundRectangle, this.ForegroundImage.Bounds);
Rectangle backgroundRectangle = Rectangle.Intersect(new(left, top, width, height), this.SourceRectangle);
Configuration configuration = this.Configuration;
DrawImageProcessor<TPixelBg, TPixelFg>.RowOperation operation =
new(
configuration,
source.PixelBuffer,
this.ForegroundImage.Frames.RootFrame.PixelBuffer,
backgroundRectangle,
foregroundRectangle,
this.Blender,
this.Opacity);
ParallelRowIterator.IterateRows(
configuration,
workingRect,
new(0, 0, foregroundRectangle.Width, foregroundRectangle.Height),
in operation);
}
@ -110,36 +130,30 @@ internal class DrawImageProcessor<TPixelBg, TPixelFg> : ImageProcessor<TPixelBg>
/// </summary>
private readonly struct RowOperation : IRowOperation
{
private readonly Buffer2D<TPixelBg> source;
private readonly Buffer2D<TPixelFg> target;
private readonly Buffer2D<TPixelBg> background;
private readonly Buffer2D<TPixelFg> foreground;
private readonly PixelBlender<TPixelBg> blender;
private readonly Configuration configuration;
private readonly int minX;
private readonly int width;
private readonly int locationY;
private readonly int targetX;
private readonly Rectangle foregroundRectangle;
private readonly Rectangle backgroundRectangle;
private readonly float opacity;
[MethodImpl(InliningOptions.ShortMethod)]
public RowOperation(
Buffer2D<TPixelBg> source,
Buffer2D<TPixelFg> target,
PixelBlender<TPixelBg> blender,
Configuration configuration,
int minX,
int width,
int locationY,
int targetX,
Buffer2D<TPixelBg> background,
Buffer2D<TPixelFg> foreground,
Rectangle backgroundRectangle,
Rectangle foregroundRectangle,
PixelBlender<TPixelBg> blender,
float opacity)
{
this.source = source;
this.target = target;
this.blender = blender;
this.configuration = configuration;
this.minX = minX;
this.width = width;
this.locationY = locationY;
this.targetX = targetX;
this.background = background;
this.foreground = foreground;
this.backgroundRectangle = backgroundRectangle;
this.foregroundRectangle = foregroundRectangle;
this.blender = blender;
this.opacity = opacity;
}
@ -147,8 +161,8 @@ internal class DrawImageProcessor<TPixelBg, TPixelFg> : ImageProcessor<TPixelBg>
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(int y)
{
Span<TPixelBg> background = this.source.DangerousGetRowSpan(y).Slice(this.minX, this.width);
Span<TPixelFg> foreground = this.target.DangerousGetRowSpan(y - this.locationY).Slice(this.targetX, this.width);
Span<TPixelBg> background = this.background.DangerousGetRowSpan(y + this.backgroundRectangle.Top).Slice(this.backgroundRectangle.Left, this.backgroundRectangle.Width);
Span<TPixelFg> foreground = this.foreground.DangerousGetRowSpan(y + this.foregroundRectangle.Top).Slice(this.foregroundRectangle.Left, this.foregroundRectangle.Width);
this.blender.Blend<TPixelFg>(this.configuration, background, background, foreground, this.opacity);
}
}

4
src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs

@ -149,13 +149,13 @@ internal sealed class EuclideanPixelMap<TPixel> : IDisposable
/// The granularity of the cache has been determined based upon the current
/// suite of test images and provides the lowest possible memory usage while
/// providing enough match accuracy.
/// Entry count is currently limited to 1185921 entries (2371842 bytes ~2.26MB).
/// Entry count is currently limited to 2335905 entries (4671810 bytes ~4.45MB).
/// </para>
/// </remarks>
private unsafe struct ColorDistanceCache : IDisposable
{
private const int IndexBits = 5;
private const int IndexAlphaBits = 5;
private const int IndexAlphaBits = 6;
private const int IndexCount = (1 << IndexBits) + 1;
private const int IndexAlphaCount = (1 << IndexAlphaBits) + 1;
private const int RgbShift = 8 - IndexBits;

2
tests/Directory.Build.targets

@ -30,7 +30,7 @@
<PackageReference Update="PhotoSauce.MagicScaler" Version="0.12.1" />
<PackageReference Update="Pfim" Version="0.9.1" />
<PackageReference Update="runtime.osx.10.10-x64.CoreCompat.System.Drawing" Version="5.8.64" Condition="'$(IsOSX)'=='true'" />
<PackageReference Update="SharpZipLib" Version="1.3.2" />
<PackageReference Update="SharpZipLib" Version="1.4.2" />
<PackageReference Update="SkiaSharp" Version="2.80.2" />
<PackageReference Update="System.Drawing.Common" Version="6.0.0" />
<PackageReference Update="System.IO.Compression" Version="4.3.0" />

20
tests/ImageSharp.Tests/Drawing/DrawImageExtensionsTests.cs

@ -13,11 +13,12 @@ public class DrawImageExtensionsTests : BaseImageOperationsExtensionTest
[Fact]
public void DrawImage_OpacityOnly_VerifyGraphicOptionsTakenFromContext()
{
// non-default values as we cant easly defect usage otherwise
// non-default values as we cant easily defect usage otherwise
this.options.AlphaCompositionMode = PixelAlphaCompositionMode.Xor;
this.options.ColorBlendingMode = PixelColorBlendingMode.Screen;
this.operations.DrawImage(null, 0.5f);
using Image<Rgba32> image = new(Configuration.Default, 1, 1);
this.operations.DrawImage(image, 0.5f);
DrawImageProcessor dip = this.Verify<DrawImageProcessor>();
Assert.Equal(0.5, dip.Opacity);
@ -28,11 +29,12 @@ public class DrawImageExtensionsTests : BaseImageOperationsExtensionTest
[Fact]
public void DrawImage_OpacityAndBlending_VerifyGraphicOptionsTakenFromContext()
{
// non-default values as we cant easly defect usage otherwise
// non-default values as we cant easily defect usage otherwise
this.options.AlphaCompositionMode = PixelAlphaCompositionMode.Xor;
this.options.ColorBlendingMode = PixelColorBlendingMode.Screen;
this.operations.DrawImage(null, PixelColorBlendingMode.Multiply, 0.5f);
using Image<Rgba32> image = new(Configuration.Default, 1, 1);
this.operations.DrawImage(image, PixelColorBlendingMode.Multiply, 0.5f);
DrawImageProcessor dip = this.Verify<DrawImageProcessor>();
Assert.Equal(0.5, dip.Opacity);
@ -43,11 +45,12 @@ public class DrawImageExtensionsTests : BaseImageOperationsExtensionTest
[Fact]
public void DrawImage_LocationAndOpacity_VerifyGraphicOptionsTakenFromContext()
{
// non-default values as we cant easly defect usage otherwise
// non-default values as we cant easily defect usage otherwise
this.options.AlphaCompositionMode = PixelAlphaCompositionMode.Xor;
this.options.ColorBlendingMode = PixelColorBlendingMode.Screen;
this.operations.DrawImage(null, Point.Empty, 0.5f);
using Image<Rgba32> image = new(Configuration.Default, 1, 1);
this.operations.DrawImage(image, Point.Empty, 0.5f);
DrawImageProcessor dip = this.Verify<DrawImageProcessor>();
Assert.Equal(0.5, dip.Opacity);
@ -58,11 +61,12 @@ public class DrawImageExtensionsTests : BaseImageOperationsExtensionTest
[Fact]
public void DrawImage_LocationAndOpacityAndBlending_VerifyGraphicOptionsTakenFromContext()
{
// non-default values as we cant easly defect usage otherwise
// non-default values as we cant easily defect usage otherwise
this.options.AlphaCompositionMode = PixelAlphaCompositionMode.Xor;
this.options.ColorBlendingMode = PixelColorBlendingMode.Screen;
this.operations.DrawImage(null, Point.Empty, PixelColorBlendingMode.Multiply, 0.5f);
using Image<Rgba32> image = new(Configuration.Default, 1, 1);
this.operations.DrawImage(image, Point.Empty, PixelColorBlendingMode.Multiply, 0.5f);
DrawImageProcessor dip = this.Verify<DrawImageProcessor>();
Assert.Equal(0.5, dip.Opacity);

67
tests/ImageSharp.Tests/Drawing/DrawImageTests.cs

@ -190,18 +190,65 @@ public class DrawImageTests
}
[Theory]
[WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, -30, -30)]
[WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, 130, -30)]
[WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, 130, 130)]
[WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, -30, 130)]
public void NonOverlappingImageThrows(TestImageProvider<Rgba32> provider, int x, int y)
[WithFile(TestImages.Png.Issue2447, PixelTypes.Rgba32)]
public void Issue2447_A<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<Rgba32> background = provider.GetImage();
using Image<Rgba32> overlay = new(Configuration.Default, 10, 10, Color.Black);
ImageProcessingException ex = Assert.Throws<ImageProcessingException>(Test);
using Image<TPixel> foreground = provider.GetImage();
using Image<Rgba32> background = new(100, 100, new Rgba32(0, 255, 255));
Assert.Contains("does not overlap", ex.ToString());
background.Mutate(c => c.DrawImage(foreground, new Point(64, 10), new Rectangle(32, 32, 32, 32), 1F));
void Test() => background.Mutate(context => context.DrawImage(overlay, new Point(x, y), new GraphicsOptions()));
background.DebugSave(
provider,
appendPixelTypeToFileName: false,
appendSourceFileOrDescription: false);
background.CompareToReferenceOutput(
provider,
appendPixelTypeToFileName: false,
appendSourceFileOrDescription: false);
}
[Theory]
[WithFile(TestImages.Png.Issue2447, PixelTypes.Rgba32)]
public void Issue2447_B<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> foreground = provider.GetImage();
using Image<Rgba32> background = new(100, 100, new Rgba32(0, 255, 255));
background.Mutate(c => c.DrawImage(foreground, new Point(10, 10), new Rectangle(320, 128, 32, 32), 1F));
background.DebugSave(
provider,
appendPixelTypeToFileName: false,
appendSourceFileOrDescription: false);
background.CompareToReferenceOutput(
provider,
appendPixelTypeToFileName: false,
appendSourceFileOrDescription: false);
}
[Theory]
[WithFile(TestImages.Png.Issue2447, PixelTypes.Rgba32)]
public void Issue2447_C<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> foreground = provider.GetImage();
using Image<Rgba32> background = new(100, 100, new Rgba32(0, 255, 255));
background.Mutate(c => c.DrawImage(foreground, new Point(10, 10), new Rectangle(32, 32, 32, 32), 1F));
background.DebugSave(
provider,
appendPixelTypeToFileName: false,
appendSourceFileOrDescription: false);
background.CompareToReferenceOutput(
provider,
appendPixelTypeToFileName: false,
appendSourceFileOrDescription: false);
}
}

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

@ -370,6 +370,30 @@ public class BmpEncoderTests
TestBmpEncoderCore(provider, bitsPerPixel);
}
[Theory]
[WithFile(BlackWhitePalletDataMatrix, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel1)]
public void Encode_Issue2467<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage();
using var reencodedStream = new MemoryStream();
var encoder = new BmpEncoder
{
BitsPerPixel = bitsPerPixel,
SupportTransparency = false,
Quantizer = KnownQuantizers.Octree
};
image.SaveAsBmp(reencodedStream, encoder);
reencodedStream.Seek(0, SeekOrigin.Begin);
using Image<TPixel> reencodedImage = Image.Load<TPixel>(reencodedStream);
reencodedImage.DebugSave(provider);
reencodedImage.CompareToOriginal(provider);
}
private static void TestBmpEncoderCore<TPixel>(
TestImageProvider<TPixel> provider,
BmpBitsPerPixel bitsPerPixel,

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

@ -81,6 +81,7 @@ public class PbmDecoderTests
[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")]

6
tests/ImageSharp.Tests/Formats/Pbm/PbmEncoderTests.cs

@ -26,6 +26,7 @@ public class PbmEncoderTests
{
{ BlackAndWhiteBinary, PbmColorType.BlackAndWhite },
{ BlackAndWhitePlain, PbmColorType.BlackAndWhite },
{ Issue2477, PbmColorType.BlackAndWhite },
{ GrayscaleBinary, PbmColorType.Grayscale },
{ GrayscaleBinaryWide, PbmColorType.Grayscale },
{ GrayscalePlain, PbmColorType.Grayscale },
@ -96,6 +97,11 @@ public class PbmEncoderTests
public void PbmEncoder_P4_Works<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> => TestPbmEncoderCore(provider, PbmColorType.BlackAndWhite, PbmEncoding.Binary);
[Theory]
[WithFile(Issue2477, PixelTypes.Rgb24)]
public void PbmEncoder_P4_Irregular_Works<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> => TestPbmEncoderCore(provider, PbmColorType.BlackAndWhite, PbmEncoding.Binary);
[Theory]
[WithFile(GrayscalePlainMagick, PixelTypes.Rgb24)]
public void PbmEncoder_P2_Works<TPixel>(TestImageProvider<TPixel> provider)

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

@ -7,6 +7,7 @@ using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Quantization;
using SixLabors.ImageSharp.Tests.TestUtilities;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs;
@ -537,7 +538,6 @@ public partial class PngDecoderTests
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage(PngDecoder.Instance);
image.DebugSave(provider);
PngMetadata metadata = image.Metadata.GetPngMetadata();
Assert.True(metadata.HasTransparency);
}

64
tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs

@ -129,8 +129,8 @@ public partial class PngEncoderTests
PngFilterMethod.Adaptive,
PngBitDepth.Bit8,
interlaceMode,
appendPixelType: true,
appendPngColorType: true);
appendPngColorType: true,
appendPixelType: true);
}
}
@ -321,7 +321,7 @@ public partial class PngEncoderTests
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage();
using var ms = new MemoryStream();
using MemoryStream ms = new();
image.Save(ms, PngEncoder);
byte[] data = ms.ToArray().Take(8).ToArray();
@ -344,13 +344,13 @@ public partial class PngEncoderTests
[MemberData(nameof(RatioFiles))]
public void Encode_PreserveRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{
var testFile = TestFile.Create(imagePath);
TestFile testFile = TestFile.Create(imagePath);
using Image<Rgba32> input = testFile.CreateRgba32Image();
using var memStream = new MemoryStream();
using MemoryStream memStream = new();
input.Save(memStream, PngEncoder);
memStream.Position = 0;
using var output = Image.Load<Rgba32>(memStream);
using Image<Rgba32> output = Image.Load<Rgba32>(memStream);
ImageMetadata meta = output.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
Assert.Equal(yResolution, meta.VerticalResolution);
@ -361,13 +361,13 @@ public partial class PngEncoderTests
[MemberData(nameof(PngBitDepthFiles))]
public void Encode_PreserveBits(string imagePath, PngBitDepth pngBitDepth)
{
var testFile = TestFile.Create(imagePath);
TestFile testFile = TestFile.Create(imagePath);
using Image<Rgba32> input = testFile.CreateRgba32Image();
using var memStream = new MemoryStream();
using MemoryStream memStream = new();
input.Save(memStream, PngEncoder);
memStream.Position = 0;
using var output = Image.Load<Rgba32>(memStream);
using Image<Rgba32> output = Image.Load<Rgba32>(memStream);
PngMetadata meta = output.Metadata.GetPngMetadata();
Assert.Equal(pngBitDepth, meta.BitDepth);
@ -380,8 +380,8 @@ public partial class PngEncoderTests
public void Encode_WithPngTransparentColorBehaviorClear_Works(PngColorType colorType)
{
// arrange
var image = new Image<Rgba32>(50, 50);
var encoder = new PngEncoder()
Image<Rgba32> image = new(50, 50);
PngEncoder encoder = new()
{
TransparentColorMode = PngTransparentColorMode.Clear,
ColorType = colorType
@ -391,7 +391,7 @@ public partial class PngEncoderTests
{
for (int y = 0; y < image.Height; y++)
{
System.Span<Rgba32> rowSpan = accessor.GetRowSpan(y);
Span<Rgba32> rowSpan = accessor.GetRowSpan(y);
// Half of the test image should be transparent.
if (y > 25)
@ -407,12 +407,12 @@ public partial class PngEncoderTests
});
// act
using var memStream = new MemoryStream();
using MemoryStream memStream = new();
image.Save(memStream, encoder);
// assert
memStream.Position = 0;
using var actual = Image.Load<Rgba32>(memStream);
using Image<Rgba32> actual = Image.Load<Rgba32>(memStream);
Rgba32 expectedColor = Color.Blue;
if (colorType is PngColorType.Grayscale or PngColorType.GrayscaleWithAlpha)
{
@ -424,7 +424,7 @@ public partial class PngEncoderTests
{
for (int y = 0; y < accessor.Height; y++)
{
System.Span<Rgba32> rowSpan = accessor.GetRowSpan(y);
Span<Rgba32> rowSpan = accessor.GetRowSpan(y);
if (y > 25)
{
@ -443,15 +443,15 @@ public partial class PngEncoderTests
[MemberData(nameof(PngTrnsFiles))]
public void Encode_PreserveTrns(string imagePath, PngBitDepth pngBitDepth, PngColorType pngColorType)
{
var testFile = TestFile.Create(imagePath);
TestFile testFile = TestFile.Create(imagePath);
using Image<Rgba32> input = testFile.CreateRgba32Image();
PngMetadata inMeta = input.Metadata.GetPngMetadata();
Assert.True(inMeta.HasTransparency);
using var memStream = new MemoryStream();
using MemoryStream memStream = new();
input.Save(memStream, PngEncoder);
memStream.Position = 0;
using var output = Image.Load<Rgba32>(memStream);
using Image<Rgba32> output = Image.Load<Rgba32>(memStream);
PngMetadata outMeta = output.Metadata.GetPngMetadata();
Assert.True(outMeta.HasTransparency);
@ -501,8 +501,8 @@ public partial class PngEncoderTests
PngFilterMethod.Adaptive,
PngBitDepth.Bit8,
interlaceMode,
appendPixelType: true,
appendPngColorType: true);
appendPngColorType: true,
appendPixelType: true);
}
}
@ -523,8 +523,8 @@ public partial class PngEncoderTests
PngFilterMethod.Adaptive,
PngBitDepth.Bit8,
interlaceMode,
appendPixelType: true,
appendPngColorType: true);
appendPngColorType: true,
appendPixelType: true);
}
}
@ -538,13 +538,27 @@ public partial class PngEncoderTests
public void EncodeFixesInvalidOptions()
{
// https://github.com/SixLabors/ImageSharp/issues/935
using var ms = new MemoryStream();
var testFile = TestFile.Create(TestImages.Png.Issue935);
using MemoryStream ms = new();
TestFile testFile = TestFile.Create(TestImages.Png.Issue935);
using Image<Rgba32> image = testFile.CreateRgba32Image(PngDecoder.Instance);
image.Save(ms, new PngEncoder { ColorType = PngColorType.RgbWithAlpha });
}
// https://github.com/SixLabors/ImageSharp/issues/2469
[Theory]
[WithFile(TestImages.Png.Issue2469, PixelTypes.Rgba32)]
public void Issue2469_Quantized_Encode_Artifacts<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage(PngDecoder.Instance);
PngEncoder encoder = new() { BitDepth = PngBitDepth.Bit8, ColorType = PngColorType.Palette };
string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "png", encoder);
using Image<Rgba32> encoded = Image.Load<Rgba32>(actualOutputFile);
encoded.CompareToReferenceOutput(ImageComparer.Exact, provider);
}
private static void TestPngEncoderCore<TPixel>(
TestImageProvider<TPixel> provider,
PngColorType pngColorType,
@ -563,7 +577,7 @@ public partial class PngEncoderTests
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage();
var encoder = new PngEncoder
PngEncoder encoder = new()
{
ColorType = pngColorType,
FilterMethod = pngFilterMethod,

1
tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs

@ -308,6 +308,7 @@ public class TiffDecoderTests : TiffDecoderBaseTester
[Theory]
[WithFile(Cmyk, PixelTypes.Rgba32)]
[WithFile(CmykLzwPredictor, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_Cmyk<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{

8
tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedMemoryPoolTests.Trim.cs

@ -113,9 +113,15 @@ public partial class UniformUnmanagedMemoryPoolTests
public static readonly bool Is32BitProcess = !Environment.Is64BitProcess;
private static readonly List<byte[]> PressureArrays = new();
[ConditionalFact(nameof(Is32BitProcess))]
[Fact]
public static void GC_Collect_OnHighLoad_TrimsEntirePool()
{
if (!Is32BitProcess)
{
// This test is only relevant for 32-bit processes.
return;
}
RemoteExecutor.Invoke(RunTest).Dispose();
static void RunTest()

45
tests/ImageSharp.Tests/Numerics/RationalTests.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Tests;
@ -14,15 +14,15 @@ public class RationalTests
[Fact]
public void AreEqual()
{
var r1 = new Rational(3, 2);
var r2 = new Rational(3, 2);
Rational r1 = new(3, 2);
Rational r2 = new(3, 2);
Assert.Equal(r1, r2);
Assert.True(r1 == r2);
var r3 = new Rational(7.55);
var r4 = new Rational(755, 100);
var r5 = new Rational(151, 20);
Rational r3 = new(7.55);
Rational r4 = new(755, 100);
Rational r5 = new(151, 20);
Assert.Equal(r3, r4);
Assert.Equal(r4, r5);
@ -34,20 +34,39 @@ public class RationalTests
[Fact]
public void AreNotEqual()
{
var first = new Rational(0, 100);
var second = new Rational(100, 100);
Rational first = new(0, 100);
Rational second = new(100, 100);
Assert.NotEqual(first, second);
Assert.True(first != second);
}
/// <summary>
/// Tests known out-of-range values.
/// </summary>
/// <param name="value">The input value.</param>
/// <param name="numerator">The expected numerator.</param>
/// <param name="denominator">The expected denominator.</param>
[Theory]
[InlineData(0, 0, 1)]
[InlineData(double.NaN, 0, 0)]
[InlineData(double.PositiveInfinity, 1, 0)]
[InlineData(double.NegativeInfinity, 1, 0)]
public void FromDoubleOutOfRange(double value, uint numerator, uint denominator)
{
Rational r = Rational.FromDouble(value);
Assert.Equal(numerator, r.Numerator);
Assert.Equal(denominator, r.Denominator);
}
/// <summary>
/// Tests whether the Rational constructor correctly assign properties.
/// </summary>
[Fact]
public void ConstructorAssignsProperties()
{
var rational = new Rational(7, 55);
Rational rational = new(7, 55);
Assert.Equal(7U, rational.Numerator);
Assert.Equal(55U, rational.Denominator);
@ -71,15 +90,15 @@ public class RationalTests
[Fact]
public void Fraction()
{
var first = new Rational(1.0 / 1600);
var second = new Rational(1.0 / 1600, true);
Rational first = new(1.0 / 1600);
Rational second = new(1.0 / 1600, true);
Assert.False(first.Equals(second));
}
[Fact]
public void ToDouble()
{
var rational = new Rational(0, 0);
Rational rational = new(0, 0);
Assert.Equal(double.NaN, rational.ToDouble());
rational = new Rational(2, 0);
@ -89,7 +108,7 @@ public class RationalTests
[Fact]
public void ToStringRepresentation()
{
var rational = new Rational(0, 0);
Rational rational = new(0, 0);
Assert.Equal("[ Indeterminate ]", rational.ToString());
rational = new Rational(double.PositiveInfinity);

12
tests/ImageSharp.Tests/TestImages.cs

@ -129,9 +129,15 @@ public static class TestImages
// Issue 2209: https://github.com/SixLabors/ImageSharp/issues/2209
public const string Issue2209IndexedWithTransparency = "Png/issues/Issue_2209.png";
// Issue 2259: https://github.com/SixLabors/ImageSharp/issues/2259
// Issue 2259: https://github.com/SixLabors/ImageSharp/issues/2469
public const string Issue2259 = "Png/issues/Issue_2259.png";
// Issue 2259: https://github.com/SixLabors/ImageSharp/issues/2469
public const string Issue2469 = "Png/issues/issue_2469.png";
// Issue 2447: https://github.com/SixLabors/ImageSharp/issues/2447
public const string Issue2447 = "Png/issues/issue_2447.png";
public static class Bad
{
public const string MissingDataChunk = "Png/xdtn0g01.png";
@ -407,6 +413,8 @@ public static class TestImages
public const string Rgba321010102 = "Bmp/rgba32-1010102.bmp";
public const string RgbaAlphaBitfields = "Bmp/rgba32abf.bmp";
public const string BlackWhitePalletDataMatrix = "Bmp/bit1datamatrix.bmp";
public static readonly string[] BitFields =
{
Rgb32bfdef,
@ -958,6 +966,7 @@ public static class TestImages
public const string Cmyk = "Tiff/Cmyk.tiff";
public const string Cmyk64BitDeflate = "Tiff/cmyk_deflate_64bit.tiff";
public const string CmykLzwPredictor = "Tiff/Cmyk-lzw-predictor.tiff";
public const string Issues1716Rgb161616BitLittleEndian = "Tiff/Issues/Issue1716.tiff";
public const string Issues1891 = "Tiff/Issues/Issue1891.tiff";
@ -1029,6 +1038,7 @@ public static class TestImages
public const string RgbPlain = "Pbm/rgb_plain.ppm";
public const string RgbPlainNormalized = "Pbm/rgb_plain_normalized.ppm";
public const string RgbPlainMagick = "Pbm/rgb_plain_magick.ppm";
public const string Issue2477 = "Pbm/issue2477.pbm";
}
public static class Qoi

4
tests/Images/External/ReferenceOutput/DitherTests/ApplyDitherFilterInBox_Rgba32_CalliphoraPartial.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4d88eb2e50ca9dbed0e8dfe4ad278cd88ddb9d3408b30d9dfe59102b167f570b
size 262887
oid sha256:98115a7087aced0c28cefa32a57bc72be245886cabeefc4ff7faf7984236218c
size 271226

4
tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer16x16.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:97cfbef27319988b67aeac87d469d044edd925c90e4774170465f51eed85c16a
size 42915
oid sha256:58c03e354b108033873e2a4c0b043ce15919c4d0630e6ca72ff70b89cbedb979
size 44239

4
tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer2x2.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3a799b69938507e3fd2a74ffa7c6c6ad6574acb25861a0a50cb8361520d468de
size 41809
oid sha256:f987f4d270568facefc11eee7f81dd156af56c26b69fe3a6d2d2e9818652befa
size 43116

4
tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer4x4.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9932db58eeb966cd293b1b7a375e9c1b17b6d09153c679ebf03d42a08d2ce9b3
size 43332
oid sha256:ebdad83936e50bbb00fd74b7dd7d2f5a480bb7347aa3d151e7827107cd279bac
size 44441

4
tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer8x8.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:67ebf42bc82483d1778254d95a376230437611dce91c80f8ecda608de56bffe7
size 43108
oid sha256:ccdf5937c30999e3b09071200de2e1db63b606ad9cbf6f7677a7499fb0b52963
size 44252

4
tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Ordered3x3.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8d5cdda990ac146a7580f58cc2bcab72f903dde564a394de7df4cc37e6dcf2dd
size 43906
oid sha256:baf70b732646d7c6cec60cfbe569ec673418dfb2dd0b5937bccfb91d9821d586
size 45053

4
tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer16x16.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c11e6c197bd1c227ae8f4af7e8c232cfe75db6929ab12bddf5e6554fbaed3f01
size 50716
oid sha256:f6a1eae610ed730e4cec41693829929ba8db674886c2bd558f1b8893d2b76802
size 51201

4
tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer2x2.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:69ff9654eb61f2bfdd44fb25aff959c5b831015e283cc91a90e3abf6f681dc88
size 52429
oid sha256:ba674e0236c2e146c64a7f3e224c702030769304cd0fd624d1989536da341659
size 52814

4
tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer4x4.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6ee945ac5120e4198d1f94e6467cc0f77c90869bf5a09942e7720dddcfdfbe07
size 51262
oid sha256:316231c8d837f864cf62dcc79fdce698dc8c45c0327372de42c2b89eac1d9f81
size 51851

4
tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer8x8.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1b023505175ae39a93fa55c85aa31466f0aca76fab0ee54f9667648b91f9aeb9
size 50789
oid sha256:b58144146585f50960dfd6ac5dc3f52238160287ae5f9b18c6796962cc3d2fd2
size 51550

4
tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Ordered3x3.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6b18e8b80035a3c5985ebedab5eaf1b0e580d26dd2a8167e687e7b3dd6536751
size 51922
oid sha256:6515be764d7026a87cfeea2d58344c404e4f15908139a25f413d51cc7cc61a0c
size 52216

3
tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/Issue2447_A.png

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

3
tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/Issue2447_B.png

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

3
tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/Issue2447_C.png

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

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

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

3
tests/Images/External/ReferenceOutput/PngEncoderTests/Issue2469_Quantized_Encode_Artifacts_Rgba32_issue_2469.png

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

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.25.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:97805a6a6de3cf1e97026a4913afa573f7ec40f82e718dd9c5e4df69482a6e19
size 13097
oid sha256:033bb9e0ce89ffe4abda4d409af5741958d4035f9c9824c28d7598d72c4db96f
size 13818

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.5.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3c7d3da0ced1c66c6351d530565a190cfc1fdb7f3b7b05d39844f61fb87871ad
size 13758
oid sha256:9c6617ebf10f2fe1608fbc2a3c75f1a86ff4e3835b5d3fd7fcc2e5d0a4e5bbb1
size 14380

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.75.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2a6bb9a04f0663eb8a95d6d46c72557078de35ac935499d5ec4ab591d7f59eb9
size 13940
oid sha256:5bb52f047f410e2b0bdcd8d186043f0d3b03835f39007775608fb05365ac9a20
size 14616

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:97805a6a6de3cf1e97026a4913afa573f7ec40f82e718dd9c5e4df69482a6e19
size 13097
oid sha256:033bb9e0ce89ffe4abda4d409af5741958d4035f9c9824c28d7598d72c4db96f
size 13818

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_1.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f0facae77f6022c92cdaaa7f27efb424962933c0e86ec4e8a7d62237a0f58d03
size 13919
oid sha256:47e0924ddbf191dca8932eb46b9c533d0983b9fbce956026b392d5fe589fb90a
size 14630

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.25.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ec99338895bdada5cabe504afdcb0c0c95d8951e4404d31615a406b9956995c0
size 14154
oid sha256:4ede7ffc5d07a09c7c5706e8e2554897d29acaabf71701191b0f689f2c22ae71
size 17826

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.5.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9699207803467b8718a719c7581e1ed6bf0c923a5adaf325aea8358d274fece5
size 18334
oid sha256:f91c7f1f687c73dd909b629e40f703740270042507c47aa3834ccd38bf289dc3
size 19394

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.75.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0e3acfa5b7c6ef3bec68b5fa8db91b2e6160e01d1f952a055831cea2f0a58b0f
size 18675
oid sha256:2b836ab4e0f1c95fe5d553bf5bca37eac402ba431268d25e4641e86c952f5fdd
size 19802

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:97805a6a6de3cf1e97026a4913afa573f7ec40f82e718dd9c5e4df69482a6e19
size 13097
oid sha256:033bb9e0ce89ffe4abda4d409af5741958d4035f9c9824c28d7598d72c4db96f
size 13818

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_1.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fc1c1b5d0d0abec9b52ae7a83946a46020d2394a5f49f42e2ddb50fac988e974
size 18874
oid sha256:00bcd2ac107f45cb31efee44de275dd597eae6d2d4fda71c397416ff5f2f0914
size 20175

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.25.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2eac7954110e82c7c9cb1c0d3734467b7e46745ea19b2fd10d0af7df0aad552c
size 9007
oid sha256:b04b71b0a4718e5b3f91c33c23ef792fc81a67c9fef7b9e4d80bdb9dce3539dd
size 9107

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.5.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:51b06fc436e322ff9fc9e367b8117eb1178e112eb90fbd41a87847ab64a24136
size 8801
oid sha256:e0125454d2c3859d8457202856e21591ab96f61e2a29c3f017af29bf03961c48
size 8883

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.75.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e46c5f17ef76f11ca1dfe70dd4b38858de049832c26add1e9f987f87319a3491
size 11029
oid sha256:213ebd9fc7a190ad7226b487387edb9452284193cee4c4720448d7e19ef38e76
size 11149

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3527a0577720e7e8abf36b534540e72d17854d7b3b7d70cf3cdb519318e9e3c8
size 7702
oid sha256:43b21e948795abb52ebbbf94e785542e55488cc7f17996e2b92404ca8ad1a7cb
size 7844

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_1.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e73014c6698526f3341e1f6001938bf5c60501bd6114451903a654c43c5f1997
size 11719
oid sha256:0bb8f730a43a8f58e4269905014461bab8dc8b47387ec86a84c1064b1cdabe14
size 11813

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.25.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:420d8ff32aa8ffa789e0c5dd00151856a016bc4f83ad035fdb4a8a22c338e247
size 8952
oid sha256:7500be583beb22759dec7e5bbb2a8d2230054366bfbd0e39bf10fdc8af63eb58
size 8925

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.5.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:93f3be15cb660c7c74c0de12d459c390c5f3c950d09dc4bcf617f5093e2b818b
size 8606
oid sha256:c48da7aad9c0aad576293d7085f9ddb2ea90a76d53bea54cbe0cb7aef71c7bb4
size 9136

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.75.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a035a0b97ac471500a9dbead47a0d13deb449136980b89795b671b3e14481c9e
size 9716
oid sha256:72e6c327e98d9929a4d850905b1471fcd1191088feb38b028e4240e9f93b4996
size 9827

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3527a0577720e7e8abf36b534540e72d17854d7b3b7d70cf3cdb519318e9e3c8
size 7702
oid sha256:43b21e948795abb52ebbbf94e785542e55488cc7f17996e2b92404ca8ad1a7cb
size 7844

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_1.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fac9fc2316ccf7a464e93d0406acdf37d5aac7f76f54c87454fa41b13c8224fc
size 9731
oid sha256:70f8fc84d6e578822582ebee5888514dcd70c8d0da1a920f35e63a1617d1e92c
size 9841

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.25.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c738cea16a714bdfa54cfcc213102d53ebe3aee576390902d352f04be65edac2
size 11166
oid sha256:ff4d6e3a7c8e69db0d5a88b7f1c91621692962bdbcedd6b8af1311506243bcde
size 11259

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.5.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:42b44354480a1d2c869f541e6f3ed9feec15fb04ad32eb2a21b7d65290eeec54
size 11972
oid sha256:520910b75cae834b9844ce896ad9ab6d0b6c33c44c7bd822ce63752aaa2a8c5a
size 12122

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.75.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d7d62b46acff22858a1621656ddaa97c3610a7f13df9c5d77747b7364620b174
size 12772
oid sha256:8e1fb4bb5d1591ac6bb8a4fb2504e2e836578c9c42d8286061cf4f57f0b7f97d
size 12876

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9e532758291dd3d18b5b81c1d788db7854b322a633557f3ee273bb9d68c465ba
size 9582
oid sha256:3f5babf5f6ae746a9b9f131ecf990f037c8e8bdb257bdbb7f6127460c9b8f98d
size 10507

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_1.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:581febc9878288785ae82b23f2946dc0c506ae86fba32bb02ba5e69cf1c8cda1
size 14069
oid sha256:56a9088fdca14b82fa3ac3ecfb67b6b8e97e8d69b89907c8408e17861e8609e0
size 14195

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.25.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:12f7bacf0402f821e3c80f65c29218bc1f1334392edc463b617cf711667db722
size 12381
oid sha256:7d4ef129d8846e6802997c0ace90abdc7412d232e9a31fc53f25bb9f32de08f2
size 12665

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.5.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:436d168a3501da20c327cb3d2909cdd465585ee3f76a2534e37a36771e10115e
size 12596
oid sha256:69b5771a313aa777341d1460db94a7b3cc74b69c44f6c9d1a1b5b3734936e795
size 12791

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.75.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c952f81377c83b2255c427d0911b898e500d163d870de778b69778a9ab8c8278
size 12459
oid sha256:a56f72c5a12e6d216a32404c996e72721b4cf350d82071a43ebe44190adef94a
size 12895

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9e532758291dd3d18b5b81c1d788db7854b322a633557f3ee273bb9d68c465ba
size 9582
oid sha256:3f5babf5f6ae746a9b9f131ecf990f037c8e8bdb257bdbb7f6127460c9b8f98d
size 10507

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_1.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2b542c86ea4fef3a37e89c1087dddafeeccf523e7c0721743f34d35da5e0653e
size 13116
oid sha256:39f85cb564a257381656fd969acaeda04016e09380133f772eb029e332aeaa95
size 13482

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.25.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:147b7ebbe92f2379d513a44214a8383ed96a94b92f9d80cb3c5944e5e32e94bc
size 13097
oid sha256:9d528ea896a2e56e0b8967d5ce3486078cbd7bf29e5f0d43a58ef21100147915
size 13818

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.5.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5b55add6cd3dc0e130f399a6932ba279aa29dc72579ee575df88e0faf76a3835
size 13073
oid sha256:4e96967a2a6362f42026ab2e2cdd82437e573c16a52c5631f7495cb30615441d
size 13841

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.75.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ed5c1745e2ef33654023ed0a8bfabe5a75d46186aa5c42df54ac1a9506dcf632
size 13431
oid sha256:d5f9e9e4f7f48681d5b240d6df6ae282c6b9e896eacc1ad73f2a097975fa8d29
size 14060

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:147b7ebbe92f2379d513a44214a8383ed96a94b92f9d80cb3c5944e5e32e94bc
size 13097
oid sha256:9d528ea896a2e56e0b8967d5ce3486078cbd7bf29e5f0d43a58ef21100147915
size 13818

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_1.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:945c33feb2f3408b54e4574781eee3c2868885af25acd9172d420360e505b54a
size 13463
oid sha256:97d6923c3342d600a9a2ab3fa713136b2649b74364d6e90a905de607838e0cb7
size 14319

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.25.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3edb6672168fc58a2bb6766d48a0883aa35fdc6873d2f4b9f26d3b5fa6cb46dd
size 15574
oid sha256:66399a4ba262bdacdc5966fa9fc6f8f6bfa3f8c70db889363e9bbd5778dc1ecf
size 16081

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.5.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9fd79ec840f8bd82b41d93987187531187a4bd957d7f0d497a86fa61de52cec7
size 16733
oid sha256:5953a12a2fa67f9fe17485c62d156bb7f80a4bcf4124c123db4440c2559e0e69
size 17002

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.75.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:360121a75c96434daa57f2b996e9776cc1efdf25aa3f7e926abd6d04c9ee4184
size 17355
oid sha256:efc08c6969344de404692c2b367130e3f736442c0722067a9105f036a9e4511e
size 17616

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:147b7ebbe92f2379d513a44214a8383ed96a94b92f9d80cb3c5944e5e32e94bc
size 13097
oid sha256:9d528ea896a2e56e0b8967d5ce3486078cbd7bf29e5f0d43a58ef21100147915
size 13818

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_1.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:97d3b5d804c50da0d9c5db7278b16bb807e246dbd083c8c62ec7d4d7a65a1b45
size 18070
oid sha256:455488369cd943f3c3a0b2c402dbb17d6fc9c384b5f26dbc049634ad4bdab73f
size 18259

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_ErrorDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7f7ce90fb4dec4b890eb8bfd182e009b2769104ab2f14e926381c4949d6f7453
size 82121
oid sha256:2a65ffa4c6b8488f52892306052337e17a4e58d28fa43f18009e6d1f997962de
size 83060

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_NoDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2430b92bc20b2c3d142b5f84ae9fd62856fc4c717b0b226c2e096d725883d41f
size 54154
oid sha256:1f69909cdc4b65548834e30caf44a31b7e5d41be1db05cb43bd8277613f327ed
size 55263

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_OrderedDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4cd9433cdab37510cf6d98ce5838a69675359982376f7ef5c9e716c49772af74
size 79370
oid sha256:ff7d35f1ce04d8f2b6cee41c951487bd24e18f923dc84c77a7944ec3aab61540
size 80844

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_ErrorDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d74faa8d188a2915739de64ba9d71b2132b53c8d154db22510c524ae757578a5
size 61183
oid sha256:48ac9eea396e010b1c110413a6861b1708f3928243271ea78f390e64dfe11737
size 62249

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_NoDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a5ad9cb26866b35f6ad8c0ae054c7172a15b2fb2512bd123af3c0e5685c30410
size 32766
oid sha256:a4786eb2c04be00302996f3ad65987f54fe5d80ded438fdcccf7b9bfe9520dbb
size 33930

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_OrderedDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:67ebf42bc82483d1778254d95a376230437611dce91c80f8ecda608de56bffe7
size 43108
oid sha256:ccdf5937c30999e3b09071200de2e1db63b606ad9cbf6f7677a7499fb0b52963
size 44252

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_ErrorDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b5271fba5dcee48982ccad321f987a67d6663dabc01d380eb0cafc178251bc00
size 33971
oid sha256:898c8524d6fcad8498a22dd97956265302458d43f8d3f93846c2268d7b47fb73
size 35351

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_NoDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1ba613bc2cf88dfb357e88671464272ab4279667b8c776b8b9db913161b7f450
size 33060
oid sha256:5f37abc44b703b6feac3a2a950df7f40a8a67fe64fa25c19af59862e5272f0ff
size 34311

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_OrderedDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:242379eee61c3d82f10e8b36db0567749443f91a6e13e766cc1ee3a3eeff7e2c
size 43006
oid sha256:1cb4518f6b9e1ed1409b0f4e87c17ae990cff2725c650d69941cc76ba90b2f7b
size 44672

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_ErrorDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fe72f6268d445f204afcea4723624398ff49e479e8b608843cf287dfb94ebe4e
size 101257
oid sha256:16a592718ba5aa15f79ef4864cba75fae5a7cc5e13ca56eeab5fd13a0e5347de
size 102049

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_NoDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c29c21979beeb7f659979893d05d1da15602a8fbc4a61309cd6380b296d69367
size 83563
oid sha256:86ebb09209d4bfbe266c633df1c7062755cd413f47d0a96a05bcf003a02cb12b
size 84428

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_OrderedDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:49e072dc73ba96dffa021b3e9bbf169102bd9ae7b9d4ed0a69b55178f1592ae5
size 97415
oid sha256:779521e132b4ee6b3ac7a9186fca3250c6d2ace7e55f4f6c9601fe5393d9eb10
size 99561

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_ErrorDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8c6041ecc220ee8cd576aff06871bc1f3b7363dffe334bbab83344c5b96cbde3
size 94511
oid sha256:a6d0b12e19b980fd558a4920ec18620a9bdb00bd1379a20719ff0ee92c6887a1
size 96007

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_NoDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:912de82dc98a8dd72ffc5549125c397379a859a23ffe48f01e4f1c5a28ff1d18
size 77029
oid sha256:82c34b115c081a1f3723540b9a273724353930c53006dd6daea576a227271e01
size 78599

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_OrderedDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bedb363c412c4c387fabe4d65ca769079376f4cc56a3bfdd767f0ae8441b3dfb
size 92003
oid sha256:6fbe71277a196e5c57fba7caba5c0a1b2bff2da9eadbd7bab1ae1853fab2dd93
size 92581

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_ErrorDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d4a64da29f144d4d4c525ea45e56819e02a46030ae09542be01fdd8ffc85a295
size 60377
oid sha256:b1061a363744661febdd051ef2f6839bfe288eb83f7ebf281fb06717fbe6703a
size 60739

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_NoDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:eee438f7cbe6615bab0df73689f6924ea153da28eaf1f4c0c22076f24f18085d
size 46476
oid sha256:cacd80b681c086310d3be7d90575da357e6ab0a62e24227a1e7e3ae4cab1de2d
size 46905

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1b023505175ae39a93fa55c85aa31466f0aca76fab0ee54f9667648b91f9aeb9
size 50789
oid sha256:b58144146585f50960dfd6ac5dc3f52238160287ae5f9b18c6796962cc3d2fd2
size 51550

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_ErrorDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c175f0db79d3ac74043dce3fe57d5c15c6ca38c954c008baf5fa917d3b9d4e0e
size 67374
oid sha256:d54a2b762a16c76ad52919708d0126ae63958e9d900e3870cced695540e16192
size 68366

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_NoDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7c76f0df12da8eac1fefb6ba9c0c89f5c8a7bcfbff442a4ebd763f1a4b359637
size 63046
oid sha256:87450152fdccfaebb55e22040206cb246bc59b61461fd8b6ca6e099256fa0f1d
size 63839

4
tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f2636953295972ede173dbfaf3b67f7cb91f1c3f4ccc79f70e078bd94af9422d
size 68579
oid sha256:7136f92f3fd1927e98204b1140ca36a901dcd9b67c17f7080413588c2e2dcc28
size 69579

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save