Browse Source

Merge branch 'master' of https://github.com/JimBobSquarePants/ImageSharp into jpeg-optimizations-experimental

Conflicts:
	tests/ImageSharp.Tests/Formats/Jpg/JpegTests.cs
af/merge-core
antonfirsov 9 years ago
parent
commit
c3599abbce
  1. 6
      ImageSharp.ruleset
  2. 3
      ImageSharp.sln
  3. 3
      README.md
  4. 58
      src/ImageSharp/Colors/Color.cs
  5. 20
      src/ImageSharp/Colors/ColorspaceTransforms.cs
  6. 8
      src/ImageSharp/Colors/ComponentOrder.cs
  7. 58
      src/ImageSharp/Colors/PackedPixel/Alpha8.cs
  8. 60
      src/ImageSharp/Colors/PackedPixel/Argb.cs
  9. 60
      src/ImageSharp/Colors/PackedPixel/Bgr565.cs
  10. 60
      src/ImageSharp/Colors/PackedPixel/Bgra4444.cs
  11. 60
      src/ImageSharp/Colors/PackedPixel/Bgra5551.cs
  12. 60
      src/ImageSharp/Colors/PackedPixel/Byte4.cs
  13. 73
      src/ImageSharp/Colors/PackedPixel/HalfSingle.cs
  14. 73
      src/ImageSharp/Colors/PackedPixel/HalfVector2.cs
  15. 73
      src/ImageSharp/Colors/PackedPixel/HalfVector4.cs
  16. 32
      src/ImageSharp/Colors/PackedPixel/IPackedBytes.cs
  17. 79
      src/ImageSharp/Colors/PackedPixel/NormalizedByte2.cs
  18. 79
      src/ImageSharp/Colors/PackedPixel/NormalizedByte4.cs
  19. 79
      src/ImageSharp/Colors/PackedPixel/NormalizedShort2.cs
  20. 79
      src/ImageSharp/Colors/PackedPixel/NormalizedShort4.cs
  21. 64
      src/ImageSharp/Colors/PackedPixel/Rg32.cs
  22. 64
      src/ImageSharp/Colors/PackedPixel/Rgba1010102.cs
  23. 64
      src/ImageSharp/Colors/PackedPixel/Rgba64.cs
  24. 79
      src/ImageSharp/Colors/PackedPixel/Short2.cs
  25. 91
      src/ImageSharp/Colors/PackedPixel/Short4.cs
  26. 17
      src/ImageSharp/Colors/Spaces/Bgra32.cs
  27. 24
      src/ImageSharp/Colors/Spaces/CieLab.cs
  28. 24
      src/ImageSharp/Colors/Spaces/CieXyz.cs
  29. 26
      src/ImageSharp/Colors/Spaces/Cmyk.cs
  30. 32
      src/ImageSharp/Colors/Spaces/Hsl.cs
  31. 32
      src/ImageSharp/Colors/Spaces/Hsv.cs
  32. 2
      src/ImageSharp/Colors/Spaces/IAlmostEquatable.cs
  33. 33
      src/ImageSharp/Colors/Spaces/YCbCr.cs
  34. 13
      src/ImageSharp/Colors/Vector4BlendTransforms.cs
  35. 18
      src/ImageSharp/Common/Constants.cs
  36. 17
      src/ImageSharp/Common/Helpers/ImageMaths.cs
  37. 4
      src/ImageSharp/Drawing/Processors/DrawPathProcessor.cs
  38. 4
      src/ImageSharp/Drawing/Processors/FillShapeProcessor.cs
  39. 7
      src/ImageSharp/Filters/Processors/Effects/BackgroundColorProcessor.cs
  40. 13
      src/ImageSharp/Filters/Processors/Transforms/RotateProcessor.cs
  41. 6
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  42. 8
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  43. 2
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  44. 7
      src/ImageSharp/Formats/Gif/GifEncoderCore.cs
  45. 18
      src/ImageSharp/Formats/Jpg/Components/BlockQuad.cs
  46. 4
      src/ImageSharp/Formats/Jpg/Components/Decoder/Bits.cs
  47. 287
      src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs
  48. 70
      src/ImageSharp/Formats/Jpg/Utils/JpegUtils.cs
  49. 6
      src/ImageSharp/Formats/Png/PngEncoderCore.cs
  50. 2
      src/ImageSharp/Image/ImageBase{TColor}.cs
  51. 251
      src/ImageSharp/Image/PixelAccessor{TColor}.cs
  52. 114
      src/ImageSharp/Image/PixelArea{TColor}.cs
  53. 28
      src/ImageSharp/PixelAccessor.cs
  54. 50
      src/ImageSharp/Profiles/Exif/ExifTag.cs
  55. 14
      src/ImageSharp/Quantizers/Octree/OctreeQuantizer.cs
  56. 2
      src/ImageSharp/Quantizers/Palette/PaletteQuantizer.cs
  57. 15
      src/ImageSharp/Quantizers/Wu/WuQuantizer.cs
  58. 4
      src/ImageSharp/project.json
  59. 21
      tests/ImageSharp.Benchmarks/Image/CopyPixels.cs
  60. 2
      tests/ImageSharp.Tests/Colors/ColorConversionTests.cs
  61. 165
      tests/ImageSharp.Tests/Colors/PackedPixelTests.cs
  62. 18
      tests/ImageSharp.Tests/Common/ConstantsTests.cs
  63. 4
      tests/ImageSharp.Tests/Formats/Jpg/JpegTests.cs
  64. 6
      tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementations.cs
  65. 24
      tests/ImageSharp.Tests/Image/PixelAccessorTests.cs
  66. 12
      tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs
  67. 8
      tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs
  68. 7
      tests/ImageSharp.Tests/project.json

6
ImageSharp.ruleset

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="ImageSharp" ToolsVersion="14.0">
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
<Rule Id="SA1413" Action="None" />
</Rules>
</RuleSet>

3
ImageSharp.sln

@ -20,8 +20,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionIt
build\dotnet-latest.ps1 = build\dotnet-latest.ps1
features.md = features.md
global.json = global.json
ImageSharp.ruleset = ImageSharp.ruleset
NuGet.config = NuGet.config
build\package.json = build\package.json
README.md = README.md
Rebracer.xml = Rebracer.xml
Settings.StyleCop = Settings.StyleCop
EndProjectSection
EndProject

3
README.md

@ -98,3 +98,6 @@ Grand High Eternal Dictator
Core Team
- [Dirk Lemstra](https://github.com/dlemstra)
- [Jeavon Leopold](https://github.com/jeavon)
- [Anton Firsov](https://github.com/antonfirsov)
- [Olivia Ifrim](https://github.com/olivif)
- [Scott Williams](https://github.com/tocsoft)

58
src/ImageSharp/Colors/Color.cs

@ -273,35 +273,37 @@ namespace ImageSharp
}
/// <inheritdoc/>
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
bytes[startIndex + 3] = this.A;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
bytes[startIndex + 3] = this.A;
break;
default:
throw new NotSupportedException();
}
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
}
/// <inheritdoc/>
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
bytes[startIndex + 3] = this.A;
}
/// <inheritdoc/>
public void ToZyxBytes(byte[] bytes, int startIndex)
{
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
}
/// <inheritdoc/>
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
bytes[startIndex + 3] = this.A;
}
/// <inheritdoc/>

20
src/ImageSharp/Colors/ColorspaceTransforms.cs

@ -7,6 +7,7 @@ namespace ImageSharp
{
using System;
using System.Numerics;
using Colors.Spaces;
/// <summary>
/// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 255.
@ -18,11 +19,6 @@ namespace ImageSharp
/// </remarks>
public partial struct Color
{
/// <summary>
/// The epsilon for comparing floating point numbers.
/// </summary>
private const float Epsilon = 0.001F;
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
/// <see cref="Bgra32"/>.
@ -62,9 +58,9 @@ namespace ImageSharp
/// </returns>
public static implicit operator Color(YCbCr color)
{
byte y = color.Y;
int cb = color.Cb - 128;
int cr = color.Cr - 128;
float y = color.Y;
float cb = color.Cb - 128;
float cr = color.Cr - 128;
byte r = (byte)(y + (1.402F * cr)).Clamp(0, 255);
byte g = (byte)(y - (0.34414F * cb) - (0.71414F * cr)).Clamp(0, 255);
@ -109,12 +105,12 @@ namespace ImageSharp
float s = color.S;
float v = color.V;
if (Math.Abs(s) < Epsilon)
if (Math.Abs(s) < Constants.Epsilon)
{
return new Color(v, v, v, 1);
}
float h = (Math.Abs(color.H - 360) < Epsilon) ? 0 : color.H / 60;
float h = (Math.Abs(color.H - 360) < Constants.Epsilon) ? 0 : color.H / 60;
int i = (int)Math.Truncate(h);
float f = h - i;
@ -182,9 +178,9 @@ namespace ImageSharp
float s = color.S;
float l = color.L;
if (Math.Abs(l) > Epsilon)
if (Math.Abs(l) > Constants.Epsilon)
{
if (Math.Abs(s) < Epsilon)
if (Math.Abs(s) < Constants.Epsilon)
{
r = g = b = l;
}

8
src/ImageSharp/Colors/ComponentOrder.cs

@ -13,21 +13,21 @@ namespace ImageSharp
/// <summary>
/// Z-> Y-> X order. Equivalent to B-> G-> R in <see cref="Color"/>
/// </summary>
ZYX,
Zyx,
/// <summary>
/// Z-> Y-> X-> W order. Equivalent to B-> G-> R-> A in <see cref="Color"/>
/// </summary>
ZYXW,
Zyxw,
/// <summary>
/// X-> Y-> Z order. Equivalent to R-> G-> B in <see cref="Color"/>
/// </summary>
XYZ,
Xyz,
/// <summary>
/// X-> Y-> Z-> W order. Equivalent to R-> G-> B-> A in <see cref="Color"/>
/// </summary>
XYZW,
Xyzw,
}
}

58
src/ImageSharp/Colors/PackedPixel/Alpha8.cs

@ -74,35 +74,37 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = 0;
bytes[startIndex + 1] = 0;
bytes[startIndex + 2] = 0;
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = 0;
bytes[startIndex + 1] = 0;
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = this.PackedValue;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = 0;
bytes[startIndex + 1] = 0;
bytes[startIndex + 2] = 0;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = 0;
bytes[startIndex + 1] = 0;
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = this.PackedValue;
break;
default:
throw new NotSupportedException();
}
bytes[startIndex] = 0;
bytes[startIndex + 1] = 0;
bytes[startIndex + 2] = 0;
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
bytes[startIndex] = 0;
bytes[startIndex + 1] = 0;
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = this.PackedValue;
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
bytes[startIndex] = 0;
bytes[startIndex + 1] = 0;
bytes[startIndex + 2] = 0;
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
bytes[startIndex] = 0;
bytes[startIndex + 1] = 0;
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = this.PackedValue;
}
/// <summary>

60
src/ImageSharp/Colors/PackedPixel/Argb.cs

@ -220,36 +220,38 @@ namespace ImageSharp
this.PackedValue = Pack(x, y, z, w);
}
/// <inheritdoc/>
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
/// <inheritdoc />
public void ToXyzBytes(byte[] bytes, int startIndex)
{
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
bytes[startIndex + 3] = this.A;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
bytes[startIndex + 3] = this.A;
break;
default:
throw new NotSupportedException();
}
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
bytes[startIndex + 3] = this.A;
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
bytes[startIndex + 3] = this.A;
}
/// <inheritdoc/>

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

@ -96,37 +96,41 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
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);
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
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);
}
switch (componentOrder)
{
case ComponentOrder.ZYX:
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);
break;
case ComponentOrder.ZYXW:
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);
break;
case ComponentOrder.XYZ:
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);
break;
case ComponentOrder.XYZW:
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);
break;
default:
throw new NotSupportedException();
}
/// <inheritdoc />
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);
}
/// <inheritdoc />

60
src/ImageSharp/Colors/PackedPixel/Bgra4444.cs

@ -88,37 +88,41 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
}
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
break;
default:
throw new NotSupportedException();
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />

60
src/ImageSharp/Colors/PackedPixel/Bgra5551.cs

@ -88,37 +88,41 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
}
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
break;
default:
throw new NotSupportedException();
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />

60
src/ImageSharp/Colors/PackedPixel/Byte4.cs

@ -95,37 +95,41 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
}
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
break;
default:
throw new NotSupportedException();
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />

73
src/ImageSharp/Colors/PackedPixel/HalfSingle.cs

@ -97,40 +97,57 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
break;
default:
throw new NotSupportedException();
}
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />

73
src/ImageSharp/Colors/PackedPixel/HalfVector2.cs

@ -111,40 +111,57 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
break;
default:
throw new NotSupportedException();
}
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />

73
src/ImageSharp/Colors/PackedPixel/HalfVector4.cs

@ -105,40 +105,57 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
break;
default:
throw new NotSupportedException();
}
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />

32
src/ImageSharp/Colors/PackedPixel/IPackedBytes.cs

@ -12,7 +12,7 @@ namespace ImageSharp
public interface IPackedBytes
{
/// <summary>
/// Gets the packed representation from the gives bytes.
/// Sets the packed representation from the given byte array.
/// </summary>
/// <param name="x">The x-component.</param>
/// <param name="y">The y-component.</param>
@ -21,11 +21,35 @@ namespace ImageSharp
void PackFromBytes(byte x, byte y, byte z, byte w);
/// <summary>
/// Sets the packed representation into the gives bytes.
/// Expands the packed representation into a given byte array.
/// Output is expanded to X-> Y-> Z order. Equivalent to R-> G-> B in <see cref="Color"/>
/// </summary>
/// <param name="bytes">The bytes to set the color in.</param>
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
/// <param name="componentOrder">The order of the components.</param>
void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder);
void ToXyzBytes(byte[] bytes, int startIndex);
/// <summary>
/// Expands the packed representation into a given byte array.
/// Output is expanded to X-> Y-> Z-> W order. Equivalent to R-> G-> B-> A in <see cref="Color"/>
/// </summary>
/// <param name="bytes">The bytes to set the color in.</param>
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
void ToXyzwBytes(byte[] bytes, int startIndex);
/// <summary>
/// Expands the packed representation into a given byte array.
/// Output is expanded to Z-> Y-> X order. Equivalent to B-> G-> R in <see cref="Color"/>
/// </summary>
/// <param name="bytes">The bytes to set the color in.</param>
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
void ToZyxBytes(byte[] bytes, int startIndex);
/// <summary>
/// Expands the packed representation into a given byte array.
/// Output is expanded to Z-> Y-> X-> W order. Equivalent to B-> G-> R-> A in <see cref="Color"/>
/// </summary>
/// <param name="bytes">The bytes to set the color in.</param>
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
void ToZyxwBytes(byte[] bytes, int startIndex);
}
}

79
src/ImageSharp/Colors/PackedPixel/NormalizedByte2.cs

@ -120,7 +120,7 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
@ -129,33 +129,56 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = 255;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = 0;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = 255;
break;
default:
throw new NotSupportedException();
}
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = 0;
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = 255;
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = 255;
}
/// <inheritdoc />

79
src/ImageSharp/Colors/PackedPixel/NormalizedByte4.cs

@ -114,7 +114,7 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
@ -123,33 +123,56 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
break;
default:
throw new NotSupportedException();
}
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />

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

@ -108,7 +108,7 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
@ -117,33 +117,56 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 3] = 255;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = 0;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = 255;
break;
default:
throw new NotSupportedException();
}
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = 0;
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
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] = 0;
bytes[startIndex + 3] = 255;
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
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);
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
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 + 3] = 255;
}
/// <summary>

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

@ -116,7 +116,7 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
@ -125,33 +125,56 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
switch (componentOrder)
{
case ComponentOrder.ZYX:
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);
break;
case ComponentOrder.ZYXW:
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);
break;
case ComponentOrder.XYZ:
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);
break;
case ComponentOrder.XYZW:
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);
break;
default:
throw new NotSupportedException();
}
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);
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
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);
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
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);
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
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);
}
/// <inheritdoc />

64
src/ImageSharp/Colors/PackedPixel/Rg32.cs

