Browse Source

Merge remote-tracking branch 'refs/remotes/origin/master' into feature/icc

# Conflicts:
#	src/ImageSharp/Colors/ColorspaceTransforms.cs
#	src/ImageSharp/Colors/Spaces/CieLab.cs
#	src/ImageSharp/Colors/Spaces/Cmyk.cs
#	src/ImageSharp/Colors/Spaces/Hsl.cs
#	src/ImageSharp/Colors/Spaces/Hsv.cs
af/merge-core
James Jackson-South 9 years ago
parent
commit
b7a94b9be3
  1. 2
      src/ImageSharp.Drawing/Brushes/ImageBrush{TColor}.cs
  2. 8
      src/ImageSharp.Drawing/Paths/RectangleExtensions.cs
  3. 2
      src/ImageSharp.Drawing/Pens/Pen{TColor}.cs
  4. 4
      src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs
  5. 28
      src/ImageSharp/Colors/PackedPixel/Bgr565.cs
  6. 20
      src/ImageSharp/Colors/PackedPixel/NormalizedShort2.cs
  7. 36
      src/ImageSharp/Colors/PackedPixel/NormalizedShort4.cs
  8. 28
      src/ImageSharp/Colors/PackedPixel/Rgba1010102.cs
  9. 28
      src/ImageSharp/Colors/PackedPixel/Rgba64.cs
  10. 16
      src/ImageSharp/Colors/PackedPixel/Short2.cs
  11. 28
      src/ImageSharp/Colors/PackedPixel/Short4.cs
  12. 11
      src/ImageSharp/Colors/Vector4BlendTransforms.cs
  13. 4
      src/ImageSharp/Common/Extensions/Vector4Extensions.cs
  14. 22
      src/ImageSharp/Common/Helpers/ImageMaths.cs
  15. 144
      src/ImageSharp/Common/Helpers/MathF.cs
  16. 7
      src/ImageSharp/Formats/Png/PngEncoderCore.cs
  17. 4
      src/ImageSharp/Formats/Png/PngInterlaceMode.cs
  18. 84
      src/ImageSharp/IO/BigEndianBitConverter.cs
  19. 4
      src/ImageSharp/IO/EndianBinaryReader.cs
  20. 52
      src/ImageSharp/IO/EndianBinaryWriter.cs
  21. 63
      src/ImageSharp/IO/EndianBitConverter.Conversion.cs
  22. 145
      src/ImageSharp/IO/EndianBitConverter.CopyBytes.cs
  23. 139
      src/ImageSharp/IO/EndianBitConverter.GetBytes.cs
  24. 141
      src/ImageSharp/IO/EndianBitConverter.ToType.cs
  25. 682
      src/ImageSharp/IO/EndianBitConverter.cs
  26. 80
      src/ImageSharp/IO/LittleEndianBitConverter.cs
  27. 6
      src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs
  28. 2
      src/ImageSharp/Processing/Processors/Effects/BackgroundColorProcessor.cs
  29. 6
      src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs
  30. 2
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs
  31. 6
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs
  32. 2
      src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs
  33. 10
      src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs
  34. 36
      src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs
  35. 2
      src/ImageSharp/Quantizers/Octree/Quantizer.cs
  36. 2
      tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs
  37. 56
      tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs
  38. 83
      tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs
  39. 69
      tests/ImageSharp.Tests/Helpers/MathFTests.cs
  40. 230
      tests/ImageSharp.Tests/IO/BigEndianBitConverter.CopyBytesTests.cs
  41. 110
      tests/ImageSharp.Tests/IO/BigEndianBitConverter.GetBytesTests.cs
  42. 158
      tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs
  43. 230
      tests/ImageSharp.Tests/IO/LittleEndianBitConverter.CopyBytesTests.cs
  44. 110
      tests/ImageSharp.Tests/IO/LittleEndianBitConverter.GetBytesTests.cs
  45. 157
      tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs
  46. 119
      tests/ImageSharp.Tests/ImageComparer.cs
  47. 34
      tests/ImageSharp.Tests/Processors/Filters/GrayscaleTest.cs
  48. 38
      tests/ImageSharp.Tests/TestUtilities/Attributes/WithTestPatternImageAttribute.cs
  49. 27
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/BlankProvider.cs
  50. 20
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs
  51. 38
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs
  52. 53
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs
  53. 210
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs
  54. 43
      tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs
  55. 20
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

2
src/ImageSharp.Drawing/Brushes/ImageBrush{TColor}.cs

@ -80,7 +80,7 @@ namespace ImageSharp.Drawing.Brushes
this.source = image.Lock();
this.xLength = image.Width;
this.yLength = image.Height;
this.offset = new Vector2((float)Math.Max(Math.Floor(region.Top), 0), (float)Math.Max(Math.Floor(region.Left), 0));
this.offset = new Vector2(MathF.Max(MathF.Floor(region.Top), 0), MathF.Max(MathF.Floor(region.Left), 0));
}
/// <summary>

8
src/ImageSharp.Drawing/Paths/RectangleExtensions.cs

@ -19,10 +19,10 @@ namespace ImageSharp.Drawing
/// <returns>A <see cref="Rectangle"/> representation of this <see cref="SixLabors.Shapes.Rectangle"/></returns>
public static Rectangle Convert(this SixLabors.Shapes.Rectangle source)
{
int left = (int)Math.Floor(source.Left);
int right = (int)Math.Ceiling(source.Right);
int top = (int)Math.Floor(source.Top);
int bottom = (int)Math.Ceiling(source.Bottom);
int left = (int)MathF.Floor(source.Left);
int right = (int)MathF.Ceiling(source.Right);
int top = (int)MathF.Floor(source.Top);
int bottom = (int)MathF.Ceiling(source.Bottom);
return new Rectangle(left, top, right - left, bottom - top);
}
}

2
src/ImageSharp.Drawing/Pens/Pen{TColor}.cs

@ -241,7 +241,7 @@ namespace ImageSharp.Drawing.Pens
float distanceFromStart = length - start;
float distanceFromEnd = end - length;
float closestEdge = Math.Min(distanceFromStart, distanceFromEnd);
float closestEdge = MathF.Min(distanceFromStart, distanceFromEnd);
float distanceAcross = closestEdge;

4
src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs

@ -128,8 +128,8 @@ namespace ImageSharp.Drawing.Processors
// points will be paired up
float scanStart = buffer[point] - minX;
float scanEnd = buffer[point + 1] - minX;
int startX = (int)Math.Floor(scanStart);
int endX = (int)Math.Floor(scanEnd);
int startX = (int)MathF.Floor(scanStart);
int endX = (int)MathF.Floor(scanEnd);
if (startX >= 0 && startX < scanline.Length)
{

28
src/ImageSharp/Colors/PackedPixel/Bgr565.cs

@ -110,9 +110,9 @@ namespace ImageSharp
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
@ -120,10 +120,10 @@ namespace ImageSharp
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
}
/// <inheritdoc />
@ -131,9 +131,9 @@ namespace ImageSharp
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
}
/// <inheritdoc />
@ -141,10 +141,10 @@ namespace ImageSharp
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
}
/// <inheritdoc />

20
src/ImageSharp/Colors/PackedPixel/NormalizedShort2.cs

@ -127,8 +127,8 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = 0;
}
@ -143,8 +143,8 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = 255;
}
@ -161,8 +161,8 @@ namespace ImageSharp
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
}
/// <inheritdoc />
@ -177,8 +177,8 @@ namespace ImageSharp
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = 255;
}
@ -237,8 +237,8 @@ namespace ImageSharp
// Clamp the value between min and max values
// Round rather than truncate.
uint word2 = (uint)((int)(float)Math.Round(x * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF);
uint word1 = (uint)(((int)(float)Math.Round(y * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x10);
uint word2 = (uint)((int)MathF.Round(x * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF);
uint word1 = (uint)(((int)MathF.Round(y * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x10);
return word2 | word1;
}

36
src/ImageSharp/Colors/PackedPixel/NormalizedShort4.cs

@ -135,9 +135,9 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
@ -151,10 +151,10 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
}
/// <inheritdoc />
@ -168,9 +168,9 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
}
/// <inheritdoc />
@ -184,10 +184,10 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
}
/// <inheritdoc />
@ -231,10 +231,10 @@ namespace ImageSharp
const float MinNeg = -MaxPos;
// Clamp the value between min and max values
ulong word4 = ((ulong)(float)Math.Round(x * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x00;
ulong word3 = ((ulong)(float)Math.Round(y * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x10;
ulong word2 = ((ulong)(float)Math.Round(z * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x20;
ulong word1 = ((ulong)(float)Math.Round(w * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x30;
ulong word4 = ((ulong)MathF.Round(x * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x00;
ulong word3 = ((ulong)MathF.Round(y * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x10;
ulong word2 = ((ulong)MathF.Round(z * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x20;
ulong word1 = ((ulong)MathF.Round(w * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x30;
return word4 | word3 | word2 | word1;
}

28
src/ImageSharp/Colors/PackedPixel/Rgba1010102.cs

@ -109,9 +109,9 @@ namespace ImageSharp
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
@ -120,10 +120,10 @@ namespace ImageSharp
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
}
/// <inheritdoc />
@ -132,9 +132,9 @@ namespace ImageSharp
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
}
/// <inheritdoc />
@ -143,10 +143,10 @@ namespace ImageSharp
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
}
/// <inheritdoc />

28
src/ImageSharp/Colors/PackedPixel/Rgba64.cs

@ -108,9 +108,9 @@ namespace ImageSharp
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
@ -119,10 +119,10 @@ namespace ImageSharp
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
}
/// <inheritdoc />
@ -131,9 +131,9 @@ namespace ImageSharp
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
}
/// <inheritdoc />
@ -142,10 +142,10 @@ namespace ImageSharp
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
}
/// <inheritdoc />

16
src/ImageSharp/Colors/PackedPixel/Short2.cs

@ -125,8 +125,8 @@ namespace ImageSharp
vector += Round;
vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes);
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = 0;
}
@ -141,8 +141,8 @@ namespace ImageSharp
vector += Round;
vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes);
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = 255;
}
@ -159,8 +159,8 @@ namespace ImageSharp
vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes);
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
}
/// <inheritdoc />
@ -175,8 +175,8 @@ namespace ImageSharp
vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes);
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = 255;
}

28
src/ImageSharp/Colors/PackedPixel/Short4.cs

@ -131,9 +131,9 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
@ -147,10 +147,10 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
}
/// <inheritdoc />
@ -164,9 +164,9 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
}
/// <inheritdoc />
@ -180,10 +180,10 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)(float)Math.Round(vector.Z);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
}
/// <inheritdoc />

11
src/ImageSharp/Colors/Vector4BlendTransforms.cs

@ -5,7 +5,6 @@
namespace ImageSharp
{
using System;
using System.Numerics;
/// <summary>
@ -198,13 +197,13 @@ namespace ImageSharp
amount = amount.Clamp(0, 1);
// Santize on zero alpha
if (Math.Abs(backdrop.W) < Constants.Epsilon)
if (MathF.Abs(backdrop.W) < Constants.Epsilon)
{
source.W *= amount;
return source;
}
if (Math.Abs(source.W) < Constants.Epsilon)
if (MathF.Abs(source.W) < Constants.Epsilon)
{
return backdrop;
}
@ -248,7 +247,7 @@ namespace ImageSharp
/// </returns>
private static float BlendSoftLight(float b, float s)
{
return s <= .5F ? ((2F * b * s) + (b * b * (1F - (2F * s)))) : (float)((Math.Sqrt(b) * ((2F * s) - 1F)) + (2F * b * (1F - s)));
return s <= .5F ? ((2F * b * s) + (b * b * (1F - (2F * s)))) : (MathF.Sqrt(b) * ((2F * s) - 1F)) + (2F * b * (1F - s));
}
/// <summary>
@ -261,7 +260,7 @@ namespace ImageSharp
/// </returns>
private static float BlendDodge(float b, float s)
{
return Math.Abs(s - 1F) < Constants.Epsilon ? s : Math.Min(b / (1F - s), 1F);
return MathF.Abs(s - 1F) < Constants.Epsilon ? s : MathF.Min(b / (1F - s), 1F);
}
/// <summary>
@ -274,7 +273,7 @@ namespace ImageSharp
/// </returns>
private static float BlendBurn(float b, float s)
{
return Math.Abs(s) < Constants.Epsilon ? s : Math.Max(1F - ((1F - b) / s), 0F);
return MathF.Abs(s) < Constants.Epsilon ? s : MathF.Max(1F - ((1F - b) / s), 0F);
}
/// <summary>

4
src/ImageSharp/Common/Extensions/Vector4Extensions.cs

@ -57,7 +57,7 @@ namespace ImageSharp
return signal * 12.92F;
}
return (1.055F * (float)Math.Pow(signal, 0.41666666F)) - 0.055F;
return (1.055F * MathF.Pow(signal, 0.41666666F)) - 0.055F;
}
/// <summary>
@ -77,7 +77,7 @@ namespace ImageSharp
return signal / 12.92F;
}
return (float)Math.Pow((signal + 0.055F) / 1.055F, 2.4F);
return MathF.Pow((signal + 0.055F) / 1.055F, 2.4F);
}
}
}

22
src/ImageSharp/Common/Helpers/ImageMaths.cs

@ -53,13 +53,13 @@ namespace ImageSharp
public static float Gaussian(float x, float sigma)
{
const float Numerator = 1.0f;
float denominator = (float)(Math.Sqrt(2 * Math.PI) * sigma);
float denominator = MathF.Sqrt(2 * MathF.PI) * sigma;
float exponentNumerator = -x * x;
float exponentDenominator = (float)(2 * Math.Pow(sigma, 2));
float left = Numerator / denominator;
float right = (float)Math.Exp(exponentNumerator / exponentDenominator);
float right = MathF.Exp(exponentNumerator / exponentDenominator);
return left * right;
}
@ -110,10 +110,10 @@ namespace ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float SinC(float x)
{
if (Math.Abs(x) > Constants.Epsilon)
if (MathF.Abs(x) > Constants.Epsilon)
{
x *= (float)Math.PI;
return Clean((float)Math.Sin(x) / x);
x *= MathF.PI;
return Clean(MathF.Sin(x) / x);
}
return 1.0f;
@ -129,7 +129,7 @@ namespace ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float DegreesToRadians(float degrees)
{
return degrees * (float)(Math.PI / 180);
return degrees * (MathF.PI / 180);
}
/// <summary>
@ -196,19 +196,19 @@ namespace ImageSharp
switch (channel)
{
case RgbaComponent.R:
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().X - b) > Constants.Epsilon;
delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().X - b) > Constants.Epsilon;
break;
case RgbaComponent.G:
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().Y - b) > Constants.Epsilon;
delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().Y - b) > Constants.Epsilon;
break;
case RgbaComponent.B:
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().Z - b) > Constants.Epsilon;
delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().Z - b) > Constants.Epsilon;
break;
default:
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().W - b) > Constants.Epsilon;
delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().W - b) > Constants.Epsilon;
break;
}
@ -297,7 +297,7 @@ namespace ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static float Clean(float x)
{
if (Math.Abs(x) < Constants.Epsilon)
if (MathF.Abs(x) < Constants.Epsilon)
{
return 0F;
}

144
src/ImageSharp/Common/Helpers/MathF.cs

@ -0,0 +1,144 @@
// <copyright file="MathF.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Runtime.CompilerServices;
/// <summary>
/// Provides single-precision floating point constants and static methods for trigonometric, logarithmic, and other common mathematical functions.
/// </summary>
// ReSharper disable InconsistentNaming
internal static class MathF
{
/// <summary>
/// Represents the ratio of the circumference of a circle to its diameter, specified by the constant, π.
/// </summary>
public const float PI = (float)Math.PI;
/// <summary>Returns the absolute value of a single-precision floating-point number.</summary>
/// <param name="f">A number that is greater than or equal to <see cref="F:System.Single.MinValue" />, but less than or equal to <see cref="F:System.Single.MaxValue" />.</param>
/// <returns>A single-precision floating-point number, x, such that 0 ≤ x ≤<see cref="F:System.Single.MaxValue" />.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Abs(float f)
{
return Math.Abs(f);
}
/// <summary>Returns the smallest integral value that is greater than or equal to the specified single-precision floating-point number.</summary>
/// <param name="f">A single-precision floating-point number. </param>
/// <returns>The smallest integral value that is greater than or equal to <paramref name="f" />.
/// If <paramref name="f" /> is equal to <see cref="F:System.Single.NaN" />, <see cref="F:System.Single.NegativeInfinity" />,
/// or <see cref="F:System.Single.PositiveInfinity" />, that value is returned.
/// Note that this method returns a <see cref="T:System.Single" /> instead of an integral type.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Ceiling(float f)
{
return (float)Math.Ceiling(f);
}
/// <summary>Returns e raised to the specified power.</summary>
/// <param name="f">A number specifying a power.</param>
/// <returns>
/// The number e raised to the power <paramref name="f" />.
/// If <paramref name="f" /> equals <see cref="F:System.Single.NaN" /> or <see cref="F:System.Single.PositiveInfinity" />, that value is returned.
/// If <paramref name="f" /> equals <see cref="F:System.Single.NegativeInfinity" />, 0 is returned.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Exp(float f)
{
return (float)Math.Exp(f);
}
/// <summary>Returns the largest integer less than or equal to the specified single-precision floating-point number.</summary>
/// <param name="f">A single-precision floating-point number. </param>
/// <returns>The largest integer less than or equal to <paramref name="f" />.
/// If <paramref name="f" /> is equal to <see cref="F:System.Single.NaN" />, <see cref="F:System.Single.NegativeInfinity" />,
/// or <see cref="F:System.Single.PositiveInfinity" />, that value is returned.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Floor(float f)
{
return (float)Math.Floor(f);
}
/// <summary>Returns the larger of two single-precision floating-point numbers.</summary>
/// <param name="val1">The first of two single-precision floating-point numbers to compare. </param>
/// <param name="val2">The second of two single-precision floating-point numbers to compare. </param>
/// <returns>Parameter <paramref name="val1" /> or <paramref name="val2" />, whichever is larger.
/// If <paramref name="val1" />, or <paramref name="val2" />, or both <paramref name="val1" /> and <paramref name="val2" /> are
/// equal to <see cref="F:System.Single.NaN" />, <see cref="F:System.Single.NaN" /> is returned.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Max(float val1, float val2)
{
return Math.Max(val1, val2);
}
/// <summary>Returns the smaller of two single-precision floating-point numbers.</summary>
/// <param name="val1">The first of two single-precision floating-point numbers to compare. </param>
/// <param name="val2">The second of two single-precision floating-point numbers to compare. </param>
/// <returns>Parameter <paramref name="val1" /> or <paramref name="val2" />, whichever is smaller.
/// If <paramref name="val1" />, <paramref name="val2" />, or both <paramref name="val1" /> and <paramref name="val2" /> are equal
/// to <see cref="F:System.Single.NaN" />, <see cref="F:System.Single.NaN" /> is returned.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Min(float val1, float val2)
{
return Math.Min(val1, val2);
}
/// <summary>Returns a specified number raised to the specified power.</summary>
/// <param name="x">A single-precision floating-point number to be raised to a power. </param>
/// <param name="y">A single-precision floating-point number that specifies a power. </param>
/// <returns>The number <paramref name="x" /> raised to the power <paramref name="y" />.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Pow(float x, float y)
{
return (float)Math.Pow(x, y);
}
/// <summary>Rounds a single-precision floating-point value to the nearest integral value.</summary>
/// <param name="f">A single-precision floating-point number to be rounded. </param>
/// <returns>
/// The integer nearest <paramref name="f" />.
/// If the fractional component of <paramref name="f" /> is halfway between two integers, one of which is even and the other odd, then the even number is returned.
/// Note that this method returns a <see cref="T:System.Single" /> instead of an integral type.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Round(float f)
{
return (float)Math.Round(f);
}
/// <summary>Returns the sine of the specified angle.</summary>
/// <param name="f">An angle, measured in radians. </param>
/// <returns>
/// The sine of <paramref name="f" />.
/// If <paramref name="f" /> is equal to <see cref="F:System.Single.NaN" />, <see cref="F:System.Single.NegativeInfinity" />,
/// or <see cref="F:System.Single.PositiveInfinity" />, this method returns <see cref="F:System.Single.NaN" />.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Sin(float f)
{
return (float)Math.Sin(f);
}
/// <summary>Returns the square root of a specified number.</summary>
/// <param name="f">The number whose square root is to be found. </param>
/// <returns>
/// One of the values in the following table.
/// <paramref name="f" /> parameter Return value Zero or positive The positive square root of <paramref name="f" />.
/// Negative <see cref="F:System.Single.NaN" />Equals <see cref="F:System.Single.NaN" />
/// <see cref="F:System.Single.NaN" />Equals <see cref="F:System.Single.PositiveInfinity" />
/// <see cref="F:System.Single.PositiveInfinity" />
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Sqrt(float f)
{
return (float)Math.Sqrt(f);
}
}
}

