diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/ComponentUtils.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/ComponentUtils.cs
index a051df809d..d513401864 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/ComponentUtils.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/ComponentUtils.cs
@@ -1,11 +1,7 @@
-using System.Collections.Generic;
-using System.Linq;
-using SixLabors.Primitives;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
+namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
{
///
- /// Various utilities for and .
+ /// Various utilities for .
///
internal static class ComponentUtils
{
@@ -13,105 +9,5 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
{
return ref component.SpectralBlocks[bx, by];
}
-
- public static SubsampleRatio GetSubsampleRatio(int horizontalRatio, int verticalRatio)
- {
- switch ((horizontalRatio << 4) | verticalRatio)
- {
- case 0x11:
- return SubsampleRatio.Ratio444;
- case 0x12:
- return SubsampleRatio.Ratio440;
- case 0x21:
- return SubsampleRatio.Ratio422;
- case 0x22:
- return SubsampleRatio.Ratio420;
- case 0x41:
- return SubsampleRatio.Ratio411;
- case 0x42:
- return SubsampleRatio.Ratio410;
- }
-
- return SubsampleRatio.Ratio444;
- }
-
- // https://en.wikipedia.org/wiki/Chroma_subsampling
- public static SubsampleRatio GetSubsampleRatio(IEnumerable components)
- {
- IJpegComponent[] componentArray = components.ToArray();
- if (componentArray.Length == 3)
- {
- Size s0 = componentArray[0].SamplingFactors;
- Size ratio = s0.DivideBy(componentArray[1].SamplingFactors);
-
- return GetSubsampleRatio(ratio.Width, ratio.Height);
- }
- else
- {
- return SubsampleRatio.Undefined;
- }
- }
-
- ///
- /// Returns the height and width of the chroma components
- /// TODO: Not needed by new JpegImagePostprocessor
- ///
- /// The subsampling ratio.
- /// The width.
- /// The height.
- /// The of the chrominance channel
- public static Size CalculateChrominanceSize(this SubsampleRatio ratio, int width, int height)
- {
- (int divX, int divY) = ratio.GetChrominanceSubSampling();
- var size = new Size(width, height);
- return size.DivideRoundUp(divX, divY);
- }
-
-
-
- // TODO: Not needed by new JpegImagePostprocessor
- public static (int divX, int divY) GetChrominanceSubSampling(this SubsampleRatio ratio)
- {
- switch (ratio)
- {
- case SubsampleRatio.Ratio422: return (2, 1);
- case SubsampleRatio.Ratio420: return (2, 2);
- case SubsampleRatio.Ratio440: return (1, 2);
- case SubsampleRatio.Ratio411: return (4, 1);
- case SubsampleRatio.Ratio410: return (4, 2);
- default: return (1, 1);
- }
- }
-
- public static bool IsChromaComponent(this IJpegComponent component) =>
- component.Index > 0 && component.Index < 3;
-
- // TODO: Not needed by new JpegImagePostprocessor
- public static Size[] CalculateJpegChannelSizes(IEnumerable components, SubsampleRatio ratio)
- {
- IJpegComponent[] c = components.ToArray();
- Size[] sizes = new Size[c.Length];
-
- Size s0 = c[0].SizeInBlocks * 8;
- sizes[0] = s0;
-
- if (c.Length > 1)
- {
- Size chromaSize = ratio.CalculateChrominanceSize(s0.Width, s0.Height);
- sizes[1] = chromaSize;
-
- if (c.Length > 2)
- {
- sizes[2] = chromaSize;
- }
- }
-
- if (c.Length > 3)
- {
- sizes[3] = s0;
- }
-
- return sizes;
- }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/IRawJpegData.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/IRawJpegData.cs
index 0e4f953f3d..3873656a4e 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/IRawJpegData.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/IRawJpegData.cs
@@ -1,13 +1,15 @@
+using System;
using System.Collections.Generic;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
{
+ ///
///
- /// Represents decompressed, unprocessed jpeg data with spectral space -s.
+ /// Represents decompressed, unprocessed jpeg data with spectral space -s.
///
- internal interface IRawJpegData
+ internal interface IRawJpegData : IDisposable
{
///
/// Gets the image size in pixels.
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegBlockPostProcessor.cs
similarity index 72%
rename from src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockPostProcessor.cs
rename to src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegBlockPostProcessor.cs
index 29149a186c..4c47017530 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockPostProcessor.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegBlockPostProcessor.cs
@@ -1,14 +1,11 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.Formats.Jpeg.Common;
-using SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder;
using SixLabors.ImageSharp.Memory;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
+namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
{
///
/// Encapsulates the implementation of processing "raw" -s into Jpeg image channels.
@@ -36,22 +33,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
postProcessor->pointers = new DataPointers(&postProcessor->data);
}
- ///
- /// Dequantize, perform the inverse DCT and store the blocks to the into the corresponding instances.
- ///
- /// The instance
- /// The component
- public void ProcessAllBlocks(OrigJpegDecoderCore decoder, IJpegComponent component)
- {
- for (int by = 0; by < component.SizeInBlocks.Height; by++)
- {
- for (int bx = 0; bx < component.SizeInBlocks.Width; bx++)
- {
- this.ProcessBlockColors(decoder, component, bx, by);
- }
- }
- }
-
public void QuantizeAndTransform(IRawJpegData decoder, IJpegComponent component, ref Block8x8 sourceBlock)
{
this.data.SourceBlock = sourceBlock.AsFloatBlock();
@@ -84,25 +65,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
this.data.WorkspaceBlock1.CopyTo(destArea, divs.Width, divs.Height);
}
- ///
- /// Dequantize, perform the inverse DCT and store decodedBlock.Block to the into the corresponding instance.
- ///
- /// The
- /// The
- /// The x index of the block in
- /// The y index of the block in
- private void ProcessBlockColors(OrigJpegDecoderCore decoder, IJpegComponent component, int bx, int by)
- {
- ref Block8x8 sourceBlock = ref component.GetBlockReference(bx, @by);
-
- this.QuantizeAndTransform(decoder, component, ref sourceBlock);
-
- OrigJpegPixelArea destChannel = decoder.GetDestinationChannel(component.Index);
- OrigJpegPixelArea destArea = destChannel.GetOffsetedSubAreaForBlock(bx, by);
- destArea.LoadColorsFrom(this.pointers.WorkspaceBlock1, this.pointers.WorkspaceBlock2);
- }
-
-
///
/// Holds the "large" data blocks needed for computations.
///
@@ -140,7 +102,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// The
public static ComputationData Create()
{
- ComputationData data = default(ComputationData);
+ var data = default(ComputationData);
data.Unzig = UnzigData.Create();
return data;
}
diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegImagePostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegImagePostProcessor.cs
index ae1180a52f..2b583bdbb5 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegImagePostProcessor.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegImagePostProcessor.cs
@@ -8,7 +8,7 @@ using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
{
///
- /// Encapsulates the execution post-processing algorithms to be applied on a to produce a valid :
+ /// Encapsulates the execution od post-processing algorithms to be applied on a to produce a valid :
/// (1) Dequantization
/// (2) IDCT
/// (3) Color conversion form one of the -s into a buffer of RGBA values
diff --git a/src/ImageSharp/Formats/Jpeg/Common/SubsampleRatio.cs b/src/ImageSharp/Formats/Jpeg/Common/SubsampleRatio.cs
deleted file mode 100644
index 235c2352a3..0000000000
--- a/src/ImageSharp/Formats/Jpeg/Common/SubsampleRatio.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-namespace SixLabors.ImageSharp.Formats.Jpeg.Common
-{
- ///
- /// Provides enumeration of the various available subsample ratios.
- /// https://en.wikipedia.org/wiki/Chroma_subsampling
- /// TODO: Not needed by new JpegImagePostprocessor
- ///
- internal enum SubsampleRatio
- {
- Undefined,
-
- ///
- /// 4:4:4
- ///
- Ratio444,
-
- ///
- /// 4:2:2
- ///
- Ratio422,
-
- ///
- /// 4:2:0
- ///
- Ratio420,
-
- ///
- /// 4:4:0
- ///
- Ratio440,
-
- ///
- /// 4:1:1
- ///
- Ratio411,
-
- ///
- /// 4:1:0
- ///
- Ratio410,
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegPixelArea.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegPixelArea.cs
deleted file mode 100644
index 91b9b3a101..0000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegPixelArea.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.Memory;
-using Block8x8F = SixLabors.ImageSharp.Formats.Jpeg.Common.Block8x8F;
-using SixLabors.ImageSharp.Formats.Jpeg.Common;
-using SixLabors.Primitives;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// Represents an area of a Jpeg subimage (channel)
- ///
- internal struct OrigJpegPixelArea
- {
- ///
- /// Initializes a new instance of the struct from existing data.
- ///
- /// The pixel buffer
- /// The stride
- /// The offset
- public OrigJpegPixelArea(Buffer2D pixels, int stride, int offset)
- {
- this.Stride = stride;
- this.Pixels = pixels;
- this.Offset = offset;
- }
-
- ///
- /// Initializes a new instance of the struct from existing buffer.
- /// will be set to of and will be set to 0.
- ///
- /// The pixel buffer
- public OrigJpegPixelArea(Buffer2D pixels)
- : this(pixels, pixels.Width, 0)
- {
- }
-
- public OrigJpegPixelArea(Size size)
- : this(Buffer2D.CreateClean(size))
- {
- }
-
- ///
- /// Gets the pixels buffer.
- ///
- public Buffer2D Pixels { get; private set; }
-
- ///
- /// Gets a value indicating whether the instance has been initalized. (Is not default(JpegPixelArea))
- ///
- public bool IsInitialized => this.Pixels != null;
-
- ///
- /// Gets the stride.
- ///
- public int Stride { get; }
-
- ///
- /// Gets the offset.
- ///
- public int Offset { get; }
-
- ///
- /// Gets a of bytes to the pixel area
- ///
- public Span Span => new Span(this.Pixels.Array, this.Offset);
-
- ///
- /// Returns the pixel at (x, y)
- ///
- /// The x index
- /// The y index
- /// The pixel value
- public byte this[int x, int y]
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- return this.Pixels[(y * this.Stride) + x];
- }
- }
-
- ///
- /// Gets the subarea that belongs to the Block8x8 defined by block indices
- ///
- /// The block X index
- /// The block Y index
- /// The subarea offseted by block indices
- public OrigJpegPixelArea GetOffsetedSubAreaForBlock(int bx, int by)
- {
- int offset = this.Offset + (8 * ((by * this.Stride) + bx));
- return new OrigJpegPixelArea(this.Pixels, this.Stride, offset);
- }
-
- ///
- /// Gets the row offset at the given position
- ///
- /// The y-coordinate of the image.
- /// The
- public int GetRowOffset(int y)
- {
- return this.Offset + (y * this.Stride);
- }
-
- ///
- /// Load values to the pixel area from the given .
- /// Level shift [-128.0, 128.0] floating point color values by +128, clip them to [0, 255], and convert them to
- /// values
- ///
- /// The block holding the color values
- /// Temporal block provided by the caller
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe void LoadColorsFrom(Block8x8F* block, Block8x8F* temp)
- {
- // Level shift by +128, clip to [0, 255], and write to dst.
- block->CopyColorsTo(new Span(this.Pixels.Array, this.Offset), this.Stride, temp);
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/YCbCrImage.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/YCbCrImage.cs
deleted file mode 100644
index c56d2d3417..0000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/YCbCrImage.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using SixLabors.ImageSharp.Memory;
-using SixLabors.Primitives;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- using SixLabors.ImageSharp.Formats.Jpeg.Common;
- using SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder;
-
- ///
- /// Represents an image made up of three color components (luminance, blue chroma, red chroma)
- ///
- internal class YCbCrImage : IDisposable
- {
- // Complex value type field + mutable + available to other classes = the field MUST NOT be private :P
-#pragma warning disable SA1401 // FieldsMustBePrivate
- ///
- /// Gets the luminance components channel as .
- ///
- public Buffer2D YChannel;
-
- ///
- /// Gets the blue chroma components channel as .
- ///
- public Buffer2D CbChannel;
-
- ///
- /// Gets an offseted to the Cr channel
- ///
- public Buffer2D CrChannel;
-#pragma warning restore SA1401
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The width.
- /// The height.
- /// The ratio.
- public YCbCrImage(int width, int height, SubsampleRatio ratio)
- {
- Size cSize = ratio.CalculateChrominanceSize(width, height);
-
- this.Ratio = ratio;
- this.YStride = width;
- this.CStride = cSize.Width;
-
- this.YChannel = Buffer2D.CreateClean(width, height);
- this.CbChannel = Buffer2D.CreateClean(cSize.Width, cSize.Height);
- this.CrChannel = Buffer2D.CreateClean(cSize.Width, cSize.Height);
- }
-
- ///
- /// Gets the Y slice index delta between vertically adjacent pixels.
- ///
- public int YStride { get; }
-
- ///
- /// Gets the red and blue chroma slice index delta between vertically adjacent pixels
- /// that map to separate chroma samples.
- ///
- public int CStride { get; }
-
- ///
- /// Gets or sets the subsampling ratio.
- ///
- public SubsampleRatio Ratio { get; set; }
-
- ///
- /// Disposes the returning rented arrays to the pools.
- ///
- public void Dispose()
- {
- this.YChannel.Dispose();
- this.CbChannel.Dispose();
- this.CrChannel.Dispose();
- }
-
- ///
- /// Returns the offset of the first chroma component at the given row
- ///
- /// The row number.
- ///
- /// The .
- ///
- public int GetRowCOffset(int y)
- {
- switch (this.Ratio)
- {
- case SubsampleRatio.Ratio422:
- return y * this.CStride;
- case SubsampleRatio.Ratio420:
- return (y / 2) * this.CStride;
- case SubsampleRatio.Ratio440:
- return (y / 2) * this.CStride;
- case SubsampleRatio.Ratio411:
- return y * this.CStride;
- case SubsampleRatio.Ratio410:
- return (y / 2) * this.CStride;
- default:
- return y * this.CStride;
- }
- }
-
- ///
- /// Returns the offset of the first luminance component at the given row
- ///
- /// The row number.
- ///
- /// The .
- ///
- public int GetRowYOffset(int y)
- {
- return y * this.YStride;
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/YCbCrToRgbTables.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/YCbCrToRgbTables.cs
deleted file mode 100644
index fe0cd6fc08..0000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/YCbCrToRgbTables.cs
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.PixelFormats;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// Provides 8-bit lookup tables for converting from YCbCr to Rgb colorspace.
- /// Methods to build the tables are based on libjpeg implementation.
- ///
- internal unsafe struct YCbCrToRgbTables
- {
- ///
- /// The red red-chrominance table
- ///
- public fixed int CrRTable[256];
-
- ///
- /// The blue blue-chrominance table
- ///
- public fixed int CbBTable[256];
-
- ///
- /// The green red-chrominance table
- ///
- public fixed int CrGTable[256];
-
- ///
- /// The green blue-chrominance table
- ///
- public fixed int CbGTable[256];
-
- // Speediest right-shift on some machines and gives us enough accuracy at 4 decimal places.
- private const int ScaleBits = 16;
-
- private const int Half = 1 << (ScaleBits - 1);
-
- ///
- /// Initializes the YCbCr tables
- ///
- /// The intialized
- public static YCbCrToRgbTables Create()
- {
- YCbCrToRgbTables tables = default(YCbCrToRgbTables);
-
- for (int i = 0, x = -128; i <= 255; i++, x++)
- {
- // i is the actual input pixel value, in the range 0..255
- // The Cb or Cr value we are thinking of is x = i - 128
- // Cr=>R value is nearest int to 1.402 * x
- tables.CrRTable[i] = RightShift((Fix(1.402F) * x) + Half);
-
- // Cb=>B value is nearest int to 1.772 * x
- tables.CbBTable[i] = RightShift((Fix(1.772F) * x) + Half);
-
- // Cr=>G value is scaled-up -0.714136286
- tables.CrGTable[i] = (-Fix(0.714136286F)) * x;
-
- // Cb => G value is scaled - up - 0.344136286 * x
- // We also add in Half so that need not do it in inner loop
- tables.CbGTable[i] = ((-Fix(0.344136286F)) * x) + Half;
- }
-
- return tables;
- }
-
- ///
- /// Optimized method to pack bytes to the image from the YCbCr color space.
- ///
- /// The pixel format.
- /// The packed pixel.
- /// The reference to the tables instance.
- /// The y luminance component.
- /// The cb chroma component.
- /// The cr chroma component.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void Pack(ref TPixel packed, YCbCrToRgbTables* tables, byte y, byte cb, byte cr)
- where TPixel : struct, IPixel
- {
- // float r = MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero);
- byte r = (byte)(y + tables->CrRTable[cr]).Clamp(0, 255);
-
- // float g = MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero);
- // The values for the G calculation are left scaled up, since we must add them together before rounding.
- byte g = (byte)(y + RightShift(tables->CbGTable[cb] + tables->CrGTable[cr])).Clamp(0, 255);
-
- // float b = MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero);
- byte b = (byte)(y + tables->CbBTable[cb]).Clamp(0, 255);
-
- packed.PackFromRgba32(new Rgba32(r, g, b, 255));
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int Fix(float x)
- {
- return (int)((x * (1L << ScaleBits)) + 0.5F);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int RightShift(int x)
- {
- return x >> ScaleBits;
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
index e8e8fe06e5..d37ec91490 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
@@ -4,8 +4,6 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Runtime.CompilerServices;
-using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats.Jpeg.Common;
using SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder;
@@ -18,10 +16,11 @@ using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
{
+ ///
///
/// Performs the jpeg decoding operation.
///
- internal sealed unsafe class OrigJpegDecoderCore : IDisposable, IRawJpegData
+ internal sealed unsafe class OrigJpegDecoderCore : IRawJpegData
{
///
/// The maximum number of color components
@@ -43,11 +42,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
public InputProcessor InputProcessor;
#pragma warning restore SA401
- ///
- /// Lookup tables for converting YCbCr to Rgb
- ///
- private static YCbCrToRgbTables yCbCrToRgbTables = YCbCrToRgbTables.Create();
-
///
/// The global configuration
///
@@ -63,16 +57,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
///
private bool adobeTransformValid;
- ///
- /// The black image to decode to.
- ///
- private OrigJpegPixelArea blackImage;
-
- ///
- /// A grayscale image to decode to.
- ///
- private OrigJpegPixelArea grayImage;
-
///
/// The horizontal resolution. Calculated if the image has a JFIF header.
///
@@ -93,11 +77,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
///
private short verticalResolution;
- ///
- /// The full color image to decode to.
- ///
- private YCbCrImage ycbcrImage;
-
///
/// Initializes a new instance of the class.
///
@@ -112,11 +91,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
this.Temp = new byte[2 * Block8x8F.Size];
}
- ///
- /// Gets the ratio.
- ///
- public SubsampleRatio SubsampleRatio { get; private set; }
-
+ ///
public JpegColorSpace ColorSpace { get; private set; }
///
@@ -138,13 +113,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
///
public byte[] Temp { get; }
+ ///
public Size ImageSizeInPixels { get; private set; }
- public Size ImageSizeInMCU { get; private set; }
-
///
- /// Gets the number of color components within the image.
+ /// Gets the number of MCU blocks in the image as .
///
+ public Size ImageSizeInMCU { get; private set; }
+
+ ///
public int ComponentCount { get; private set; }
IEnumerable IRawJpegData.Components => this.Components;
@@ -192,7 +169,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
///
/// Gets a value indicating whether the metadata should be ignored when the image is being decoded.
///
- public bool IgnoreMetadata { get; private set; }
+ public bool IgnoreMetadata { get; }
///
/// Gets the decoded by this decoder instance.
@@ -211,15 +188,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
{
this.ParseStream(stream);
-#if OLDCODE
- this.ProcessBlocksIntoJpegImageChannels();
-
- return this.ConvertJpegPixelsToImagePixels();
-#else
return this.PostProcessIntoImage();
-#endif
}
-
+
///
public void Dispose()
{
@@ -236,39 +207,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
}
}
- this.ycbcrImage?.Dispose();
this.InputProcessor.Dispose();
- this.grayImage.Pixels?.Dispose();
- this.blackImage.Pixels?.Dispose();
- }
-
- ///
- /// Gets the representing the channel at a given component index
- ///
- /// The component index
- /// The of the channel
- public OrigJpegPixelArea GetDestinationChannel(int compIndex)
- {
- if (this.ComponentCount == 1)
- {
- return this.grayImage;
- }
- else
- {
- switch (compIndex)
- {
- case 0:
- return new OrigJpegPixelArea(this.ycbcrImage.YChannel);
- case 1:
- return new OrigJpegPixelArea(this.ycbcrImage.CbChannel);
- case 2:
- return new OrigJpegPixelArea(this.ycbcrImage.CrChannel);
- case 3:
- return this.blackImage;
- default:
- throw new ImageFormatException("Too many components");
- }
- }
}
///
@@ -452,6 +391,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
break;
}
}
+
+ this.InitDerivedMetaDataProperties();
}
///
@@ -471,297 +412,30 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
}
///
- /// Process the blocks in into Jpeg image channels ( and )
- /// are in a "raw" frequency-domain form. We need to apply IDCT, dequantization and unzigging to transform them into color-space blocks.
- /// We can copy these blocks into -s afterwards.
- ///
- private void ProcessBlocksIntoJpegImageChannels()
- {
- this.InitJpegImageChannels();
-
- Parallel.For(
- 0,
- this.ComponentCount,
- componentIndex =>
- {
- var postProcessor = default(JpegBlockPostProcessor);
- JpegBlockPostProcessor.Init(&postProcessor);
- IJpegComponent component = this.Components[componentIndex];
- postProcessor.ProcessAllBlocks(this, component);
- });
- }
-
- ///
- /// Convert the pixel data in and/or into pixels of
+ /// Assigns derived metadata properties to , eg. horizontal and vertical resolution if it has a JFIF header.
///
- /// The pixel type
- /// The decoded image.
- private Image ConvertJpegPixelsToImagePixels()
- where TPixel : struct, IPixel
- {
- var image = new Image(this.configuration, this.ImageWidth, this.ImageHeight, this.MetaData);
-
- if (this.grayImage.IsInitialized)
- {
- this.ConvertFromGrayScale(image);
- return image;
- }
- else if (this.ycbcrImage != null)
- {
- if (this.ComponentCount == 4)
- {
- if (!this.adobeTransformValid)
- {
- throw new ImageFormatException(
- "Unknown color model: 4-component JPEG doesn't have Adobe APP14 metadata");
- }
-
- // See http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe
- // See https://docs.oracle.com/javase/8/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html
- // TODO: YCbCrA?
- if (this.adobeTransform == OrigJpegConstants.Adobe.ColorTransformYcck)
- {
- this.ConvertFromYcck(image);
- }
- else if (this.adobeTransform == OrigJpegConstants.Adobe.ColorTransformUnknown)
- {
- // Assume CMYK
- this.ConvertFromCmyk(image);
- }
-
- return image;
- }
-
- if (this.ComponentCount == 3)
- {
- if (this.IsRGB())
- {
- this.ConvertFromRGB(image);
- return image;
- }
-
- this.ConvertFromYCbCr(image);
- return image;
- }
-
- throw new ImageFormatException("JpegDecoder only supports RGB, CMYK and Grayscale color spaces.");
- }
- else
- {
- throw new ImageFormatException("Missing SOS marker.");
- }
- }
-
- ///
- /// Assigns the horizontal and vertical resolution to the image if it has a JFIF header.
- ///
- /// The pixel format.
- /// The image to assign the resolution to.
- private void AssignResolution(Image image)
- where TPixel : struct, IPixel
+ private void InitDerivedMetaDataProperties()
{
if (this.isJfif && this.horizontalResolution > 0 && this.verticalResolution > 0)
{
- image.MetaData.HorizontalResolution = this.horizontalResolution;
- image.MetaData.VerticalResolution = this.verticalResolution;
+ this.MetaData.HorizontalResolution = this.horizontalResolution;
+ this.MetaData.VerticalResolution = this.verticalResolution;
}
else if (this.isExif)
{
- ExifValue horizontal = image.MetaData.ExifProfile.GetValue(ExifTag.XResolution);
- ExifValue vertical = image.MetaData.ExifProfile.GetValue(ExifTag.YResolution);
+ ExifValue horizontal = this.MetaData.ExifProfile.GetValue(ExifTag.XResolution);
+ ExifValue vertical = this.MetaData.ExifProfile.GetValue(ExifTag.YResolution);
double horizontalValue = horizontal != null ? ((Rational)horizontal.Value).ToDouble() : 0;
double verticalValue = vertical != null ? ((Rational)vertical.Value).ToDouble() : 0;
if (horizontalValue > 0 && verticalValue > 0)
{
- image.MetaData.HorizontalResolution = horizontalValue;
- image.MetaData.VerticalResolution = verticalValue;
+ this.MetaData.HorizontalResolution = horizontalValue;
+ this.MetaData.VerticalResolution = verticalValue;
}
}
}
- ///
- /// Converts the image from the original CMYK image pixels.
- ///
- /// The pixel format.
- /// The image.
- private void ConvertFromCmyk(Image image)
- where TPixel : struct, IPixel
- {
- int scale = this.Components[0].HorizontalSamplingFactor / this.Components[1].HorizontalSamplingFactor;
-
- using (PixelAccessor pixels = image.Lock())
- {
- Parallel.For(
- 0,
- image.Height,
- y =>
- {
- // TODO: Simplify + optimize + share duplicate code across converter methods
- int yo = this.ycbcrImage.GetRowYOffset(y);
- int co = this.ycbcrImage.GetRowCOffset(y);
-
- for (int x = 0; x < image.Width; x++)
- {
- byte cyan = this.ycbcrImage.YChannel[yo + x];
- byte magenta = this.ycbcrImage.CbChannel[co + (x / scale)];
- byte yellow = this.ycbcrImage.CrChannel[co + (x / scale)];
-
- TPixel packed = default(TPixel);
- this.PackCmyk(ref packed, cyan, magenta, yellow, x, y);
- pixels[x, y] = packed;
- }
- });
- }
-
- this.AssignResolution(image);
- }
-
- ///
- /// Converts the image from the original grayscale image pixels.
- ///
- /// The pixel format.
- /// The image.
- private void ConvertFromGrayScale(Image image)
- where TPixel : struct, IPixel
- {
- Parallel.For(
- 0,
- image.Height,
- image.Configuration.ParallelOptions,
- y =>
- {
- ref TPixel pixelRowBaseRef = ref image.GetPixelReference(0, y);
-
- int yoff = this.grayImage.GetRowOffset(y);
-
- for (int x = 0; x < image.Width; x++)
- {
- byte rgb = this.grayImage.Pixels[yoff + x];
- ref TPixel pixel = ref Unsafe.Add(ref pixelRowBaseRef, x);
- pixel.PackFromRgba32(new Rgba32(rgb, rgb, rgb, 255));
- }
- });
-
- this.AssignResolution(image);
- }
-
- ///
- /// Converts the image from the original RBG image pixels.
- ///
- /// The pixel format.
- /// The image.
- private void ConvertFromRGB(Image image)
- where TPixel : struct, IPixel
- {
- int scale = this.Components[0].HorizontalSamplingFactor / this.Components[1].HorizontalSamplingFactor;
-
- Parallel.For(
- 0,
- image.Height,
- image.Configuration.ParallelOptions,
- y =>
- {
- // TODO: Simplify + optimize + share duplicate code across converter methods
- int yo = this.ycbcrImage.GetRowYOffset(y);
- int co = this.ycbcrImage.GetRowCOffset(y);
- ref TPixel pixelRowBaseRef = ref image.GetPixelReference(0, y);
-
- Rgba32 rgba = new Rgba32(0, 0, 0, 255);
-
- for (int x = 0; x < image.Width; x++)
- {
- rgba.R = this.ycbcrImage.YChannel[yo + x];
- rgba.G = this.ycbcrImage.CbChannel[co + (x / scale)];
- rgba.B = this.ycbcrImage.CrChannel[co + (x / scale)];
-
- ref TPixel pixel = ref Unsafe.Add(ref pixelRowBaseRef, x);
- pixel.PackFromRgba32(rgba);
- }
- });
-
- this.AssignResolution(image);
- }
-
- ///
- /// Converts the image from the original YCbCr image pixels.
- ///
- /// The pixel format.
- /// The image.
- private void ConvertFromYCbCr(Image image)
- where TPixel : struct, IPixel
- {
- int scale = this.Components[0].HorizontalSamplingFactor / this.Components[1].HorizontalSamplingFactor;
- using (PixelAccessor pixels = image.Lock())
- {
- Parallel.For(
- 0,
- image.Height,
- image.Configuration.ParallelOptions,
- y =>
- {
- // TODO. This Parallel loop doesn't give us the boost it should.
- ref byte ycRef = ref this.ycbcrImage.YChannel[0];
- ref byte cbRef = ref this.ycbcrImage.CbChannel[0];
- ref byte crRef = ref this.ycbcrImage.CrChannel[0];
- fixed (YCbCrToRgbTables* tables = &yCbCrToRgbTables)
- {
- // TODO: Simplify + optimize + share duplicate code across converter methods
- int yo = this.ycbcrImage.GetRowYOffset(y);
- int co = this.ycbcrImage.GetRowCOffset(y);
-
- for (int x = 0; x < image.Width; x++)
- {
- int cOff = co + (x / scale);
- byte yy = Unsafe.Add(ref ycRef, yo + x);
- byte cb = Unsafe.Add(ref cbRef, cOff);
- byte cr = Unsafe.Add(ref crRef, cOff);
-
- TPixel packed = default(TPixel);
- YCbCrToRgbTables.Pack(ref packed, tables, yy, cb, cr);
- pixels[x, y] = packed;
- }
- }
- });
- }
-
- this.AssignResolution(image);
- }
-
- ///
- /// Converts the image from the original YCCK image pixels.
- ///
- /// The pixel format.
- /// The image.
- private void ConvertFromYcck(Image image)
- where TPixel : struct, IPixel
- {
- int scale = this.Components[0].HorizontalSamplingFactor / this.Components[1].HorizontalSamplingFactor;
-
- Parallel.For(
- 0,
- image.Height,
- y =>
- {
- // TODO: Simplify + optimize + share duplicate code across converter methods
- int yo = this.ycbcrImage.GetRowYOffset(y);
- int co = this.ycbcrImage.GetRowCOffset(y);
- ref TPixel pixelRowBaseRef = ref image.GetPixelReference(0, y);
-
- for (int x = 0; x < image.Width; x++)
- {
- byte yy = this.ycbcrImage.YChannel[yo + x];
- byte cb = this.ycbcrImage.CbChannel[co + (x / scale)];
- byte cr = this.ycbcrImage.CrChannel[co + (x / scale)];
-
- ref TPixel pixel = ref Unsafe.Add(ref pixelRowBaseRef, x);
- this.PackYcck(ref pixel, yy, cb, cr, x, y);
- }
- });
-
- this.AssignResolution(image);
- }
-
///
/// Returns a value indicating whether the image in an RGB image.
///
@@ -786,99 +460,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
&& this.Components[2].Identifier == 'B';
}
- ///
- /// Initializes the image channels.
- ///
- private void InitJpegImageChannels()
- {
- Size[] sizes = ComponentUtils.CalculateJpegChannelSizes(this.Components, this.SubsampleRatio);
-
- if (this.ComponentCount == 1)
- {
- this.grayImage = new OrigJpegPixelArea(sizes[0]);
- }
- else
- {
- Size size = sizes[0];
-
- this.ycbcrImage = new YCbCrImage(size.Width, size.Height, this.SubsampleRatio);
-
- if (this.ComponentCount == 4)
- {
- this.blackImage = new OrigJpegPixelArea(sizes[3]);
- }
- }
- }
-
- ///
- /// Optimized method to pack bytes to the image from the CMYK color space.
- /// This is faster than implicit casting as it avoids double packing.
- ///
- /// The pixel format.
- /// The packed pixel.
- /// The cyan component.
- /// The magenta component.
- /// The yellow component.
- /// The x-position within the image.
- /// The y-position within the image.
- private void PackCmyk(ref TPixel packed, byte c, byte m, byte y, int xx, int yy)
- where TPixel : struct, IPixel
- {
- // Get keyline
- float keyline = (255 - this.blackImage[xx, yy]) / 255F;
-
- // Convert back to RGB. CMY are not inverted
- byte r = (byte)(((c / 255F) * (1F - keyline)).Clamp(0, 1) * 255);
- byte g = (byte)(((m / 255F) * (1F - keyline)).Clamp(0, 1) * 255);
- byte b = (byte)(((y / 255F) * (1F - keyline)).Clamp(0, 1) * 255);
-
- packed.PackFromRgba32(new Rgba32(r, g, b));
- }
-
- ///
- /// Optimized method to pack bytes to the image from the YCCK color space.
- /// This is faster than implicit casting as it avoids double packing.
- ///
- /// The pixel format.
- /// The packed pixel.
- /// The y luminance component.
- /// The cb chroma component.
- /// The cr chroma component.
- /// The x-position within the image.
- /// The y-position within the image.
- private void PackYcck(ref TPixel packed, byte y, byte cb, byte cr, int xx, int yy)
- where TPixel : struct, IPixel
- {
- // Convert the YCbCr part of the YCbCrK to RGB, invert the RGB to get
- // CMY, and patch in the original K. The RGB to CMY inversion cancels
- // out the 'Adobe inversion' described in the applyBlack doc comment
- // above, so in practice, only the fourth channel (black) is inverted.
- int ccb = cb - 128;
- int ccr = cr - 128;
-
- // Speed up the algorithm by removing floating point calculation
- // Scale by 65536, add .5F and truncate value. We use bit shifting to divide the result
- int r0 = 91881 * ccr; // (1.402F * 65536) + .5F
- int g0 = 22554 * ccb; // (0.34414F * 65536) + .5F
- int g1 = 46802 * ccr; // (0.71414F * 65536) + .5F
- int b0 = 116130 * ccb; // (1.772F * 65536) + .5F
-
- // First convert from YCbCr to CMY
- float cyan = (y + (r0 >> 16)).Clamp(0, 255) / 255F;
- float magenta = (byte)(y - (g0 >> 16) - (g1 >> 16)).Clamp(0, 255) / 255F;
- float yellow = (byte)(y + (b0 >> 16)).Clamp(0, 255) / 255F;
-
- // Get keyline
- float keyline = (255 - this.blackImage[xx, yy]) / 255F;
-
- // Convert back to RGB
- byte r = (byte)(((1 - cyan) * (1 - keyline)).Clamp(0, 1) * 255);
- byte g = (byte)(((1 - magenta) * (1 - keyline)).Clamp(0, 1) * 255);
- byte b = (byte)(((1 - yellow) * (1 - keyline)).Clamp(0, 1) * 255);
-
- packed.PackFromRgba32(new Rgba32(r, g, b));
- }
-
///
/// Processes the "Adobe" APP14 segment stores image encoding information for DCT filters.
/// This segment may be copied or deleted as a block using the Extra "Adobe" tag, but note that it is not
@@ -913,7 +494,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
/// Processes the App1 marker retrieving any stored metadata
///
/// The remaining bytes in the segment block.
- /// The image.
private void ProcessApp1Marker(int remaining)
{
if (remaining < 6 || this.IgnoreMetadata)
@@ -1193,8 +773,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
}
this.ColorSpace = this.DeduceJpegColorSpace();
-
- this.SubsampleRatio = ComponentUtils.GetSubsampleRatio(this.Components);
}
private JpegColorSpace DeduceJpegColorSpace()
diff --git a/src/ImageSharp/Memory/BufferArea.cs b/src/ImageSharp/Memory/BufferArea.cs
index 67dddd77cc..0e14d1eacf 100644
--- a/src/ImageSharp/Memory/BufferArea.cs
+++ b/src/ImageSharp/Memory/BufferArea.cs
@@ -18,8 +18,8 @@ namespace SixLabors.ImageSharp.Memory
{
Guard.MustBeGreaterThanOrEqualTo(rectangle.X, 0, nameof(rectangle));
Guard.MustBeGreaterThanOrEqualTo(rectangle.Y, 0, nameof(rectangle));
- Guard.MustBeLessThan(rectangle.Width, destinationBuffer.Width, nameof(rectangle));
- Guard.MustBeLessThan(rectangle.Height, destinationBuffer.Height, nameof(rectangle));
+ Guard.MustBeLessThanOrEqualTo(rectangle.Width, destinationBuffer.Width, nameof(rectangle));
+ Guard.MustBeLessThanOrEqualTo(rectangle.Height, destinationBuffer.Height, nameof(rectangle));
this.DestinationBuffer = destinationBuffer;
this.Rectangle = rectangle;
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ComponentUtilsTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/ComponentUtilsTests.cs
deleted file mode 100644
index c5f3dcc73f..0000000000
--- a/tests/ImageSharp.Tests/Formats/Jpg/ComponentUtilsTests.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-// ReSharper disable InconsistentNaming
-
-using SixLabors.ImageSharp.Formats.Jpeg.Common;
-using SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder;
-using SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder;
-using SixLabors.Primitives;
-
-using Xunit;
-using Xunit.Abstractions;
-
-namespace SixLabors.ImageSharp.Tests.Formats.Jpg
-{
- public class ComponentUtilsTests
- {
- public ComponentUtilsTests(ITestOutputHelper output)
- {
- this.Output = output;
- }
-
- private ITestOutputHelper Output { get; }
-
- [Theory]
- [InlineData(SubsampleRatio.Ratio410, 4, 2)]
- [InlineData(SubsampleRatio.Ratio411, 4, 1)]
- [InlineData(SubsampleRatio.Ratio420, 2, 2)]
- [InlineData(SubsampleRatio.Ratio422, 2, 1)]
- [InlineData(SubsampleRatio.Ratio440, 1, 2)]
- [InlineData(SubsampleRatio.Ratio444, 1, 1)]
- internal void CalculateChrominanceSize(SubsampleRatio ratio, int expectedDivX, int expectedDivY)
- {
- //this.Output.WriteLine($"RATIO: {ratio}");
- Size size = ratio.CalculateChrominanceSize(400, 400);
- //this.Output.WriteLine($"Ch Size: {size}");
-
- Assert.Equal(new Size(400 / expectedDivX, 400 / expectedDivY), size);
- }
-
- [Theory]
- [InlineData(SubsampleRatio.Ratio410, 4, 2)]
- [InlineData(SubsampleRatio.Ratio411, 4, 1)]
- [InlineData(SubsampleRatio.Ratio420, 2, 2)]
- [InlineData(SubsampleRatio.Ratio422, 2, 1)]
- [InlineData(SubsampleRatio.Ratio440, 1, 2)]
- [InlineData(SubsampleRatio.Ratio444, 1, 1)]
- [InlineData(SubsampleRatio.Undefined, 1, 1)]
- internal void GetChrominanceSubSampling(SubsampleRatio ratio, int expectedDivX, int expectedDivY)
- {
- (int divX, int divY) = ratio.GetChrominanceSubSampling();
-
- Assert.Equal(expectedDivX, divX);
- Assert.Equal(expectedDivY, divY);
- }
-
- [Theory]
- [InlineData(SubsampleRatio.Ratio410, 4)]
- [InlineData(SubsampleRatio.Ratio411, 4)]
- [InlineData(SubsampleRatio.Ratio420, 2)]
- [InlineData(SubsampleRatio.Ratio422, 2)]
- [InlineData(SubsampleRatio.Ratio440, 1)]
- [InlineData(SubsampleRatio.Ratio444, 1)]
- internal void Create(SubsampleRatio ratio, int expectedCStrideDiv)
- {
- this.Output.WriteLine($"RATIO: {ratio}");
-
- YCbCrImage img = new YCbCrImage(400, 400, ratio);
-
- //this.PrintChannel("Y", img.YChannel);
- //this.PrintChannel("Cb", img.CbChannel);
- //this.PrintChannel("Cr", img.CrChannel);
-
- Assert.Equal(400, img.YChannel.Width);
- Assert.Equal(img.CbChannel.Width, 400 / expectedCStrideDiv);
- Assert.Equal(img.CrChannel.Width, 400 / expectedCStrideDiv);
- }
-
- private void PrintChannel(string name, OrigJpegPixelArea channel)
- {
- this.Output.WriteLine($"{name}: Stride={channel.Stride}");
- }
- }
-}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/Exceptions/ImagePixelsAreDifferentException.cs b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/Exceptions/ImageDifferenceIsOverThresholdException.cs
similarity index 74%
rename from tests/ImageSharp.Tests/TestUtilities/ImageComparison/Exceptions/ImagePixelsAreDifferentException.cs
rename to tests/ImageSharp.Tests/TestUtilities/ImageComparison/Exceptions/ImageDifferenceIsOverThresholdException.cs
index 56bf6e90b2..e5f031b504 100644
--- a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/Exceptions/ImagePixelsAreDifferentException.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/Exceptions/ImageDifferenceIsOverThresholdException.cs
@@ -5,12 +5,12 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
using System.Linq;
using System.Text;
- public class ImagePixelsAreDifferentException : ImagesSimilarityException
+ public class ImageDifferenceIsOverThresholdException : ImagesSimilarityException
{
public ImageSimilarityReport[] Reports { get; }
- public ImagePixelsAreDifferentException(IEnumerable reports)
- : base("Images are not similar enough!" + StringifyReports(reports))
+ public ImageDifferenceIsOverThresholdException(IEnumerable reports)
+ : base("Image difference is over threshold!" + StringifyReports(reports))
{
this.Reports = reports.ToArray();
}
diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs
index 74f46a869a..4fabd60761 100644
--- a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs
@@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
IEnumerable reports = comparer.CompareImages(expected, actual);
if (reports.Any())
{
- throw new ImagePixelsAreDifferentException(reports);
+ throw new ImageDifferenceIsOverThresholdException(reports);
}
}
@@ -119,7 +119,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
if (cleanedReports.Any())
{
- throw new ImagePixelsAreDifferentException(cleanedReports);
+ throw new ImageDifferenceIsOverThresholdException(cleanedReports);
}
}
}
diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/ImageComparerTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/ImageComparerTests.cs
index 29acabdc4f..f131f51f21 100644
--- a/tests/ImageSharp.Tests/TestUtilities/Tests/ImageComparerTests.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/Tests/ImageComparerTests.cs
@@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.Tests
var comparer = ImageComparer.Tolerant();
- ImagePixelsAreDifferentException ex = Assert.ThrowsAny(
+ ImageDifferenceIsOverThresholdException ex = Assert.ThrowsAny(
() =>
{
comparer.VerifySimilarity(image, clone);
diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageExtensionsTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageExtensionsTests.cs
index 34300c56e3..45ac2d6cca 100644
--- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageExtensionsTests.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageExtensionsTests.cs
@@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Tests
{
ImagingTestCaseUtility.ModifyPixel(image, 3, 1, 1);
- Assert.ThrowsAny(
+ Assert.ThrowsAny(
() =>
{
image.CompareToOriginal(provider, ImageComparer.Exact);