@ -100,37 +100,45 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
break;
default:
throw new NotSupportedException();
}
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
}
/// <inheritdoc />

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

@ -95,37 +95,45 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
switch (componentOrder)
{
case ComponentOrder.ZYX:
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);
break;
case ComponentOrder.ZYXW:
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);
break;
case ComponentOrder.XYZ:
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);
break;
case ComponentOrder.XYZW:
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);
break;
default:
throw new NotSupportedException();
}
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);
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
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);
}
/// <inheritdoc />

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

@ -94,37 +94,45 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4() * 255F;
switch (componentOrder)
{
case ComponentOrder.ZYX:
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);
break;
case ComponentOrder.ZYXW:
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);
break;
case ComponentOrder.XYZ:
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);
break;
case ComponentOrder.XYZW:
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);
break;
default:
throw new NotSupportedException();
}
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);
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
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);
}
/// <inheritdoc />

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

@ -106,7 +106,7 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector2 vector = this.ToVector2();
vector /= 65534;
@ -115,33 +115,56 @@ namespace ImageSharp
vector += Round;
vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes);
switch (componentOrder)
{
case ComponentOrder.ZYX:
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
break;
case ComponentOrder.ZYXW:
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 3] = 255;
break;
case ComponentOrder.XYZ:
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = 0;
break;
case ComponentOrder.XYZW:
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = 255;
break;
default:
throw new NotSupportedException();
}
bytes[startIndex] = (byte)(float)Math.Round(vector.X);
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y);
bytes[startIndex + 2] = 0;
}
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector2 vector = this.ToVector2();
vector /= 65534;
vector *= 255;
vector += Half;
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 + 2] = 0;
bytes[startIndex + 3] = 255;
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector2 vector = this.ToVector2();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
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);
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector2 vector = this.ToVector2();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
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 + 3] = 255;
}
/// <summary>

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

@ -112,7 +112,7 @@ namespace ImageSharp
}
/// <inheritdoc />
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder)
public void ToXyzBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector /= 65534;
@ -121,50 +121,65 @@ namespace ImageSharp
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
switch (componentOrder)
{
case ComponentOrder.ZYX:
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);
break;
case ComponentOrder.ZYXW:
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);
break;
case ComponentOrder.XYZ:
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);
break;
case ComponentOrder.XYZW:
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);
break;
default:
throw new NotSupportedException();
}
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);
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to a specified object.
/// </summary>
/// <param name="obj">The object with which to make the comparison.</param>
/// <returns>true if the current instance is equal to the specified object; false otherwise.</returns>
/// <inheritdoc />
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector /= 65534;
vector *= 255;
vector += Half;
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);
}
/// <inheritdoc />
public void ToZyxBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector /= 65534;
vector *= 255;
vector += Half;
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);
}
/// <inheritdoc />
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
Vector4 vector = this.ToVector4();
vector /= 65534;
vector *= 255;
vector += Half;
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);
}
/// <inheritdoc />
public override bool Equals(object obj)
{
return (obj is Short4) && this == (Short4)obj;
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to a specified object.
/// </summary>
/// <param name="other">The object with which to make the comparison.</param>
/// <returns>true if the current instance is equal to the specified object; false otherwise.</returns>
/// <inheritdoc />
public bool Equals(Short4 other)
{
return this == other;

17
src/ImageSharp/Colors/Colorspaces/Bgra32.cs → src/ImageSharp/Colors/Spaces/Bgra32.cs

@ -3,7 +3,7 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
namespace ImageSharp.Colors.Spaces
{
using System;
using System.ComponentModel;
@ -22,7 +22,7 @@ namespace ImageSharp
/// <summary>
/// The backing vector for SIMD support.
/// </summary>
private Vector4 backingVector;
private readonly Vector4 backingVector;
/// <summary>
/// Initializes a new instance of the <see cref="Bgra32"/> struct.
@ -133,7 +133,7 @@ namespace ImageSharp
/// <inheritdoc/>
public override int GetHashCode()
{
return GetHashCode(this);
return this.backingVector.GetHashCode();
}
/// <inheritdoc/>
@ -152,16 +152,5 @@ namespace ImageSharp
{
return this.backingVector.Equals(other.backingVector);
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <param name="color">
/// The instance of <see cref="Bgra32"/> to return the hash code for.
/// </param>
/// <returns>
/// A 32-bit signed integer that is the hash code for this instance.
/// </returns>
private static int GetHashCode(Bgra32 color) => color.backingVector.GetHashCode();
}
}

24
src/ImageSharp/Colors/Colorspaces/CieLab.cs → src/ImageSharp/Colors/Spaces/CieLab.cs

@ -3,7 +3,7 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
namespace ImageSharp.Colors.Spaces
{
using System;
using System.ComponentModel;
@ -20,15 +20,10 @@ namespace ImageSharp
/// </summary>
public static readonly CieLab Empty = default(CieLab);
/// <summary>
/// The epsilon for comparing floating point numbers.
/// </summary>
private const float Epsilon = 0.001f;
/// <summary>
/// The backing vector for SIMD support.
/// </summary>
private Vector3 backingVector;
private readonly Vector3 backingVector;
/// <summary>
/// Initializes a new instance of the <see cref="CieLab"/> struct.
@ -138,7 +133,7 @@ namespace ImageSharp
/// <inheritdoc/>
public override int GetHashCode()
{
return GetHashCode(this);
return this.backingVector.GetHashCode();
}
/// <inheritdoc/>
@ -166,7 +161,7 @@ namespace ImageSharp
/// <inheritdoc/>
public bool Equals(CieLab other)
{
return this.AlmostEquals(other, Epsilon);
return this.AlmostEquals(other, Constants.Epsilon);
}
/// <inheritdoc/>
@ -178,16 +173,5 @@ namespace ImageSharp
&& result.Y < precision
&& result.Z < precision;
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <param name="color">
/// The instance of <see cref="CieLab"/> to return the hash code for.
/// </param>
/// <returns>
/// A 32-bit signed integer that is the hash code for this instance.
/// </returns>
private static int GetHashCode(CieLab color) => color.backingVector.GetHashCode();
}
}

24
src/ImageSharp/Colors/Colorspaces/CieXyz.cs → src/ImageSharp/Colors/Spaces/CieXyz.cs

@ -3,7 +3,7 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
namespace ImageSharp.Colors.Spaces
{
using System;
using System.ComponentModel;
@ -20,15 +20,10 @@ namespace ImageSharp
/// </summary>
public static readonly CieXyz Empty = default(CieXyz);
/// <summary>
/// The epsilon for comparing floating point numbers.
/// </summary>
private const float Epsilon = 0.001f;
/// <summary>
/// The backing vector for SIMD support.
/// </summary>
private Vector3 backingVector;
private readonly Vector3 backingVector;
/// <summary>
/// Initializes a new instance of the <see cref="CieXyz"/> struct.
@ -129,7 +124,7 @@ namespace ImageSharp
/// <inheritdoc/>
public override int GetHashCode()
{
return GetHashCode(this);
return this.backingVector.GetHashCode();
}
/// <inheritdoc/>
@ -157,7 +152,7 @@ namespace ImageSharp
/// <inheritdoc/>
public bool Equals(CieXyz other)
{
return this.AlmostEquals(other, Epsilon);
return this.AlmostEquals(other, Constants.Epsilon);
}
/// <inheritdoc/>
@ -169,16 +164,5 @@ namespace ImageSharp
&& result.Y < precision
&& result.Z < precision;
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <param name="color">
/// The instance of <see cref="Hsv"/> to return the hash code for.
/// </param>
/// <returns>
/// A 32-bit signed integer that is the hash code for this instance.
/// </returns>
private static int GetHashCode(CieXyz color) => color.backingVector.GetHashCode();
}
}

26
src/ImageSharp/Colors/Colorspaces/Cmyk.cs → src/ImageSharp/Colors/Spaces/Cmyk.cs

@ -3,7 +3,7 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
namespace ImageSharp.Colors.Spaces
{
using System;
using System.ComponentModel;
@ -19,15 +19,10 @@ namespace ImageSharp
/// </summary>
public static readonly Cmyk Empty = default(Cmyk);
/// <summary>
/// The epsilon for comparing floating point numbers.
/// </summary>
private const float Epsilon = 0.001f;
/// <summary>
/// The backing vector for SIMD support.
/// </summary>
private Vector4 backingVector;
private readonly Vector4 backingVector;
/// <summary>
/// Initializes a new instance of the <see cref="Cmyk"/> struct.
@ -90,7 +85,7 @@ namespace ImageSharp
float k = Math.Min(c, Math.Min(m, y));
if (Math.Abs(k - 1.0f) <= Epsilon)
if (Math.Abs(k - 1.0f) <= Constants.Epsilon)
{
return new Cmyk(0, 0, 0, 1);
}
@ -139,7 +134,7 @@ namespace ImageSharp
/// <inheritdoc/>
public override int GetHashCode()
{
return GetHashCode(this);
return this.backingVector.GetHashCode();
}
/// <inheritdoc/>
@ -167,7 +162,7 @@ namespace ImageSharp
/// <inheritdoc/>
public bool Equals(Cmyk other)
{
return this.AlmostEquals(other, Epsilon);
return this.AlmostEquals(other, Constants.Epsilon);
}
/// <inheritdoc/>
@ -180,16 +175,5 @@ namespace ImageSharp
&& result.Z < precision
&& result.W < precision;
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <param name="color">
/// The instance of <see cref="Cmyk"/> to return the hash code for.
/// </param>
/// <returns>
/// A 32-bit signed integer that is the hash code for this instance.
/// </returns>
private static int GetHashCode(Cmyk color) => color.backingVector.GetHashCode();
}
}

32
src/ImageSharp/Colors/Colorspaces/Hsl.cs → src/ImageSharp/Colors/Spaces/Hsl.cs

@ -3,7 +3,7 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
namespace ImageSharp.Colors.Spaces
{
using System;
using System.ComponentModel;
@ -19,15 +19,10 @@ namespace ImageSharp
/// </summary>
public static readonly Hsl Empty = default(Hsl);
/// <summary>
/// The epsilon for comparing floating point numbers.
/// </summary>
private const float Epsilon = 0.001F;
/// <summary>
/// The backing vector for SIMD support.
/// </summary>
private Vector3 backingVector;
private readonly Vector3 backingVector;
/// <summary>
/// Initializes a new instance of the <see cref="Hsl"/> struct.
@ -85,20 +80,20 @@ namespace ImageSharp
float s = 0;
float l = (max + min) / 2;
if (Math.Abs(chroma) < Epsilon)
if (Math.Abs(chroma) < Constants.Epsilon)
{
return new Hsl(0, s, l);
}
if (Math.Abs(r - max) < Epsilon)
if (Math.Abs(r - max) < Constants.Epsilon)
{
h = (g - b) / chroma;
}
else if (Math.Abs(g - max) < Epsilon)
else if (Math.Abs(g - max) < Constants.Epsilon)
{
h = 2 + ((b - r) / chroma);
}
else if (Math.Abs(b - max) < Epsilon)
else if (Math.Abs(b - max) < Constants.Epsilon)
{
h = 4 + ((r - g) / chroma);
}
@ -158,7 +153,7 @@ namespace ImageSharp
/// <inheritdoc/>
public override int GetHashCode()
{
return GetHashCode(this);
return this.backingVector.GetHashCode();
}
/// <inheritdoc/>
@ -186,7 +181,7 @@ namespace ImageSharp
/// <inheritdoc/>
public bool Equals(Hsl other)
{
return this.AlmostEquals(other, Epsilon);
return this.AlmostEquals(other, Constants.Epsilon);
}
/// <inheritdoc/>
@ -198,16 +193,5 @@ namespace ImageSharp
&& result.Y < precision
&& result.Z < precision;
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <param name="color">
/// The instance of <see cref="Hsl"/> to return the hash code for.
/// </param>
/// <returns>
/// A 32-bit signed integer that is the hash code for this instance.
/// </returns>
private static int GetHashCode(Hsl color) => color.backingVector.GetHashCode();
}
}

32
src/ImageSharp/Colors/Colorspaces/Hsv.cs → src/ImageSharp/Colors/Spaces/Hsv.cs

@ -3,7 +3,7 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
namespace ImageSharp.Colors.Spaces
{
using System;
using System.ComponentModel;
@ -19,15 +19,10 @@ namespace ImageSharp
/// </summary>
public static readonly Hsv Empty = default(Hsv);
/// <summary>
/// The epsilon for comparing floating point numbers.
/// </summary>
private const float Epsilon = 0.001F;
/// <summary>
/// The backing vector for SIMD support.
/// </summary>
private Vector3 backingVector;
private readonly Vector3 backingVector;
/// <summary>
/// Initializes a new instance of the <see cref="Hsv"/> struct.
@ -85,20 +80,20 @@ namespace ImageSharp
float s = 0;
float v = max;
if (Math.Abs(chroma) < Epsilon)
if (Math.Abs(chroma) < Constants.Epsilon)
{
return new Hsv(0, s, v);
}
if (Math.Abs(r - max) < Epsilon)
if (Math.Abs(r - max) < Constants.Epsilon)
{
h = (g - b) / chroma;
}
else if (Math.Abs(g - max) < Epsilon)
else if (Math.Abs(g - max) < Constants.Epsilon)
{
h = 2 + ((b - r) / chroma);
}
else if (Math.Abs(b - max) < Epsilon)
else if (Math.Abs(b - max) < Constants.Epsilon)
{
h = 4 + ((r - g) / chroma);
}
@ -151,7 +146,7 @@ namespace ImageSharp
/// <inheritdoc/>
public override int GetHashCode()
{
return GetHashCode(this);
return this.backingVector.GetHashCode();
}
/// <inheritdoc/>
@ -179,7 +174,7 @@ namespace ImageSharp
/// <inheritdoc/>
public bool Equals(Hsv other)
{
return this.AlmostEquals(other, Epsilon);
return this.AlmostEquals(other, Constants.Epsilon);
}
/// <inheritdoc/>
@ -191,16 +186,5 @@ namespace ImageSharp
&& result.Y < precision
&& result.Z < precision;
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <param name="color">
/// The instance of <see cref="Hsv"/> to return the hash code for.
/// </param>
/// <returns>
/// A 32-bit signed integer that is the hash code for this instance.
/// </returns>
private static int GetHashCode(Hsv color) => color.backingVector.GetHashCode();
}
}

2
src/ImageSharp/Colors/Colorspaces/IAlmostEquatable.cs → src/ImageSharp/Colors/Spaces/IAlmostEquatable.cs

@ -3,7 +3,7 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
namespace ImageSharp.Colors.Spaces
{
using System;

33
src/ImageSharp/Colors/Colorspaces/YCbCr.cs → src/ImageSharp/Colors/Spaces/YCbCr.cs

@ -3,10 +3,11 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
namespace ImageSharp.Colors.Spaces
{
using System;
using System.ComponentModel;
using System.Numerics;
/// <summary>
/// Represents an YCbCr (luminance, blue chroma, red chroma) color conforming to the full range standard used in digital imaging systems.
@ -19,6 +20,16 @@ namespace ImageSharp
/// </summary>
public static readonly YCbCr Empty = default(YCbCr);
/// <summary>
/// Vector which is used in clamping to the max value
/// </summary>
private static readonly Vector3 VectorMax = new Vector3(255);
/// <summary>
/// The backing vector for SIMD support.
/// </summary>
private readonly Vector3 backingVector;
/// <summary>
/// Initializes a new instance of the <see cref="YCbCr"/> struct.
/// </summary>
@ -28,28 +39,26 @@ namespace ImageSharp
public YCbCr(byte y, byte cb, byte cr)
: this()
{
this.Y = y;
this.Cb = cb;
this.Cr = cr;
this.backingVector = Vector3.Clamp(new Vector3(y, cb, cr), Vector3.Zero, VectorMax);
}
/// <summary>
/// Gets the Y luminance component.
/// <remarks>A value ranging between 0 and 255.</remarks>
/// </summary>
public byte Y { get; }
public float Y => this.backingVector.X;
/// <summary>
/// Gets the Cb chroma component.
/// <remarks>A value ranging between 0 and 255.</remarks>
/// </summary>
public byte Cb { get; }
public float Cb => this.backingVector.Y;
/// <summary>
/// Gets the Cr chroma component.
/// <remarks>A value ranging between 0 and 255.</remarks>
/// </summary>
public byte Cr { get; }
public float Cr => this.backingVector.Z;
/// <summary>
/// Gets a value indicating whether this <see cref="YCbCr"/> is empty.
@ -117,13 +126,7 @@ namespace ImageSharp
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
int hashCode = this.Y.GetHashCode();
hashCode = (hashCode * 397) ^ this.Cb.GetHashCode();
hashCode = (hashCode * 397) ^ this.Cr.GetHashCode();
return hashCode;
}
return this.backingVector.GetHashCode();
}
/// <inheritdoc/>
@ -151,7 +154,7 @@ namespace ImageSharp
/// <inheritdoc/>
public bool Equals(YCbCr other)
{
return this.Y == other.Y && this.Cb == other.Cb && this.Cr == other.Cr;
return this.backingVector.Equals(other.backingVector);
}
}
}