7
src/ImageSharp/Formats/Png/PngEncoderCore.cs

@ -544,12 +544,11 @@ namespace ImageSharp.Formats
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <param name="imageBase">The image base.</param>
private void WritePhysicalChunk<TColor>(Stream stream, ImageBase<TColor> imageBase)
/// <param name="image">The image.</param>
private void WritePhysicalChunk<TColor>(Stream stream, Image<TColor> image)
where TColor : struct, IPixel<TColor>
{
Image<TColor> image = imageBase as Image<TColor>;
if (image != null && image.MetaData.HorizontalResolution > 0 && image.MetaData.VerticalResolution > 0)
if (image.MetaData.HorizontalResolution > 0 && image.MetaData.VerticalResolution > 0)
{
// 39.3700787 = inches in a meter.
int dpmX = (int)Math.Round(image.MetaData.HorizontalResolution * 39.3700787D);

4
src/ImageSharp/Formats/Png/PngInterlaceMode.cs

@ -13,11 +13,11 @@ namespace ImageSharp.Formats
/// <summary>
/// Non interlaced
/// </summary>
None,
None = 0,
/// <summary>
/// Adam 7 interlacing.
/// </summary>
Adam7
Adam7 = 1
}
}

84
src/ImageSharp/IO/BigEndianBitConverter.cs

