Browse Source

Merge branch 'master' of https://github.com/JimBobSquarePants/ImageSharp into drop-pointers

pull/174/head
Anton Firszov 9 years ago
parent
commit
7aea2a4645
  1. 87
      README.md
  2. BIN
      build/icons/imagesharp-logo-128.png
  3. BIN
      build/icons/imagesharp-logo-256.png
  4. BIN
      build/icons/imagesharp-logo-32.png
  5. BIN
      build/icons/imagesharp-logo-512.png
  6. BIN
      build/icons/imagesharp-logo-64.png
  7. BIN
      build/icons/imagesharp-logo-heading.png
  8. BIN
      build/icons/imagesharp-logo.png
  9. 2
      build/icons/imagesharp-logo.svg
  10. 2
      src/ImageSharp.Drawing/Brushes/ImageBrush{TColor}.cs
  11. 2
      src/ImageSharp.Drawing/ImageSharp.Drawing.csproj
  12. 8
      src/ImageSharp.Drawing/Paths/RectangleExtensions.cs
  13. 2
      src/ImageSharp.Drawing/Pens/Pen{TColor}.cs
  14. 4
      src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs
  15. 8
      src/ImageSharp/Colors/ColorspaceTransforms.cs
  16. 28
      src/ImageSharp/Colors/PackedPixel/Bgr565.cs
  17. 20
      src/ImageSharp/Colors/PackedPixel/NormalizedShort2.cs
  18. 36
      src/ImageSharp/Colors/PackedPixel/NormalizedShort4.cs
  19. 28
      src/ImageSharp/Colors/PackedPixel/Rgba1010102.cs
  20. 28
      src/ImageSharp/Colors/PackedPixel/Rgba64.cs
  21. 16
      src/ImageSharp/Colors/PackedPixel/Short2.cs
  22. 28
      src/ImageSharp/Colors/PackedPixel/Short4.cs
  23. 8
      src/ImageSharp/Colors/Spaces/CieLab.cs
  24. 4
      src/ImageSharp/Colors/Spaces/Cmyk.cs
  25. 12
      src/ImageSharp/Colors/Spaces/Hsl.cs
  26. 12
      src/ImageSharp/Colors/Spaces/Hsv.cs
  27. 11
      src/ImageSharp/Colors/Vector4BlendTransforms.cs
  28. 4
      src/ImageSharp/Common/Extensions/Vector4Extensions.cs
  29. 22
      src/ImageSharp/Common/Helpers/ImageMaths.cs
  30. 144
      src/ImageSharp/Common/Helpers/MathF.cs
  31. 6
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  32. 16
      src/ImageSharp/Formats/Png/PngEncoderCore.cs
  33. 4
      src/ImageSharp/Formats/Png/PngInterlaceMode.cs
  34. 84
      src/ImageSharp/IO/BigEndianBitConverter.cs
  35. 4
      src/ImageSharp/IO/EndianBinaryReader.cs
  36. 52
      src/ImageSharp/IO/EndianBinaryWriter.cs
  37. 63
      src/ImageSharp/IO/EndianBitConverter.Conversion.cs
  38. 145
      src/ImageSharp/IO/EndianBitConverter.CopyBytes.cs
  39. 139
      src/ImageSharp/IO/EndianBitConverter.GetBytes.cs
  40. 141
      src/ImageSharp/IO/EndianBitConverter.ToType.cs
  41. 682
      src/ImageSharp/IO/EndianBitConverter.cs
  42. 80
      src/ImageSharp/IO/LittleEndianBitConverter.cs
  43. 4
      src/ImageSharp/Image.FromStream.cs
  44. 7
      src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs
  45. 6
      src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs
  46. 2
      src/ImageSharp/Processing/Processors/Effects/BackgroundColorProcessor.cs
  47. 6
      src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs
  48. 2
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs
  49. 6
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs
  50. 2
      src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs
  51. 2
      src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs
  52. 10
      src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs
  53. 36
      src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs
  54. 2
      src/ImageSharp/Quantizers/Octree/Quantizer.cs
  55. 1
      src/ImageSharp/Quantizers/QuantizedImage.cs
  56. 2
      tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs
  57. 56
      tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs
  58. 83
      tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs
  59. 69
      tests/ImageSharp.Tests/Helpers/MathFTests.cs
  60. 230
      tests/ImageSharp.Tests/IO/BigEndianBitConverter.CopyBytesTests.cs
  61. 110
      tests/ImageSharp.Tests/IO/BigEndianBitConverter.GetBytesTests.cs
  62. 214
      tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs
  63. 230
      tests/ImageSharp.Tests/IO/LittleEndianBitConverter.CopyBytesTests.cs
  64. 110
      tests/ImageSharp.Tests/IO/LittleEndianBitConverter.GetBytesTests.cs
  65. 212
      tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs
  66. 14
      tests/ImageSharp.Tests/Image/ImageLoadTests.cs
  67. 50
      tests/ImageSharp.Tests/Image/NoneSeekableStream.cs
  68. 119
      tests/ImageSharp.Tests/ImageComparer.cs
  69. 18
      tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs
  70. 34
      tests/ImageSharp.Tests/Processors/Filters/GrayscaleTest.cs
  71. 1
      tests/ImageSharp.Tests/TestImages.cs
  72. BIN
      tests/ImageSharp.Tests/TestImages/Formats/Jpg/baseline/ExifUndefType.jpg
  73. 38
      tests/ImageSharp.Tests/TestUtilities/Attributes/WithTestPatternImageAttribute.cs
  74. 27
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/BlankProvider.cs
  75. 20
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs
  76. 38
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs
  77. 53
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs
  78. 210
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs
  79. 43
      tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs
  80. 20
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