13
src/ImageSharp/Colors/Vector4BlendTransforms.cs

@ -14,11 +14,6 @@ namespace ImageSharp
/// </summary>
public class Vector4BlendTransforms
{
/// <summary>
/// The epsilon for comparing floating point numbers.
/// </summary>
private const float Epsilon = 0.0001F;
/// <summary>
/// The blending formula simply selects the source vector.
/// </summary>
@ -203,13 +198,13 @@ namespace ImageSharp
amount = amount.Clamp(0, 1);
// Santize on zero alpha
if (Math.Abs(backdrop.W) < Epsilon)
if (Math.Abs(backdrop.W) < Constants.Epsilon)
{
source.W *= amount;
return source;
}
if (Math.Abs(source.W) < Epsilon)
if (Math.Abs(source.W) < Constants.Epsilon)
{
return backdrop;
}
@ -266,7 +261,7 @@ namespace ImageSharp
/// </returns>
private static float BlendDodge(float b, float s)
{
return Math.Abs(s - 1F) < Epsilon ? s : Math.Min(b / (1F - s), 1F);
return Math.Abs(s - 1F) < Constants.Epsilon ? s : Math.Min(b / (1F - s), 1F);
}
/// <summary>
@ -279,7 +274,7 @@ namespace ImageSharp
/// </returns>
private static float BlendBurn(float b, float s)
{
return Math.Abs(s) < Epsilon ? s : Math.Max(1F - ((1F - b) / s), 0F);
return Math.Abs(s) < Constants.Epsilon ? s : Math.Max(1F - ((1F - b) / s), 0F);
}
/// <summary>

18
src/ImageSharp/Common/Constants.cs

@ -0,0 +1,18 @@
// <copyright file="Constants.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
/// <summary>
/// Common constants used throughout the project
/// </summary>
internal static class Constants
{
/// <summary>
/// The epsilon for comparing floating point numbers.
/// </summary>
public static readonly float Epsilon = 0.001f;
}
}

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