@ -6,43 +6,81 @@
namespace ImageSharp.IO
{
/// <summary>
/// Implementation of EndianBitConverter which converts to/from big-endian
/// byte arrays.
/// <remarks>
/// Adapted from Miscellaneous Utility Library <see href="http://jonskeet.uk/csharp/miscutil/" />
/// This product includes software developed by Jon Skeet and Marc Gravell. Contact <see href="mailto:skeet@pobox.com" />, or see
/// <see href="http://www.pobox.com/~skeet/" />.
/// </remarks>
/// Implementation of EndianBitConverter which converts to/from big-endian byte arrays.
/// </summary>
internal sealed class BigEndianBitConverter : EndianBitConverter
{
/// <inheritdoc/>
public override Endianness Endianness => Endianness.BigEndian;
public override Endianness Endianness
{
get { return Endianness.BigEndian; }
}
/// <inheritdoc/>
public override bool IsLittleEndian() => false;
public override bool IsLittleEndian
{
get { return false; }
}
/// <inheritdoc/>
protected internal override void CopyBytesImpl(long value, int bytes, byte[] buffer, int index)
public override void CopyBytes(short value, byte[] buffer, int index)
{
int endOffset = index + bytes - 1;
for (int i = 0; i < bytes; i++)
{
buffer[endOffset - i] = unchecked((byte)(value & 0xff));
value = value >> 8;
}
CheckByteArgument(buffer, index, 2);
buffer[index] = (byte)(value >> 8);
buffer[index + 1] = (byte)value;
}
/// <inheritdoc/>
public override void CopyBytes(int value, byte[] buffer, int index)
{
CheckByteArgument(buffer, index, 4);
buffer[index] = (byte)(value >> 24);
buffer[index + 1] = (byte)(value >> 16);
buffer[index + 2] = (byte)(value >> 8);
buffer[index + 3] = (byte)value;
}
/// <inheritdoc/>
public override void CopyBytes(long value, byte[] buffer, int index)
{
CheckByteArgument(buffer, index, 8);
buffer[index] = (byte)(value >> 56);
buffer[index + 1] = (byte)(value >> 48);
buffer[index + 2] = (byte)(value >> 40);
buffer[index + 3] = (byte)(value >> 32);
buffer[index + 4] = (byte)(value >> 24);
buffer[index + 5] = (byte)(value >> 16);
buffer[index + 6] = (byte)(value >> 8);
buffer[index + 7] = (byte)value;
}
/// <inheritdoc/>
public override short ToInt16(byte[] value, int startIndex)
{
CheckByteArgument(value, startIndex, 2);
return (short)((value[0] << 8) | value[1]);
}
/// <inheritdoc/>
public override int ToInt32(byte[] value, int startIndex)
{
CheckByteArgument(value, startIndex, 4);
return (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
}
/// <inheritdoc/>
protected internal override long FromBytes(byte[] buffer, int startIndex, int bytesToConvert)
public override long ToInt64(byte[] value, int startIndex)
{
long ret = 0;
for (int i = 0; i < bytesToConvert; i++)
{
ret = unchecked((ret << 8) | buffer[startIndex + i]);
}
CheckByteArgument(value, startIndex, 8);
return ret;
long p1 = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
long p2 = (value[4] << 24) | (value[5] << 16) | (value[6] << 8) | value[7];
return p2 | (p1 << 32);
}
}
}

4
src/ImageSharp/IO/EndianBinaryReader.cs

@ -68,7 +68,7 @@ namespace ImageSharp.IO
{
Guard.NotNull(stream, nameof(stream));
Guard.NotNull(encoding, nameof(encoding));
Guard.IsTrue(stream.CanRead, nameof(stream), "Stream isn't readable.");
Guard.IsTrue(stream.CanRead, nameof(stream), "Stream isn't readable");
this.BaseStream = stream;
this.BitConverter = EndianBitConverter.GetConverter(endianness);
@ -510,7 +510,7 @@ namespace ImageSharp.IO
{
if (this.disposed)
{
throw new ObjectDisposedException("EndianBinaryReader");
throw new ObjectDisposedException(nameof(EndianBinaryReader));
}
}

52
src/ImageSharp/IO/EndianBinaryWriter.cs

@ -52,31 +52,12 @@ namespace ImageSharp.IO
/// </param>
public EndianBinaryWriter(Endianness endianness, Stream stream, Encoding encoding)
{
EndianBitConverter bitConverter = EndianBitConverter.GetConverter(endianness);
// TODO: Use Guard
if (bitConverter == null)
{
throw new ArgumentNullException("bitConverter");
}
if (stream == null)
{
throw new ArgumentNullException("stream");
}
if (encoding == null)
{
throw new ArgumentNullException("encoding");
}
if (!stream.CanWrite)
{
throw new ArgumentException("Stream isn't writable", "stream");
}
Guard.NotNull(stream, nameof(stream));
Guard.NotNull(stream, nameof(encoding));
Guard.IsTrue(stream.CanWrite, nameof(stream), "Stream isn't writable");
this.BaseStream = stream;
this.BitConverter = bitConverter;
this.BitConverter = EndianBitConverter.GetConverter(endianness);
this.Encoding = encoding;
}
@ -256,13 +237,10 @@ namespace ImageSharp.IO
/// Writes an array of bytes to the stream.
/// </summary>
/// <param name="value">The values to write</param>
/// <exception cref="ArgumentNullException">value is null</exception>
public void Write(byte[] value)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
Guard.NotNull(value, nameof(value));
this.WriteInternal(value, value.Length);
}
@ -272,6 +250,7 @@ namespace ImageSharp.IO
/// <param name="value">An array containing the bytes to write</param>
/// <param name="offset">The index of the first byte to write within the array</param>
/// <param name="count">The number of bytes to write</param>
/// <exception cref="ArgumentNullException">value is null</exception>
public void Write(byte[] value, int offset, int count)
{
this.CheckDisposed();
@ -292,12 +271,10 @@ namespace ImageSharp.IO
/// Writes an array of characters to the stream, using the encoding for this writer.
/// </summary>
/// <param name="value">An array containing the characters to write</param>
/// <exception cref="ArgumentNullException">value is null</exception>
public void Write(char[] value)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
Guard.NotNull(value, nameof(value));
this.CheckDisposed();
byte[] data = this.Encoding.GetBytes(value, 0, value.Length);
@ -305,16 +282,13 @@ namespace ImageSharp.IO
}
/// <summary>
/// Writes a string to the stream, using the encoding for this writer.
/// Writes a length-prefixed string to the stream, using the encoding for this writer.
/// </summary>
/// <param name="value">The value to write. Must not be null.</param>
/// <exception cref="System.ArgumentNullException">value is null</exception>
/// <exception cref="ArgumentNullException">value is null</exception>
public void Write(string value)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
Guard.NotNull(value, nameof(value));
this.CheckDisposed();
byte[] data = this.Encoding.GetBytes(value);
@ -368,7 +342,7 @@ namespace ImageSharp.IO
{
if (this.disposed)
{
throw new ObjectDisposedException("EndianBinaryWriter");
throw new ObjectDisposedException(nameof(EndianBinaryWriter));
}
}

63
src/ImageSharp/IO/EndianBitConverter.Conversion.cs

@ -0,0 +1,63 @@
// <copyright file="EndianBitConverter.Conversion.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.IO
{
using System;
/// <summary>
/// Equivalent of <see cref="BitConverter"/>, but with either endianness.
/// </summary>
internal abstract partial class EndianBitConverter
{
/// <summary>
/// Converts the specified double-precision floating point number to a
/// 64-bit signed integer. Note: the endianness of this converter does not
/// affect the returned value.
/// </summary>
/// <param name="value">The number to convert. </param>
/// <returns>A 64-bit signed integer whose value is equivalent to value.</returns>
public unsafe long DoubleToInt64Bits(double value)
{
return *((long*)&value);
}
/// <summary>
/// Converts the specified 64-bit signed integer to a double-precision
/// floating point number. Note: the endianness of this converter does not
/// affect the returned value.
/// </summary>
/// <param name="value">The number to convert. </param>
/// <returns>A double-precision floating point number whose value is equivalent to value.</returns>
public unsafe double Int64BitsToDouble(long value)
{
return *((double*)&value);
}
/// <summary>
/// Converts the specified single-precision floating point number to a
/// 32-bit signed integer. Note: the endianness of this converter does not
/// affect the returned value.
/// </summary>
/// <param name="value">The number to convert. </param>
/// <returns>A 32-bit signed integer whose value is equivalent to value.</returns>
public unsafe int SingleToInt32Bits(float value)
{
return *((int*)&value);
}
/// <summary>
/// Converts the specified 32-bit signed integer to a single-precision floating point
/// number. Note: the endianness of this converter does not
/// affect the returned value.
/// </summary>
/// <param name="value">The number to convert. </param>
/// <returns>A single-precision floating point number whose value is equivalent to value.</returns>
public unsafe float Int32BitsToSingle(int value)
{
return *((float*)&value);
}
}
}

145
src/ImageSharp/IO/EndianBitConverter.CopyBytes.cs

@ -0,0 +1,145 @@
// <copyright file="EndianBitConverter.CopyBytes.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.IO
{
using System;
/// <summary>
/// Equivalent of <see cref="BitConverter"/>, but with either endianness.
/// </summary>
internal abstract partial class EndianBitConverter
{
/// <summary>
/// Copies the specified 16-bit signed integer value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public abstract void CopyBytes(short value, byte[] buffer, int index);
/// <summary>
/// Copies the specified 32-bit signed integer value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public abstract void CopyBytes(int value, byte[] buffer, int index);
/// <summary>
/// Copies the specified 64-bit signed integer value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public abstract void CopyBytes(long value, byte[] buffer, int index);
/// <summary>
/// Copies the specified 16-bit unsigned integer value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(ushort value, byte[] buffer, int index)
{
this.CopyBytes(unchecked((short)value), buffer, index);
}
/// <summary>
/// Copies the specified 32-bit unsigned integer value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(uint value, byte[] buffer, int index)
{
this.CopyBytes(unchecked((int)value), buffer, index);
}
/// <summary>
/// Copies the specified 64-bit unsigned integer value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(ulong value, byte[] buffer, int index)
{
this.CopyBytes(unchecked((long)value), buffer, index);
}
/// <summary>
/// Copies the specified Boolean value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">A Boolean value.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(bool value, byte[] buffer, int index)
{
CheckByteArgument(buffer, index, 1);
buffer[index] = value ? (byte)1 : (byte)0;
}
/// <summary>
/// Copies the specified Unicode character value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">A character to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(char value, byte[] buffer, int index)
{
this.CopyBytes(unchecked((short)value), buffer, index);
}
/// <summary>
/// Copies the specified double-precision floating point value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public unsafe void CopyBytes(double value, byte[] buffer, int index)
{
this.CopyBytes(*((long*)&value), buffer, index);
}
/// <summary>
/// Copies the specified single-precision floating point value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public unsafe void CopyBytes(float value, byte[] buffer, int index)
{
this.CopyBytes(*((int*)&value), buffer, index);
}
/// <summary>
/// Copies the specified decimal value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">A character to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public unsafe void CopyBytes(decimal value, byte[] buffer, int index)
{
CheckByteArgument(buffer, index, 16);
int* pvalue = (int*)&value;
this.CopyBytes(pvalue[0], buffer, index);
this.CopyBytes(pvalue[1], buffer, index + 4);
this.CopyBytes(pvalue[2], buffer, index + 8);
this.CopyBytes(pvalue[3], buffer, index + 12);
}
}
}

139
src/ImageSharp/IO/EndianBitConverter.GetBytes.cs

@ -0,0 +1,139 @@
// <copyright file="EndianBitConverter.GetBytes.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.IO
{
using System;
/// <summary>
/// Equivalent of <see cref="BitConverter"/>, but with either endianness.
/// </summary>
internal abstract partial class EndianBitConverter
{
/// <summary>
/// Returns the specified 16-bit signed integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public byte[] GetBytes(short value)
{
byte[] result = new byte[2];
this.CopyBytes(value, result, 0);
return result;
}
/// <summary>
/// Returns the specified 32-bit signed integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public byte[] GetBytes(int value)
{
byte[] result = new byte[4];
this.CopyBytes(value, result, 0);
return result;
}
/// <summary>
/// Returns the specified 64-bit signed integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public byte[] GetBytes(long value)
{
byte[] result = new byte[8];
this.CopyBytes(value, result, 0);
return result;
}
/// <summary>
/// Returns the specified 16-bit unsigned integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public byte[] GetBytes(ushort value)
{
return this.GetBytes(unchecked((short)value));
}
/// <summary>
/// Returns the specified 32-bit unsigned integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public byte[] GetBytes(uint value)
{
return this.GetBytes(unchecked((int)value));
}
/// <summary>
/// Returns the specified 64-bit unsigned integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public byte[] GetBytes(ulong value)
{
return this.GetBytes(unchecked((long)value));
}
/// <summary>
/// Returns the specified Boolean value as an array of bytes.
/// </summary>
/// <param name="value">A Boolean value.</param>
/// <returns>An array of bytes with length 1.</returns>
/// <returns>
/// The <see cref="T:byte[]"/>.
/// </returns>
public byte[] GetBytes(bool value)
{
return new byte[1] { value ? (byte)1 : (byte)0 };
}
/// <summary>
/// Returns the specified Unicode character value as an array of bytes.
/// </summary>
/// <param name="value">A character to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
/// <returns>
/// The <see cref="T:byte[]"/>.
/// </returns>
public byte[] GetBytes(char value)
{
return this.GetBytes((short)value);
}
/// <summary>
/// Returns the specified double-precision floating point value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public unsafe byte[] GetBytes(double value)
{
return this.GetBytes(*((long*)&value));
}
/// <summary>
/// Returns the specified single-precision floating point value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public unsafe byte[] GetBytes(float value)
{
return this.GetBytes(*((int*)&value));
}
/// <summary>
/// Returns the specified decimal value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 16.</returns>
public byte[] GetBytes(decimal value)
{
byte[] result = new byte[16];
this.CopyBytes(value, result, 0);
return result;
}
}
}

141
src/ImageSharp/IO/EndianBitConverter.ToType.cs

@ -0,0 +1,141 @@
// <copyright file="EndianBitConverter.ToType.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.IO
{
using System;
/// <summary>
/// Equivalent of <see cref="BitConverter"/>, but with either endianness.
/// </summary>
internal abstract partial class EndianBitConverter
{
/// <summary>
/// Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 16-bit signed integer formed by two bytes beginning at startIndex.</returns>
public abstract short ToInt16(byte[] value, int startIndex);
/// <summary>
/// Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 32-bit signed integer formed by four bytes beginning at startIndex.</returns>
public abstract int ToInt32(byte[] value, int startIndex);
/// <summary>
/// Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 64-bit signed integer formed by eight bytes beginning at startIndex.</returns>
public abstract long ToInt64(byte[] value, int startIndex);
/// <summary>
/// Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 16-bit unsigned integer formed by two bytes beginning at startIndex.</returns>
public ushort ToUInt16(byte[] value, int startIndex)
{
return unchecked((ushort)this.ToInt16(value, startIndex));
}
/// <summary>
/// Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 32-bit unsigned integer formed by four bytes beginning at startIndex.</returns>
public uint ToUInt32(byte[] value, int startIndex)
{
return unchecked((uint)this.ToInt32(value, startIndex));
}
/// <summary>
/// Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 64-bit unsigned integer formed by eight bytes beginning at startIndex.</returns>
public ulong ToUInt64(byte[] value, int startIndex)
{
return unchecked((ulong)this.ToInt64(value, startIndex));
}
/// <summary>
/// Returns a Boolean value converted from one byte at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>true if the byte at startIndex in value is nonzero; otherwise, false.</returns>
public bool ToBoolean(byte[] value, int startIndex)
{
CheckByteArgument(value, startIndex, 1);
return value[startIndex] != 0;
}
/// <summary>
/// Returns a Unicode character converted from two bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A character formed by two bytes beginning at startIndex.</returns>
public char ToChar(byte[] value, int startIndex)
{
return unchecked((char)this.ToInt16(value, startIndex));
}
/// <summary>
/// Returns a double-precision floating point number converted from eight bytes
/// at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A double precision floating point number formed by eight bytes beginning at startIndex.</returns>
public unsafe double ToDouble(byte[] value, int startIndex)
{
long intValue = this.ToInt64(value, startIndex);
return *((double*)&intValue);
}
/// <summary>
/// Returns a single-precision floating point number converted from four bytes
/// at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A single precision floating point number formed by four bytes beginning at startIndex.</returns>
public unsafe float ToSingle(byte[] value, int startIndex)
{
int intValue = this.ToInt32(value, startIndex);
return *((float*)&intValue);
}
/// <summary>
/// Returns a decimal value converted from sixteen bytes
/// at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A decimal formed by sixteen bytes beginning at startIndex.</returns>
public unsafe decimal ToDecimal(byte[] value, int startIndex)
{
CheckByteArgument(value, startIndex, 16);
decimal result = 0m;
int* presult = (int*)&result;
presult[0] = this.ToInt32(value, startIndex);
presult[1] = this.ToInt32(value, startIndex + 4);
presult[2] = this.ToInt32(value, startIndex + 8);
presult[3] = this.ToInt32(value, startIndex + 12);
return result;
}
}
}

682
src/ImageSharp/IO/EndianBitConverter.cs

@ -6,291 +6,56 @@
namespace ImageSharp.IO
{
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
/// <summary>
/// Equivalent of <see cref="System.BitConverter"/>, but with either endianness.
/// <remarks>
/// Adapted from Miscellaneous Utility Library <see href="http://jonskeet.uk/csharp/miscutil/"/>
/// This product includes software developed by Jon Skeet and Marc Gravell. Contact <see href="mailto:skeet@pobox.com"/>, or see
/// <see href="http://www.pobox.com/~skeet/"/>.
/// </remarks>
/// Equivalent of <see cref="BitConverter"/>, but with either endianness.
/// </summary>
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:ElementsMustAppearInTheCorrectOrder", Justification = "Reviewed. Suppression is OK here. Better readability.")]
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "Reviewed. Suppression is OK here. Better readability.")]
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1204:StaticElementsMustAppearBeforeInstanceElements", Justification = "Reviewed. Suppression is OK here. Better readability.")]
[SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1124:DoNotUseRegions", Justification = "Reviewed. Suppression is OK here. Better readability.")]
internal abstract class EndianBitConverter
internal abstract partial class EndianBitConverter
{
#region Endianness of this converter
/// <summary>
/// Indicates the byte order ("endianness") in which data is converted using this class.
/// The little-endian bit converter.
/// </summary>
/// <remarks>
/// Different computer architectures store data using different byte orders. "Big-endian"
/// means the most significant byte is on the left end of a word. "Little-endian" means the
/// most significant byte is on the right end of a word.
/// </remarks>
/// <returns>true if this converter is little-endian, false otherwise.</returns>
public abstract bool IsLittleEndian();
public static readonly LittleEndianBitConverter LittleEndianConverter = new LittleEndianBitConverter();
/// <summary>
/// Gets the byte order ("endianness") in which data is converted using this class.
/// The big-endian bit converter.
/// </summary>
public abstract Endianness Endianness { get; }
#endregion
#region Factory properties
public static readonly BigEndianBitConverter BigEndianConverter = new BigEndianBitConverter();
/// <summary>
/// The little-endian bit converter.
/// Gets the byte order ("endianness") in which data is converted using this class.
/// </summary>
private static readonly LittleEndianBitConverter LittleConverter = new LittleEndianBitConverter();
public abstract Endianness Endianness { get; }
/// <summary>
/// The big-endian bit converter.
/// Gets a value indicating whether the byte order ("endianness") in which data is converted is little endian.
/// </summary>
private static readonly BigEndianBitConverter BigConverter = new BigEndianBitConverter();
/// <remarks>
/// Different computer architectures store data using different byte orders. "Big-endian"
/// means the most significant byte is on the left end of a word. "Little-endian" means the
/// most significant byte is on the right end of a word.
/// </remarks>
public abstract bool IsLittleEndian { get; }
/// <summary>
/// Gets the converter.
/// </summary>
/// <param name="endianness">The endianness.</param>
/// <returns>an <see cref="EndianBitConverter"/></returns>
/// <exception cref="System.ArgumentException">Not a valid form of Endianness - endianness</exception>
internal static EndianBitConverter GetConverter(Endianness endianness)
/// <exception cref="ArgumentException">Not a valid form of Endianness - endianness</exception>
public static EndianBitConverter GetConverter(Endianness endianness)
{
switch (endianness)
{
case Endianness.LittleEndian:
return LittleConverter;
return LittleEndianConverter;
case Endianness.BigEndian:
return BigConverter;
return BigEndianConverter;
default:
throw new ArgumentException("Not a valid form of Endianness", nameof(endianness));
}
}
#endregion
#region Double/primitive conversions
/// <summary>
/// Converts the specified double-precision floating point number to a
/// 64-bit signed integer. Note: the endianness of this converter does not
/// affect the returned value.
/// </summary>
/// <param name="value">The number to convert. </param>
/// <returns>A 64-bit signed integer whose value is equivalent to value.</returns>
public long DoubleToInt64Bits(double value)
{
return BitConverter.DoubleToInt64Bits(value);
}
/// <summary>
/// Converts the specified 64-bit signed integer to a double-precision
/// floating point number. Note: the endianness of this converter does not
/// affect the returned value.
/// </summary>
/// <param name="value">The number to convert. </param>
/// <returns>A double-precision floating point number whose value is equivalent to value.</returns>
public double Int64BitsToDouble(long value)
{
return BitConverter.Int64BitsToDouble(value);
}
/// <summary>
/// Converts the specified single-precision floating point number to a
/// 32-bit signed integer. Note: the endianness of this converter does not
/// affect the returned value.
/// </summary>
/// <param name="value">The number to convert. </param>
/// <returns>A 32-bit signed integer whose value is equivalent to value.</returns>
public int SingleToInt32Bits(float value)
{
return new Int32SingleUnion(value).AsInt32;
}
/// <summary>
/// Converts the specified 32-bit signed integer to a single-precision floating point
/// number. Note: the endianness of this converter does not
/// affect the returned value.
/// </summary>
/// <param name="value">The number to convert. </param>
/// <returns>A single-precision floating point number whose value is equivalent to value.</returns>
public float Int32BitsToSingle(int value)
{
return new Int32SingleUnion(value).AsSingle;
}
#endregion
#region To(PrimitiveType) conversions
/// <summary>
/// Returns a Boolean value converted from one byte at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>true if the byte at startIndex in value is nonzero; otherwise, false.</returns>
public bool ToBoolean(byte[] value, int startIndex)
{
CheckByteArgument(value, startIndex, 1);
return BitConverter.ToBoolean(value, startIndex);
}
/// <summary>
/// Returns a Unicode character converted from two bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A character formed by two bytes beginning at startIndex.</returns>
public char ToChar(byte[] value, int startIndex)
{
return unchecked((char)this.CheckedFromBytes(value, startIndex, 2));
}
/// <summary>
/// Returns a double-precision floating point number converted from eight bytes
/// at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A double precision floating point number formed by eight bytes beginning at startIndex.</returns>
public double ToDouble(byte[] value, int startIndex)
{
return this.Int64BitsToDouble(this.ToInt64(value, startIndex));
}
/// <summary>
/// Returns a single-precision floating point number converted from four bytes
/// at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A single precision floating point number formed by four bytes beginning at startIndex.</returns>
public float ToSingle(byte[] value, int startIndex)
{
return this.Int32BitsToSingle(this.ToInt32(value, startIndex));
}
/// <summary>
/// Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 16-bit signed integer formed by two bytes beginning at startIndex.</returns>
public short ToInt16(byte[] value, int startIndex)
{
return unchecked((short)this.CheckedFromBytes(value, startIndex, 2));
}
/// <summary>
/// Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 32-bit signed integer formed by four bytes beginning at startIndex.</returns>
public int ToInt32(byte[] value, int startIndex)
{
return unchecked((int)this.CheckedFromBytes(value, startIndex, 4));
}
/// <summary>
/// Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 64-bit signed integer formed by eight bytes beginning at startIndex.</returns>
public long ToInt64(byte[] value, int startIndex)
{
return this.CheckedFromBytes(value, startIndex, 8);
}
/// <summary>
/// Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 16-bit unsigned integer formed by two bytes beginning at startIndex.</returns>
public ushort ToUInt16(byte[] value, int startIndex)
{
return unchecked((ushort)this.CheckedFromBytes(value, startIndex, 2));
}
/// <summary>
/// Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 32-bit unsigned integer formed by four bytes beginning at startIndex.</returns>
public uint ToUInt32(byte[] value, int startIndex)
{
return unchecked((uint)this.CheckedFromBytes(value, startIndex, 4));
}
/// <summary>
/// Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A 64-bit unsigned integer formed by eight bytes beginning at startIndex.</returns>
public ulong ToUInt64(byte[] value, int startIndex)
{
return unchecked((ulong)this.CheckedFromBytes(value, startIndex, 8));
}
/// <summary>
/// Convert the given number of bytes from the given array, from the given start
/// position, into a long, using the bytes as the least significant part of the long.
/// By the time this is called, the arguments have been checked for validity.
/// </summary>
/// <param name="value">The bytes to convert</param>
/// <param name="startIndex">The index of the first byte to convert</param>
/// <param name="bytesToConvert">The number of bytes to use in the conversion</param>
/// <returns>The converted number</returns>
protected internal abstract long FromBytes(byte[] value, int startIndex, int bytesToConvert);
/// <summary>
/// Checks the given argument for validity.
/// </summary>
/// <param name="value">The byte array passed in</param>
/// <param name="startIndex">The start index passed in</param>
/// <param name="bytesRequired">The number of bytes required</param>
/// <exception cref="System.ArgumentNullException">value is a null reference</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value minus bytesRequired.
/// </exception>
[SuppressMessage("ReSharper", "UnusedParameter.Local", Justification = "Keeps code DRY")]
private static void CheckByteArgument(byte[] value, int startIndex, int bytesRequired)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
if (startIndex < 0 || startIndex > value.Length - bytesRequired)
{
throw new ArgumentOutOfRangeException(nameof(startIndex));
}
}
/// <summary>
/// Checks the arguments for validity before calling FromBytes
/// (which can therefore assume the arguments are valid).
/// </summary>
/// <param name="value">The bytes to convert after checking</param>
/// <param name="startIndex">The index of the first byte to convert</param>
/// <param name="bytesToConvert">The number of bytes to convert</param>
/// <returns>The <see cref="long"/></returns>
private long CheckedFromBytes(byte[] value, int startIndex, int bytesToConvert)
{
CheckByteArgument(value, startIndex, bytesToConvert);
return this.FromBytes(value, startIndex, bytesToConvert);
}
#endregion
#region ToString conversions
/// <summary>
/// Returns a String converted from the elements of a byte array.
@ -336,406 +101,29 @@ namespace ImageSharp.IO
{
return BitConverter.ToString(value, startIndex, length);
}
#endregion
#region Decimal conversions
/// <summary>
/// Returns a decimal value converted from sixteen bytes
/// at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A decimal formed by sixteen bytes beginning at startIndex.</returns>
public decimal ToDecimal(byte[] value, int startIndex)
{
// HACK: This always assumes four parts, each in their own endianness,
// starting with the first part at the start of the byte array.
// On the other hand, there's no real format specified...
int[] parts = new int[4];
for (int i = 0; i < 4; i++)
{
parts[i] = this.ToInt32(value, startIndex + (i * 4));
}
return new decimal(parts);
}
/// <summary>
/// Returns the specified decimal value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 16.</returns>
public byte[] GetBytes(decimal value)
{
byte[] bytes = new byte[16];
int[] parts = decimal.GetBits(value);
for (int i = 0; i < 4; i++)
{
this.CopyBytesImpl(parts[i], 4, bytes, i * 4);
}
return bytes;
}
/// <summary>
/// Copies the specified decimal value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">A character to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(decimal value, byte[] buffer, int index)
{
int[] parts = decimal.GetBits(value);
for (int i = 0; i < 4; i++)
{
this.CopyBytesImpl(parts[i], 4, buffer, (i * 4) + index);
}
}
#endregion
#region GetBytes conversions
/// <summary>
/// Returns an array with the given number of bytes formed
/// from the least significant bytes of the specified value.
/// This is used to implement the other GetBytes methods.
/// </summary>
/// <param name="value">The value to get bytes for</param>
/// <param name="bytes">The number of significant bytes to return</param>
/// <returns>
/// The <see cref="T:byte[]"/>.
/// </returns>
private byte[] GetBytes(long value, int bytes)
{
byte[] buffer = new byte[bytes];
this.CopyBytes(value, bytes, buffer, 0);
return buffer;
}
/// <summary>
/// Returns the specified Boolean value as an array of bytes.
/// </summary>
/// <param name="value">A Boolean value.</param>
/// <returns>An array of bytes with length 1.</returns>
/// <returns>
/// The <see cref="T:byte[]"/>.
/// </returns>
public byte[] GetBytes(bool value)
{
return BitConverter.GetBytes(value);
}
/// <summary>
/// Returns the specified Unicode character value as an array of bytes.
/// </summary>
/// <param name="value">A character to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
/// <returns>
/// The <see cref="T:byte[]"/>.
/// </returns>
public byte[] GetBytes(char value)
{
return this.GetBytes(value, 2);
}
/// <summary>
/// Returns the specified double-precision floating point value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public byte[] GetBytes(double value)
{
return this.GetBytes(this.DoubleToInt64Bits(value), 8);
}
/// <summary>
/// Returns the specified 16-bit signed integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public byte[] GetBytes(short value)
{
return this.GetBytes(value, 2);
}
/// <summary>
/// Returns the specified 32-bit signed integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public byte[] GetBytes(int value)
{
return this.GetBytes(value, 4);
}
/// <summary>
/// Returns the specified 64-bit signed integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public byte[] GetBytes(long value)
{
return this.GetBytes(value, 8);
}
/// <summary>
/// Returns the specified single-precision floating point value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public byte[] GetBytes(float value)
{
return this.GetBytes(this.SingleToInt32Bits(value), 4);
}
/// <summary>
/// Returns the specified 16-bit unsigned integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public byte[] GetBytes(ushort value)
{
return this.GetBytes(value, 2);
}
/// <summary>
/// Returns the specified 32-bit unsigned integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 4.</returns>
public byte[] GetBytes(uint value)
{
return this.GetBytes(value, 4);
}
/// <summary>
/// Returns the specified 64-bit unsigned integer value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 8.</returns>
public byte[] GetBytes(ulong value)
{
return this.GetBytes(unchecked((long)value), 8);
}
#endregion
#region CopyBytes conversions
/// <summary>
/// Copies the given number of bytes from the least-specific
/// end of the specified value into the specified byte array, beginning
/// at the specified index.
/// This is used to implement the other CopyBytes methods.
/// </summary>
/// <param name="value">The value to copy bytes for</param>
/// <param name="bytes">The number of significant bytes to copy</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
private void CopyBytes(long value, int bytes, byte[] buffer, int index)
{
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer), "Byte array must not be null");
}
if (buffer.Length < index + bytes)
{
throw new ArgumentOutOfRangeException(nameof(buffer), "Buffer not big enough for value");
}
this.CopyBytesImpl(value, bytes, buffer, index);
}
/// <summary>
/// Copies the given number of bytes from the least-specific
/// end of the specified value into the specified byte array, beginning
/// at the specified index.
/// This must be implemented in concrete derived classes, but the implementation
/// may assume that the value will fit into the buffer.
/// </summary>
/// <param name="value">The value to copy bytes for</param>
/// <param name="bytes">The number of significant bytes to copy</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
protected internal abstract void CopyBytesImpl(long value, int bytes, byte[] buffer, int index);
/// <summary>
/// Copies the specified Boolean value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">A Boolean value.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(bool value, byte[] buffer, int index)
{
this.CopyBytes(value ? 1 : 0, 1, buffer, index);
}
/// <summary>
/// Copies the specified Unicode character value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">A character to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(char value, byte[] buffer, int index)
{
this.CopyBytes(value, 2, buffer, index);
}
/// <summary>
/// Copies the specified double-precision floating point value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(double value, byte[] buffer, int index)
{
this.CopyBytes(this.DoubleToInt64Bits(value), 8, buffer, index);
}
/// <summary>
/// Copies the specified 16-bit signed integer value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(short value, byte[] buffer, int index)
{
this.CopyBytes(value, 2, buffer, index);
}
/// <summary>
/// Copies the specified 32-bit signed integer value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(int value, byte[] buffer, int index)
{
this.CopyBytes(value, 4, buffer, index);
}
/// <summary>
/// Copies the specified 64-bit signed integer value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(long value, byte[] buffer, int index)
{
this.CopyBytes(value, 8, buffer, index);
}
/// <summary>
/// Copies the specified single-precision floating point value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(float value, byte[] buffer, int index)
{
this.CopyBytes(this.SingleToInt32Bits(value), 4, buffer, index);
}
/// <summary>
/// Copies the specified 16-bit unsigned integer value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(ushort value, byte[] buffer, int index)
{
this.CopyBytes(value, 2, buffer, index);
}
/// <summary>
/// Copies the specified 32-bit unsigned integer value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(uint value, byte[] buffer, int index)
{
this.CopyBytes(value, 4, buffer, index);
}
/// <summary>
/// Copies the specified 64-bit unsigned integer value into the specified byte array,
/// beginning at the specified index.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <param name="buffer">The byte array to copy the bytes into</param>
/// <param name="index">The first index into the array to copy the bytes into</param>
public void CopyBytes(ulong value, byte[] buffer, int index)
{
this.CopyBytes(unchecked((long)value), 8, buffer, index);
}
#endregion
#region Private struct used for Single/Int32 conversions
/// <summary>
/// Union used solely for the equivalent of DoubleToInt64Bits and vice versa.
/// Checks the given argument for validity.
/// </summary>
[StructLayout(LayoutKind.Explicit)]
private struct Int32SingleUnion
/// <param name="value">The byte array passed in</param>
/// <param name="startIndex">The start index passed in</param>
/// <param name="bytesRequired">The number of bytes required</param>
/// <exception cref="ArgumentNullException">value is a null reference</exception>
/// <exception cref="ArgumentOutOfRangeException">
/// startIndex is less than zero or greater than the length of value minus bytesRequired.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected static void CheckByteArgument(byte[] value, int startIndex, int bytesRequired)
{
/// <summary>
/// Int32 version of the value.
/// </summary>
[FieldOffset(0)]
private readonly int i;
/// <summary>
/// Single version of the value.
/// </summary>
[FieldOffset(0)]
private readonly float f;
/// <summary>
/// Initializes a new instance of the <see cref="Int32SingleUnion"/> struct.
/// </summary>
/// <param name="i">The integer value of the new instance.</param>
internal Int32SingleUnion(int i)
if (value == null)
{
this.f = 0; // Just to keep the compiler happy
this.i = i;
throw new ArgumentNullException(nameof(value));
}
/// <summary>
/// Initializes a new instance of the <see cref="Int32SingleUnion"/> struct.
/// </summary>
/// <param name="f">
/// The floating point value of the new instance.
/// </param>
internal Int32SingleUnion(float f)
if (startIndex < 0 || startIndex > value.Length - bytesRequired)
{
this.i = 0; // Just to keep the compiler happy
this.f = f;
throw new ArgumentOutOfRangeException(nameof(startIndex));
}
/// <summary>
/// Gets the value of the instance as an integer.
/// </summary>
internal int AsInt32 => this.i;
/// <summary>
/// Gets the value of the instance as a floating point number.
/// </summary>
internal float AsSingle => this.f;
}
#endregion
}
}
}