87
README.md

@ -1,9 +1,13 @@
# <img src="build/icons/imagesharp-logo-heading.png" alt="ImageSharp"/>
# <img src="https://github.com/JimBobSquarePants/ImageSharp/blob/master/build/icons/imagesharp-logo-256.png" alt="ImageSharp" width="52"/> ImageSharp
**ImageSharp** is a new cross-platform 2D graphics API designed to allow the processing of images without the use of `System.Drawing`.
**ImageSharp** is a new, fully featured, fully managed, cross-platform, 2D graphics API designed to allow the processing of images without the use of `System.Drawing`.
> **ImageSharp is still in early stages (alpha) but progress has been pretty quick. As such, please do not use on production environments until the library reaches release candidate status. Pre-release downloads are available from the [MyGet package repository](https://www.myget.org/gallery/imagesharp).**
Built against .Net Standard 1.1 ImageSharp can be used in device, cloud, and embedded/IoT scenarios.
> **ImageSharp** has made excellent progress and contains many great features but is still considered by us to be still in early stages (alpha). As such, we cannot support its use on production environments until the library reaches release candidate status.
>
> Pre-release downloads are available from the [MyGet package repository](https://www.myget.org/gallery/imagesharp).
[![GitHub license](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://raw.githubusercontent.com/JimBobSquarePants/ImageSharp/master/APACHE-2.0-LICENSE.txt)
[![GitHub issues](https://img.shields.io/github/issues/JimBobSquarePants/ImageSharp.svg)](https://github.com/JimBobSquarePants/ImageSharp/issues)
@ -11,6 +15,9 @@
[![GitHub forks](https://img.shields.io/github/forks/JimBobSquarePants/ImageSharp.svg)](https://github.com/JimBobSquarePants/ImageSharp/network)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ImageSharp/General?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Twitter](https://img.shields.io/twitter/url/https/github.com/JimBobSquarePants/ImageSharp.svg?style=social)](https://twitter.com/intent/tweet?hashtags=imagesharp,dotnet,oss&text=ImageSharp.+A+new+cross-platform+2D+graphics+API+in+C%23&url=https%3a%2f%2fgithub.com%2fJimBobSquarePants%2fImageSharp&via=james_m_south)
[![OpenCollective](https://opencollective.com/imagesharp/backers/badge.svg)](#backers)
[![OpenCollective](https://opencollective.com/imagesharp/sponsors/badge.svg)](#sponsors)
| |Build Status|Code Coverage|
@ -66,7 +73,9 @@ There's plenty there and more coming. Check out the [current features](features.
### API
Without the constraints of `System.Drawing` We have been able to develop something much more flexible, easier to code against, and much, much less prone to memory leaks. Gone are system-wide process-locks. Images and processors are thread safe usable in parallel processing utilizing all the availables cores.
Without the constraints of `System.Drawing` We have been able to develop something much more flexible, easier to code against, and much, much less prone to memory leaks.
Gone are system-wide process-locks; ImageSharp images are thread-safe and fully supported in web environments.
Many `Image` methods are also fluent.
@ -126,3 +135,73 @@ Core Team
- [Anton Firsov](https://github.com/antonfirsov)
- [Olivia Ifrim](https://github.com/olivif)
- [Scott Williams](https://github.com/tocsoft)
### Backers
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/imagesharp#backer)]
<a href="https://opencollective.com/imagesharp/backer/0/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/0/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/1/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/1/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/2/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/2/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/3/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/3/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/4/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/4/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/5/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/5/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/6/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/6/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/7/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/7/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/8/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/8/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/9/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/9/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/10/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/10/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/11/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/11/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/12/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/12/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/13/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/13/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/14/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/14/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/15/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/15/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/16/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/16/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/17/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/17/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/18/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/18/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/19/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/19/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/20/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/20/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/21/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/21/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/22/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/22/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/23/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/23/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/24/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/24/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/25/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/25/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/26/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/26/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/27/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/27/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/28/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/28/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/backer/29/website" target="_blank"><img src="https://opencollective.com/imagesharp/backer/29/avatar.svg"></a>
### Sponsors
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/imagesharp#sponsor)]
<a href="https://opencollective.com/imagesharp/sponsor/0/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/1/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/2/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/3/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/4/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/5/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/6/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/7/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/8/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/9/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/9/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/10/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/10/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/11/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/11/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/12/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/12/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/13/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/13/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/14/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/14/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/15/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/15/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/16/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/16/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/17/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/17/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/18/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/18/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/19/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/19/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/20/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/20/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/21/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/21/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/22/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/22/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/23/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/23/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/24/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/24/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/25/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/25/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/26/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/26/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/27/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/27/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/28/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/28/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/29/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/29/avatar.svg"></a>

BIN
build/icons/imagesharp-logo-128.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

BIN
build/icons/imagesharp-logo-256.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

BIN
build/icons/imagesharp-logo-32.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
build/icons/imagesharp-logo-512.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 34 KiB

BIN
build/icons/imagesharp-logo-64.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
build/icons/imagesharp-logo-heading.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
build/icons/imagesharp-logo.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 34 KiB

2
build/icons/imagesharp-logo.svg

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

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

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

2
src/ImageSharp.Drawing/ImageSharp.Drawing.csproj

@ -40,7 +40,7 @@
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="SixLabors.Fonts" Version="0.1.0-alpha0002" />
<PackageReference Include="SixLabors.Shapes" Version="0.1.0-alpha0009" />
<PackageReference Include="SixLabors.Shapes" Version="0.1.0-alpha0010" />
</ItemGroup>
<PropertyGroup>
<CodeAnalysisRuleSet>..\..\ImageSharp.ruleset</CodeAnalysisRuleSet>

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

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

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

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

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

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

8
src/ImageSharp/Colors/ColorspaceTransforms.cs

@ -105,12 +105,12 @@ namespace ImageSharp
float s = color.S;
float v = color.V;
if (Math.Abs(s) < Constants.Epsilon)
if (MathF.Abs(s) < Constants.Epsilon)
{
return new Color(v, v, v, 1);
}
float h = (Math.Abs(color.H - 360) < Constants.Epsilon) ? 0 : color.H / 60;
float h = (MathF.Abs(color.H - 360) < Constants.Epsilon) ? 0 : color.H / 60;
int i = (int)Math.Truncate(h);
float f = h - i;
@ -178,9 +178,9 @@ namespace ImageSharp
float s = color.S;
float l = color.L;
if (Math.Abs(l) > Constants.Epsilon)
if (MathF.Abs(l) > Constants.Epsilon)
{
if (Math.Abs(s) < Constants.Epsilon)
if (MathF.Abs(s) < Constants.Epsilon)
{
r = g = b = l;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

8
src/ImageSharp/Colors/Spaces/CieLab.cs

@ -95,11 +95,11 @@ namespace ImageSharp.Colors.Spaces
// y /= 1F;
z /= 1.08883F;
x = x > 0.008856F ? (float)Math.Pow(x, 0.3333333F) : ((903.3F * x) + 16F) / 116F;
y = y > 0.008856F ? (float)Math.Pow(y, 0.3333333F) : ((903.3F * y) + 16F) / 116F;
z = z > 0.008856F ? (float)Math.Pow(z, 0.3333333F) : ((903.3F * z) + 16F) / 116F;
x = x > 0.008856F ? MathF.Pow(x, 0.3333333F) : ((903.3F * x) + 16F) / 116F;
y = y > 0.008856F ? MathF.Pow(y, 0.3333333F) : ((903.3F * y) + 16F) / 116F;
z = z > 0.008856F ? MathF.Pow(z, 0.3333333F) : ((903.3F * z) + 16F) / 116F;
float l = Math.Max(0, (116F * y) - 16F);
float l = MathF.Max(0, (116F * y) - 16F);
float a = 500F * (x - y);
float b = 200F * (y - z);

4
src/ImageSharp/Colors/Spaces/Cmyk.cs

@ -93,9 +93,9 @@ namespace ImageSharp.Colors.Spaces
float m = 1f - (color.G / 255F);
float y = 1f - (color.B / 255F);
float k = Math.Min(c, Math.Min(m, y));
float k = MathF.Min(c, MathF.Min(m, y));
if (Math.Abs(k - 1.0f) <= Constants.Epsilon)
if (MathF.Abs(k - 1.0f) <= Constants.Epsilon)
{
return new Cmyk(0, 0, 0, 1);
}

12
src/ImageSharp/Colors/Spaces/Hsl.cs

@ -83,27 +83,27 @@ namespace ImageSharp.Colors.Spaces
float g = color.G / 255F;
float b = color.B / 255F;
float max = Math.Max(r, Math.Max(g, b));
float min = Math.Min(r, Math.Min(g, b));
float max = MathF.Max(r, MathF.Max(g, b));
float min = MathF.Min(r, MathF.Min(g, b));
float chroma = max - min;
float h = 0;
float s = 0;
float l = (max + min) / 2;
if (Math.Abs(chroma) < Constants.Epsilon)
if (MathF.Abs(chroma) < Constants.Epsilon)
{
return new Hsl(0, s, l);
}
if (Math.Abs(r - max) < Constants.Epsilon)
if (MathF.Abs(r - max) < Constants.Epsilon)
{
h = (g - b) / chroma;
}
else if (Math.Abs(g - max) < Constants.Epsilon)
else if (MathF.Abs(g - max) < Constants.Epsilon)
{
h = 2 + ((b - r) / chroma);
}
else if (Math.Abs(b - max) < Constants.Epsilon)
else if (MathF.Abs(b - max) < Constants.Epsilon)
{
h = 4 + ((r - g) / chroma);
}

12
src/ImageSharp/Colors/Spaces/Hsv.cs

@ -83,27 +83,27 @@ namespace ImageSharp.Colors.Spaces
float g = color.G / 255F;
float b = color.B / 255F;
float max = Math.Max(r, Math.Max(g, b));
float min = Math.Min(r, Math.Min(g, b));
float max = MathF.Max(r, MathF.Max(g, b));
float min = MathF.Min(r, MathF.Min(g, b));
float chroma = max - min;
float h = 0;
float s = 0;
float v = max;
if (Math.Abs(chroma) < Constants.Epsilon)
if (MathF.Abs(chroma) < Constants.Epsilon)
{
return new Hsv(0, s, v);
}
if (Math.Abs(r - max) < Constants.Epsilon)
if (MathF.Abs(r - max) < Constants.Epsilon)
{
h = (g - b) / chroma;
}
else if (Math.Abs(g - max) < Constants.Epsilon)
else if (MathF.Abs(g - max) < Constants.Epsilon)
{
h = 2 + ((b - r) / chroma);
}
else if (Math.Abs(b - max) < Constants.Epsilon)
else if (MathF.Abs(b - max) < Constants.Epsilon)
{
h = 4 + ((r - g) / chroma);
}

11
src/ImageSharp/Colors/Vector4BlendTransforms.cs

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

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

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

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

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

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

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

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

@ -579,7 +579,7 @@ namespace ImageSharp.Formats
// channel and we should try to read it.
for (int x = 0; x < this.header.Width; x++)
{
int index = newScanline[x];
int index = newScanline[x + 1];
int pixelOffset = index * 3;
byte a = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255;
@ -603,7 +603,7 @@ namespace ImageSharp.Formats
{
for (int x = 0; x < this.header.Width; x++)
{
int index = newScanline[x];
int index = newScanline[x + 1];
int pixelOffset = index * 3;
byte r = this.palette[pixelOffset];
@ -982,4 +982,4 @@ namespace ImageSharp.Formats
}
}
}
}
}

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

@ -516,9 +516,14 @@ namespace ImageSharp.Formats
colorTable[offset + 1] = bytes[1];
colorTable[offset + 2] = bytes[2];
if (alpha <= this.options.Threshold)
if (alpha < 255 && alpha <= this.options.Threshold)
{
transparentPixels.Add((byte)offset);
// Ensure the index is actually being used in our array.
// I'd like to find a faster way of doing this.
if (quantized.Pixels.Contains((byte)i))
{
transparentPixels.Add((byte)i);
}
}
}
@ -544,12 +549,11 @@ namespace ImageSharp.Formats
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <param name="imageBase">The image base.</param>
private void WritePhysicalChunk<TColor>(Stream stream, ImageBase<TColor> imageBase)
/// <param name="image">The image.</param>
private void WritePhysicalChunk<TColor>(Stream stream, Image<TColor> image)
where TColor : struct, IPixel<TColor>
{
Image<TColor> image = imageBase as Image<TColor>;
if (image != null && image.MetaData.HorizontalResolution > 0 && image.MetaData.VerticalResolution > 0)
if (image.MetaData.HorizontalResolution > 0 && image.MetaData.VerticalResolution > 0)
{
// 39.3700787 = inches in a meter.
int dpmX = (int)Math.Round(image.MetaData.HorizontalResolution * 39.3700787D);

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

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

84
src/ImageSharp/IO/BigEndianBitConverter.cs

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

4
src/ImageSharp/IO/EndianBinaryReader.cs

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

52
src/ImageSharp/IO/EndianBinaryWriter.cs

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

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

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

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

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

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

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

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

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

682
src/ImageSharp/IO/EndianBitConverter.cs

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

80
src/ImageSharp/IO/LittleEndianBitConverter.cs

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

4
src/ImageSharp/Image.FromStream.cs

@ -201,7 +201,7 @@ namespace ImageSharp
{
config = config ?? Configuration.Default;
Image<TColor> img = WithSeekableStream(stream, s => Decode<TColor>(stream, options, config));
Image<TColor> img = WithSeekableStream(stream, s => Decode<TColor>(s, options, config));
if (img != null)
{
@ -238,7 +238,7 @@ namespace ImageSharp
stream.CopyTo(ms);
ms.Position = 0;
return action(stream);
return action(ms);
}
}
}

7
src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs

@ -319,6 +319,13 @@ namespace ImageSharp
uint numberOfComponents = this.GetLong();
// Issue #132: ExifDataType == Undefined is treated like a byte array.
// If numberOfComponents == 0 this value can only be handled as an inline value and must fallback to 4 (bytes)
if (dataType == ExifDataType.Undefined && numberOfComponents == 0)
{
numberOfComponents = 4;
}
uint size = numberOfComponents * ExifValue.GetSize(dataType);
byte[] data = this.GetBytes(4);

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

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

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

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

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

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

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

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

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

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

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

@ -168,7 +168,7 @@ namespace ImageSharp.Processing.Processors
/// <returns>The weights</returns>
public WeightsWindow GetWeightsWindow(int destIdx, int leftIdx, int rightIdx)
{
BufferSpan<float> span = this.dataBuffer.GetRowSpan(destIdx).Slice(leftIdx, rightIdx - leftIdx);
BufferSpan<float> span = this.dataBuffer.GetRowSpan(destIdx).Slice(leftIdx, rightIdx - leftIdx + 1);
return new WeightsWindow(leftIdx, span);
}
}

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

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

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

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

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

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

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

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

1
src/ImageSharp/Quantizers/QuantizedImage.cs

@ -6,7 +6,6 @@
namespace ImageSharp.Quantizers
{
using System;
using System.Threading.Tasks;
/// <summary>
/// Represents a quantized image where the pixels indexed by a color palette.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

14
tests/ImageSharp.Tests/Image/ImageLoadTests.cs

@ -86,6 +86,20 @@ namespace ImageSharp.Tests
}
[Fact]
public void LoadFromNoneSeekableStream()
{
NoneSeekableStream stream = new NoneSeekableStream(this.DataStream);
Image img = Image.Load(stream);
Assert.NotNull(img);
Assert.Equal(TestFormat.GlobalTestFormat, img.CurrentImageFormat);
TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, null, Configuration.Default);
}
[Fact]
public void LoadFromStreamWithType()
{

50
tests/ImageSharp.Tests/Image/NoneSeekableStream.cs

@ -0,0 +1,50 @@
using System;
using System.IO;
namespace ImageSharp.Tests
{
internal class NoneSeekableStream : Stream
{
private Stream dataStream;
public NoneSeekableStream(Stream dataStream)
{
this.dataStream = dataStream;
}
public override bool CanRead => this.dataStream.CanRead;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override long Length => this.dataStream.Length;
public override long Position { get => this.dataStream.Position; set => throw new NotImplementedException(); }
public override void Flush()
{
this.dataStream.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
return this.dataStream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
}
}

119
tests/ImageSharp.Tests/ImageComparer.cs

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

18
tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs

@ -268,6 +268,24 @@ namespace ImageSharp.Tests
}
}
[Fact]
public void ExifTypeUndefined()
{
Image image = TestFile.Create(TestImages.Jpeg.Baseline.Bad.ExifUndefType).CreateImage();
Assert.NotNull(image);
ExifProfile profile = image.MetaData.ExifProfile;
Assert.NotNull(profile);
foreach (ExifValue value in profile.Values)
{
if (value.DataType == ExifDataType.Undefined)
{
Assert.Equal(4, value.NumberOfComponents);
}
}
}
private static ExifProfile GetExifProfile()
{
Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage();

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

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

1
tests/ImageSharp.Tests/TestImages.cs

@ -61,6 +61,7 @@ namespace ImageSharp.Tests
public static class Bad
{
public const string MissingEOF = "Jpg/baseline/badeof.jpg";
public const string ExifUndefType = "Jpg/baseline/ExifUndefType.jpg";
}
public const string Cmyk = "Jpg/baseline/cmyk.jpg";

BIN
tests/ImageSharp.Tests/TestImages/Formats/Jpg/baseline/ExifUndefType.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -0,0 +1,20 @@

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