@ -91,9 +91,7 @@ namespace ImageSharp
/// </returns>
public static float SinC(float x)
{
const float Epsilon = .00001F;
if (Math.Abs(x) > Epsilon)
if (Math.Abs(x) > Constants.Epsilon)
{
x *= (float)Math.PI;
return Clean((float)Math.Sin(x) / x);
@ -166,7 +164,6 @@ namespace ImageSharp
public static Rectangle GetFilteredBoundingRectangle<TColor>(ImageBase<TColor> bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
const float Epsilon = .00001f;
int width = bitmap.Width;
int height = bitmap.Height;
Point topLeft = default(Point);
@ -178,19 +175,19 @@ namespace ImageSharp
switch (channel)
{
case RgbaComponent.R:
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().X - b) > Epsilon;
delegateFunc = (pixels, x, y, b) => Math.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) > Epsilon;
delegateFunc = (pixels, x, y, b) => Math.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) > Epsilon;
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().Z - b) > Constants.Epsilon;
break;
default:
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().W - b) > Epsilon;
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().W - b) > Constants.Epsilon;
break;
}
@ -278,9 +275,7 @@ namespace ImageSharp
/// </returns>.
private static float Clean(float x)
{
const float Epsilon = .00001F;
if (Math.Abs(x) < Epsilon)
if (Math.Abs(x) < Constants.Epsilon)
{
return 0F;
}

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

@ -9,7 +9,6 @@ namespace ImageSharp.Drawing.Processors
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using ImageSharp.Processors;
using Paths;
using Pens;
@ -27,7 +26,6 @@ namespace ImageSharp.Drawing.Processors
{
private const float AntialiasFactor = 1f;
private const int PaddingFactor = 1; // needs to been the same or greater than AntialiasFactor
private const float Epsilon = 0.001f;
private readonly IPen<TColor> pen;
private readonly IPath[] paths;
@ -138,7 +136,7 @@ namespace ImageSharp.Drawing.Processors
var opacity = this.Opacity(color.DistanceFromElement);
if (opacity > Epsilon)
if (opacity > Constants.Epsilon)
{
int offsetColorX = x - minX;

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

@ -21,8 +21,6 @@ namespace ImageSharp.Drawing.Processors
public class FillShapeProcessor<TColor> : ImageFilteringProcessor<TColor>
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
private const float Epsilon = 0.001f;
private const float AntialiasFactor = 1f;
private const int DrawPadding = 1;
private readonly IBrush<TColor> fillColor;
@ -95,7 +93,7 @@ namespace ImageSharp.Drawing.Processors
float dist = this.poly.Distance(currentPoint);
float opacity = this.Opacity(dist);
if (opacity > Epsilon)
if (opacity > Constants.Epsilon)
{
Vector4 backgroundVector = sourcePixels[offsetX, offsetY].ToVector4();
Vector4 sourceVector = applicator.GetColor(currentPoint).ToVector4();

7
src/ImageSharp/Filters/Processors/Effects/BackgroundColorProcessor.cs

@ -16,11 +16,6 @@ namespace ImageSharp.Processors
public class BackgroundColorProcessor<TColor> : ImageFilteringProcessor<TColor>
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
/// <summary>
/// The epsilon for comparing floating point numbers.
/// </summary>
private const float Epsilon = 0.001f;
/// <summary>
/// Initializes a new instance of the <see cref="BackgroundColorProcessor{TColor}"/> class.
/// </summary>
@ -82,7 +77,7 @@ namespace ImageSharp.Processors
color = Vector4BlendTransforms.PremultipliedLerp(backgroundColor, color, .5F);
}
if (Math.Abs(a) < Epsilon)
if (Math.Abs(a) < Constants.Epsilon)
{
color = backgroundColor;
}

13
src/ImageSharp/Filters/Processors/Transforms/RotateProcessor.cs

@ -70,9 +70,7 @@ namespace ImageSharp.Processors
/// <inheritdoc/>
protected override void BeforeApply(ImageBase<TColor> source, Rectangle sourceRectangle)
{
const float Epsilon = .0001F;
if (Math.Abs(this.Angle) < Epsilon || Math.Abs(this.Angle - 90) < Epsilon || Math.Abs(this.Angle - 180) < Epsilon || Math.Abs(this.Angle - 270) < Epsilon)
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)
{
return;
}
@ -91,26 +89,25 @@ namespace ImageSharp.Processors
/// <returns>The <see cref="bool"/></returns>
private bool OptimizedApply(ImageBase<TColor> source)
{
const float Epsilon = .0001F;
if (Math.Abs(this.Angle) < Epsilon)
if (Math.Abs(this.Angle) < Constants.Epsilon)
{
// No need to do anything so return.
return true;
}
if (Math.Abs(this.Angle - 90) < Epsilon)
if (Math.Abs(this.Angle - 90) < Constants.Epsilon)
{
this.Rotate90(source);
return true;
}
if (Math.Abs(this.Angle - 180) < Epsilon)
if (Math.Abs(this.Angle - 180) < Constants.Epsilon)
{
this.Rotate180(source);
return true;
}
if (Math.Abs(this.Angle - 270) < Epsilon)
if (Math.Abs(this.Angle - 270) < Constants.Epsilon)
{
this.Rotate270(source);
return true;

6
src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

@ -275,7 +275,7 @@ namespace ImageSharp.Formats
const int ComponentCount = 2;
TColor color = default(TColor);
using (PixelArea<TColor> row = new PixelArea<TColor>(width, ComponentOrder.XYZ))
using (PixelArea<TColor> row = new PixelArea<TColor>(width, ComponentOrder.Xyz))
{
for (int y = 0; y < height; y++)
{
@ -312,7 +312,7 @@ namespace ImageSharp.Formats
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
int padding = CalculatePadding(width, 3);
using (PixelArea<TColor> row = new PixelArea<TColor>(width, ComponentOrder.ZYX, padding))
using (PixelArea<TColor> row = new PixelArea<TColor>(width, ComponentOrder.Zyx, padding))
{
for (int y = 0; y < height; y++)
{
@ -336,7 +336,7 @@ namespace ImageSharp.Formats
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
int padding = CalculatePadding(width, 4);
using (PixelArea<TColor> row = new PixelArea<TColor>(width, ComponentOrder.ZYXW, padding))
using (PixelArea<TColor> row = new PixelArea<TColor>(width, ComponentOrder.Zyxw, padding))
{
for (int y = 0; y < height; y++)
{

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

@ -150,12 +150,12 @@ namespace ImageSharp.Formats
private void Write32Bit<TColor>(EndianBinaryWriter writer, PixelAccessor<TColor> pixels)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
using (PixelArea<TColor> row = new PixelArea<TColor>(pixels.Width, ComponentOrder.ZYXW, this.padding))
using (PixelArea<TColor> row = new PixelArea<TColor>(pixels.Width, ComponentOrder.Zyxw, this.padding))
{
for (int y = pixels.Height - 1; y >= 0; y--)
{
pixels.CopyTo(row, y);
writer.Write(row.Bytes);
writer.Write(row.Bytes, 0, row.Length);
}
}
}
@ -169,12 +169,12 @@ namespace ImageSharp.Formats
private void Write24Bit<TColor>(EndianBinaryWriter writer, PixelAccessor<TColor> pixels)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
using (PixelArea<TColor> row = new PixelArea<TColor>(pixels.Width, ComponentOrder.ZYX, this.padding))
using (PixelArea<TColor> row = new PixelArea<TColor>(pixels.Width, ComponentOrder.Zyx, this.padding))
{
for (int y = pixels.Height - 1; y >= 0; y--)
{
pixels.CopyTo(row, y);
writer.Write(row.Bytes);
writer.Write(row.Bytes, 0, row.Length);
}
}
}

2
src/ImageSharp/Formats/Gif/GifDecoderCore.cs

@ -451,7 +451,7 @@ namespace ImageSharp.Formats
}
else
{
using (PixelArea<TColor> emptyRow = new PixelArea<TColor>(this.restoreArea.Value.Width, ComponentOrder.XYZW))
using (PixelArea<TColor> emptyRow = new PixelArea<TColor>(this.restoreArea.Value.Width, ComponentOrder.Xyzw))
{
using (PixelAccessor<TColor> pixelAccessor = frame.Lock())
{

7
src/ImageSharp/Formats/Gif/GifEncoderCore.cs

@ -129,10 +129,10 @@ namespace ImageSharp.Formats
bool hasEmpty = false;
// Some images may have more than one quantized pixel returned with an alpha value of zero
// (No idea why?!) so we should always ignore if we have empty pixels present.
// so we should always ignore if we have empty pixels present.
for (int i = 0; i < quantized.Palette.Length; i++)
{
quantized.Palette[i].ToBytes(this.buffer, 0, ComponentOrder.XYZW);
quantized.Palette[i].ToXyzwBytes(this.buffer, 0);
if (!hasEmpty)
{
@ -282,6 +282,7 @@ namespace ImageSharp.Formats
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
writer.Write(GifConstants.ImageDescriptorLabel); // 2c
// TODO: Can we capture this?
writer.Write((ushort)0); // Left position
writer.Write((ushort)0); // Top position
@ -318,7 +319,7 @@ namespace ImageSharp.Formats
for (int i = 0; i < pixelCount; i++)
{
int offset = i * 3;
image.Palette[i].ToBytes(this.buffer, 0, ComponentOrder.XYZ);
image.Palette[i].ToXyzBytes(this.buffer, 0);
colorTable[offset] = this.buffer[0];
colorTable[offset + 1] = this.buffer[1];
colorTable[offset + 2] = this.buffer[2];

18
src/ImageSharp/Formats/Jpg/Components/BlockQuad.cs

@ -0,0 +1,18 @@
// <copyright file="BlockQuad.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Formats.Jpg.Components
{
/// <summary>
/// Poor man's stackalloc: Contains a value-type <see cref="float"/> buffer sized for 4 <see cref="Block8x8F"/> instances.
/// Useful for decoder/encoder operations allocating a block for each Jpeg component.
/// </summary>
internal unsafe struct BlockQuad
{
/// <summary>
/// The value-type <see cref="float"/> buffer sized for 4 <see cref="Block8x8F"/> instances.
/// </summary>
public fixed float Data[4 * Block8x8F.ScalarCount];
}
}

4
src/ImageSharp/Formats/Jpg/Components/Decoder/Bits.cs

@ -47,7 +47,7 @@ namespace ImageSharp.Formats.Jpg
// Grab the decode bytes, use them and then set them
// back on the decoder.
var decoderBytes = decoder.Bytes;
Bytes decoderBytes = decoder.Bytes;
byte c = decoderBytes.ReadByteStuffedByte(decoder.InputStream, out errorCode);
decoder.Bytes = decoderBytes;
@ -84,7 +84,7 @@ namespace ImageSharp.Formats.Jpg
{
if (this.UnreadBits < t)
{
var errorCode = this.EnsureNBits(t, decoder);
JpegDecoderCore.ErrorCodes errorCode = this.EnsureNBits(t, decoder);
if (errorCode != JpegDecoderCore.ErrorCodes.NoError)
{
throw new JpegDecoderCore.MissingFF00Exception();

287
src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs

@ -2,6 +2,7 @@
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Formats
{
using System;
@ -11,19 +12,20 @@ namespace ImageSharp.Formats
using System.Runtime.CompilerServices;
using ImageSharp.Formats.Jpg;
using ImageSharp.Formats.Jpg.Components;
/// <summary>
/// Image encoder for writing an image to a stream as a jpeg.
/// Image encoder for writing an image to a stream as a jpeg.
/// </summary>
internal unsafe class JpegEncoderCore
{
/// <summary>
/// The number of quantization tables.
/// The number of quantization tables.
/// </summary>
private const int QuantizationTableCount = 2;
/// <summary>
/// Counts the number of bits needed to hold an integer.
/// Counts the number of bits needed to hold an integer.
/// </summary>
private static readonly uint[] BitCountLut =
{
@ -43,15 +45,15 @@ namespace ImageSharp.Formats
};
/// <summary>
/// The SOS (Start Of Scan) marker "\xff\xda" followed by 12 bytes:
/// - the marker length "\x00\x0c",
/// - the number of components "\x03",
/// - component 1 uses DC table 0 and AC table 0 "\x01\x00",
/// - component 2 uses DC table 1 and AC table 1 "\x02\x11",
/// - component 3 uses DC table 1 and AC table 1 "\x03\x11",
/// - the bytes "\x00\x3f\x00". Section B.2.3 of the spec says that for
/// sequential DCTs, those bytes (8-bit Ss, 8-bit Se, 4-bit Ah, 4-bit Al)
/// should be 0x00, 0x3f, 0x00&lt;&lt;4 | 0x00.
/// The SOS (Start Of Scan) marker "\xff\xda" followed by 12 bytes:
/// - the marker length "\x00\x0c",
/// - the number of components "\x03",
/// - component 1 uses DC table 0 and AC table 0 "\x01\x00",
/// - component 2 uses DC table 1 and AC table 1 "\x02\x11",
/// - component 3 uses DC table 1 and AC table 1 "\x03\x11",
/// - the bytes "\x00\x3f\x00". Section B.2.3 of the spec says that for
/// sequential DCTs, those bytes (8-bit Ss, 8-bit Se, 4-bit Ah, 4-bit Al)
/// should be 0x00, 0x3f, 0x00&lt;&lt;4 | 0x00.
/// </summary>
private static readonly byte[] SosHeaderYCbCr =
{
@ -76,10 +78,10 @@ namespace ImageSharp.Formats
};
/// <summary>
/// The unscaled quantization tables in zig-zag order. Each
/// encoder copies and scales the tables according to its quality parameter.
/// The values are derived from section K.1 after converting from natural to
/// zig-zag order.
/// The unscaled quantization tables in zig-zag order. Each
/// encoder copies and scales the tables according to its quality parameter.
/// The values are derived from section K.1 after converting from natural to
/// zig-zag order.
/// </summary>
private static readonly byte[,] UnscaledQuant =
{
@ -102,69 +104,59 @@ namespace ImageSharp.Formats
};
/// <summary>
/// A scratch buffer to reduce allocations.
/// A scratch buffer to reduce allocations.
/// </summary>
private readonly byte[] buffer = new byte[16];
/// <summary>
/// A buffer for reducing the number of stream writes when emitting Huffman tables. 64 seems to be enough.
/// A buffer for reducing the number of stream writes when emitting Huffman tables. 64 seems to be enough.
/// </summary>
private readonly byte[] emitBuffer = new byte[64];
/// <summary>
/// A buffer for reducing the number of stream writes when emitting Huffman tables. Max combined table lengths +
/// identifier.
/// A buffer for reducing the number of stream writes when emitting Huffman tables. Max combined table lengths +
/// identifier.
/// </summary>
private readonly byte[] huffmanBuffer = new byte[179];
/// <summary>
/// The accumulated bits to write to the stream.
/// The accumulated bits to write to the stream.
/// </summary>
private uint accumulatedBits;
/// <summary>
/// The accumulated bit count.
/// The accumulated bit count.
/// </summary>
private uint bitCount;
/// <summary>
/// The scaled chrominance table, in zig-zag order.
/// The scaled chrominance table, in zig-zag order.
/// </summary>
private Block8x8F chrominanceQuantTable;
/// <summary>
/// The scaled luminance table, in zig-zag order.
/// The scaled luminance table, in zig-zag order.
/// </summary>
private Block8x8F luminanceQuantTable;
/// <summary>
/// The output stream. All attempted writes after the first error become no-ops.
/// The output stream. All attempted writes after the first error become no-ops.
/// </summary>
private Stream outputStream;
/// <summary>
/// The subsampling method to use.
/// The subsampling method to use.
/// </summary>
private JpegSubsample subsample;
/// <summary>
/// Encode writes the image to the jpeg baseline format with the given options.
/// </summary>
/// <typeparam name="TColor">
/// The pixel format.
/// </typeparam>
/// <param name="image">
/// The image to write from.
/// </param>
/// <param name="stream">
/// The stream to write to.
/// </param>
/// <param name="quality">
/// The quality.
/// </param>
/// <param name="sample">
/// The subsampling mode.
/// </param>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The image to write from.</param>
/// <param name="stream">The stream to write to.</param>
/// <param name="quality">The quality.</param>
/// <param name="sample">The subsampling mode.</param>
public void Encode<TColor>(Image<TColor> image, Stream stream, int quality, JpegSubsample sample)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
@ -235,6 +227,28 @@ namespace ImageSharp.Formats
stream.Flush();
}
/// <summary>
/// Writes data to "Define Quantization Tables" block for QuantIndex
/// </summary>
/// <param name="dqt">The "Define Quantization Tables" block</param>
/// <param name="offset">Offset in "Define Quantization Tables" block</param>
/// <param name="i">The quantization index</param>
/// <param name="quant">The quantization table to copy data from</param>
private static void WriteDataToDqt(byte[] dqt, ref int offset, QuantIndex i, ref Block8x8F quant)
{
dqt[offset++] = (byte)i;
for (int j = 0; j < Block8x8F.ScalarCount; j++)
{
dqt[offset++] = (byte)quant[j];
}
}
/// <summary>
/// Initializes quantization table.
/// </summary>
/// <param name="i">The quantization index.</param>
/// <param name="scale">The scaling factor.</param>
/// <param name="quant">The quantization table.</param>
private static void InitQuantizationTable(int i, int scale, ref Block8x8F quant)
{
for (int j = 0; j < Block8x8F.ScalarCount; j++)
@ -258,30 +272,14 @@ namespace ImageSharp.Formats
/// <summary>
/// Converts the 8x8 region of the image whose top-left corner is x,y to its YCbCr values.
/// </summary>
/// <typeparam name="TColor">
/// The pixel format.
/// </typeparam>
/// <param name="pixels">
/// The pixel accessor.
/// </param>
/// <param name="x">
/// The x-position within the image.
/// </param>
/// <param name="y">
/// The y-position within the image.
/// </param>
/// <param name="yBlock">
/// The luminance block.
/// </param>
/// <param name="cbBlock">
/// The red chroma block.
/// </param>
/// <param name="crBlock">
/// The blue chroma block.
/// </param>
/// <param name="rgbBytes">
/// Temporal <see cref="PixelArea{TColor}"/> provided by the caller
/// </param>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="pixels">The pixel accessor.</param>
/// <param name="x">The x-position within the image.</param>
/// <param name="y">The y-position within the image.</param>
/// <param name="yBlock">The luminance block.</param>
/// <param name="cbBlock">The red chroma block.</param>
/// <param name="crBlock">The blue chroma block.</param>
/// <param name="rgbBytes">Temporal <see cref="PixelArea{TColor}"/> provided by the caller</param>
private static void ToYCbCr<TColor>(
PixelAccessor<TColor> pixels,
int x,
@ -326,18 +324,14 @@ namespace ImageSharp.Formats
/// <summary>
/// Emits the least significant count of bits of bits to the bit-stream.
/// The precondition is bits
/// <example>
/// The precondition is bits
/// <example>
/// &lt; 1&lt;&lt;nBits &amp;&amp; nBits &lt;= 16
/// </example>
/// .
/// </summary>
/// <param name="bits">
/// The packed bits.
/// </param>
/// <param name="count">
/// The number of bits
/// </param>
/// <param name="bits">The packed bits.</param>
/// <param name="count">The number of bits</param>
private void Emit(uint bits, uint count)
{
count += this.bitCount;
@ -375,12 +369,8 @@ namespace ImageSharp.Formats
/// <summary>
/// Emits the given value with the given Huffman encoder.
/// </summary>
/// <param name="index">
/// The index of the Huffman encoder
/// </param>
/// <param name="value">
/// The value to encode.
/// </param>
/// <param name="index">The index of the Huffman encoder</param>
/// <param name="value">The value to encode.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void EmitHuff(HuffIndex index, int value)
{
@ -391,15 +381,9 @@ namespace ImageSharp.Formats
/// <summary>
/// Emits a run of runLength copies of value encoded with the given Huffman encoder.
/// </summary>
/// <param name="index">
/// The index of the Huffman encoder
/// </param>
/// <param name="runLength">
/// The number of copies to encode.
/// </param>
/// <param name="value">
/// The value to encode.
/// </param>
/// <param name="index">The index of the Huffman encoder</param>
/// <param name="runLength">The number of copies to encode.</param>
/// <param name="value">The value to encode.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void EmitHuffRLE(HuffIndex index, int runLength, int value)
{
@ -431,12 +415,8 @@ namespace ImageSharp.Formats
/// <summary>
/// Encodes the image with no subsampling.
/// </summary>
/// <typeparam name="TColor">
/// The pixel format.
/// </typeparam>
/// <param name="pixels">
/// The pixel accessor providing access to the image pixels.
/// </param>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="pixels">The pixel accessor providing access to the image pixels.</param>
private void Encode444<TColor>(PixelAccessor<TColor> pixels)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
@ -456,7 +436,7 @@ namespace ImageSharp.Formats
// ReSharper disable once InconsistentNaming
float prevDCY = 0, prevDCCb = 0, prevDCCr = 0;
using (PixelArea<TColor> rgbBytes = new PixelArea<TColor>(8, 8, ComponentOrder.XYZ, true))
using (PixelArea<TColor> rgbBytes = new PixelArea<TColor>(8, 8, ComponentOrder.Xyz))
{
for (int y = 0; y < pixels.Height; y += 8)
{
@ -496,12 +476,8 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the application header containing the JFIF identifier plus extra data.
/// </summary>
/// <param name="horizontalResolution">
/// The resolution of the image in the x- direction.
/// </param>
/// <param name="verticalResolution">
/// The resolution of the image in the y- direction.
/// </param>
/// <param name="horizontalResolution">The resolution of the image in the x- direction.</param>
/// <param name="verticalResolution">The resolution of the image in the y- direction.</param>
private void WriteApplicationHeader(short horizontalResolution, short verticalResolution)
{
// Write the start of image marker. Markers are always prefixed with with 0xff.
@ -539,30 +515,16 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes a block of pixel data using the given quantization table,
/// returning the post-quantized DC value of the DCT-transformed block.
/// The block is in natural (not zig-zag) order.
/// returning the post-quantized DC value of the DCT-transformed block.
/// The block is in natural (not zig-zag) order.
/// </summary>
/// <param name="index">
/// The quantization table index.
/// </param>
/// <param name="prevDC">
/// The previous DC value.
/// </param>
/// <param name="src">
/// Source block
/// </param>
/// <param name="tempDest">
/// Temporal block to be used as FDCT Destination
/// </param>
/// <param name="temp2">
/// Temporal block 2
/// </param>
/// <param name="quant">
/// Quantization table
/// </param>
/// <param name="unzigPtr">
/// The 8x8 Unzig block ptr
/// </param>
/// <param name="index">The quantization table index.</param>
/// <param name="prevDC">The previous DC value.</param>
/// <param name="src">Source block</param>
/// <param name="tempDest">Temporal block to be used as FDCT Destination</param>
/// <param name="temp2">Temporal block 2</param>
/// <param name="quant">Quantization table</param>
/// <param name="unzigPtr">The 8x8 Unzig block pointer</param>
/// <returns>
/// The <see cref="int"/>
/// </returns>
@ -622,9 +584,7 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the Define Huffman Table marker and tables.
/// </summary>
/// <param name="componentCount">
/// The number of components to write.
/// </param>
/// <param name="componentCount">The number of components to write.</param>
private void WriteDefineHuffmanTables(int componentCount)
{
// Table identifiers.
@ -671,7 +631,7 @@ namespace ImageSharp.Formats
}
/// <summary>
/// Writes the Define Quantization Marker and tables.
/// Writes the Define Quantization Marker and tables.
/// </summary>
private void WriteDefineQuantizationTables()
{
@ -685,8 +645,8 @@ namespace ImageSharp.Formats
byte[] dqt = ArrayPool<byte>.Shared.Rent(dqtCount);
int offset = 0;
JpegUtils.WriteDataToDqt(dqt, ref offset, QuantIndex.Luminance, ref this.luminanceQuantTable);
JpegUtils.WriteDataToDqt(dqt, ref offset, QuantIndex.Chrominance, ref this.chrominanceQuantTable);
WriteDataToDqt(dqt, ref offset, QuantIndex.Luminance, ref this.luminanceQuantTable);
WriteDataToDqt(dqt, ref offset, QuantIndex.Chrominance, ref this.chrominanceQuantTable);
this.outputStream.Write(dqt, 0, dqtCount);
ArrayPool<byte>.Shared.Return(dqt);
@ -695,9 +655,7 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the EXIF profile.
/// </summary>
/// <param name="exifProfile">
/// The exif profile.
/// </param>
/// <param name="exifProfile">The exif profile.</param>
/// <exception cref="ImageFormatException">
/// Thrown if the EXIF profile size exceeds the limit
/// </exception>
@ -729,12 +687,8 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the metadata profiles to the image.
/// </summary>
/// <param name="image">
/// The image.
/// </param>
/// <typeparam name="TColor">
/// The pixel format.
/// </typeparam>
/// <param name="image">The image.</param>
/// <typeparam name="TColor">The pixel format.</typeparam>
private void WriteProfiles<TColor>(Image<TColor> image)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
@ -744,15 +698,9 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the Start Of Frame (Baseline) marker
/// </summary>
/// <param name="width">
/// The width of the image
/// </param>
/// <param name="height">
/// The height of the image
/// </param>
/// <param name="componentCount">
/// The number of components in a pixel
/// </param>
/// <param name="width">The width of the image</param>
/// <param name="height">The height of the image</param>
/// <param name="componentCount">The number of components in a pixel</param>
private void WriteStartOfFrame(int width, int height, int componentCount)
{
// "default" to 4:2:0
@ -806,12 +754,8 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the StartOfScan marker.
/// </summary>
/// <typeparam name="TColor">
/// The pixel format.
/// </typeparam>
/// <param name="pixels">
/// The pixel accessor providing access to the image pixels.
/// </param>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="pixels">The pixel accessor providing access to the image pixels.</param>
private void WriteStartOfScan<TColor>(PixelAccessor<TColor> pixels)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
@ -833,28 +777,12 @@ namespace ImageSharp.Formats
this.Emit(0x7f, 7);
}
#pragma warning disable SA1201 // MethodShouldNotFollowAStruct
/// <summary>
/// Poor man's stackalloc for Encode420.
/// This struct belongs to Encode420. Much easeier to understand code if they are close to each other. Why should I
/// move it Up? :P
/// </summary>
private struct BlockQuad
{
public fixed float Data[4 * Block8x8F.ScalarCount];
}
/// <summary>
/// Encodes the image with subsampling. The Cb and Cr components are each subsampled
/// at a factor of 2 both horizontally and vertically.
/// at a factor of 2 both horizontally and vertically.
/// </summary>
/// <typeparam name="TColor">
/// The pixel format.
/// </typeparam>
/// <param name="pixels">
/// The pixel accessor providing access to the image pixels.
/// </param>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="pixels">The pixel accessor providing access to the image pixels.</param>
private void Encode420<TColor>(PixelAccessor<TColor> pixels)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
@ -877,7 +805,7 @@ namespace ImageSharp.Formats
// ReSharper disable once InconsistentNaming
float prevDCY = 0, prevDCCb = 0, prevDCCr = 0;
using (var rgbBytes = new PixelArea<TColor>(8, 8, ComponentOrder.XYZ, true))
using (PixelArea<TColor> rgbBytes = new PixelArea<TColor>(8, 8, ComponentOrder.Xyz))
{
for (int y = 0; y < pixels.Height; y += 16)
{
@ -909,6 +837,7 @@ namespace ImageSharp.Formats
&temp2,
&onStackChrominanceQuantTable,
unzig.Data);
Block8x8F.Scale16X16To8X8(&b, crPtr);
prevDCCr = this.WriteBlock(
QuantIndex.Chrominance,
@ -923,17 +852,11 @@ namespace ImageSharp.Formats
}
}
#pragma warning restore SA1201
/// <summary>
/// Writes the header for a marker with the given length.
/// </summary>
/// <param name="marker">
/// The marker to write.
/// </param>
/// <param name="length">
/// The marker length.
/// </param>
/// <param name="marker">The marker to write.</param>
/// <param name="length">The marker length.</param>
private void WriteMarkerHeader(byte marker, int length)
{
// Markers are always prefixed with with 0xff.

70
src/ImageSharp/Formats/Jpg/Utils/JpegUtils.cs

@ -13,24 +13,13 @@ namespace ImageSharp.Formats.Jpg
internal static unsafe class JpegUtils
{
/// <summary>
/// Copy a region of an image into dest. De "outlier" area will be stretched out with pixels on the right and bottom of
/// the image.
/// Copy a region of an image into dest. De "outlier" area will be stretched out with pixels on the right and bottom of the image.
/// </summary>
/// <typeparam name="TColor">
/// The pixel type
/// </typeparam>
/// <param name="pixels">
/// The input pixel acessor
/// </param>
/// <param name="dest">
/// The destination <see cref="PixelArea{TColor}"/>
/// </param>
/// <param name="sourceY">
/// Starting Y coord
/// </param>
/// <param name="sourceX">
/// Starting X coord
/// </param>
/// <typeparam name="TColor">The pixel type</typeparam>
/// <param name="pixels">The input pixel acessor</param>
/// <param name="dest">The destination <see cref="PixelArea{TColor}"/></param>
/// <param name="sourceY">Starting Y coord</param>
/// <param name="sourceX">Starting X coord</param>
public static void CopyRGBBytesStretchedTo<TColor>(
this PixelAccessor<TColor> pixels,
PixelArea<TColor> dest,
@ -38,7 +27,7 @@ namespace ImageSharp.Formats.Jpg
int sourceX)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
pixels.CopyTo(dest, sourceY, sourceX);
pixels.SafeCopyTo(dest, sourceY, sourceX);
int stretchFromX = pixels.Width - sourceX;
int stretchFromY = pixels.Height - sourceY;
StretchPixels(dest, stretchFromX, stretchFromY);
@ -47,46 +36,19 @@ namespace ImageSharp.Formats.Jpg
/// <summary>
/// Copy an RGB value
/// </summary>
/// <param name="source">
/// Source pointer
/// </param>
/// <param name="dest">
/// Destination pointer
/// </param>
/// <param name="source">Source pointer</param>
/// <param name="dest">Destination pointer</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void CopyRgb(byte* source, byte* dest)
public static void CopyRgb(byte* source, byte* dest)
{
*dest++ = *source++; // R
*dest++ = *source++; // G
*dest = *source; // B
}
/// <summary>
/// Writes data to "Define Quantization Tables" block for QuantIndex
/// </summary>
/// <param name="dqt">
/// The "Define Quantization Tables" block
/// </param>
/// <param name="offset">
/// Offset in dqt
/// </param>
/// <param name="i">
/// The quantization index
/// </param>
/// <param name="q">
/// The quantazation table to copy data from
/// </param>
internal static void WriteDataToDqt(byte[] dqt, ref int offset, QuantIndex i, ref Block8x8F q)
{
dqt[offset++] = (byte)i;
for (int j = 0; j < Block8x8F.ScalarCount; j++)
{
dqt[offset++] = (byte)q[j];
}
}
// Nothing to stretch if (fromX, fromY) is outside the area, or is at (0,0)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsInvalidStretchArea<TColor>(PixelArea<TColor> area, int fromX, int fromY)
private static bool IsInvalidStretchStartingPosition<TColor>(PixelArea<TColor> area, int fromX, int fromY)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return fromX <= 0 || fromY <= 0 || fromX >= area.Width || fromY >= area.Height;
@ -95,14 +57,14 @@ namespace ImageSharp.Formats.Jpg
private static void StretchPixels<TColor>(PixelArea<TColor> area, int fromX, int fromY)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
if (IsInvalidStretchArea(area, fromX, fromY))
if (IsInvalidStretchStartingPosition(area, fromX, fromY))
{
return;
}
for (int y = 0; y < fromY; y++)
{
byte* ptrBase = (byte*)area.DataPointer + (y * area.RowByteCount);
byte* ptrBase = (byte*)area.DataPointer + (y * area.RowStride);
for (int x = fromX; x < area.Width; x++)
{
@ -115,8 +77,8 @@ namespace ImageSharp.Formats.Jpg
for (int y = fromY; y < area.Height; y++)
{
byte* currBase = (byte*)area.DataPointer + (y * area.RowByteCount);
byte* prevBase = (byte*)area.DataPointer + ((y - 1) * area.RowByteCount);
byte* currBase = (byte*)area.DataPointer + (y * area.RowStride);
byte* prevBase = (byte*)area.DataPointer + ((y - 1) * area.RowStride);
for (int x = 0; x < area.Width; x++)
{

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

@ -286,7 +286,7 @@ namespace ImageSharp.Formats
// Convert the color to YCbCr and store the luminance
// Optionally store the original color alpha.
int offset = x * this.bytesPerPixel;
pixels[x, row].ToBytes(this.chunkTypeBuffer, 0, ComponentOrder.XYZW);
pixels[x, row].ToXyzwBytes(this.chunkTypeBuffer, 0);
byte luminance = (byte)((0.299F * this.chunkTypeBuffer[0]) + (0.587F * this.chunkTypeBuffer[1]) + (0.114F * this.chunkTypeBuffer[2]));
for (int i = 0; i < this.bytesPerPixel; i++)
@ -314,7 +314,7 @@ namespace ImageSharp.Formats
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
// We can use the optimized PixelAccessor here and copy the bytes in unmanaged memory.
using (PixelArea<TColor> pixelRow = new PixelArea<TColor>(this.width, rawScanline, this.bytesPerPixel == 4 ? ComponentOrder.XYZW : ComponentOrder.XYZ))
using (PixelArea<TColor> pixelRow = new PixelArea<TColor>(this.width, rawScanline, this.bytesPerPixel == 4 ? ComponentOrder.Xyzw : ComponentOrder.Xyz))
{
pixels.CopyTo(pixelRow, row);
}
@ -507,7 +507,7 @@ namespace ImageSharp.Formats
for (int i = 0; i < pixelCount; i++)
{
int offset = i * 3;
palette[i].ToBytes(bytes, 0, ComponentOrder.XYZW);
palette[i].ToXyzwBytes(bytes, 0);
int alpha = bytes[3];

2
src/ImageSharp/Image/ImageBase{TColor}.cs

@ -64,7 +64,7 @@ namespace ImageSharp
using (PixelAccessor<TColor> sourcePixels = other.Lock())
using (PixelAccessor<TColor> target = this.Lock())
{
sourcePixels.CopyImage(target);
sourcePixels.CopyTo(target);
}
}

251
src/ImageSharp/Image/PixelAccessor{TColor}.cs

@ -145,69 +145,40 @@ namespace ImageSharp
}
/// <summary>
/// Copies a block of pixels at the specified position.
/// Copy an area of pixels to the image.
/// </summary>
/// <param name="sourceX">The x-coordinate of the source image.</param>
/// <param name="sourceY">The y-coordinate of the source image.</param>
/// <param name="target">The target pixel buffer accessor.</param>
/// <param name="targetX">The x-coordinate of the target image.</param>
/// <param name="targetY">The y-coordinate of the target image.</param>
/// <param name="pixelCount">The number of pixels to copy</param>
public void CopyBlock(int sourceX, int sourceY, PixelAccessor<TColor> target, int targetX, int targetY, int pixelCount)
/// <param name="area">The area.</param>
/// <param name="targetY">The target row index.</param>
/// <param name="targetX">The target column index.</param>
/// <exception cref="NotSupportedException">
/// Thrown when an unsupported component order value is passed.
/// </exception>
public void CopyFrom(PixelArea<TColor> area, int targetY, int targetX = 0)
{
int size = Unsafe.SizeOf<TColor>();
byte* sourcePtr = this.pixelsBase + (((sourceY * this.Width) + sourceX) * size);
byte* targetPtr = target.pixelsBase + (((targetY * target.Width) + targetX) * size);
uint byteCount = (uint)(pixelCount * size);
Unsafe.CopyBlock(targetPtr, sourcePtr, byteCount);
}
this.CheckCoordinates(area, targetX, targetY);
/// <summary>
/// Copies an entire image.
/// </summary>
/// <param name="target">The target pixel buffer accessor.</param>
public void CopyImage(PixelAccessor<TColor> target)
{
this.CopyBlock(0, 0, target, 0, 0, target.Width * target.Height);
this.CopyFrom(area, targetX, targetY, area.Width, area.Height);
}
/// <summary>
/// Copied a row of pixels from the image.
/// Copy pixels from the image to an area of pixels.
/// </summary>
/// <param name="area">The area.</param>
/// <param name="targetY">The target row index.</param>
/// <param name="targetX">The target column index.</param>
/// <param name="sourceY">The source row index.</param>
/// <param name="sourceX">The source column index.</param>
/// <exception cref="NotSupportedException">
/// Thrown when an unsupported component order value is passed.
/// </exception>
public void CopyFrom(PixelArea<TColor> area, int targetY, int targetX = 0)
public void CopyTo(PixelArea<TColor> area, int sourceY, int sourceX = 0)
{
int width = Math.Min(area.Width, this.Width - targetX);
int height = Math.Min(area.Height, this.Height - targetY);
this.CheckCoordinates(area, sourceX, sourceY);
// this.CheckDimensions(width, height); TODO: Why was width == 0 or height == 0 considered a problem? Copy implementations do not fail on this (just do nothing)!
switch (area.ComponentOrder)
{
case ComponentOrder.ZYX:
this.CopyFromZYX(area, targetY, targetX, width, height);
break;
case ComponentOrder.ZYXW:
this.CopyFromZYXW(area, targetY, targetX, width, height);
break;
case ComponentOrder.XYZ:
this.CopyFromXYZ(area, targetY, targetX, width, height);
break;
case ComponentOrder.XYZW:
this.CopyFromXYZW(area, targetY, targetX, width, height);
break;
default:
throw new NotSupportedException();
}
this.CopyTo(area, sourceX, sourceY, area.Width, area.Height);
}
/// <summary>
/// Copied an area of pixels to the image.
/// Copy pixels from the image to an area of pixels. This method will make sure that the pixels
/// that are copied are within the bounds of the image.
/// </summary>
/// <param name="area">The area.</param>
/// <param name="sourceY">The source row index.</param>
@ -215,29 +186,21 @@ namespace ImageSharp
/// <exception cref="NotSupportedException">
/// Thrown when an unsupported component order value is passed.
/// </exception>
public void CopyTo(PixelArea<TColor> area, int sourceY, int sourceX = 0)
public void SafeCopyTo(PixelArea<TColor> area, int sourceY, int sourceX = 0)
{
int width = Math.Min(area.Width, this.Width - sourceX);
int height = Math.Min(area.Height, this.Height - sourceY);
if (width < 1)
{
return;
}
// this.CheckDimensions(width, height); TODO: Why was width == 0 or height == 0 considered a problem? Copy implementations do not fail on this (just do nothing)!
switch (area.ComponentOrder)
int height = Math.Min(area.Height, this.Height - sourceY);
if (height < 1)
{
case ComponentOrder.ZYX:
this.CopyToZYX(area, sourceY, sourceX, width, height);
break;
case ComponentOrder.ZYXW:
this.CopyToZYXW(area, sourceY, sourceX, width, height);
break;
case ComponentOrder.XYZ:
this.CopyToXYZ(area, sourceY, sourceX, width, height);
break;
case ComponentOrder.XYZW:
this.CopyToXYZW(area, sourceY, sourceX, width, height);
break;
default:
throw new NotSupportedException();
return;
}
this.CopyTo(area, sourceX, sourceY, width, height);
}
/// <summary>
@ -269,6 +232,17 @@ namespace ImageSharp
GC.SuppressFinalize(this);
}
/// <summary>
/// Copies the pixels to another <see cref="PixelAccessor{TColor}"/> of the same size.
/// </summary>
/// <param name="target">The target pixel buffer accessor.</param>
internal void CopyTo(PixelAccessor<TColor> target)
{
uint byteCount = (uint)(this.Width * this.Height * Unsafe.SizeOf<TColor>());
Unsafe.CopyBlock(target.pixelsBase, this.pixelsBase, byteCount);
}
/// <summary>
/// Resets all the pixels to it's initial value.
/// </summary>
@ -278,21 +252,21 @@ namespace ImageSharp
}
/// <summary>
/// Copies from an area in <see cref="ComponentOrder.ZYX"/> format.
/// Copies from an area in <see cref="ComponentOrder.Zyx"/> format.
/// </summary>
/// <param name="area">The area.</param>
/// <param name="targetY">The target row index.</param>
/// <param name="targetX">The target column index.</param>
/// <param name="targetY">The target row index.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
protected virtual void CopyFromZYX(PixelArea<TColor> area, int targetY, int targetX, int width, int height)
protected virtual void CopyFromZyx(PixelArea<TColor> area, int targetX, int targetY, int width, int height)
{
TColor packed = default(TColor);
int size = Unsafe.SizeOf<TColor>();
for (int y = 0; y < height; y++)
{
byte* source = area.PixelBase + (y * area.RowByteCount);
byte* source = area.PixelBase + (y * area.RowStride);
byte* destination = this.GetRowPointer(targetX, targetY + y);
for (int x = 0; x < width; x++)
@ -307,21 +281,21 @@ namespace ImageSharp
}
/// <summary>
/// Copies from an area in <see cref="ComponentOrder.ZYXW"/> format.
/// Copies from an area in <see cref="ComponentOrder.Zyxw"/> format.
/// </summary>
/// <param name="area">The area.</param>
/// <param name="targetY">The target row index.</param>
/// <param name="targetX">The target column index.</param>
/// <param name="targetY">The target row index.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
protected virtual void CopyFromZYXW(PixelArea<TColor> area, int targetY, int targetX, int width, int height)
protected virtual void CopyFromZyxw(PixelArea<TColor> area, int targetX, int targetY, int width, int height)
{
TColor packed = default(TColor);
int size = Unsafe.SizeOf<TColor>();
for (int y = 0; y < height; y++)
{
byte* source = area.PixelBase + (y * area.RowByteCount);
byte* source = area.PixelBase + (y * area.RowStride);
byte* destination = this.GetRowPointer(targetX, targetY + y);
for (int x = 0; x < width; x++)
@ -336,21 +310,21 @@ namespace ImageSharp
}
/// <summary>
/// Copies from an area in <see cref="ComponentOrder.XYZ"/> format.
/// Copies from an area in <see cref="ComponentOrder.Xyz"/> format.
/// </summary>
/// <param name="area">The area.</param>
/// <param name="targetY">The target row index.</param>
/// <param name="targetX">The target column index.</param>
/// <param name="targetY">The target row index.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
protected virtual void CopyFromXYZ(PixelArea<TColor> area, int targetY, int targetX, int width, int height)
protected virtual void CopyFromXyz(PixelArea<TColor> area, int targetX, int targetY, int width, int height)
{
TColor packed = default(TColor);
int size = Unsafe.SizeOf<TColor>();
for (int y = 0; y < height; y++)
{
byte* source = area.PixelBase + (y * area.RowByteCount);
byte* source = area.PixelBase + (y * area.RowStride);
byte* destination = this.GetRowPointer(targetX, targetY + y);
for (int x = 0; x < width; x++)
@ -365,21 +339,21 @@ namespace ImageSharp
}
/// <summary>
/// Copies from an area in <see cref="ComponentOrder.XYZW"/> format.
/// Copies from an area in <see cref="ComponentOrder.Xyzw"/> format.
/// </summary>
/// <param name="area">The area.</param>
/// <param name="targetY">The target row index.</param>
/// <param name="targetX">The target column index.</param>
/// <param name="targetY">The target row index.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
protected virtual void CopyFromXYZW(PixelArea<TColor> area, int targetY, int targetX, int width, int height)
protected virtual void CopyFromXyzw(PixelArea<TColor> area, int targetX, int targetY, int width, int height)
{
TColor packed = default(TColor);
int size = Unsafe.SizeOf<TColor>();
for (int y = 0; y < height; y++)
{
byte* source = area.PixelBase + (y * area.RowByteCount);
byte* source = area.PixelBase + (y * area.RowStride);
byte* destination = this.GetRowPointer(targetX, targetY + y);
for (int x = 0; x < width; x++)
@ -394,84 +368,84 @@ namespace ImageSharp
}
/// <summary>
/// Copies to an area in <see cref="ComponentOrder.ZYX"/> format.
/// Copies to an area in <see cref="ComponentOrder.Zyx"/> format.
/// </summary>
/// <param name="area">The row.</param>
/// <param name="sourceY">The source row index.</param>
/// <param name="sourceX">The source column index.</param>
/// <param name="sourceY">The source row index.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
protected virtual void CopyToZYX(PixelArea<TColor> area, int sourceY, int sourceX, int width, int height)
protected virtual void CopyToZyx(PixelArea<TColor> area, int sourceX, int sourceY, int width, int height)
{
for (int y = 0; y < height; y++)
{
int offset = y * area.RowByteCount;
int offset = y * area.RowStride;
for (int x = 0; x < width; x++)
{
this[sourceX + x, sourceY + y].ToBytes(area.Bytes, offset, ComponentOrder.ZYX);
this[sourceX + x, sourceY + y].ToZyxBytes(area.Bytes, offset);
offset += 3;
}
}
}
/// <summary>
/// Copies to an area in <see cref="ComponentOrder.ZYXW"/> format.
/// Copies to an area in <see cref="ComponentOrder.Zyxw"/> format.
/// </summary>
/// <param name="area">The row.</param>
/// <param name="sourceY">The source row index.</param>
/// <param name="sourceX">The source column index.</param>
/// <param name="sourceY">The source row index.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
protected virtual void CopyToZYXW(PixelArea<TColor> area, int sourceY, int sourceX, int width, int height)
protected virtual void CopyToZyxw(PixelArea<TColor> area, int sourceX, int sourceY, int width, int height)
{
for (int y = 0; y < height; y++)
{
int offset = y * area.RowByteCount;
int offset = y * area.RowStride;
for (int x = 0; x < width; x++)
{
this[sourceX + x, sourceY + y].ToBytes(area.Bytes, offset, ComponentOrder.ZYXW);
this[sourceX + x, sourceY + y].ToZyxwBytes(area.Bytes, offset);
offset += 4;
}
}
}
/// <summary>
/// Copies to an area in <see cref="ComponentOrder.XYZ"/> format.
/// Copies to an area in <see cref="ComponentOrder.Xyz"/> format.
/// </summary>
/// <param name="area">The row.</param>
/// <param name="sourceY">The source row index.</param>
/// <param name="sourceX">The source column index.</param>
/// <param name="sourceY">The source row index.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
protected virtual void CopyToXYZ(PixelArea<TColor> area, int sourceY, int sourceX, int width, int height)
protected virtual void CopyToXyz(PixelArea<TColor> area, int sourceX, int sourceY, int width, int height)
{
for (int y = 0; y < height; y++)
{
int offset = y * area.RowByteCount;
int offset = y * area.RowStride;
for (int x = 0; x < width; x++)
{
this[sourceX + x, sourceY + y].ToBytes(area.Bytes, offset, ComponentOrder.XYZ);
this[sourceX + x, sourceY + y].ToXyzBytes(area.Bytes, offset);
offset += 3;
}
}
}
/// <summary>
/// Copies to an area in <see cref="ComponentOrder.XYZW"/> format.
/// Copies to an area in <see cref="ComponentOrder.Xyzw"/> format.
/// </summary>
/// <param name="area">The row.</param>
/// <param name="sourceY">The source row index.</param>
/// <param name="sourceX">The source column index.</param>
/// <param name="sourceY">The source row index.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
protected virtual void CopyToXYZW(PixelArea<TColor> area, int sourceY, int sourceX, int width, int height)
protected virtual void CopyToXyzw(PixelArea<TColor> area, int sourceX, int sourceY, int width, int height)
{
for (int y = 0; y < height; y++)
{
int offset = y * area.RowByteCount;
int offset = y * area.RowStride;
for (int x = 0; x < width; x++)
{
this[sourceX + x, sourceY + y].ToBytes(area.Bytes, offset, ComponentOrder.XYZW);
this[sourceX + x, sourceY + y].ToXyzwBytes(area.Bytes, offset);
offset += 4;
}
}
@ -491,21 +465,88 @@ namespace ImageSharp
}
/// <summary>
/// Checks that the given dimensions are within the bounds of the image.
/// Copy an area of pixels to the image.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="area">The area.</param>
/// <param name="targetX">The target column index.</param>
/// <param name="targetY">The target row index.</param>
/// <param name="width">The width of the area to copy.</param>
/// <param name="height">The height of the area to copy.</param>
/// <exception cref="NotSupportedException">
/// Thrown when an unsupported component order value is passed.
/// </exception>
private void CopyFrom(PixelArea<TColor> area, int targetX, int targetY, int width, int height)
{
switch (area.ComponentOrder)
{
case ComponentOrder.Zyx:
this.CopyFromZyx(area, targetX, targetY, width, height);
break;
case ComponentOrder.Zyxw:
this.CopyFromZyxw(area, targetX, targetY, width, height);
break;
case ComponentOrder.Xyz:
this.CopyFromXyz(area, targetX, targetY, width, height);
break;
case ComponentOrder.Xyzw:
this.CopyFromXyzw(area, targetX, targetY, width, height);
break;
default:
throw new NotSupportedException();
}
}
/// <summary>
/// Copy pixels from the image to an area of pixels.
/// </summary>
/// <param name="area">The area.</param>
/// <param name="sourceX">The source column index.</param>
/// <param name="sourceY">The source row index.</param>
/// <param name="width">The width of the area to copy.</param>
/// <param name="height">The height of the area to copy.</param>
/// <exception cref="NotSupportedException">
/// Thrown when an unsupported component order value is passed.
/// </exception>
private void CopyTo(PixelArea<TColor> area, int sourceX, int sourceY, int width, int height)
{
switch (area.ComponentOrder)
{
case ComponentOrder.Zyx:
this.CopyToZyx(area, sourceX, sourceY, width, height);
break;
case ComponentOrder.Zyxw:
this.CopyToZyxw(area, sourceX, sourceY, width, height);
break;
case ComponentOrder.Xyz:
this.CopyToXyz(area, sourceX, sourceY, width, height);
break;
case ComponentOrder.Xyzw:
this.CopyToXyzw(area, sourceX, sourceY, width, height);
break;
default:
throw new NotSupportedException();
}
}
/// <summary>
/// Checks that the given area and offset are within the bounds of the image.
/// </summary>
/// <param name="area">The area.</param>
/// <param name="x">The x-coordinate of the pixel. Must be greater than zero and smaller than the width of the pixel.</param>
/// <param name="y">The y-coordinate of the pixel. Must be greater than zero and smaller than the width of the pixel.</param>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if the dimensions are not within the bounds of the image.
/// </exception>
[Conditional("DEBUG")]
private void CheckDimensions(int width, int height)
private void CheckCoordinates(PixelArea<TColor> area, int x, int y)
{
int width = Math.Min(area.Width, this.Width - x);
if (width < 1)
{
throw new ArgumentOutOfRangeException(nameof(width), width, $"Invalid area size specified.");
}
int height = Math.Min(area.Height, this.Height - y);
if (height < 1)
{
throw new ArgumentOutOfRangeException(nameof(height), height, $"Invalid area size specified.");

114
src/ImageSharp/Image/PixelArea{TColor}.cs

@ -18,6 +18,11 @@ namespace ImageSharp
public sealed unsafe class PixelArea<TColor> : IDisposable
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
/// <summary>
/// True if <see cref="Bytes"/> was rented from <see cref="BytesPool"/> by the constructor
/// </summary>
private readonly bool isBufferRented;
/// <summary>
/// Provides a way to access the pixels from unmanaged memory.
/// </summary>
@ -28,11 +33,6 @@ namespace ImageSharp
/// </summary>
private IntPtr dataPointer;
/// <summary>
/// True if <see cref="Bytes"/> was rented from <see cref="BytesPool"/> by the constructor
/// </summary>
private bool isBufferRented;
/// <summary>
/// A value indicating whether this instance of the given entity has been disposed.
/// </summary>
@ -75,8 +75,10 @@ namespace ImageSharp
this.Width = width;
this.Height = height;
this.ComponentOrder = componentOrder;
this.RowByteCount = width * GetComponentCount(componentOrder);
this.RowStride = width * GetComponentCount(componentOrder);
this.Bytes = bytes;
this.Length = bytes.Length;
this.isBufferRented = false;
this.pixelsHandle = GCHandle.Alloc(this.Bytes, GCHandleType.Pinned);
// TODO: Why is Resharper warning us about an impure method call?
@ -88,34 +90,31 @@ namespace ImageSharp
/// Initializes a new instance of the <see cref="PixelArea{TColor}"/> class.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="componentOrder">The component order.</param>
/// <param name="usePool">True if the buffer should be rented from ArrayPool</param>
public PixelArea(int width, int height, ComponentOrder componentOrder, bool usePool = false)
: this(width, height, componentOrder, 0, usePool)
public PixelArea(int width, ComponentOrder componentOrder)
: this(width, 1, componentOrder, 0)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PixelArea{TColor}"/> class.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="width">The width. </param>
/// <param name="componentOrder">The component order.</param>
/// <param name="usePool">True if the buffer should be rented from ArrayPool</param>
public PixelArea(int width, ComponentOrder componentOrder, bool usePool = false)
: this(width, 1, componentOrder, 0, usePool)
/// <param name="padding">The number of bytes to pad each row.</param>
public PixelArea(int width, ComponentOrder componentOrder, int padding)
: this(width, 1, componentOrder, padding)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PixelArea{TColor}"/> class.
/// </summary>
/// <param name="width">The width. </param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="componentOrder">The component order.</param>
/// <param name="padding">The number of bytes to pad each row.</param>
/// <param name="usePool">True if the buffer should be rented from ArrayPool</param>
public PixelArea(int width, ComponentOrder componentOrder, int padding, bool usePool = false)
: this(width, 1, componentOrder, padding, usePool)
public PixelArea(int width, int height, ComponentOrder componentOrder)
: this(width, height, componentOrder, 0)
{
}
@ -126,27 +125,15 @@ namespace ImageSharp
/// <param name="height">The height.</param>
/// <param name="componentOrder">The component order.</param>
/// <param name="padding">The number of bytes to pad each row.</param>
/// <param name="usePool">True if the buffer should be rented from ArrayPool</param>
public PixelArea(int width, int height, ComponentOrder componentOrder, int padding, bool usePool = false)
public PixelArea(int width, int height, ComponentOrder componentOrder, int padding)
{
this.Width = width;
this.Height = height;
this.ComponentOrder = componentOrder;
this.RowByteCount = (width * GetComponentCount(componentOrder)) + padding;
int bufferSize = this.RowByteCount * height;
if (usePool)
{
this.Bytes = BytesPool.Rent(bufferSize);
this.isBufferRented = true;
Array.Clear(this.Bytes, 0, bufferSize);
}
else
{
this.Bytes = new byte[bufferSize];
}
this.RowStride = (width * GetComponentCount(componentOrder)) + padding;
this.Length = this.RowStride * height;
this.Bytes = BytesPool.Rent(this.Length);
this.isBufferRented = true;
this.pixelsHandle = GCHandle.Alloc(this.Bytes, GCHandleType.Pinned);
// TODO: Why is Resharper warning us about an impure method call?
@ -167,6 +154,11 @@ namespace ImageSharp
/// </summary>
public byte[] Bytes { get; }
/// <summary>
/// Gets the length of the buffer.
/// </summary>
public int Length { get; }
/// <summary>
/// Gets the component order.
/// </summary>
@ -188,9 +180,9 @@ namespace ImageSharp
public byte* PixelBase { get; private set; }
/// <summary>
/// Gets number of bytes in a row.
/// Gets the width of one row in the number of bytes.
/// </summary>
public int RowByteCount { get; }
public int RowStride { get; }
/// <summary>
/// Gets the width.
@ -198,9 +190,9 @@ namespace ImageSharp
public int Width { get; }
/// <summary>
/// Gets the pool used to rent <see cref="Bytes"/>, when it's not coming from an external source
/// Gets the pool used to rent bytes, when it's not coming from an external source.
/// </summary>
// ReSharper disable once StaticMemberInGenericType
// TODO: Use own pool?
private static ArrayPool<byte> BytesPool => ArrayPool<byte>.Shared;
/// <summary>
@ -209,6 +201,13 @@ namespace ImageSharp
public void Dispose()
{
this.Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SuppressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
/// <summary>
@ -217,7 +216,7 @@ namespace ImageSharp
/// <param name="stream">The stream.</param>
public void Read(Stream stream)
{
stream.Read(this.Bytes, 0, this.Bytes.Length);
stream.Read(this.Bytes, 0, this.Length);
}
/// <summary>
@ -226,7 +225,7 @@ namespace ImageSharp
/// <param name="stream">The stream.</param>
public void Write(Stream stream)
{
stream.Write(this.Bytes, 0, this.Bytes.Length);
stream.Write(this.Bytes, 0, this.Length);
}
/// <summary>
@ -234,7 +233,7 @@ namespace ImageSharp
/// </summary>
internal void Reset()
{
Unsafe.InitBlock(this.PixelBase, 0, (uint)(this.RowByteCount * this.Height));
Unsafe.InitBlock(this.PixelBase, 0, (uint)(this.RowStride * this.Height));
}
/// <summary>
@ -251,17 +250,27 @@ namespace ImageSharp
{
switch (componentOrder)
{
case ComponentOrder.ZYX:
case ComponentOrder.XYZ:
case ComponentOrder.Zyx:
case ComponentOrder.Xyz:
return 3;
case ComponentOrder.ZYXW:
case ComponentOrder.XYZW:
case ComponentOrder.Zyxw:
case ComponentOrder.Xyzw:
return 4;
}
throw new NotSupportedException();
}
/// <summary>
/// Checks that the length of the byte array to ensure that it matches the given width and height.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="bytes">The byte array.</param>
/// <param name="componentOrder">The component order.</param>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if the byte array is th incorrect length.
/// </exception>
[Conditional("DEBUG")]
private void CheckBytesLength(int width, int height, byte[] bytes, ComponentOrder componentOrder)
{
@ -274,6 +283,10 @@ namespace ImageSharp
}
}
/// <summary>
/// Disposes the object and frees resources for the Garbage Collector.
/// </summary>
/// <param name="disposing">If true, the object gets disposed.</param>
private void Dispose(bool disposing)
{
if (this.isDisposed)
@ -300,13 +313,6 @@ namespace ImageSharp
this.PixelBase = null;
this.isDisposed = true;
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SuppressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
}
}

28
src/ImageSharp/PixelAccessor.cs

@ -22,13 +22,13 @@ namespace ImageSharp
}
/// <inheritdoc />
protected override void CopyFromXYZW(PixelArea<Color> area, int targetY, int targetX, int width, int height)
protected override void CopyFromXyzw(PixelArea<Color> area, int targetX, int targetY, int width, int height)
{
uint byteCount = (uint)width * 4;
for (int y = 0; y < height; y++)
{
byte* source = area.PixelBase + (y * area.RowByteCount);
byte* source = area.PixelBase + (y * area.RowStride);
byte* destination = this.GetRowPointer(targetX, targetY + y);
Unsafe.CopyBlock(destination, source, byteCount);
@ -36,11 +36,11 @@ namespace ImageSharp
}
/// <inheritdoc />
protected override void CopyFromXYZ(PixelArea<Color> area, int targetY, int targetX, int width, int height)
protected override void CopyFromXyz(PixelArea<Color> area, int targetX, int targetY, int width, int height)
{
for (int y = 0; y < height; y++)
{
byte* source = area.PixelBase + (y * area.RowByteCount);
byte* source = area.PixelBase + (y * area.RowStride);
byte* destination = this.GetRowPointer(targetX, targetY + y);
for (int x = 0; x < width; x++)
@ -54,11 +54,11 @@ namespace ImageSharp
}
/// <inheritdoc />
protected override void CopyFromZYX(PixelArea<Color> area, int targetY, int targetX, int width, int height)
protected override void CopyFromZyx(PixelArea<Color> area, int targetX, int targetY, int width, int height)
{
for (int y = 0; y < height; y++)
{
byte* source = area.PixelBase + (y * area.RowByteCount);
byte* source = area.PixelBase + (y * area.RowStride);
byte* destination = this.GetRowPointer(targetX, targetY + y);
for (int x = 0; x < width; x++)
@ -72,11 +72,11 @@ namespace ImageSharp
}
/// <inheritdoc />
protected override void CopyFromZYXW(PixelArea<Color> area, int targetY, int targetX, int width, int height)
protected override void CopyFromZyxw(PixelArea<Color> area, int targetX, int targetY, int width, int height)
{
for (int y = 0; y < height; y++)
{
byte* source = area.PixelBase + (y * area.RowByteCount);
byte* source = area.PixelBase + (y * area.RowStride);
byte* destination = this.GetRowPointer(targetX, targetY + y);
for (int x = 0; x < width; x++)
@ -90,12 +90,12 @@ namespace ImageSharp
}
/// <inheritdoc />
protected override void CopyToZYX(PixelArea<Color> area, int sourceY, int sourceX, int width, int height)
protected override void CopyToZyx(PixelArea<Color> area, int sourceX, int sourceY, int width, int height)
{
for (int y = 0; y < height; y++)
{
byte* source = this.GetRowPointer(sourceX, sourceY + y);
byte* destination = area.PixelBase + (y * area.RowByteCount);
byte* destination = area.PixelBase + (y * area.RowStride);
for (int x = 0; x < width; x++)
{
@ -110,12 +110,12 @@ namespace ImageSharp
}
/// <inheritdoc />
protected override unsafe void CopyToXYZ(PixelArea<Color> area, int sourceY, int sourceX, int width, int height)
protected override void CopyToXyz(PixelArea<Color> area, int sourceX, int sourceY, int width, int height)
{
for (int y = 0; y < height; y++)
{
byte* source = this.GetRowPointer(sourceX, sourceY + y);
byte* destination = area.PixelBase + (y * area.RowByteCount);
byte* destination = area.PixelBase + (y * area.RowStride);
for (int x = 0; x < width; x++)
{
@ -130,12 +130,12 @@ namespace ImageSharp
}
/// <inheritdoc />
protected override void CopyToZYXW(PixelArea<Color> area, int sourceY, int sourceX, int width, int height)
protected override void CopyToZyxw(PixelArea<Color> area, int sourceX, int sourceY, int width, int height)
{
for (int y = 0; y < height; y++)
{
byte* source = this.GetRowPointer(sourceX, sourceY + y);
byte* destination = area.PixelBase + (y * area.RowByteCount);
byte* destination = area.PixelBase + (y * area.RowStride);
for (int x = 0; x < width; x++)
{

50
src/ImageSharp/Profiles/Exif/ExifTag.cs

@ -29,15 +29,15 @@ namespace ImageSharp
/// <summary>
/// SubfileType
/// </summary>
[ExifTagDescription((uint)0, "Full-resolution Image")]
[ExifTagDescription((uint)1, "Reduced-resolution image")]
[ExifTagDescription((uint)2, "Single page of multi-page image")]
[ExifTagDescription((uint)3, "Single page of multi-page reduced-resolution image")]
[ExifTagDescription((uint)4, "Transparency mask")]
[ExifTagDescription((uint)5, "Transparency mask of reduced-resolution image")]
[ExifTagDescription((uint)6, "Transparency mask of multi-page image")]
[ExifTagDescription((uint)7, "Transparency mask of reduced-resolution multi-page image")]
[ExifTagDescription((uint)0x10001, "Alternate reduced-resolution image ")]
[ExifTagDescription(0U, "Full-resolution Image")]
[ExifTagDescription(1U, "Reduced-resolution image")]
[ExifTagDescription(2U, "Single page of multi-page image")]
[ExifTagDescription(3U, "Single page of multi-page reduced-resolution image")]
[ExifTagDescription(4U, "Transparency mask")]
[ExifTagDescription(5U, "Transparency mask of reduced-resolution image")]
[ExifTagDescription(6U, "Transparency mask of multi-page image")]
[ExifTagDescription(7U, "Transparency mask of reduced-resolution multi-page image")]
[ExifTagDescription(0x10001U, "Alternate reduced-resolution image ")]
SubfileType = 0x00FE,
/// <summary>
@ -276,15 +276,15 @@ namespace ImageSharp
/// <summary>
/// T4Options
/// </summary>
[ExifTagDescription((uint)0, "2-Dimensional encoding")]
[ExifTagDescription((uint)1, "Uncompressed")]
[ExifTagDescription((uint)2, "Fill bits added")]
[ExifTagDescription(0U, "2-Dimensional encoding")]
[ExifTagDescription(1U, "Uncompressed")]
[ExifTagDescription(2U, "Fill bits added")]
T4Options = 0x0124,
/// <summary>
/// T6Options
/// </summary>
[ExifTagDescription((uint)1, "Uncompressed")]
[ExifTagDescription(1U, "Uncompressed")]
T6Options = 0x0125,
/// <summary>
@ -383,9 +383,9 @@ namespace ImageSharp
/// <summary>
/// CleanFaxData
/// </summary>
[ExifTagDescription((uint)0, "Clean")]
[ExifTagDescription((uint)1, "Regenerated")]
[ExifTagDescription((uint)2, "Unclean")]
[ExifTagDescription(0U, "Clean")]
[ExifTagDescription(1U, "Regenerated")]
[ExifTagDescription(2U, "Unclean")]
CleanFaxData = 0x0147,
/// <summary>
@ -491,8 +491,8 @@ namespace ImageSharp
/// <summary>
/// ProfileType
/// </summary>
[ExifTagDescription((uint)0, "Unspecified")]
[ExifTagDescription((uint)1, "Group 3 FAX")]
[ExifTagDescription(0U, "Unspecified")]
[ExifTagDescription(1U, "Group 3 FAX")]
ProfileType = 0x0191,
/// <summary>
@ -512,13 +512,13 @@ namespace ImageSharp
/// <summary>
/// CodingMethods
/// </summary>
[ExifTagDescription((ulong)0, "Unspecified compression")]
[ExifTagDescription((ulong)1, "Modified Huffman")]
[ExifTagDescription((ulong)2, "Modified Read")]
[ExifTagDescription((ulong)4, "Modified MR")]
[ExifTagDescription((ulong)8, "JBIG")]
[ExifTagDescription((ulong)16, "Baseline JPEG")]
[ExifTagDescription((ulong)32, "JBIG color")]
[ExifTagDescription(0UL, "Unspecified compression")]
[ExifTagDescription(1UL, "Modified Huffman")]
[ExifTagDescription(2UL, "Modified Read")]
[ExifTagDescription(4UL, "Modified MR")]
[ExifTagDescription(8UL, "JBIG")]
[ExifTagDescription(16UL, "Baseline JPEG")]
[ExifTagDescription(32UL, "JBIG color")]
CodingMethods = 0x0193,
/// <summary>

14
src/ImageSharp/Quantizers/Octree/OctreeQuantizer.cs

@ -47,12 +47,7 @@ namespace ImageSharp.Quantizers
public override QuantizedImage<TColor> Quantize(ImageBase<TColor> image, int maxColors)
{
this.colors = maxColors.Clamp(1, 255);
if (this.octree == null)
{
// Construct the Octree
this.octree = new Octree(this.GetBitsNeededForColorDepth(maxColors));
}
this.octree = new Octree(this.GetBitsNeededForColorDepth(maxColors));
return base.Quantize(image, maxColors);
}
@ -117,6 +112,7 @@ namespace ImageSharp.Quantizers
/// <summary>
/// Mask used when getting the appropriate pixels for a given node
/// </summary>
// ReSharper disable once StaticMemberInGenericType
private static readonly int[] Mask = { 0x100, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
/// <summary>
@ -380,7 +376,7 @@ namespace ImageSharp.Quantizers
{
// Go to the next level down in the tree
int shift = 7 - level;
pixel.ToBytes(buffer, 0, ComponentOrder.XYZW);
pixel.ToXyzwBytes(buffer, 0);
int index = ((buffer[3] & Mask[0]) >> (shift - 3)) |
((buffer[2] & Mask[level + 1]) >> (shift - 2)) |
@ -484,7 +480,7 @@ namespace ImageSharp.Quantizers
if (!this.leaf)
{
int shift = 7 - level;
pixel.ToBytes(buffer, 0, ComponentOrder.XYZW);
pixel.ToXyzwBytes(buffer, 0);
int pixelIndex = ((buffer[3] & Mask[0]) >> (shift - 3)) |
((buffer[2] & Mask[level + 1]) >> (shift - 2)) |
@ -511,7 +507,7 @@ namespace ImageSharp.Quantizers
/// <param name="buffer">The buffer array.</param>
public void Increment(TColor pixel, byte[] buffer)
{
pixel.ToBytes(buffer, 0, ComponentOrder.XYZW);
pixel.ToXyzwBytes(buffer, 0);
this.pixelCount++;
this.red += buffer[0];
this.green += buffer[1];

2
src/ImageSharp/Quantizers/Palette/PaletteQuantizer.cs

@ -49,7 +49,7 @@ namespace ImageSharp.Quantizers
for (int i = 0; i < constants.Length; i++)
{
constants[i].ToBytes(this.pixelBuffer, 0, ComponentOrder.XYZW);
constants[i].ToXyzwBytes(this.pixelBuffer, 0);
TColor packed = default(TColor);
packed.PackFromBytes(this.pixelBuffer[0], this.pixelBuffer[1], this.pixelBuffer[2], this.pixelBuffer[3]);
safe[i] = packed;

15
src/ImageSharp/Quantizers/Wu/WuQuantizer.cs

@ -33,11 +33,6 @@ namespace ImageSharp.Quantizers
public sealed class WuQuantizer<TColor> : IQuantizer<TColor>
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
/// <summary>
/// The epsilon for comparing floating point numbers.
/// </summary>
private const float Epsilon = 1e-5F;
/// <summary>
/// The index bits.
/// </summary>
@ -340,7 +335,7 @@ namespace ImageSharp.Quantizers
for (int x = 0; x < pixels.Width; x++)
{
// Colors are expected in r->g->b->a format
pixels[x, y].ToBytes(this.rgbaBuffer, 0, ComponentOrder.XYZW);
pixels[x, y].ToXyzwBytes(this.rgbaBuffer, 0);
byte r = this.rgbaBuffer[0];
byte g = this.rgbaBuffer[1];
@ -542,7 +537,7 @@ namespace ImageSharp.Quantizers
double temp;
if (Math.Abs(halfW) < Epsilon)
if (Math.Abs(halfW) < Constants.Epsilon)
{
continue;
}
@ -555,7 +550,7 @@ namespace ImageSharp.Quantizers
halfA = wholeA - halfA;
halfW = wholeW - halfW;
if (Math.Abs(halfW) < Epsilon)
if (Math.Abs(halfW) < Constants.Epsilon)
{
continue;
}
@ -762,7 +757,7 @@ namespace ImageSharp.Quantizers
double weight = Volume(cube[k], this.vwt);
if (Math.Abs(weight) > Epsilon)
if (Math.Abs(weight) > Constants.Epsilon)
{
float r = (float)(Volume(cube[k], this.vmr) / weight);
float g = (float)(Volume(cube[k], this.vmg) / weight);
@ -785,7 +780,7 @@ namespace ImageSharp.Quantizers
for (int x = 0; x < width; x++)
{
// Expected order r->g->b->a
imagePixels[x, y].ToBytes(rgba, 0, ComponentOrder.XYZW);
imagePixels[x, y].ToXyzwBytes(rgba, 0);
int r = rgba[0] >> (8 - IndexBits);
int g = rgba[1] >> (8 - IndexBits);

4
src/ImageSharp/project.json

@ -24,7 +24,7 @@
"buildOptions": {
"allowUnsafe": true,
"xmlDoc": true,
"additionalArguments": [ "/additionalfile:stylecop.json" ]
"additionalArguments": [ "/additionalfile:stylecop.json", "/ruleset:../../ImageSharp.ruleset" ]
},
"configurations": {
"Release": {
@ -36,7 +36,7 @@
},
"dependencies": {
"StyleCop.Analyzers": {
"version": "1.0.0",
"version": "1.1.0-beta001",
"type": "build"
},
"System.Buffers": "4.0.0",

21
tests/ImageSharp.Benchmarks/Image/CopyPixels.cs

@ -37,26 +37,5 @@ namespace ImageSharp.Benchmarks.Image
return targetPixels[0, 0];
}
}
[Benchmark(Description = "Copy by Row")]
public CoreColor CopyByRow()
{
CoreImage source = new CoreImage(1024, 768);
CoreImage target = new CoreImage(1024, 768);
using (PixelAccessor<CoreColor> sourcePixels = source.Lock())
using (PixelAccessor<CoreColor> targetPixels = target.Lock())
{
Parallel.For(
0,
source.Height,
Bootstrapper.ParallelOptions,
y =>
{
sourcePixels.CopyBlock(0, y, targetPixels, 0, y, source.Width);
});
return targetPixels[0, 0];
}
}
}
}

2
tests/ImageSharp.Tests/Colors/ColorConversionTests.cs

@ -7,7 +7,7 @@ namespace ImageSharp.Tests
{
using System;
using System.Diagnostics.CodeAnalysis;
using ImageSharp.Colors.Spaces;
using Xunit;
/// <summary>

165
tests/ImageSharp.Tests/Colors/PackedPixelTests.cs

@ -15,7 +15,7 @@ namespace ImageSharp.Tests.Colors
/// </summary>
/// <remarks>
/// The "ToVector4" tests should now be covered in <see cref="ColorConstructorTests"/>
/// and at some point they can be safely removed from here.
/// and at some point they can be safely removed from here.
/// </remarks>
public class PackedPixelTests
{
@ -47,16 +47,16 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new Alpha8(.5F).ToBytes(rgb, 0, ComponentOrder.XYZ);
new Alpha8(.5F).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 0, 0, 0 });
new Alpha8(.5F).ToBytes(rgba, 0, ComponentOrder.XYZW);
new Alpha8(.5F).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 0, 0, 0, 128 });
new Alpha8(.5F).ToBytes(bgr, 0, ComponentOrder.ZYX);
new Alpha8(.5F).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 0, 0, 0 });
new Alpha8(.5F).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new Alpha8(.5F).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 0, 0, 0, 128 });
}
@ -92,16 +92,16 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
argb.ToBytes(rgb, 0, ComponentOrder.XYZ);
argb.ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 0x1a, 0, 0x80 });
argb.ToBytes(rgba, 0, ComponentOrder.XYZW);
argb.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 0x1a, 0, 0x80, 0 });
argb.ToBytes(bgr, 0, ComponentOrder.ZYX);
argb.ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 0x80, 0, 0x1a });
argb.ToBytes(bgra, 0, ComponentOrder.ZYXW);
argb.ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 0x80, 0, 0x1a, 0 });
}
@ -133,23 +133,22 @@ namespace ImageSharp.Tests.Colors
float z = 0.5F;
Assert.Equal(6160, new Bgr565(x, y, z).PackedValue);
// Test ordering
byte[] rgb = new byte[3];
byte[] rgba = new byte[4];
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new Bgr565(x, y, z).ToBytes(rgb, 0, ComponentOrder.XYZ);
new Bgr565(x, y, z).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 25, 0, 132 });
new Bgr565(x, y, z).ToBytes(rgba, 0, ComponentOrder.XYZW);
new Bgr565(x, y, z).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 25, 0, 132, 255 });
new Bgr565(x, y, z).ToBytes(bgr, 0, ComponentOrder.ZYX);
new Bgr565(x, y, z).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 132, 0, 25 });
new Bgr565(x, y, z).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new Bgr565(x, y, z).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 132, 0, 25, 255 });
}
@ -190,16 +189,16 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new Bgra4444(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ);
new Bgra4444(x, y, z, w).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 34, 0, 136 });
new Bgra4444(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW);
new Bgra4444(x, y, z, w).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 34, 0, 136, 0 });
new Bgra4444(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX);
new Bgra4444(x, y, z, w).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 136, 0, 34 });
new Bgra4444(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new Bgra4444(x, y, z, w).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 136, 0, 34, 0 });
}
@ -236,16 +235,16 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new Bgra5551(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ);
new Bgra5551(x, y, z, w).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 24, 0, 131 });
new Bgra5551(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW);
new Bgra5551(x, y, z, w).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 24, 0, 131, 0 });
new Bgra5551(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX);
new Bgra5551(x, y, z, w).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 131, 0, 24 });
new Bgra5551(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new Bgra5551(x, y, z, w).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 131, 0, 24, 0 });
}
@ -287,21 +286,21 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new Byte4(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ);
new Byte4(x, y, z, w).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 128, 0, 0 });
new Byte4(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW);
new Byte4(x, y, z, w).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 128, 0, 0, 0 });
new Byte4(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX);
new Byte4(x, y, z, w).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 0, 0, 128 });
new Byte4(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new Byte4(x, y, z, w).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 0, 0, 128, 0 });
Byte4 r = new Byte4();
r.PackFromBytes(20, 38, 0, 255);
r.ToBytes(rgba, 0, ComponentOrder.XYZW);
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 });
}
@ -326,16 +325,16 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new HalfSingle(x).ToBytes(rgb, 0, ComponentOrder.XYZ);
new HalfSingle(x).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 128, 0, 0 });
new HalfSingle(x).ToBytes(rgba, 0, ComponentOrder.XYZW);
new HalfSingle(x).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 128, 0, 0, 255 });
new HalfSingle(x).ToBytes(bgr, 0, ComponentOrder.ZYX);
new HalfSingle(x).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 0, 0, 128 });
new HalfSingle(x).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new HalfSingle(x).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 0, 0, 128, 255 });
}
@ -363,16 +362,16 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new HalfVector2(x, y).ToBytes(rgb, 0, ComponentOrder.XYZ);
new HalfVector2(x, y).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 128, 64, 0 });
new HalfVector2(x, y).ToBytes(rgba, 0, ComponentOrder.XYZW);
new HalfVector2(x, y).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 128, 64, 0, 255 });
new HalfVector2(x, y).ToBytes(bgr, 0, ComponentOrder.ZYX);
new HalfVector2(x, y).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 0, 64, 128 });
new HalfVector2(x, y).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new HalfVector2(x, y).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 0, 64, 128, 255 });
}
@ -409,16 +408,16 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new HalfVector4(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ);
new HalfVector4(x, y, z, w).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 64, 128, 191 });
new HalfVector4(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW);
new HalfVector4(x, y, z, w).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 64, 128, 191, 255 });
new HalfVector4(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX);
new HalfVector4(x, y, z, w).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 191, 128, 64 });
new HalfVector4(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new HalfVector4(x, y, z, w).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 191, 128, 64, 255 });
}
@ -454,16 +453,16 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new NormalizedByte2(x, y).ToBytes(rgb, 0, ComponentOrder.XYZ);
new NormalizedByte2(x, y).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 141, 90, 0 });
new NormalizedByte2(x, y).ToBytes(rgba, 0, ComponentOrder.XYZW);
new NormalizedByte2(x, y).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 141, 90, 0, 255 });
new NormalizedByte2(x, y).ToBytes(bgr, 0, ComponentOrder.ZYX);
new NormalizedByte2(x, y).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 0, 90, 141 });
new NormalizedByte2(x, y).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new NormalizedByte2(x, y).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 0, 90, 141, 255 });
}
@ -499,26 +498,26 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new NormalizedByte4(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ);
new NormalizedByte4(x, y, z, w).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 141, 90, 192 });
new NormalizedByte4(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW);
new NormalizedByte4(x, y, z, w).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 141, 90, 192, 39 });
new NormalizedByte4(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX);
new NormalizedByte4(x, y, z, w).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 192, 90, 141 });
new NormalizedByte4(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new NormalizedByte4(x, y, z, w).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 192, 90, 141, 39 });
// http://community.monogame.net/t/normalizedbyte4-texture2d-gives-different-results-from-xna/8012/8
NormalizedByte4 r = new NormalizedByte4();
r.PackFromBytes(9, 115, 202, 127);
r.ToBytes(rgba, 0, ComponentOrder.XYZW);
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 9, 115, 202, 127 });
r.PackedValue = 0xff4af389;
r.ToBytes(rgba, 0, ComponentOrder.XYZW);
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 9, 115, 202, 127 });
}
@ -553,22 +552,22 @@ namespace ImageSharp.Tests.Colors
NormalizedShort2 n = new NormalizedShort2();
n.PackFromBytes(141, 90, 0, 0);
n.ToBytes(rgb, 0, ComponentOrder.XYZ);
n.ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 141, 90, 0 });
// TODO: I don't think this can ever pass since the bytes are already truncated.
// Assert.Equal(3650751693, n.PackedValue);
new NormalizedShort2(x, y).ToBytes(rgb, 0, ComponentOrder.XYZ);
new NormalizedShort2(x, y).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 141, 90, 0 });
new NormalizedShort2(x, y).ToBytes(rgba, 0, ComponentOrder.XYZW);
new NormalizedShort2(x, y).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 141, 90, 0, 255 });
new NormalizedShort2(x, y).ToBytes(bgr, 0, ComponentOrder.ZYX);
new NormalizedShort2(x, y).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 0, 90, 141 });
new NormalizedShort2(x, y).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new NormalizedShort2(x, y).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 0, 90, 141, 255 });
}
@ -600,21 +599,21 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new NormalizedShort4(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ);
new NormalizedShort4(x, y, z, w).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 141, 90, 192 });
new NormalizedShort4(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW);
new NormalizedShort4(x, y, z, w).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 141, 90, 192, 39 });
new NormalizedShort4(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX);
new NormalizedShort4(x, y, z, w).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 192, 90, 141 });
new NormalizedShort4(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new NormalizedShort4(x, y, z, w).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 192, 90, 141, 39 });
NormalizedShort4 r = new NormalizedShort4();
r.PackFromBytes(9, 115, 202, 127);
r.ToBytes(rgba, 0, ComponentOrder.XYZW);
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 9, 115, 202, 127 });
}
@ -647,16 +646,16 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new Rg32(x, y).ToBytes(rgb, 0, ComponentOrder.XYZ);
new Rg32(x, y).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 25, 0, 0 });
new Rg32(x, y).ToBytes(rgba, 0, ComponentOrder.XYZW);
new Rg32(x, y).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 25, 0, 0, 255 });
new Rg32(x, y).ToBytes(bgr, 0, ComponentOrder.ZYX);
new Rg32(x, y).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 0, 0, 25 });
new Rg32(x, y).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new Rg32(x, y).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 0, 0, 25, 255 });
}
@ -692,22 +691,22 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new Rgba1010102(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ);
new Rgba1010102(x, y, z, w).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 25, 0, 128 });
new Rgba1010102(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW);
new Rgba1010102(x, y, z, w).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 25, 0, 128, 0 });
new Rgba1010102(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX);
new Rgba1010102(x, y, z, w).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 128, 0, 25 });
new Rgba1010102(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new Rgba1010102(x, y, z, w).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 128, 0, 25, 0 });
// Alpha component accuracy will be awful.
Rgba1010102 r = new Rgba1010102();
r.PackFromBytes(25, 0, 128, 0);
r.ToBytes(rgba, 0, ComponentOrder.XYZW);
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 25, 0, 128, 0 });
}
@ -741,21 +740,21 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new Rgba64(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ);
new Rgba64(x, y, z, w).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 20, 38, 76 });
new Rgba64(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW);
new Rgba64(x, y, z, w).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 20, 38, 76, 115 });
new Rgba64(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX);
new Rgba64(x, y, z, w).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 76, 38, 20 });
new Rgba64(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new Rgba64(x, y, z, w).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 76, 38, 20, 115 });
Rgba64 r = new Rgba64();
r.PackFromBytes(20, 38, 76, 115);
r.ToBytes(rgba, 0, ComponentOrder.XYZW);
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 20, 38, 76, 115 });
}
@ -796,21 +795,21 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new Short2(x, y).ToBytes(rgb, 0, ComponentOrder.XYZ);
new Short2(x, y).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 128, 127, 0 });
new Short2(x, y).ToBytes(rgba, 0, ComponentOrder.XYZW);
new Short2(x, y).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 128, 127, 0, 255 });
new Short2(x, y).ToBytes(bgr, 0, ComponentOrder.ZYX);
new Short2(x, y).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 0, 127, 128 });
new Short2(x, y).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new Short2(x, y).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 0, 127, 128, 255 });
Short2 r = new Short2();
r.PackFromBytes(20, 38, 0, 255);
r.ToBytes(rgba, 0, ComponentOrder.XYZW);
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 });
}
@ -853,21 +852,21 @@ namespace ImageSharp.Tests.Colors
byte[] bgr = new byte[3];
byte[] bgra = new byte[4];
new Short4(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ);
new Short4(x, y, z, w).ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 172, 177, 243 });
new Short4(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW);
new Short4(x, y, z, w).ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 172, 177, 243, 128 });
new Short4(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX);
new Short4(x, y, z, w).ToZyxBytes(bgr, 0);
Assert.Equal(bgr, new byte[] { 243, 177, 172 });
new Short4(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW);
new Short4(x, y, z, w).ToZyxwBytes(bgra, 0);
Assert.Equal(bgra, new byte[] { 243, 177, 172, 128 });
Short4 r = new Short4();
r.PackFromBytes(20, 38, 0, 255);
r.ToBytes(rgba, 0, ComponentOrder.XYZW);
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 });
}