80
src/ImageSharp/IO/LittleEndianBitConverter.cs

@ -6,42 +6,78 @@
namespace ImageSharp.IO
{
/// <summary>
/// Implementation of EndianBitConverter which converts to/from little-endian
/// byte arrays.
/// <remarks>
/// Adapted from Miscellaneous Utility Library <see href="http://jonskeet.uk/csharp/miscutil/"/>
/// This product includes software developed by Jon Skeet and Marc Gravell. Contact <see href="mailto:skeet@pobox.com"/>, or see
/// <see href="http://www.pobox.com/~skeet/"/>.
/// </remarks>
/// Implementation of EndianBitConverter which converts to/from little-endian byte arrays.
/// </summary>
internal sealed class LittleEndianBitConverter : EndianBitConverter
{
/// <inheritdoc/>
public override Endianness Endianness => Endianness.LittleEndian;
public override Endianness Endianness
{
get { return Endianness.LittleEndian; }
}
/// <inheritdoc/>
public override bool IsLittleEndian
{
get { return true; }
}
/// <inheritdoc/>
public override void CopyBytes(short value, byte[] buffer, int index)
{
CheckByteArgument(buffer, index, 2);
buffer[index + 1] = (byte)(value >> 8);
buffer[index] = (byte)value;
}
/// <inheritdoc/>
public override bool IsLittleEndian() => true;
public override void CopyBytes(int value, byte[] buffer, int index)
{
CheckByteArgument(buffer, index, 4);
buffer[index + 3] = (byte)(value >> 24);
buffer[index + 2] = (byte)(value >> 16);
buffer[index + 1] = (byte)(value >> 8);
buffer[index] = (byte)value;
}
/// <inheritdoc/>
protected internal override void CopyBytesImpl(long value, int bytes, byte[] buffer, int index)
public override void CopyBytes(long value, byte[] buffer, int index)
{
for (int i = 0; i < bytes; i++)
{
buffer[i + index] = unchecked((byte)(value & 0xff));
value = value >> 8;
}
CheckByteArgument(buffer, index, 8);
buffer[index + 7] = (byte)(value >> 56);
buffer[index + 6] = (byte)(value >> 48);
buffer[index + 5] = (byte)(value >> 40);
buffer[index + 4] = (byte)(value >> 32);
buffer[index + 3] = (byte)(value >> 24);
buffer[index + 2] = (byte)(value >> 16);
buffer[index + 1] = (byte)(value >> 8);
buffer[index] = (byte)value;
}
/// <inheritdoc/>
protected internal override long FromBytes(byte[] buffer, int startIndex, int bytesToConvert)
public unsafe override short ToInt16(byte[] value, int startIndex)
{
long ret = 0;
for (int i = 0; i < bytesToConvert; i++)
{
ret = unchecked((ret << 8) | buffer[startIndex + bytesToConvert - 1 - i]);
}
CheckByteArgument(value, startIndex, 2);
return (short)((value[1] << 8) | value[0]);
}
return ret;
/// <inheritdoc/>
public unsafe override int ToInt32(byte[] value, int startIndex)
{
CheckByteArgument(value, startIndex, 4);
return (value[3] << 24) | (value[2] << 16) | (value[1] << 8) | value[0];
}
/// <inheritdoc/>
public unsafe override long ToInt64(byte[] value, int startIndex)
{
CheckByteArgument(value, startIndex, 8);
long p1 = (value[7] << 24) | (value[6] << 16) | (value[5] << 8) | value[4];
long p2 = (value[3] << 24) | (value[2] << 16) | (value[1] << 8) | value[0];
return p2 | (p1 << 32);
}
}
}

6
src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs

@ -108,9 +108,9 @@ namespace ImageSharp.Processing.Processors
}
}
float red = (float)Math.Sqrt((rX * rX) + (rY * rY));
float green = (float)Math.Sqrt((gX * gX) + (gY * gY));
float blue = (float)Math.Sqrt((bX * bX) + (bY * bY));
float red = MathF.Sqrt((rX * rX) + (rY * rY));
float green = MathF.Sqrt((gX * gX) + (gY * gY));
float blue = MathF.Sqrt((bX * bX) + (bY * bY));
TColor packed = default(TColor);
packed.PackFromVector4(new Vector4(red, green, blue, sourcePixels[x, y].ToVector4().W));

2
src/ImageSharp/Processing/Processors/Effects/BackgroundColorProcessor.cs

@ -77,7 +77,7 @@ namespace ImageSharp.Processing.Processors
color = Vector4BlendTransforms.PremultipliedLerp(backgroundColor, color, .5F);
}
if (Math.Abs(a) < Constants.Epsilon)
if (MathF.Abs(a) < Constants.Epsilon)
{
color = backgroundColor;
}

6
src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs

@ -139,9 +139,9 @@ namespace ImageSharp.Processing.Processors
}
}
float red = Math.Abs(redBin[maxIndex] / maxIntensity);
float green = Math.Abs(greenBin[maxIndex] / maxIntensity);
float blue = Math.Abs(blueBin[maxIndex] / maxIntensity);
float red = MathF.Abs(redBin[maxIndex] / maxIntensity);
float green = MathF.Abs(greenBin[maxIndex] / maxIntensity);
float blue = MathF.Abs(blueBin[maxIndex] / maxIntensity);
TColor packed = default(TColor);
packed.PackFromVector4(new Vector4(red, green, blue, sourcePixels[x, y].ToVector4().W));

2
src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs

@ -44,7 +44,7 @@ namespace ImageSharp.Processing.Processors
int endX = sourceRectangle.Right;
TColor glowColor = this.GlowColor;
Vector2 centre = Rectangle.Center(sourceRectangle).ToVector2();
float maxDistance = this.Radius > 0 ? Math.Min(this.Radius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F;
float maxDistance = this.Radius > 0 ? MathF.Min(this.Radius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F;
// Align start/end positions.
int minX = Math.Max(0, startX);

6
src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs

@ -49,9 +49,9 @@ namespace ImageSharp.Processing.Processors
int endX = sourceRectangle.Right;
TColor vignetteColor = this.VignetteColor;
Vector2 centre = Rectangle.Center(sourceRectangle).ToVector2();
float rX = this.RadiusX > 0 ? Math.Min(this.RadiusX, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F;
float rY = this.RadiusY > 0 ? Math.Min(this.RadiusY, sourceRectangle.Height * .5F) : sourceRectangle.Height * .5F;
float maxDistance = (float)Math.Sqrt((rX * rX) + (rY * rY));
float rX = this.RadiusX > 0 ? MathF.Min(this.RadiusX, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F;
float rY = this.RadiusY > 0 ? MathF.Min(this.RadiusY, sourceRectangle.Height * .5F) : sourceRectangle.Height * .5F;
float maxDistance = MathF.Sqrt((rX * rX) + (rY * rY));
// Align start/end positions.
int minX = Math.Max(0, startX);

2
src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs

@ -86,7 +86,7 @@ namespace ImageSharp.Processing.Processors
}
IResampler sampler = this.Sampler;
float radius = (float)Math.Ceiling(scale * sampler.Radius);
float radius = MathF.Ceiling(scale * sampler.Radius);
WeightsBuffer result = new WeightsBuffer(sourceSize, destinationSize);
for (int i = 0; i < destinationSize; i++)

10
src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs

@ -71,7 +71,7 @@ namespace ImageSharp.Processing.Processors
/// <inheritdoc/>
protected override void BeforeApply(ImageBase<TColor> source, Rectangle sourceRectangle)
{
if (Math.Abs(this.Angle) < Constants.Epsilon || Math.Abs(this.Angle - 90) < Constants.Epsilon || Math.Abs(this.Angle - 180) < Constants.Epsilon || Math.Abs(this.Angle - 270) < Constants.Epsilon)
if (MathF.Abs(this.Angle) < Constants.Epsilon || MathF.Abs(this.Angle - 90) < Constants.Epsilon || MathF.Abs(this.Angle - 180) < Constants.Epsilon || MathF.Abs(this.Angle - 270) < Constants.Epsilon)
{
return;
}
@ -90,25 +90,25 @@ namespace ImageSharp.Processing.Processors
/// <returns>The <see cref="bool"/></returns>
private bool OptimizedApply(ImageBase<TColor> source)
{
if (Math.Abs(this.Angle) < Constants.Epsilon)
if (MathF.Abs(this.Angle) < Constants.Epsilon)
{
// No need to do anything so return.
return true;
}
if (Math.Abs(this.Angle - 90) < Constants.Epsilon)
if (MathF.Abs(this.Angle - 90) < Constants.Epsilon)
{
this.Rotate90(source);
return true;
}
if (Math.Abs(this.Angle - 180) < Constants.Epsilon)
if (MathF.Abs(this.Angle - 180) < Constants.Epsilon)
{
this.Rotate180(source);
return true;
}
if (Math.Abs(this.Angle - 270) < Constants.Epsilon)
if (MathF.Abs(this.Angle - 270) < Constants.Epsilon)
{
this.Rotate270(source);
return true;

36
src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs

@ -65,7 +65,7 @@ namespace ImageSharp.Processing
return new Rectangle(0, 0, source.Width, source.Height);
}
double ratio;
float ratio;
int sourceWidth = source.Width;
int sourceHeight = source.Height;
@ -75,8 +75,8 @@ namespace ImageSharp.Processing
int destinationHeight = height;
// Fractional variants for preserving aspect ratio.
double percentHeight = Math.Abs(height / (double)sourceHeight);
double percentWidth = Math.Abs(width / (double)sourceWidth);
float percentHeight = MathF.Abs(height / (float)sourceHeight);
float percentWidth = MathF.Abs(width / (float)sourceWidth);
if (percentHeight < percentWidth)
{
@ -84,7 +84,7 @@ namespace ImageSharp.Processing
if (options.CenterCoordinates.Any())
{
double center = -(ratio * sourceHeight) * options.CenterCoordinates.First();
float center = -(ratio * sourceHeight) * options.CenterCoordinates.First();
destinationY = (int)center + (height / 2);
if (destinationY > 0)
@ -117,7 +117,7 @@ namespace ImageSharp.Processing
}
}
destinationHeight = (int)Math.Ceiling(sourceHeight * percentWidth);
destinationHeight = (int)MathF.Ceiling(sourceHeight * percentWidth);
}
else
{
@ -125,7 +125,7 @@ namespace ImageSharp.Processing
if (options.CenterCoordinates.Any())
{
double center = -(ratio * sourceWidth) * options.CenterCoordinates.ToArray()[1];
float center = -(ratio * sourceWidth) * options.CenterCoordinates.ToArray()[1];
destinationX = (int)center + (width / 2);
if (destinationX > 0)
@ -158,7 +158,7 @@ namespace ImageSharp.Processing
}
}
destinationWidth = (int)Math.Ceiling(sourceWidth * percentHeight);
destinationWidth = (int)MathF.Ceiling(sourceWidth * percentHeight);
}
return new Rectangle(destinationX, destinationY, destinationWidth, destinationHeight);
@ -184,7 +184,7 @@ namespace ImageSharp.Processing
return new Rectangle(0, 0, source.Width, source.Height);
}
double ratio;
float ratio;
int sourceWidth = source.Width;
int sourceHeight = source.Height;
@ -194,8 +194,8 @@ namespace ImageSharp.Processing
int destinationHeight = height;
// Fractional variants for preserving aspect ratio.
double percentHeight = Math.Abs(height / (double)sourceHeight);
double percentWidth = Math.Abs(width / (double)sourceWidth);
float percentHeight = MathF.Abs(height / (float)sourceHeight);
float percentWidth = MathF.Abs(width / (float)sourceWidth);
if (percentHeight < percentWidth)
{
@ -269,8 +269,8 @@ namespace ImageSharp.Processing
int sourceHeight = source.Height;
// Fractional variants for preserving aspect ratio.
double percentHeight = Math.Abs(height / (double)sourceHeight);
double percentWidth = Math.Abs(width / (double)sourceWidth);
float percentHeight = MathF.Abs(height / (float)sourceHeight);
float percentWidth = MathF.Abs(width / (float)sourceWidth);
int boxPadHeight = height > 0 ? height : Convert.ToInt32(sourceHeight * percentWidth);
int boxPadWidth = width > 0 ? width : Convert.ToInt32(sourceWidth * percentHeight);
@ -350,12 +350,12 @@ namespace ImageSharp.Processing
int destinationHeight = height;
// Fractional variants for preserving aspect ratio.
double percentHeight = Math.Abs(height / (double)source.Height);
double percentWidth = Math.Abs(width / (double)source.Width);
float percentHeight = MathF.Abs(height / (float)source.Height);
float percentWidth = MathF.Abs(width / (float)source.Width);
// Integers must be cast to doubles to get needed precision
double ratio = (double)options.Size.Height / options.Size.Width;
double sourceRatio = (double)source.Height / source.Width;
// Integers must be cast to floats to get needed precision
float ratio = (float)options.Size.Height / options.Size.Width;
float sourceRatio = (float)source.Height / source.Width;
if (sourceRatio < ratio)
{
@ -397,7 +397,7 @@ namespace ImageSharp.Processing
return new Rectangle(0, 0, source.Width, source.Height);
}
double sourceRatio = (double)source.Height / source.Width;
float sourceRatio = (float)source.Height / source.Width;
// Find the shortest distance to go.
int widthDiff = source.Width - width;

2
src/ImageSharp/Quantizers/Octree/Quantizer.cs

@ -171,7 +171,7 @@ namespace ImageSharp.Quantizers
leastDistance = distance;
// And if it's an exact match, exit the loop
if (Math.Abs(distance) < Constants.Epsilon)
if (MathF.Abs(distance) < Constants.Epsilon)
{
break;
}

2
tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs

@ -27,7 +27,7 @@ namespace ImageSharp.Tests.Drawing
[InlineData(false, 16, 4)] // we always do 4 sub=pixels when antialising is off.
public void MinimumAntialiasSubpixelDepth(bool antialias, int antialiasSubpixelDepth, int expectedAntialiasSubpixelDepth)
{
var bounds = new ImageSharp.Rectangle(0, 0, 1, 1);
ImageSharp.Rectangle bounds = new ImageSharp.Rectangle(0, 0, 1, 1);
Mock<IBrush<Color>> brush = new Mock<IBrush<Color>>();
Mock<Region> region = new Mock<Region>();

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

@ -8,47 +8,37 @@ using ImageSharp.Formats;
namespace ImageSharp.Tests
{
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using ImageSharp.IO;
using Xunit;
public class PngEncoderTests : FileTestBase
{
[Fact]
public void ImageCanSaveIndexedPng()
[Theory]
[WithBlankImages(1, 1, PixelTypes.All)]
public void WritesFileMarker<TColor>(TestImageProvider<TColor> provider)
where TColor : struct, IPixel<TColor>
{
string path = CreateOutputDirectory("Png", "Indexed");
foreach (TestFile file in Files)
using (Image<TColor> image = provider.GetImage())
using (MemoryStream ms = new MemoryStream())
{
using (Image image = file.CreateImage())
{
using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.png"))
{
image.MetaData.Quality = 256;
image.Save(output, new PngFormat());
}
}
}
}
image.Save(ms, new PngEncoder());
byte[] data = ms.ToArray().Take(8).ToArray();
byte[] expected = {
0x89, // Set the high bit.
0x50, // P
0x4E, // N
0x47, // G
0x0D, // Line ending CRLF
0x0A, // Line ending CRLF
0x1A, // EOF
0x0A // LF
};
[Fact]
public void ImageCanSavePngInParallel()
{
string path = this.CreateOutputDirectory("Png");
Parallel.ForEach(
Files,
file =>
{
using (Image image = file.CreateImage())
{
using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.png"))
{
image.SaveAsPng(output);
}
}
});
Assert.Equal(expected, data);
}
}
}
}

83
tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs

@ -0,0 +1,83 @@
// <copyright file="PngSmokeTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests.Formats.Png
{
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Xunit;
using ImageSharp.Formats;
using System.Linq;
using ImageSharp.IO;
public class PngSmokeTests
{
[Theory]
[WithTestPatternImages(300, 300, PixelTypes.All)]
public void GeneralTest<TColor>(TestImageProvider<TColor> provider)
where TColor : struct, IPixel<TColor>
{
// does saving a file then repoening mean both files are identical???
using (Image<TColor> image = provider.GetImage())
using (MemoryStream ms = new MemoryStream())
{
// image.Save(provider.Utility.GetTestOutputFileName("bmp"));
image.Save(ms, new PngEncoder());
ms.Position = 0;
using (Image img2 = Image.Load(ms, new PngDecoder()))
{
// img2.Save(provider.Utility.GetTestOutputFileName("bmp", "_loaded"), new BmpEncoder());
ImageComparer.CheckSimilarity(image, img2);
}
}
}
[Theory]
[WithTestPatternImages(100, 100, PixelTypes.All)]
public void CanSaveIndexedPng<TColor>(TestImageProvider<TColor> provider)
where TColor : struct, IPixel<TColor>
{
// does saving a file then repoening mean both files are identical???
using (Image<TColor> image = provider.GetImage())
using (MemoryStream ms = new MemoryStream())
{
// image.Save(provider.Utility.GetTestOutputFileName("bmp"));
image.MetaData.Quality = 256;
image.Save(ms, new PngEncoder());
ms.Position = 0;
using (Image img2 = Image.Load(ms, new PngDecoder()))
{
// img2.Save(provider.Utility.GetTestOutputFileName("bmp", "_loaded"), new BmpEncoder());
ImageComparer.CheckSimilarity(image, img2);
}
}
}
[Theory]
[WithTestPatternImages(300, 300, PixelTypes.All)]
public void Resize<TColor>(TestImageProvider<TColor> provider)
where TColor : struct, IPixel<TColor>
{
// does saving a file then repoening mean both files are identical???
using (Image<TColor> image = provider.GetImage())
using (MemoryStream ms = new MemoryStream())
{
// image.Save(provider.Utility.GetTestOutputFileName("png"));
image.Resize(100, 100);
// image.Save(provider.Utility.GetTestOutputFileName("png", "resize"));
image.Save(ms, new PngEncoder());
ms.Position = 0;
using (Image img2 = Image.Load(ms, new PngDecoder()))
{
ImageComparer.CheckSimilarity(image, img2);
}
}
}
}
}

69
tests/ImageSharp.Tests/Helpers/MathFTests.cs

@ -0,0 +1,69 @@
namespace ImageSharp.Tests.Helpers
{
using System;
using Xunit;
public class MathFTests
{
[Fact]
public void MathF_PI_Is_Equal()
{
Assert.Equal(MathF.PI, (float)Math.PI);
}
[Fact]
public void MathF_Ceililng_Is_Equal()
{
Assert.Equal(MathF.Ceiling(0.3333F), (float)Math.Ceiling(0.3333F));
}
[Fact]
public void MathF_Abs_Is_Equal()
{
Assert.Equal(MathF.Abs(-0.3333F), (float)Math.Abs(-0.3333F));
}
[Fact]
public void MathF_Exp_Is_Equal()
{
Assert.Equal(MathF.Exp(1.2345F), (float)Math.Exp(1.2345F));
}
[Fact]
public void MathF_Floor_Is_Equal()
{
Assert.Equal(MathF.Floor(1.2345F), (float)Math.Floor(1.2345F));
}
[Fact]
public void MathF_Min_Is_Equal()
{
Assert.Equal(MathF.Min(1.2345F, 5.4321F), (float)Math.Min(1.2345F, 5.4321F));
}
[Fact]
public void MathF_Max_Is_Equal()
{
Assert.Equal(MathF.Max(1.2345F, 5.4321F), (float)Math.Max(1.2345F, 5.4321F));
}
[Fact]
public void MathF_Pow_Is_Equal()
{
Assert.Equal(MathF.Pow(1.2345F, 5.4321F), (float)Math.Pow(1.2345F, 5.4321F));
}
[Fact]
public void MathF_Sin_Is_Equal()
{
Assert.Equal(MathF.Sin(1.2345F), (float)Math.Sin(1.2345F));
}
[Fact]
public void MathF_Sqrt_Is_Equal()
{
Assert.Equal(MathF.Sqrt(2F), (float)Math.Sqrt(2F));
}
}
}

230
tests/ImageSharp.Tests/IO/BigEndianBitConverter.CopyBytesTests.cs

@ -0,0 +1,230 @@
// <copyright file="BigEndianBitConverter.CopyBytesTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests.IO
{
using System;
using ImageSharp.IO;
using Xunit;
/// <summary>
/// The <see cref="BigEndianBitConverter"/> tests.
/// </summary>
public class BigEndianBitConverterCopyBytesTests
{
[Fact]
public void CopyToWithNullBufferThrowsException()
{
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.CopyBytes(false, null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.CopyBytes((short)42, null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.CopyBytes((ushort)42, null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.CopyBytes(42, null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.CopyBytes(42u, null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.CopyBytes(42L, null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.CopyBytes((ulong)42L, null, 0));
}
[Fact]
public void CopyToWithIndexTooBigThrowsException()
{
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes(false, new byte[1], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes((short)42, new byte[2], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes((ushort)42, new byte[2], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes(42, new byte[4], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes(42u, new byte[4], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes(42L, new byte[8], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes((ulong)42L, new byte[8], 1));
}
[Fact]
public void CopyToWithBufferTooSmallThrowsException()
{
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes(false, new byte[0], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes((short)42, new byte[1], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes((ushort)42, new byte[1], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes(42, new byte[3], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes(42u, new byte[3], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes(42L, new byte[7], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.CopyBytes((ulong)42L, new byte[7], 0));
}
/// <summary>
/// Tests that passing a <see cref="bool"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesBoolean()
{
byte[] buffer = new byte[1];
EndianBitConverter.BigEndianConverter.CopyBytes(false, buffer, 0);
this.CheckBytes(new byte[] { 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(true, buffer, 0);
this.CheckBytes(new byte[] { 1 }, buffer);
}
/// <summary>
/// Tests that passing a <see cref="short"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesShort()
{
byte[] buffer = new byte[2];
EndianBitConverter.BigEndianConverter.CopyBytes((short)0, buffer, 0);
this.CheckBytes(new byte[] { 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes((short)1, buffer, 0);
this.CheckBytes(new byte[] { 0, 1 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes((short)256, buffer, 0);
this.CheckBytes(new byte[] { 1, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes((short)-1, buffer, 0);
this.CheckBytes(new byte[] { 255, 255 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes((short)257, buffer, 0);
this.CheckBytes(new byte[] { 1, 1 }, buffer);
}
/// <summary>
/// Tests that passing a <see cref="ushort"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesUShort()
{
byte[] buffer = new byte[2];
EndianBitConverter.BigEndianConverter.CopyBytes((ushort)0, buffer, 0);
this.CheckBytes(new byte[] { 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes((ushort)1, buffer, 0);
this.CheckBytes(new byte[] { 0, 1 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes((ushort)256, buffer, 0);
this.CheckBytes(new byte[] { 1, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(ushort.MaxValue, buffer, 0);
this.CheckBytes(new byte[] { 255, 255 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes((ushort)257, buffer, 0);
this.CheckBytes(new byte[] { 1, 1 }, buffer);
}
/// <summary>
/// Tests that passing a <see cref="int"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesInt()
{
byte[] buffer = new byte[4];
EndianBitConverter.BigEndianConverter.CopyBytes(0, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(1, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 1 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(256, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 1, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(65536, buffer, 0);
this.CheckBytes(new byte[] { 0, 1, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(16777216, buffer, 0);
this.CheckBytes(new byte[] { 1, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(-1, buffer, 0);
this.CheckBytes(new byte[] { 255, 255, 255, 255 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(257, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 1, 1 }, buffer);
}
/// <summary>
/// Tests that passing a <see cref="uint"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesUInt()
{
byte[] buffer = new byte[4];
EndianBitConverter.BigEndianConverter.CopyBytes((uint)0, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes((uint)1, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 1 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes((uint)256, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 1, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes((uint)65536, buffer, 0);
this.CheckBytes(new byte[] { 0, 1, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes((uint)16777216, buffer, 0);
this.CheckBytes(new byte[] { 1, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(uint.MaxValue, buffer, 0);
this.CheckBytes(new byte[] { 255, 255, 255, 255 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes((uint)257, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 1, 1 }, buffer);
}
/// <summary>
/// Tests that passing a <see cref="long"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesLong()
{
byte[] buffer = new byte[8];
EndianBitConverter.BigEndianConverter.CopyBytes(0L, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(1L, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(256L, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(65536L, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(16777216L, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(4294967296L, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(1099511627776L, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(1099511627776L * 256, buffer, 0);
this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(1099511627776L * 256 * 256, buffer, 0);
this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(-1L, buffer, 0);
this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(257L, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, buffer);
}
/// <summary>
/// Tests that passing a <see cref="ulong"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesULong()
{
byte[] buffer = new byte[8];
EndianBitConverter.BigEndianConverter.CopyBytes(0UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(1UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(256UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(65536UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(16777216UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(4294967296UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(1099511627776UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(1099511627776UL * 256, buffer, 0);
this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(1099511627776UL * 256 * 256, buffer, 0);
this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(ulong.MaxValue, buffer, 0);
this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, buffer);
EndianBitConverter.BigEndianConverter.CopyBytes(257UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, buffer);
}
/// <summary>
/// Tests the two byte arrays for equality.
/// </summary>
/// <param name="expected">The expected bytes.</param>
/// <param name="actual">The actual bytes.</param>
private void CheckBytes(byte[] expected, byte[] actual)
{
Assert.Equal(expected.Length, actual.Length);
Assert.Equal(expected, actual);
}
}
}

110
tests/ImageSharp.Tests/IO/BigEndianBitConverterTests.cs → tests/ImageSharp.Tests/IO/BigEndianBitConverter.GetBytesTests.cs

@ -1,4 +1,4 @@
// <copyright file="BigEndianBitConverterTests.cs" company="James Jackson-South">
// <copyright file="BigEndianBitConverter.GetBytesTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -6,25 +6,47 @@
namespace ImageSharp.Tests.IO
{
using ImageSharp.IO;
using Xunit;
/// <summary>
/// The <see cref="BigEndianBitConverter"/> tests.
/// </summary>
public class BigEndianBitConverterTests
public class BigEndianBitConverterGetBytesTests
{
/// <summary>
/// Tests that passing a <see cref="bool"/> returns the correct bytes.
/// </summary>
[Fact]
public void GetBytesBoolean()
{
this.CheckBytes(new byte[] { 0 }, EndianBitConverter.BigEndianConverter.GetBytes(false));
this.CheckBytes(new byte[] { 1 }, EndianBitConverter.BigEndianConverter.GetBytes(true));
}
/// <summary>
/// Tests that passing a <see cref="short"/> returns the correct bytes.
/// </summary>
[Fact]
public void GetBytesShort()
{
this.CheckBytes(new byte[] { 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((short)0));
this.CheckBytes(new byte[] { 0, 1 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((short)1));
this.CheckBytes(new byte[] { 1, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((short)256));
this.CheckBytes(new byte[] { 255, 255 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((short)-1));
this.CheckBytes(new byte[] { 1, 1 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((short)257));
this.CheckBytes(new byte[] { 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((short)0));
this.CheckBytes(new byte[] { 0, 1 }, EndianBitConverter.BigEndianConverter.GetBytes((short)1));
this.CheckBytes(new byte[] { 1, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((short)256));
this.CheckBytes(new byte[] { 255, 255 }, EndianBitConverter.BigEndianConverter.GetBytes((short)-1));
this.CheckBytes(new byte[] { 1, 1 }, EndianBitConverter.BigEndianConverter.GetBytes((short)257));
}
/// <summary>
/// Tests that passing a <see cref="ushort"/> returns the correct bytes.
/// </summary>
[Fact]
public void GetBytesUShort()
{
this.CheckBytes(new byte[] { 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((ushort)0));
this.CheckBytes(new byte[] { 0, 1 }, EndianBitConverter.BigEndianConverter.GetBytes((ushort)1));
this.CheckBytes(new byte[] { 1, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((ushort)256));
this.CheckBytes(new byte[] { 255, 255 }, EndianBitConverter.BigEndianConverter.GetBytes(ushort.MaxValue));
this.CheckBytes(new byte[] { 1, 1 }, EndianBitConverter.BigEndianConverter.GetBytes((ushort)257));
}
/// <summary>
@ -33,13 +55,13 @@ namespace ImageSharp.Tests.IO
[Fact]
public void GetBytesInt()
{
this.CheckBytes(new byte[] { 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((int)0));
this.CheckBytes(new byte[] { 0, 0, 0, 1 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((int)1));
this.CheckBytes(new byte[] { 0, 0, 1, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((int)256));
this.CheckBytes(new byte[] { 0, 1, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((int)65536));
this.CheckBytes(new byte[] { 1, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((int)16777216));
this.CheckBytes(new byte[] { 255, 255, 255, 255 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((int)-1));
this.CheckBytes(new byte[] { 0, 0, 1, 1 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((int)257));
this.CheckBytes(new byte[] { 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(0));
this.CheckBytes(new byte[] { 0, 0, 0, 1 }, EndianBitConverter.BigEndianConverter.GetBytes(1));
this.CheckBytes(new byte[] { 0, 0, 1, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(256));
this.CheckBytes(new byte[] { 0, 1, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(65536));
this.CheckBytes(new byte[] { 1, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(16777216));
this.CheckBytes(new byte[] { 255, 255, 255, 255 }, EndianBitConverter.BigEndianConverter.GetBytes(-1));
this.CheckBytes(new byte[] { 0, 0, 1, 1 }, EndianBitConverter.BigEndianConverter.GetBytes(257));
}
/// <summary>
@ -48,13 +70,13 @@ namespace ImageSharp.Tests.IO
[Fact]
public void GetBytesUInt()
{
this.CheckBytes(new byte[] { 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((uint)0));
this.CheckBytes(new byte[] { 0, 0, 0, 1 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((uint)1));
this.CheckBytes(new byte[] { 0, 0, 1, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((uint)256));
this.CheckBytes(new byte[] { 0, 1, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((uint)65536));
this.CheckBytes(new byte[] { 1, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((uint)16777216));
this.CheckBytes(new byte[] { 255, 255, 255, 255 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((uint)uint.MaxValue));
this.CheckBytes(new byte[] { 0, 0, 1, 1 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes((uint)257));
this.CheckBytes(new byte[] { 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((uint)0));
this.CheckBytes(new byte[] { 0, 0, 0, 1 }, EndianBitConverter.BigEndianConverter.GetBytes((uint)1));
this.CheckBytes(new byte[] { 0, 0, 1, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((uint)256));
this.CheckBytes(new byte[] { 0, 1, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((uint)65536));
this.CheckBytes(new byte[] { 1, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((uint)16777216));
this.CheckBytes(new byte[] { 255, 255, 255, 255 }, EndianBitConverter.BigEndianConverter.GetBytes(uint.MaxValue));
this.CheckBytes(new byte[] { 0, 0, 1, 1 }, EndianBitConverter.BigEndianConverter.GetBytes((uint)257));
}
/// <summary>
@ -63,17 +85,17 @@ namespace ImageSharp.Tests.IO
[Fact]
public void GetBytesLong()
{
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(0L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(1L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(256L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(65536L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(16777216L));
this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(4294967296L));
this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(1099511627776L));
this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(1099511627776L * 256));
this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(1099511627776L * 256 * 256));
this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(-1L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(257L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(0L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, EndianBitConverter.BigEndianConverter.GetBytes(1L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(256L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(65536L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(16777216L));
this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(4294967296L));
this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(1099511627776L));
this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(1099511627776L * 256));
this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(1099511627776L * 256 * 256));
this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, EndianBitConverter.BigEndianConverter.GetBytes(-1L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, EndianBitConverter.BigEndianConverter.GetBytes(257L));
}
/// <summary>
@ -82,17 +104,17 @@ namespace ImageSharp.Tests.IO
[Fact]
public void GetBytesULong()
{
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(0UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(1UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(256UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(65536UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(16777216UL));
this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(4294967296UL));
this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(1099511627776UL));
this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(1099511627776UL * 256));
this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(1099511627776UL * 256 * 256));
this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(ulong.MaxValue));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, EndianBitConverter.GetConverter(Endianness.BigEndian).GetBytes(257UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(0UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, EndianBitConverter.BigEndianConverter.GetBytes(1UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(256UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(65536UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(16777216UL));
this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(4294967296UL));
this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(1099511627776UL));
this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(1099511627776UL * 256));
this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(1099511627776UL * 256 * 256));
this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, EndianBitConverter.BigEndianConverter.GetBytes(ulong.MaxValue));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, EndianBitConverter.BigEndianConverter.GetBytes(257UL));
}
/// <summary>

158
tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs

@ -0,0 +1,158 @@
// <copyright file="BigEndianBitConverter.ToTypeTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests.IO
{
using System;
using ImageSharp.IO;
using Xunit;
/// <summary>
/// The <see cref="BigEndianBitConverter"/> tests.
/// </summary>
public class BigEndianBitConverterTests
{
[Fact]
public void CopyToWithNullBufferThrowsException()
{
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.ToBoolean(null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.ToInt16(null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.ToUInt16(null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.ToInt32(null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.ToUInt32(null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.ToInt64(null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.BigEndianConverter.ToUInt64(null, 0));
}
[Fact]
public void CopyToWithIndexTooBigThrowsException()
{
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToBoolean(new byte[1], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToInt16(new byte[2], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToUInt16(new byte[2], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToInt32(new byte[4], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToUInt32(new byte[4], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToInt64(new byte[8], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToUInt64(new byte[8], 1));
}
[Fact]
public void CopyToWithBufferTooSmallThrowsException()
{
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToBoolean(new byte[0], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToInt16(new byte[1], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToUInt16(new byte[1], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToInt32(new byte[3], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToUInt32(new byte[3], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToInt64(new byte[7], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.BigEndianConverter.ToUInt64(new byte[7], 0));
}
/// <summary>
/// Tests that passing a <see cref="bool"/> returns the correct bytes.
/// </summary>
[Fact]
public void ToBoolean()
{
Assert.Equal(false, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0 }, 0));
Assert.Equal(true, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1 }, 0));
Assert.Equal(true, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 42 }, 0));
}
/// <summary>
/// Tests that passing a <see cref="short"/> returns the correct bytes.
/// </summary>
[Fact]
public void ToInt16()
{
Assert.Equal((short)0, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 0, 0 }, 0));
Assert.Equal((short)1, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 0, 1 }, 0));
Assert.Equal((short)256, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 1, 0 }, 0));
Assert.Equal((short)-1, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 255, 255 }, 0));
Assert.Equal((short)257, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 1, 1 }, 0));
}
/// <summary>
/// Tests that passing a <see cref="ushort"/> returns the correct bytes.
/// </summary>
[Fact]
public void ToUInt16()
{
Assert.Equal((ushort)0, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 0, 0 }, 0));
Assert.Equal((ushort)1, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 0, 1 }, 0));
Assert.Equal((ushort)256, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 1, 0 }, 0));
Assert.Equal(ushort.MaxValue, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 255, 255 }, 0));
Assert.Equal((ushort)257, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 1, 1 }, 0));
}
/// <summary>
/// Tests that passing a <see cref="int"/> returns the correct bytes.
/// </summary>
[Fact]
public void ToInt32()
{
Assert.Equal(0, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 0, 0, 0, 0 }, 0));
Assert.Equal(1, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 0, 0, 0, 1 }, 0));
Assert.Equal(256, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 0, 0, 1, 0 }, 0));
Assert.Equal(65536, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 0, 1, 0, 0 }, 0));
Assert.Equal(16777216, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 1, 0, 0, 0 }, 0));
Assert.Equal(-1, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 255, 255, 255, 255 }, 0));
Assert.Equal(257, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 0, 0, 1, 1 }, 0));
}
/// <summary>
/// Tests that passing a <see cref="uint"/> returns the correct bytes.
/// </summary>
[Fact]
public void ToUInt32()
{
Assert.Equal((uint)0, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 0, 0, 0, 0 }, 0));
Assert.Equal((uint)1, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 0, 0, 0, 1 }, 0));
Assert.Equal((uint)256, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 0, 0, 1, 0 }, 0));
Assert.Equal((uint)65536, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 0, 1, 0, 0 }, 0));
Assert.Equal((uint)16777216, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 1, 0, 0, 0 }, 0));
Assert.Equal(uint.MaxValue, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 255, 255, 255, 255 }, 0));
Assert.Equal((uint)257, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 0, 0, 1, 1 }, 0));
}
/// <summary>
/// Tests that passing a <see cref="long"/> returns the correct bytes.
/// </summary>
[Fact]
public void ToInt64()
{
Assert.Equal(0L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(1L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, 0));
Assert.Equal(256L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, 0));
Assert.Equal(65536L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, 0));
Assert.Equal(16777216L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, 0));
Assert.Equal(4294967296L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, 0));
Assert.Equal(1099511627776L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(1099511627776L * 256, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(1099511627776L * 256 * 256, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(-1L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, 0));
Assert.Equal(257L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, 0));
}
/// <summary>
/// Tests that passing a <see cref="ulong"/> returns the correct bytes.
/// </summary>
[Fact]
public void GetBytesULong()
{
Assert.Equal(0UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(1UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, 0));
Assert.Equal(256UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, 0));
Assert.Equal(65536UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, 0));
Assert.Equal(16777216UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, 0));
Assert.Equal(4294967296UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, 0));
Assert.Equal(1099511627776UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(1099511627776UL * 256, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(1099511627776UL * 256 * 256, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(ulong.MaxValue, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, 0));
Assert.Equal(257UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, 0));
}
}
}

230
tests/ImageSharp.Tests/IO/LittleEndianBitConverter.CopyBytesTests.cs

@ -0,0 +1,230 @@
// <copyright file="LittleEndianBitConverter.CopyBytesTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests.IO
{
using System;
using ImageSharp.IO;
using Xunit;
/// <summary>
/// The <see cref="LittleEndianBitConverter"/> tests.
/// </summary>
public class LittleEndianBitConverterCopyBytesTests
{
[Fact]
public void CopyToWithNullBufferThrowsException()
{
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes(false, null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes((short)42, null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)42, null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42, null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42u, null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42L, null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes((ulong)42L, null, 0));
}
[Fact]
public void CopyToWithIndexTooBigThrowsException()
{
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes(false, new byte[1], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes((short)42, new byte[2], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)42, new byte[2], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42, new byte[4], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42u, new byte[4], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42L, new byte[8], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes((ulong)42L, new byte[8], 1));
}
[Fact]
public void CopyToWithBufferTooSmallThrowsException()
{
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes(false, new byte[0], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes((short)42, new byte[1], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)42, new byte[1], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42, new byte[3], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42u, new byte[3], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42L, new byte[7], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.CopyBytes((ulong)42L, new byte[7], 0));
}
/// <summary>
/// Tests that passing a <see cref="bool"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesBoolean()
{
byte[] buffer = new byte[1];
EndianBitConverter.LittleEndianConverter.CopyBytes(false, buffer, 0);
this.CheckBytes(new byte[] { 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(true, buffer, 0);
this.CheckBytes(new byte[] { 1 }, buffer);
}
/// <summary>
/// Tests that passing a <see cref="short"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesShort()
{
byte[] buffer = new byte[2];
EndianBitConverter.LittleEndianConverter.CopyBytes((short)0, buffer, 0);
this.CheckBytes(new byte[] { 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes((short)1, buffer, 0);
this.CheckBytes(new byte[] { 1, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes((short)256, buffer, 0);
this.CheckBytes(new byte[] { 0, 1 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes((short)-1, buffer, 0);
this.CheckBytes(new byte[] { 255, 255 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes((short)257, buffer, 0);
this.CheckBytes(new byte[] { 1, 1 }, buffer);
}
/// <summary>
/// Tests that passing a <see cref="ushort"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesUShort()
{
byte[] buffer = new byte[2];
EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)0, buffer, 0);
this.CheckBytes(new byte[] { 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)1, buffer, 0);
this.CheckBytes(new byte[] { 1, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)256, buffer, 0);
this.CheckBytes(new byte[] { 0, 1 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(ushort.MaxValue, buffer, 0);
this.CheckBytes(new byte[] { 255, 255 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)257, buffer, 0);
this.CheckBytes(new byte[] { 1, 1 }, buffer);
}
/// <summary>
/// Tests that passing a <see cref="int"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesInt()
{
byte[] buffer = new byte[4];
EndianBitConverter.LittleEndianConverter.CopyBytes(0, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(1, buffer, 0);
this.CheckBytes(new byte[] { 1, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(256, buffer, 0);
this.CheckBytes(new byte[] { 0, 1, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(65536, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 1, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(16777216, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 1 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(-1, buffer, 0);
this.CheckBytes(new byte[] { 255, 255, 255, 255 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(257, buffer, 0);
this.CheckBytes(new byte[] { 1, 1, 0, 0 }, buffer);
}
/// <summary>
/// Tests that passing a <see cref="uint"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesUInt()
{
byte[] buffer = new byte[4];
EndianBitConverter.LittleEndianConverter.CopyBytes((uint)0, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes((uint)1, buffer, 0);
this.CheckBytes(new byte[] { 1, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes((uint)256, buffer, 0);
this.CheckBytes(new byte[] { 0, 1, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes((uint)65536, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 1, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes((uint)16777216, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 1 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(uint.MaxValue, buffer, 0);
this.CheckBytes(new byte[] { 255, 255, 255, 255 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes((uint)257, buffer, 0);
this.CheckBytes(new byte[] { 1, 1, 0, 0 }, buffer);
}
/// <summary>
/// Tests that passing a <see cref="long"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesLong()
{
byte[] buffer = new byte[8];
EndianBitConverter.LittleEndianConverter.CopyBytes(0L, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(1L, buffer, 0);
this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(256L, buffer, 0);
this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(65536L, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(16777216L, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(4294967296L, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(1099511627776L, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(1099511627776L * 256, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(1099511627776L * 256 * 256, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(-1L, buffer, 0);
this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(257L, buffer, 0);
this.CheckBytes(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, buffer);
}
/// <summary>
/// Tests that passing a <see cref="ulong"/> returns the correct bytes.
/// </summary>
[Fact]
public void CopyBytesULong()
{
byte[] buffer = new byte[8];
EndianBitConverter.LittleEndianConverter.CopyBytes(0UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(1UL, buffer, 0);
this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(256UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(65536UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(16777216UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(4294967296UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(1099511627776UL, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(1099511627776UL * 256, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(1099511627776UL * 256 * 256, buffer, 0);
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(ulong.MaxValue, buffer, 0);
this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, buffer);
EndianBitConverter.LittleEndianConverter.CopyBytes(257UL, buffer, 0);
this.CheckBytes(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, buffer);
}
/// <summary>
/// Tests the two byte arrays for equality.
/// </summary>
/// <param name="expected">The expected bytes.</param>
/// <param name="actual">The actual bytes.</param>
private void CheckBytes(byte[] expected, byte[] actual)
{
Assert.Equal(expected.Length, actual.Length);
Assert.Equal(expected, actual);
}
}
}

110
tests/ImageSharp.Tests/IO/LittleEndianBitConverterTests.cs → tests/ImageSharp.Tests/IO/LittleEndianBitConverter.GetBytesTests.cs

@ -1,4 +1,4 @@
// <copyright file="LittleEndianBitConverterTests.cs" company="James Jackson-South">
// <copyright file="LittleEndianBitConverter.GetBytesTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -6,25 +6,47 @@
namespace ImageSharp.Tests.IO
{
using ImageSharp.IO;
using Xunit;
/// <summary>
/// The <see cref="LittleEndianBitConverter"/> tests.
/// </summary>
public class LittleEndianBitConverterTests
public class LittleEndianBitConverterGetBytesTests
{
/// <summary>
/// Tests that passing a <see cref="bool"/> returns the correct bytes.
/// </summary>
[Fact]
public void GetBytesBoolean()
{
this.CheckBytes(new byte[] { 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(false));
this.CheckBytes(new byte[] { 1 }, EndianBitConverter.LittleEndianConverter.GetBytes(true));
}
/// <summary>
/// Tests that passing a <see cref="short"/> returns the correct bytes.
/// </summary>
[Fact]
public void GetBytesShort()
{
this.CheckBytes(new byte[] { 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((short)0));
this.CheckBytes(new byte[] { 1, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((short)1));
this.CheckBytes(new byte[] { 0, 1 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((short)256));
this.CheckBytes(new byte[] { 255, 255 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((short)-1));
this.CheckBytes(new byte[] { 1, 1 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((short)257));
this.CheckBytes(new byte[] { 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((short)0));
this.CheckBytes(new byte[] { 1, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((short)1));
this.CheckBytes(new byte[] { 0, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes((short)256));
this.CheckBytes(new byte[] { 255, 255 }, EndianBitConverter.LittleEndianConverter.GetBytes((short)-1));
this.CheckBytes(new byte[] { 1, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes((short)257));
}
/// <summary>
/// Tests that passing a <see cref="ushort"/> returns the correct bytes.
/// </summary>
[Fact]
public void GetBytesUShort()
{
this.CheckBytes(new byte[] { 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((ushort)0));
this.CheckBytes(new byte[] { 1, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((ushort)1));
this.CheckBytes(new byte[] { 0, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes((ushort)256));
this.CheckBytes(new byte[] { 255, 255 }, EndianBitConverter.LittleEndianConverter.GetBytes(ushort.MaxValue));
this.CheckBytes(new byte[] { 1, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes((ushort)257));
}
/// <summary>
@ -33,13 +55,13 @@ namespace ImageSharp.Tests.IO
[Fact]
public void GetBytesInt()
{
this.CheckBytes(new byte[] { 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((int)0));
this.CheckBytes(new byte[] { 1, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((int)1));
this.CheckBytes(new byte[] { 0, 1, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((int)256));
this.CheckBytes(new byte[] { 0, 0, 1, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((int)65536));
this.CheckBytes(new byte[] { 0, 0, 0, 1 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((int)16777216));
this.CheckBytes(new byte[] { 255, 255, 255, 255 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((int)-1));
this.CheckBytes(new byte[] { 1, 1, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((int)257));
this.CheckBytes(new byte[] { 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(0));
this.CheckBytes(new byte[] { 1, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1));
this.CheckBytes(new byte[] { 0, 1, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(256));
this.CheckBytes(new byte[] { 0, 0, 1, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(65536));
this.CheckBytes(new byte[] { 0, 0, 0, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes(16777216));
this.CheckBytes(new byte[] { 255, 255, 255, 255 }, EndianBitConverter.LittleEndianConverter.GetBytes(-1));
this.CheckBytes(new byte[] { 1, 1, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(257));
}
/// <summary>
@ -48,13 +70,13 @@ namespace ImageSharp.Tests.IO
[Fact]
public void GetBytesUInt()
{
this.CheckBytes(new byte[] { 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((uint)0));
this.CheckBytes(new byte[] { 1, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((uint)1));
this.CheckBytes(new byte[] { 0, 1, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((uint)256));
this.CheckBytes(new byte[] { 0, 0, 1, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((uint)65536));
this.CheckBytes(new byte[] { 0, 0, 0, 1 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((uint)16777216));
this.CheckBytes(new byte[] { 255, 255, 255, 255 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((uint)uint.MaxValue));
this.CheckBytes(new byte[] { 1, 1, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes((uint)257));
this.CheckBytes(new byte[] { 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((uint)0));
this.CheckBytes(new byte[] { 1, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((uint)1));
this.CheckBytes(new byte[] { 0, 1, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((uint)256));
this.CheckBytes(new byte[] { 0, 0, 1, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((uint)65536));
this.CheckBytes(new byte[] { 0, 0, 0, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes((uint)16777216));
this.CheckBytes(new byte[] { 255, 255, 255, 255 }, EndianBitConverter.LittleEndianConverter.GetBytes(uint.MaxValue));
this.CheckBytes(new byte[] { 1, 1, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((uint)257));
}
/// <summary>
@ -63,17 +85,17 @@ namespace ImageSharp.Tests.IO
[Fact]
public void GetBytesLong()
{
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(0L));
this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(1L));
this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(256L));
this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(65536L));
this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(16777216L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(4294967296L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(1099511627776L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(1099511627776L * 256));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(1099511627776L * 256 * 256));
this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(-1L));
this.CheckBytes(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(257L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(0L));
this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1L));
this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(256L));
this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(65536L));
this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(16777216L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(4294967296L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1099511627776L));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1099511627776L * 256));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes(1099511627776L * 256 * 256));
this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, EndianBitConverter.LittleEndianConverter.GetBytes(-1L));
this.CheckBytes(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(257L));
}
/// <summary>
@ -82,17 +104,17 @@ namespace ImageSharp.Tests.IO
[Fact]
public void GetBytesULong()
{
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(0UL));
this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(1UL));
this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(256UL));
this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(65536UL));
this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(16777216UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(4294967296UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(1099511627776UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(1099511627776UL * 256));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(1099511627776UL * 256 * 256));
this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(ulong.MaxValue));
this.CheckBytes(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.GetConverter(Endianness.LittleEndian).GetBytes(257UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(0UL));
this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1UL));
this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(256UL));
this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(65536UL));
this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(16777216UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(4294967296UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1099511627776UL));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1099511627776UL * 256));
this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes(1099511627776UL * 256 * 256));
this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, EndianBitConverter.LittleEndianConverter.GetBytes(ulong.MaxValue));
this.CheckBytes(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(257UL));
}
/// <summary>

157
tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs

@ -0,0 +1,157 @@
// <copyright file="LittleEndianBitConverter.ToTypeTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests.IO
{
using System;
using ImageSharp.IO;
using Xunit;
/// <summary>
/// The <see cref="LittleEndianBitConverter"/> tests.
/// </summary>
public class LittleEndianBitConverterToTypeTests
{
[Fact]
public void CopyToWithNullBufferThrowsException()
{
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.ToBoolean(null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.ToInt16(null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.ToUInt16(null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.ToInt32(null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.ToUInt32(null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.ToInt64(null, 0));
Assert.Throws<ArgumentNullException>(() => EndianBitConverter.LittleEndianConverter.ToUInt64(null, 0));
}
[Fact]
public void CopyToWithIndexTooBigThrowsException()
{
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[1], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToInt16(new byte[2], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[2], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToInt32(new byte[4], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[4], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToInt64(new byte[8], 1));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[8], 1));
}
[Fact]
public void CopyToWithBufferTooSmallThrowsException()
{
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[0], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToInt16(new byte[1], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[1], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToInt32(new byte[3], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[3], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToInt64(new byte[7], 0));
Assert.Throws<ArgumentOutOfRangeException>(() => EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[7], 0));
}
/// <summary>
/// Tests that passing a <see cref="bool"/> returns the correct bytes.
/// </summary>
[Fact]
public void ToBoolean()
{
Assert.Equal(false, EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0 }, 0));
Assert.Equal(true, EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1 }, 0));
}
/// <summary>
/// Tests that passing a <see cref="short"/> returns the correct bytes.
/// </summary>
[Fact]
public void ToInt16()
{
Assert.Equal((short)0, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 0, 0 }, 0));
Assert.Equal((short)1, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 1, 0 }, 0));
Assert.Equal((short)256, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 0, 1 }, 0));
Assert.Equal((short)-1, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 255, 255 }, 0));
Assert.Equal((short)257, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 1, 1 }, 0));
}
/// <summary>
/// Tests that passing a <see cref="ushort"/> returns the correct bytes.
/// </summary>
[Fact]
public void ToUInt16()
{
Assert.Equal((ushort)0, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 0, 0 }, 0));
Assert.Equal((ushort)1, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 1, 0 }, 0));
Assert.Equal((ushort)256, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 0, 1 }, 0));
Assert.Equal(ushort.MaxValue, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 255, 255 }, 0));
Assert.Equal((ushort)257, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 1, 1 }, 0));
}
/// <summary>
/// Tests that passing a <see cref="int"/> returns the correct bytes.
/// </summary>
[Fact]
public void ToInt32()
{
Assert.Equal(0, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 0, 0, 0, 0 }, 0));
Assert.Equal(1, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 1, 0, 0, 0 }, 0));
Assert.Equal(256, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 0, 1, 0, 0 }, 0));
Assert.Equal(65536, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 0, 0, 1, 0 }, 0));
Assert.Equal(16777216, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 0, 0, 0, 1 }, 0));
Assert.Equal(-1, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 255, 255, 255, 255 }, 0));
Assert.Equal(257, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 1, 1, 0, 0 }, 0));
}
/// <summary>
/// Tests that passing a <see cref="uint"/> returns the correct bytes.
/// </summary>
[Fact]
public void ToUInt32()
{
Assert.Equal((uint)0, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 0, 0, 0, 0 }, 0));
Assert.Equal((uint)1, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 1, 0, 0, 0 }, 0));
Assert.Equal((uint)256, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 0, 1, 0, 0 }, 0));
Assert.Equal((uint)65536, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 0, 0, 1, 0 }, 0));
Assert.Equal((uint)16777216, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 0, 0, 0, 1 }, 0));
Assert.Equal(uint.MaxValue, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 255, 255, 255, 255 }, 0));
Assert.Equal((uint)257, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 1, 1, 0, 0 }, 0));
}
/// <summary>
/// Tests that passing a <see cref="long"/> returns the correct bytes.
/// </summary>
[Fact]
public void ToInt64()
{
Assert.Equal(0L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(1L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(256L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(65536L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(16777216L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, 0));
Assert.Equal(4294967296L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, 0));
Assert.Equal(1099511627776L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, 0));
Assert.Equal(1099511627776L * 256, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, 0));
Assert.Equal(1099511627776L * 256 * 256, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, 0));
Assert.Equal(-1L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, 0));
Assert.Equal(257L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, 0));
}
/// <summary>
/// Tests that passing a <see cref="ulong"/> returns the correct bytes.
/// </summary>
[Fact]
public void ToUInt64()
{
Assert.Equal(0UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(1UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(256UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(65536UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, 0));
Assert.Equal(16777216UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, 0));
Assert.Equal(4294967296UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, 0));
Assert.Equal(1099511627776UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, 0));
Assert.Equal(1099511627776UL * 256, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, 0));
Assert.Equal(1099511627776UL * 256 * 256, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, 0));
Assert.Equal(ulong.MaxValue, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, 0));
Assert.Equal(257UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, 0));
}
}
}

119
tests/ImageSharp.Tests/ImageComparer.cs

@ -0,0 +1,119 @@
namespace ImageSharp.Tests
{
using System;
using ImageSharp;
using Xunit;
/// <summary>
/// Class to perform simple image comparisons.
/// </summary>
public static class ImageComparer
{
const int DefaultScalingFactor = 32; // this is means the images get scaled into a 32x32 image to sample pixels
const int DefaultSegmentThreshold = 3; // the greyscale difference between 2 segements my be > 3 before it influances the overall difference
const float DefaultImageThreshold = 0.000f; // after segment threasholds the images must have no differences
/// <summary>
/// Does a visual comparison between 2 images and then asserts the difference is less then a configurable threshold
/// </summary>
/// <typeparam name="TColorA">The color of the expected image</typeparam>
/// <typeparam name="TColorB">The color type fo the the actual image</typeparam>
/// <param name="expected">The expected image</param>
/// <param name="actual">The actual image</param>
/// <param name="imageTheshold">
/// The threshold for the percentage difference where the images are asumed to be the same.
/// The default/undefined value is <see cref="ImageComparer.DefaultImageThreshold"/>
/// </param>
/// <param name="segmentThreshold">
/// The threashold of the individual segments before it acumulates towards the overall difference.
/// The default undefined value is <see cref="ImageComparer.DefaultSegmentThreshold"/>
/// </param>
/// <param name="scalingFactor">
/// This is a sampling factor we sample a grid of average pixels <paramref name="scalingFactor"/> width by <paramref name="scalingFactor"/> high
/// The default undefined value is <see cref="ImageComparer.DefaultScalingFactor"/>
/// </param>
public static void CheckSimilarity<TColorA, TColorB>(Image<TColorA> expected, Image<TColorB> actual, float imageTheshold = DefaultImageThreshold, byte segmentThreshold = DefaultSegmentThreshold, int scalingFactor = DefaultScalingFactor)
where TColorA : struct, IPixel<TColorA>
where TColorB : struct, IPixel<TColorB>
{
float percentage = expected.PercentageDifference(actual, segmentThreshold, scalingFactor);
Assert.InRange(percentage, 0, imageTheshold);
}
/// <summary>
/// Does a visual comparison between 2 images and then and returns the percentage diffence between the 2
/// </summary>
/// <typeparam name="TColorA">The color of the source image</typeparam>
/// <typeparam name="TColorB">The color type for the target image</typeparam>
/// <param name="source">The source image</param>
/// <param name="target">The target image</param>
/// <param name="segmentThreshold">
/// The threashold of the individual segments before it acumulates towards the overall difference.
/// The default undefined value is <see cref="ImageComparer.DefaultSegmentThreshold"/>
/// </param>
/// <param name="scalingFactor">
/// This is a sampling factor we sample a grid of average pixels <paramref name="scalingFactor"/> width by <paramref name="scalingFactor"/> high
/// The default undefined value is <see cref="ImageComparer.DefaultScalingFactor"/>
/// </param>
/// <returns>Returns a number from 0 - 1 which represents the diference focter between the images.</returns>
public static float PercentageDifference<TColorA, TColorB>(this Image<TColorA> source, Image<TColorB> target, byte segmentThreshold = DefaultSegmentThreshold, int scalingFactor = DefaultScalingFactor)
where TColorA : struct, IPixel<TColorA>
where TColorB : struct, IPixel<TColorB>
{
// code adapted from https://www.codeproject.com/Articles/374386/Simple-image-comparison-in-NET
Fast2DArray<byte> differences = GetDifferences(source, target, scalingFactor);
int diffPixels = 0;
foreach (byte b in differences.Data)
{
if (b > segmentThreshold) { diffPixels++; }
}
return diffPixels / (scalingFactor * scalingFactor);
}
private static Fast2DArray<byte> GetDifferences<TColorA, TColorB>(Image<TColorA> source, Image<TColorB> target, int scalingFactor)
where TColorA : struct, IPixel<TColorA>
where TColorB : struct, IPixel<TColorB>
{
Fast2DArray<byte> differences = new Fast2DArray<byte>(scalingFactor, scalingFactor);
Fast2DArray<byte> firstGray = source.GetGrayScaleValues(scalingFactor);
Fast2DArray<byte> secondGray = target.GetGrayScaleValues(scalingFactor);
for (int y = 0; y < scalingFactor; y++)
{
for (int x = 0; x < scalingFactor; x++)
{
differences[x, y] = (byte)Math.Abs(firstGray[x, y] - secondGray[x, y]);
}
}
return differences;
}
private static Fast2DArray<byte> GetGrayScaleValues<TColorA>(this Image<TColorA> source, int scalingFactor)
where TColorA : struct, IPixel<TColorA>
{
byte[] buffer = new byte[4];
using (Image<TColorA> img = new Image<TColorA>(source).Resize(scalingFactor, scalingFactor).Grayscale())
{
using (PixelAccessor<TColorA> pixels = img.Lock())
{
Fast2DArray<byte> grayScale = new Fast2DArray<byte>(scalingFactor, scalingFactor);
for (int y = 0; y < scalingFactor; y++)
{
for (int x = 0; x < scalingFactor; x++)
{
pixels[x, y].ToXyzBytes(buffer, 0);
grayScale[x, y] = buffer[1];
}
}
return grayScale;
}
}
}
}
}

34
tests/ImageSharp.Tests/Processors/Filters/GrayscaleTest.cs

@ -9,30 +9,32 @@ namespace ImageSharp.Tests
using Xunit;
using ImageSharp.Processing;
using ImageSharp.Tests;
using System.Numerics;
public class GrayscaleTest : FileTestBase
{
public static readonly TheoryData<GrayscaleMode> GrayscaleValues
= new TheoryData<GrayscaleMode>
{
GrayscaleMode.Bt709 ,
GrayscaleMode.Bt601 ,
};
/// <summary>
/// Use test patterns over loaded images to save decode time.
/// </summary>
[Theory]
[MemberData(nameof(GrayscaleValues))]
public void ImageShouldApplyGrayscaleFilter(GrayscaleMode value)
[WithTestPatternImages(50, 50, PixelTypes.StandardImageClass, GrayscaleMode.Bt709)]
[WithTestPatternImages(50, 50, PixelTypes.StandardImageClass, GrayscaleMode.Bt601)]
public void ImageShouldApplyGrayscaleFilterAll<TColor>(TestImageProvider<TColor> provider, GrayscaleMode value)
where TColor : struct, IPixel<TColor>
{
string path = this.CreateOutputDirectory("Grayscale");
foreach (TestFile file in Files)
using (Image<TColor> image = provider.GetImage())
{
string filename = file.GetFileName(value);
using (Image image = file.CreateImage())
using (FileStream output = File.OpenWrite($"{path}/{filename}"))
image.Grayscale(value);
byte[] data = new byte[3];
foreach (TColor p in image.Pixels)
{
image.Grayscale(value).Save(output);
p.ToXyzBytes(data, 0);
Assert.Equal(data[0], data[1]);
Assert.Equal(data[1], data[2]);
}
image.DebugSave(provider);
}
}
}

38
tests/ImageSharp.Tests/TestUtilities/Attributes/WithTestPatternImageAttribute.cs

@ -0,0 +1,38 @@
// <copyright file="WithBlankImagesAttribute.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests
{
using System;
using System.Reflection;
/// <summary>
/// Triggers passing <see cref="TestImageProvider{TColor}"/> instances which produce a blank image of size width * height.
/// One <see cref="TestImageProvider{TColor}"/> instance will be passed for each the pixel format defined by the pixelTypes parameter
/// </summary>
public class WithTestPatternImagesAttribute : ImageDataAttributeBase
{
/// <summary>
/// Triggers passing an <see cref="TestImageProvider{TColor}"/> that produces a test pattern image of size width * height
/// </summary>
/// <param name="width">The required width</param>
/// <param name="height">The required height</param>
/// <param name="pixelTypes">The requested parameter</param>
/// <param name="additionalParameters">Additional theory parameter values</param>
public WithTestPatternImagesAttribute(int width, int height, PixelTypes pixelTypes, params object[] additionalParameters)
: base(pixelTypes, additionalParameters)
{
this.Width = width;
this.Height = height;
}
public int Width { get; }
public int Height { get; }
protected override string GetFactoryMethodName(MethodInfo testMethod) => "TestPattern";
protected override object[] GetFactoryMethodArgs(MethodInfo testMethod, Type factoryType) => new object[] { this.Width, this.Height };
}
}

27
tests/ImageSharp.Tests/TestUtilities/ImageProviders/BlankProvider.cs

@ -6,25 +6,46 @@
namespace ImageSharp.Tests
{
using System;
using Xunit.Abstractions;
public abstract partial class TestImageProvider<TColor>
where TColor : struct, IPixel<TColor>
{
private class BlankProvider : TestImageProvider<TColor>
private class BlankProvider : TestImageProvider<TColor>, IXunitSerializable
{
public BlankProvider(int width, int height)
{
this.Width = width;
this.Height = height;
}
public BlankProvider()
{
this.Width = 100;
this.Height = 100;
}
public override string SourceFileOrDescription => $"Blank{this.Width}x{this.Height}";
protected int Height { get; }
protected int Height { get; private set; }
protected int Width { get; }
protected int Width { get; private set; }
public override Image<TColor> GetImage() => this.Factory.CreateImage(this.Width, this.Height);
public override void Deserialize(IXunitSerializationInfo info)
{
this.Width = info.GetValue<int>("width");
this.Height = info.GetValue<int>("height");
base.Deserialize(info);
}
public override void Serialize(IXunitSerializationInfo info)
{
info.AddValue("width", this.Width);
info.AddValue("height", this.Height);
base.Serialize(info);
}
}
}
}

20
tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs

@ -7,11 +7,12 @@ namespace ImageSharp.Tests
{
using System;
using System.Collections.Concurrent;
using Xunit.Abstractions;
public abstract partial class TestImageProvider<TColor>
where TColor : struct, IPixel<TColor>
{
private class FileProvider : TestImageProvider<TColor>
private class FileProvider : TestImageProvider<TColor>, IXunitSerializable
{
// Need PixelTypes in the dictionary key, because result images of TestImageProvider<TColor>.FileProvider
// are shared between PixelTypes.Color & PixelTypes.StandardImageClass
@ -33,6 +34,10 @@ namespace ImageSharp.Tests
this.filePath = filePath;
}
public FileProvider()
{
}
public override string SourceFileOrDescription => this.filePath;
public override Image<TColor> GetImage()
@ -49,6 +54,19 @@ namespace ImageSharp.Tests
return this.Factory.CreateImage(cachedImage);
}
public override void Deserialize(IXunitSerializationInfo info)
{
this.filePath = info.GetValue<string>("path");
base.Deserialize(info); // must be called last
}
public override void Serialize(IXunitSerializationInfo info)
{
base.Serialize(info);
info.AddValue("path", this.filePath);
}
}
}
}

38
tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs

@ -6,6 +6,7 @@
namespace ImageSharp.Tests
{
using System;
using Xunit.Abstractions;
/// <summary>
/// Provides <see cref="Image{TColor}" /> instances for parametric unit tests.
@ -14,15 +15,15 @@ namespace ImageSharp.Tests
public abstract partial class TestImageProvider<TColor>
where TColor : struct, IPixel<TColor>
{
private class SolidProvider : BlankProvider
private class SolidProvider : BlankProvider
{
private readonly byte a;
private byte a;
private readonly byte b;
private byte b;
private readonly byte g;
private byte g;
private readonly byte r;
private byte r;
public SolidProvider(int width, int height, byte r, byte g, byte b, byte a)
: base(width, height)
@ -33,6 +34,15 @@ namespace ImageSharp.Tests
this.a = a;
}
public SolidProvider()
: base()
{
this.r = 0;
this.g = 0;
this.b = 0;
this.a = 0;
}
public override string SourceFileOrDescription
=> $"Solid{this.Width}x{this.Height}_({this.r},{this.g},{this.b},{this.a})";
@ -44,6 +54,24 @@ namespace ImageSharp.Tests
return image.Fill(color);
}
public override void Serialize(IXunitSerializationInfo info)
{
info.AddValue("red", this.r);
info.AddValue("green", this.g);
info.AddValue("blue", this.b);
info.AddValue("alpha", this.a);
base.Serialize(info);
}
public override void Deserialize(IXunitSerializationInfo info)
{
this.r = info.GetValue<byte>("red");
this.g = info.GetValue<byte>("green");
this.b = info.GetValue<byte>("blue");
this.a = info.GetValue<byte>("alpha");
base.Deserialize(info);
}
}
}
}

53
tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs

@ -7,12 +7,13 @@ namespace ImageSharp.Tests
{
using System;
using System.Reflection;
using Xunit.Abstractions;
/// <summary>
/// Provides <see cref="Image{TColor}" /> instances for parametric unit tests.
/// </summary>
/// <typeparam name="TColor">The pixel format of the image</typeparam>
public abstract partial class TestImageProvider<TColor>
public abstract partial class TestImageProvider<TColor>
where TColor : struct, IPixel<TColor>
{
public PixelTypes PixelType { get; private set; } = typeof(TColor).GetPixelType();
@ -25,13 +26,22 @@ namespace ImageSharp.Tests
public ImagingTestCaseUtility Utility { get; private set; }
public GenericFactory<TColor> Factory { get; private set; } = new GenericFactory<TColor>();
public string TypeName { get; private set; }
public string MethodName { get; private set; }
public static TestImageProvider<TColor> Blank(
public static TestImageProvider<TColor> TestPattern(
int width,
int height,
MethodInfo testMethod = null,
PixelTypes pixelTypeOverride = PixelTypes.Undefined)
=> new BlankProvider(width, height).Init(testMethod, pixelTypeOverride);
=> new TestPatternProvider(width, height).Init(testMethod, pixelTypeOverride);
public static TestImageProvider<TColor> Blank(
int width,
int height,
MethodInfo testMethod = null,
PixelTypes pixelTypeOverride = PixelTypes.Undefined)
=> new BlankProvider(width, height).Init(testMethod, pixelTypeOverride);
public static TestImageProvider<TColor> File(
string filePath,
@ -65,12 +75,30 @@ namespace ImageSharp.Tests
/// </summary>
public abstract Image<TColor> GetImage();
protected TestImageProvider<TColor> Init(MethodInfo testMethod, PixelTypes pixelTypeOverride)
public virtual void Deserialize(IXunitSerializationInfo info)
{
PixelTypes pixelType = info.GetValue<PixelTypes>("PixelType");
string typeName = info.GetValue<string>("TypeName");
string methodName = info.GetValue<string>("MethodName");
this.Init(typeName, methodName, pixelType);
}
public virtual void Serialize(IXunitSerializationInfo info)
{
info.AddValue("PixelType", this.PixelType);
info.AddValue("TypeName", this.TypeName);
info.AddValue("MethodName", this.MethodName);
}
protected TestImageProvider<TColor> Init(string typeName, string methodName, PixelTypes pixelTypeOverride)
{
if (pixelTypeOverride != PixelTypes.Undefined)
{
this.PixelType = pixelTypeOverride;
}
this.TypeName = typeName;
this.MethodName = methodName;
if (pixelTypeOverride == PixelTypes.StandardImageClass)
{
@ -78,19 +106,24 @@ namespace ImageSharp.Tests
}
this.Utility = new ImagingTestCaseUtility()
{
SourceFileOrDescription = this.SourceFileOrDescription,
PixelTypeName = this.PixelType.ToString()
};
{
SourceFileOrDescription = this.SourceFileOrDescription,
PixelTypeName = this.PixelType.ToString()
};
if (testMethod != null)
if (methodName != null)
{
this.Utility.Init(testMethod);
this.Utility.Init(typeName, methodName);
}
return this;
}
protected TestImageProvider<TColor> Init(MethodInfo testMethod, PixelTypes pixelTypeOverride)
{
return Init(testMethod?.DeclaringType.Name, testMethod?.Name, pixelTypeOverride);
}
public override string ToString()
{
string provName = this.GetType().Name.Replace("Provider", "");

210
tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs

@ -0,0 +1,210 @@
// <copyright file="BlankProvider.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests
{
using System;
using System.Collections.Generic;
using System.Numerics;
using Xunit.Abstractions;
public abstract partial class TestImageProvider<TColor>
where TColor : struct, IPixel<TColor>
{
/// <summary>
/// A test image provider that produces test patterns.
/// </summary>
/// <typeparam name="TColor"></typeparam>
private class TestPatternProvider : BlankProvider
{
static Dictionary<string, Image<TColor>> testImages = new Dictionary<string, Image<TColor>>();
public TestPatternProvider(int width, int height)
: base(width, height)
{
}
public TestPatternProvider()
: base()
{
}
public override string SourceFileOrDescription => $"TestPattern{this.Width}x{this.Height}";
public override Image<TColor> GetImage()
{
lock (testImages)
{
if (!testImages.ContainsKey(this.SourceFileOrDescription))
{
Image<TColor> image = new Image<TColor>(this.Width, this.Height);
DrawTestPattern(image);
testImages.Add(this.SourceFileOrDescription, image);
}
}
return new Image<TColor>(testImages[this.SourceFileOrDescription]);
}
/// <summary>
/// Draws the test pattern on an image by drawing 4 other patterns in the for quadrants of the image.
/// </summary>
/// <param name="image"></param>
private static void DrawTestPattern(Image<TColor> image)
{
// first lets split the image into 4 quadrants
using (PixelAccessor<TColor> pixels = image.Lock())
{
BlackWhiteChecker(pixels); // top left
VirticalBars(pixels); // top right
TransparentGradients(pixels); // bottom left
Rainbow(pixels); // bottom right
}
}
/// <summary>
/// Fills the top right quadrant with alternating solid vertical bars.
/// </summary>
/// <param name="pixels"></param>
private static void VirticalBars(PixelAccessor<TColor> pixels)
{
// topLeft
int left = pixels.Width / 2;
int right = pixels.Width;
int top = 0;
int bottom = pixels.Height / 2;
int stride = pixels.Width / 12;
TColor[] c = {
NamedColors<TColor>.HotPink,
NamedColors<TColor>.Blue
};
int p = 0;
for (int y = top; y < bottom; y++)
{
for (int x = left; x < right; x++)
{
if (x % stride == 0)
{
p++;
p = p % c.Length;
}
pixels[x, y] = c[p];
}
}
}
/// <summary>
/// fills the top left quadrant with a black and white checker board.
/// </summary>
/// <param name="pixels"></param>
private static void BlackWhiteChecker(PixelAccessor<TColor> pixels)
{
// topLeft
int left = 0;
int right = pixels.Width / 2;
int top = 0;
int bottom = pixels.Height / 2;
int stride = pixels.Width / 6;
TColor[] c = {
NamedColors<TColor>.Black,
NamedColors<TColor>.White
};
int p = 0;
for (int y = top; y < bottom; y++)
{
if (y % stride == 0)
{
p++;
p = p % c.Length;
}
int pstart = p;
for (int x = left; x < right; x++)
{
if (x % stride == 0)
{
p++;
p = p % c.Length;
}
pixels[x, y] = c[p];
}
p = pstart;
}
}
/// <summary>
/// Fills the bottom left quadrent with 3 horizental bars in Red, Green and Blue with a alpha gradient from left (transparent) to right (solid).
/// </summary>
/// <param name="pixels"></param>
private static void TransparentGradients(PixelAccessor<TColor> pixels)
{
// topLeft
int left = 0;
int right = pixels.Width / 2;
int top = pixels.Height / 2;
int bottom = pixels.Height;
int height = (int)Math.Ceiling(pixels.Height / 6f);
Vector4 red = Color.Red.ToVector4(); // use real color so we can see har it translates in the test pattern
Vector4 green = Color.Green.ToVector4(); // use real color so we can see har it translates in the test pattern
Vector4 blue = Color.Blue.ToVector4(); // use real color so we can see har it translates in the test pattern
TColor c = default(TColor);
for (int x = left; x < right; x++)
{
blue.W = red.W = green.W = (float)x / (float)right;
c.PackFromVector4(red);
int topBand = top;
for (int y = topBand; y < top + height; y++)
{
pixels[x, y] = c;
}
topBand = topBand + height;
c.PackFromVector4(green);
for (int y = topBand; y < topBand + height; y++)
{
pixels[x, y] = c;
}
topBand = topBand + height;
c.PackFromVector4(blue);
for (int y = topBand; y < bottom; y++)
{
pixels[x, y] = c;
}
}
}
/// <summary>
/// Fills the bottom right quadrant with all the colors producable by converting itterating over a uint and unpacking it.
/// A better algorithm could be used but it works
/// </summary>
/// <param name="pixels"></param>
private static void Rainbow(PixelAccessor<TColor> pixels)
{
int left = pixels.Width / 2;
int right = pixels.Width;
int top = pixels.Height / 2;
int bottom = pixels.Height;
int pixelCount = left * top;
uint stepsPerPixel = (uint)(uint.MaxValue / pixelCount);
TColor c = default(TColor);
Color t = new Color(0);
for (int x = left; x < right; x++)
for (int y = top; y < bottom; y++)
{
t.PackedValue += stepsPerPixel;
Vector4 v = t.ToVector4();
//v.W = (x - left) / (float)left;
c.PackFromVector4(v);
pixels[x, y] = c;
}
}
}
}
}

43
tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs

@ -44,13 +44,26 @@ namespace ImageSharp.Tests
/// </summary>
/// <param name="extension"></param>
/// <returns>The required extension</returns>
public string GetTestOutputFileName(string extension = null)
public string GetTestOutputFileName(string extension = null, string tag = null)
{
string fn = string.Empty;
if (string.IsNullOrWhiteSpace(extension))
{
extension = null;
}
fn = Path.GetFileNameWithoutExtension(this.SourceFileOrDescription);
extension = extension ?? Path.GetExtension(this.SourceFileOrDescription);
extension = extension ?? ".bmp";
if (string.IsNullOrWhiteSpace(extension))
{
extension = Path.GetExtension(this.SourceFileOrDescription);
}
if (string.IsNullOrWhiteSpace(extension))
{
extension = ".bmp";
}
if (extension[0] != '.')
{
@ -65,7 +78,14 @@ namespace ImageSharp.Tests
pixName = '_' + pixName;
}
return $"{this.GetTestOutputDir()}/{this.TestName}{pixName}{fn}{extension}";
tag = tag ?? string.Empty;
if (tag != string.Empty)
{
tag = '_' + tag;
}
return $"{this.GetTestOutputDir()}/{this.TestName}{pixName}{fn}{tag}{extension}";
}
/// <summary>
@ -80,7 +100,7 @@ namespace ImageSharp.Tests
where TColor : struct, IPixel<TColor>
{
string path = this.GetTestOutputFileName(extension);
extension = Path.GetExtension(path);
IImageFormat format = GetImageFormatByExtension(extension);
encoder = encoder ?? format.Encoder;
@ -91,16 +111,21 @@ namespace ImageSharp.Tests
}
}
internal void Init(string typeName, string methodName)
{
this.TestGroupName = typeName;
this.TestName = methodName;
}
internal void Init(MethodInfo method)
{
this.TestGroupName = method.DeclaringType.Name;
this.TestName = method.Name;
this.Init(method.DeclaringType.Name, method.Name);
}
private static IImageFormat GetImageFormatByExtension(string extension)
{
extension = extension.ToLower();
return Configuration.Default.ImageFormats.First(f => f.SupportedExtensions.Contains(extension));
extension = extension?.TrimStart('.');
return Configuration.Default.ImageFormats.First(f => f.SupportedExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase));
}
private string GetTestOutputDir()

20
tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

@ -0,0 +1,20 @@

namespace ImageSharp.Tests
{
using System;
using System.Collections.Generic;
using System.Text;
public static class TestImageExtensions
{
public static void DebugSave<TColor>(this Image<TColor> img, TestImageProvider<TColor> provider, string extension = "png")
where TColor : struct, IPixel<TColor>
{
if(!bool.TryParse(Environment.GetEnvironmentVariable("CI"), out bool isCI) || !isCI)
{
// we are running locally then we want to save it out
provider.Utility.SaveTestOutputFile(img, extension);
}
}
}
}
Loading…
Cancel
Save