18
tests/ImageSharp.Tests/Common/ConstantsTests.cs

@ -0,0 +1,18 @@
// <copyright file="ConstantsTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests.Common
{
using Xunit;
public class ConstantsTests
{
[Fact]
public void Epsilon()
{
Assert.Equal(Constants.Epsilon, 0.001f);
}
}
}

4
tests/ImageSharp.Tests/Formats/Jpg/JpegTests.cs

@ -146,7 +146,7 @@ namespace ImageSharp.Tests
{
var src = provider.GetImage();
PixelArea<TColor> area = new PixelArea<TColor>(8, 8, ComponentOrder.XYZ);
PixelArea<TColor> area = new PixelArea<TColor>(8, 8, ComponentOrder.Xyz);
var dest = provider.Factory.CreateImage(8, 8);
using (var s = src.Lock())
@ -171,7 +171,7 @@ namespace ImageSharp.Tests
{
var src = provider.GetImage();
PixelArea<TColor> area = new PixelArea<TColor>(8, 8, ComponentOrder.XYZ);
PixelArea<TColor> area = new PixelArea<TColor>(8, 8, ComponentOrder.Xyz);
var dest = provider.Factory.CreateImage(8, 8);
using (var s = src.Lock())

6
tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementations.cs

@ -362,11 +362,11 @@ namespace ImageSharp.Tests
float a0, a1, a2, a3, b0, b1, b2, b3;
float z0, z1, z2, z3, z4;
float r0 = 1.414214f;
//float r0 = 1.414214f;
float r1 = 1.387040f;
float r2 = 1.306563f;
float r3 = 1.175876f;
float r4 = 1.000000f;
//float r4 = 1.000000f;
float r5 = 0.785695f;
float r6 = 0.541196f;
float r7 = 0.275899f;
@ -794,7 +794,7 @@ namespace ImageSharp.Tests
r[7] = 0.275899f;
const float invsqrt2 = 0.707107f; //(float)(1.0f / M_SQRT2);
const float invsqrt2h = 0.353554f; //invsqrt2*0.5f;
//const float invsqrt2h = 0.353554f; //invsqrt2*0.5f;
c1 = x[0];
c2 = x[7];

24
tests/ImageSharp.Tests/Image/PixelAccessorTests.cs

@ -40,10 +40,10 @@ namespace ImageSharp.Tests
}
[Theory]
[WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.XYZ)]
[WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.ZYX)]
[WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.XYZW)]
[WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.ZYXW)]
[WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.Xyz)]
[WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.Zyx)]
[WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.Xyzw)]
[WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.Zyxw)]
public void CopyTo_Then_CopyFrom_OnFullImageRect<TColor>(TestImageProvider<TColor> provider, ComponentOrder order)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
@ -84,10 +84,10 @@ namespace ImageSharp.Tests
}
[Theory]
[WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.XYZ)]
[WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.ZYX)]
[WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.XYZW)]
[WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.ZYXW)]
[WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Xyz)]
[WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Zyx)]
[WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Xyzw)]
[WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Zyxw)]
public void CopyTo_Then_CopyFrom_WithOffset<TColor>(TestImageProvider<TColor> provider, ComponentOrder order)
where TColor : struct, IPackedPixel, IEquatable<TColor>
@ -181,7 +181,7 @@ namespace ImageSharp.Tests
byte blue = 3;
byte alpha = 255;
using (PixelArea<TColor> row = new PixelArea<TColor>(1, ComponentOrder.ZYX))
using (PixelArea<TColor> row = new PixelArea<TColor>(1, ComponentOrder.Zyx))
{
row.Bytes[0] = blue;
row.Bytes[1] = green;
@ -208,7 +208,7 @@ namespace ImageSharp.Tests
byte blue = 3;
byte alpha = 4;
using (PixelArea<TColor> row = new PixelArea<TColor>(1, ComponentOrder.ZYXW))
using (PixelArea<TColor> row = new PixelArea<TColor>(1, ComponentOrder.Zyxw))
{
row.Bytes[0] = blue;
row.Bytes[1] = green;
@ -235,7 +235,7 @@ namespace ImageSharp.Tests
byte green = 2;
byte blue = 3;
using (PixelArea<TColor> row = new PixelArea<TColor>(1, ComponentOrder.ZYX))
using (PixelArea<TColor> row = new PixelArea<TColor>(1, ComponentOrder.Zyx))
{
pixels[0, 0] = (TColor)(object)new Color(red, green, blue);
@ -258,7 +258,7 @@ namespace ImageSharp.Tests
byte blue = 3;
byte alpha = 4;
using (PixelArea<TColor> row = new PixelArea<TColor>(1, ComponentOrder.ZYXW))
using (PixelArea<TColor> row = new PixelArea<TColor>(1, ComponentOrder.Zyxw))
{
pixels[0, 0] = (TColor)(object)new Color(red, green, blue, alpha);

12
tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs

@ -21,7 +21,7 @@ namespace ImageSharp.Tests
private static readonly Assembly ImageSharpAssembly = typeof(Color).GetTypeInfo().Assembly;
private static readonly Dictionary<PixelTypes, Type> PixelTypes2ClrTypes = new Dictionary<PixelTypes, Type>();
private static readonly PixelTypes[] AllConcretePixelTypes = EnumHelper.GetSortedValues<PixelTypes>()
.Except(new [] {PixelTypes.Undefined, PixelTypes.All })
.ToArray();
@ -53,7 +53,7 @@ namespace ImageSharp.Tests
return intrfcType.GetGenericArguments().Single();
}
public static bool HasFlag(this PixelTypes pixelTypes, PixelTypes flag) => (pixelTypes & flag) == flag;
public static bool IsEquivalentTo<TColor>(this Image<TColor> a, Image<TColor> b, bool compareAlpha = true)
@ -87,11 +87,11 @@ namespace ImageSharp.Tests
}
else
{
ca.ToBytes(bytesA, 0, ComponentOrder.XYZ);
cb.ToBytes(bytesB, 0, ComponentOrder.XYZ);
ca.ToXyzBytes(bytesA, 0);
cb.ToXyzBytes(bytesB, 0);
if (bytesA[0] != bytesB[0] ||
bytesA[1] != bytesB[1] ||
if (bytesA[0] != bytesB[0] ||
bytesA[1] != bytesB[1] ||
bytesA[2] != bytesB[2])
{
return false;

8
tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs

@ -35,7 +35,7 @@ namespace ImageSharp.Tests
[WithBlankImages(42, 666, PixelTypes.All, "hello")]
public void Use_WithBlankImagesAttribute_WithAllPixelTypes<TColor>(
TestImageProvider<TColor> provider,
string message)
string message)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
var img = provider.GetImage();
@ -59,7 +59,7 @@ namespace ImageSharp.Tests
[WithBlankImages(1, 1, PixelTypes.StandardImageClass)]
[WithFile(TestImages.Bmp.F, PixelTypes.StandardImageClass)]
public void PixelTypes_ColorWithDefaultImageClass_TriggersCreatingTheNonGenericDerivedImageClass<TColor>(
TestImageProvider<TColor> provider)
TestImageProvider<TColor> provider)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
var img = provider.GetImage();
@ -112,7 +112,7 @@ namespace ImageSharp.Tests
{
for (int x = 0; x < pixels.Width; x++)
{
pixels[x, y].ToBytes(colors, 0, ComponentOrder.XYZW);
pixels[x, y].ToXyzwBytes(colors, 0);
Assert.Equal(colors[0], 255);
Assert.Equal(colors[1], 100);
@ -129,7 +129,7 @@ namespace ImageSharp.Tests
/// <typeparam name="TColor"></typeparam>
/// <param name="factory"></param>
/// <returns></returns>
public static Image<TColor> CreateTestImage<TColor>(GenericFactory<TColor> factory)
public static Image<TColor> CreateTestImage<TColor>(GenericFactory<TColor> factory)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return factory.CreateImage(3, 3);

7
tests/ImageSharp.Tests/project.json

@ -12,6 +12,13 @@
"buildOptions": {
"allowUnsafe": true
},
"configurations": {
"Release": {
"buildOptions": {
"warningsAsErrors": true
}
}
},
"dependencies": {
"ImageSharp": "1.0.0-*",
"xunit": "2.2.0-*",

Loading…
Cancel
Save