diff --git a/README.md b/README.md
index 7e47e6b06f..f9d0315f2f 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,21 @@
-
-
- ImageSharp
-
-
-
-
-
-
-
+
+
+
+SixLabors.ImageSharp
+
+
+
+[](https://raw.githubusercontent.com/SixLabors/ImageSharp/master/LICENSE)
+[](https://gitter.im/ImageSharp/General?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[](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%2fSixLabors%2fImageSharp&via=sixlabors)
+[](#backers)
+[](#sponsors)
+
+
+
### **ImageSharp** is a new, fully featured, fully managed, cross-platform, 2D graphics API.
Designed to democratize image processing, ImageSharp brings you an incredibly powerful yet beautifully simple API.
@@ -21,7 +26,7 @@ Built against .Net Standard 1.1 ImageSharp can be used in device, cloud, and emb
### Installation
-Install stable releases via Nuget;evelopment releases are available via MyGet.
+Install stable releases via Nuget; development releases are available via MyGet.
| Package Name | Release (NuGet) | Nightly (MyGet) |
|--------------------------------|-----------------|-----------------|
@@ -51,7 +56,8 @@ The **ImageSharp** library is made up of multiple packages:
### Questions?
-Do you have questions? We are happy to help! Please [join our gitter channel](https://gitter.im/ImageSharp/General), or ask them on [stackoverflow](https://stackoverflow.com) using the `ImageSharp` tag.
+- Do you have questions? We are happy to help! Please [join our gitter channel](https://gitter.im/ImageSharp/General), or ask them on [stackoverflow](https://stackoverflow.com) using the `ImageSharp` tag. **Do not** open issues for questions!
+- Please read our [Contribution Guide](https://github.com/SixLabors/ImageSharp/blob/master/.github/CONTRIBUTING.md) before opening issues or pull requests!
### API
@@ -122,7 +128,7 @@ git clone https://github.com/SixLabors/ImageSharp
### How can you help?
-Please... Spread the word, contribute algorithms, submit performance improvements, unit tests, no input is too little.
+Please... Spread the word, contribute algorithms, submit performance improvements, unit tests, no input is too little. Make sure to read our [Contribution Guide](https://github.com/SixLabors/ImageSharp/blob/master/.github/CONTRIBUTING.md) before opening a PR.
### The ImageSharp Team
diff --git a/appveyor.yml b/appveyor.yml
index 8321209905..f784ef2876 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -4,6 +4,39 @@ image: Visual Studio 2017
# prevent the double build when a branch has an active PR
skip_branch_with_pr: true
+environment:
+ matrix:
+ - target_framework: net471
+ is_32bit: True
+ - target_framework: net462
+ is_32bit: False
+ - target_framework: net462
+ is_32bit: True
+ - target_framework: net471
+ is_32bit: False
+ - target_framework: netcoreapp2.0
+ is_32bit: False
+ #- target_framework: netcoreapp2.0 # As far as I understand, 32 bit test execution is not supported by "dotnet xunit"
+ # is_32bit: True
+ #- target_framework: mono
+ # is_32bit: False
+ #- target_framework: mono
+ # is_32bit: True
+ #- target_framework: net47
+ # is_32bit: False
+ #- target_framework: net47
+ # is_32bit: True
+
+install:
+ - ps: |
+ if ($env:target_framework -eq "mono") {
+ if ($env:is_32bit -eq "True") {
+ cinst mono --x86
+ } else {
+ cinst mono
+ }
+ }
+
before_build:
- git submodule -q update --init
- cmd: dotnet --version
@@ -12,7 +45,7 @@ build_script:
- cmd: build.cmd
test_script:
-- tests\CodeCoverage\CodeCoverage.cmd
+- ps: .\run-tests.ps1 $env:target_framework $env:is_32bit
after_test:
- cmd: appveyor PushArtifact "artifacts\SixLabors.ImageSharp.%APPVEYOR_BUILD_VERSION%.nupkg"
diff --git a/build.ps1 b/build.ps1
index 2f4d1c949f..4c5a36cae5 100644
--- a/build.ps1
+++ b/build.ps1
@@ -100,9 +100,17 @@ dotnet build -c Release /p:packageversion=$version
if ($LASTEXITCODE ){ Exit $LASTEXITCODE }
-if ( $env:CI -ne "True") {
- dotnet test ./tests/ImageSharp.Tests/ImageSharp.Tests.csproj --no-build -c Release
-}
+#
+# TODO: DO WE NEED TO RUN TESTS IMPLICITLY?
+#
+# if ( $env:CI -ne "True") {
+# cd ./tests/ImageSharp.Tests/
+# dotnet xunit -nobuild -c Release -f netcoreapp2.0 --fx-version 2.0.0
+# ./RunExtendedTests.cmd
+# cd ../..
+# }
+#
+
if ($LASTEXITCODE ){ Exit $LASTEXITCODE }
Write-Host "Packaging projects"
diff --git a/run-tests.ps1 b/run-tests.ps1
new file mode 100644
index 0000000000..e13c8fa648
--- /dev/null
+++ b/run-tests.ps1
@@ -0,0 +1,67 @@
+param(
+ [string]$targetFramework,
+ [string]$is32Bit = "False"
+)
+
+if (!$targetFramework){
+ Write-Host "run-tests.ps1 ERROR: targetFramework is undefined!"
+ exit 1
+}
+
+function VerifyPath($path, $errorMessage) {
+ if (!(Test-Path -Path $path)) {
+ Write-Host "run-tests.ps1 $errorMessage `n $xunitRunnerPath"
+ exit 1
+ }
+}
+
+if ( ($targetFramework -eq "netcoreapp2.0") -and ($env:CI -eq "True") -and ($is32Bit -ne "True")) {
+ # We execute CodeCoverage.cmd only for one specific job on CI (netcoreapp2.0 + 64bit )
+ $testRunnerCmd = ".\tests\CodeCoverage\CodeCoverage.cmd"
+}
+elseif ($targetFramework -eq "mono") {
+ $testDllPath = "$PSScriptRoot\tests\ImageSharp.Tests\bin\Release\net462\SixLabors.ImageSharp.Tests.dll"
+ VerifyPath($testDllPath, "test dll missing:")
+
+ $xunitRunnerPath = "${env:HOMEPATH}\.nuget\packages\xunit.runner.console\2.3.1\tools\net452\"
+
+ VerifyPath($xunitRunnerPath, "xunit console runner is missing on path:")
+
+ cd "$xunitRunnerPath"
+
+ if ($is32Bit -ne "True") {
+ $monoPath = "${env:PROGRAMFILES}\Mono\bin\mono.exe"
+ }
+ else {
+ $monoPath = "${env:ProgramFiles(x86)}\Mono\bin\mono.exe"
+ }
+
+ VerifyPath($monoPath, "mono runtime missing:")
+
+ $testRunnerCmd = "& `"${monoPath}`" .\xunit.console.exe `"${testDllPath}`""
+}
+else {
+ cd .\tests\ImageSharp.Tests
+ $xunitArgs = "-nobuild -c Release -framework $targetFramework"
+
+ if ($targetFramework -eq "netcoreapp2.0") {
+ # There were issues matching the correct installed runtime if we do not specify it explicitly:
+ $xunitArgs += " --fx-version 2.0.0"
+ }
+
+ if ($is32Bit -eq "True") {
+ $xunitArgs += " -x86"
+ }
+
+ $testRunnerCmd = "dotnet xunit $xunitArgs"
+}
+
+Write-Host "running:"
+Write-Host $testRunnerCmd
+Write-Host "..."
+
+Invoke-Expression $testRunnerCmd
+
+cd $PSScriptRoot
+
+exit $LASTEXITCODE
diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj
index 2c4a286d63..4144487e43 100644
--- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj
+++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj
@@ -11,7 +11,7 @@
SixLabors.ImageSharp.Drawing
SixLabors.ImageSharp.Drawing
Image Draw Shape Path Font
- https://raw.githubusercontent.com/SixLabors/ImageSharp/master/build/icons/imagesharp-logo-128.png
+ https://raw.githubusercontent.com/SixLabors/Branding/master/icons/imagesharp/sixlabors.imagesharp.128.png
https://github.com/SixLabors/ImageSharp
http://www.apache.org/licenses/LICENSE-2.0
git
@@ -36,9 +36,9 @@
-
-
-
+
+
+
All
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/DrawRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/Drawing/DrawRectangleExtensions.cs
index 03be4de47d..1f4a38a277 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/DrawRectangleExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/Drawing/DrawRectangleExtensions.cs
@@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing
/// The .
public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IPen pen, RectangleF shape)
where TPixel : struct, IPixel
- => source.Draw(options, pen, new RectangularePolygon(shape.X, shape.Y, shape.Width, shape.Height));
+ => source.Draw(options, pen, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height));
///
/// Draws the outline of the rectangle with the provided pen.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/FillRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/Drawing/FillRectangleExtensions.cs
index 234b94df52..ae0afc5d5a 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/FillRectangleExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/Drawing/FillRectangleExtensions.cs
@@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing
/// The .
public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, RectangleF shape)
where TPixel : struct, IPixel
- => source.Fill(options, brush, new RectangularePolygon(shape.X, shape.Y, shape.Width, shape.Height));
+ => source.Fill(options, brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height));
///
/// Flood fills the image in the shape of the provided rectangle with the specified brush.
@@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing
/// The .
public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, RectangleF shape)
where TPixel : struct, IPixel
- => source.Fill(brush, new RectangularePolygon(shape.X, shape.Y, shape.Width, shape.Height));
+ => source.Fill(brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height));
///
/// Flood fills the image in the shape of the provided rectangle with the specified brush.
diff --git a/src/ImageSharp/ColorSpaces/CieLab.cs b/src/ImageSharp/ColorSpaces/CieLab.cs
index cb08d08bf9..ce5c6c1186 100644
--- a/src/ImageSharp/ColorSpaces/CieLab.cs
+++ b/src/ImageSharp/ColorSpaces/CieLab.cs
@@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has L, A, B values set to zero.
///
- public static readonly CieLab Empty = default(CieLab);
+ public static readonly CieLab Empty = default;
///
/// The backing vector for SIMD support.
diff --git a/src/ImageSharp/ColorSpaces/CieLch.cs b/src/ImageSharp/ColorSpaces/CieLch.cs
index 94443fd863..1b9cf9c2b7 100644
--- a/src/ImageSharp/ColorSpaces/CieLch.cs
+++ b/src/ImageSharp/ColorSpaces/CieLch.cs
@@ -194,12 +194,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is CieLch)
- {
- return this.Equals((CieLch)obj);
- }
-
- return false;
+ return obj is CieLch other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/CieLchuv.cs b/src/ImageSharp/ColorSpaces/CieLchuv.cs
index 705b770d35..7ec27806d8 100644
--- a/src/ImageSharp/ColorSpaces/CieLchuv.cs
+++ b/src/ImageSharp/ColorSpaces/CieLchuv.cs
@@ -194,12 +194,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is CieLchuv)
- {
- return this.Equals((CieLchuv)obj);
- }
-
- return false;
+ return obj is CieLchuv other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/CieLuv.cs b/src/ImageSharp/ColorSpaces/CieLuv.cs
index b0ae048ab7..e46b736a75 100644
--- a/src/ImageSharp/ColorSpaces/CieLuv.cs
+++ b/src/ImageSharp/ColorSpaces/CieLuv.cs
@@ -196,12 +196,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is CieLuv)
- {
- return this.Equals((CieLuv)obj);
- }
-
- return false;
+ return obj is CieLuv other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
index d0a70dd191..d54de43bbb 100644
--- a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
+++ b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
@@ -132,12 +132,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is CieXyChromaticityCoordinates)
- {
- return this.Equals((CieXyChromaticityCoordinates)obj);
- }
-
- return false;
+ return obj is CieXyChromaticityCoordinates other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/CieXyy.cs b/src/ImageSharp/ColorSpaces/CieXyy.cs
index 751830a0ba..9633f83ad0 100644
--- a/src/ImageSharp/ColorSpaces/CieXyy.cs
+++ b/src/ImageSharp/ColorSpaces/CieXyy.cs
@@ -148,12 +148,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is CieXyy)
- {
- return this.Equals((CieXyy)obj);
- }
-
- return false;
+ return obj is CieXyy other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/CieXyz.cs b/src/ImageSharp/ColorSpaces/CieXyz.cs
index 0f1866009b..eedfed0798 100644
--- a/src/ImageSharp/ColorSpaces/CieXyz.cs
+++ b/src/ImageSharp/ColorSpaces/CieXyz.cs
@@ -148,12 +148,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is CieXyz)
- {
- return this.Equals((CieXyz)obj);
- }
-
- return false;
+ return obj is CieXyz other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/Cmyk.cs b/src/ImageSharp/ColorSpaces/Cmyk.cs
index 2eb148a8c3..2e44ea920a 100644
--- a/src/ImageSharp/ColorSpaces/Cmyk.cs
+++ b/src/ImageSharp/ColorSpaces/Cmyk.cs
@@ -150,12 +150,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is Cmyk)
- {
- return this.Equals((Cmyk)obj);
- }
-
- return false;
+ return obj is Cmyk other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs
index 0a5ae3627e..53d9c927ad 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs
@@ -15,8 +15,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLabColor
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieXyz Convert(CieLab input)
{
- DebugGuard.NotNull(input, nameof(input));
-
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_Lab_to_XYZ.html
float l = input.L, a = input.A, b = input.B;
float fy = (l + 16) / 116F;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs
index 22308260c2..454601b884 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs
@@ -3,7 +3,6 @@
using System;
using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.ColorSpaces;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLabColorSapce
{
@@ -44,8 +43,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLabColor
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieLab Convert(CieXyz input)
{
- DebugGuard.NotNull(input, nameof(input));
-
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html
float wx = this.LabWhitePoint.X, wy = this.LabWhitePoint.Y, wz = this.LabWhitePoint.Z;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs
index 35fae30e83..0b1ebae0ed 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs
@@ -3,7 +3,6 @@
using System;
using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.ColorSpaces;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchColorSapce
{
@@ -16,8 +15,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchColor
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieLab Convert(CieLch input)
{
- DebugGuard.NotNull(input, nameof(input));
-
// Conversion algorithm described here:
// https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC
float l = input.L, c = input.C, hDegrees = input.H;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs
index aa4614f9ca..ec73a830f6 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs
@@ -3,7 +3,6 @@
using System;
using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.ColorSpaces;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchColorSapce
{
@@ -16,8 +15,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchColor
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieLch Convert(CieLab input)
{
- DebugGuard.NotNull(input, nameof(input));
-
// Conversion algorithm described here:
// https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC
float l = input.L, a = input.A, b = input.B;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs
index fc6554a905..eb523806a4 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs
@@ -3,7 +3,6 @@
using System;
using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.ColorSpaces;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvColorSapce
{
@@ -16,8 +15,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvCol
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieLuv Convert(CieLchuv input)
{
- DebugGuard.NotNull(input, nameof(input));
-
// Conversion algorithm described here:
// https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_.28CIELCH.29
float l = input.L, c = input.C, hDegrees = input.H;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs
index f0d7a80a22..7a9dd2c6a7 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs
@@ -3,7 +3,6 @@
using System;
using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.ColorSpaces;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvColorSapce
{
@@ -16,8 +15,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvCol
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieLchuv Convert(CieLuv input)
{
- DebugGuard.NotNull(input, nameof(input));
-
// Conversion algorithm described here:
// https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_.28CIELCH.29
float l = input.L, a = input.U, b = input.V;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs
index 50e8335ed6..7a264fdfe2 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs
@@ -3,7 +3,6 @@
using System;
using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.ColorSpaces;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColorSapce
{
@@ -16,8 +15,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColor
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieXyz Convert(CieLuv input)
{
- DebugGuard.NotNull(input, nameof(input));
-
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_Luv_to_XYZ.html
float l = input.L, u = input.U, v = input.V;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/LmsAdaptationMatrix.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/LmsAdaptationMatrix.cs
index 1bd0c4ad50..d535d73342 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/LmsAdaptationMatrix.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/LmsAdaptationMatrix.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.LmsColorSap
/// DISCo, Department of Informatics, Systems and Communication, University of Milan-Bicocca, viale Sarca 336, 20126 Milan, Italy
/// https://web.stanford.edu/~sujason/ColorBalancing/Papers/Two%20New%20von%20Kries%20Based%20Chromatic%20Adaptation.pdf
///
- public static class LmsAdaptationMatrix
+ internal static class LmsAdaptationMatrix
{
///
/// Von Kries chromatic adaptation transform matrix (Hunt-Pointer-Estevez adjusted for D65)
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs
index 21a80225ee..a7b0ecc984 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
///
///
///
- public class GammaCompanding : ICompanding
+ internal class GammaCompanding : ICompanding
{
///
/// Initializes a new instance of the class.
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs
index 132861b476..30cd8dc510 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs
@@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
///
///
///
- public class LCompanding : ICompanding
+ internal class LCompanding : ICompanding
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs
index d279aba850..8afe2ffa05 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs
@@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
/// Represents the chromaticity coordinates of RGB primaries.
/// One of the specifiers of .
///
- internal struct RgbPrimariesChromaticityCoordinates : IEquatable
+ internal readonly struct RgbPrimariesChromaticityCoordinates : IEquatable
{
///
/// Initializes a new instance of the struct.
@@ -76,12 +76,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
///
public override bool Equals(object obj)
{
- if (obj is RgbPrimariesChromaticityCoordinates)
- {
- return this.Equals((RgbPrimariesChromaticityCoordinates)obj);
- }
-
- return false;
+ return obj is RgbPrimariesChromaticityCoordinates other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs
index 11761f0e4d..0b2b28b2d2 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
///
/// For 10-bits, companding is identical to
///
- public class Rec2020Companding : ICompanding
+ internal class Rec2020Companding : ICompanding
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs
index ccda6bf521..439cb29018 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs
@@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
///
/// http://en.wikipedia.org/wiki/Rec._709
///
- public class Rec709Companding : ICompanding
+ internal class Rec709Companding : ICompanding
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs
index 5a5c39647f..530c016916 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs
@@ -73,12 +73,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
///
public override bool Equals(object obj)
{
- if (obj is RgbWorkingSpace)
- {
- return this.Equals((RgbWorkingSpace)obj);
- }
-
- return false;
+ return obj is RgbWorkingSpace other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs
index ce8ea7c6e5..bde1b9123f 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs
@@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
///
///
///
- public class SRgbCompanding : ICompanding
+ internal class SRgbCompanding : ICompanding
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/ImageSharp/ColorSpaces/Hsl.cs b/src/ImageSharp/ColorSpaces/Hsl.cs
index 1944ac0c6b..3b2ceae27f 100644
--- a/src/ImageSharp/ColorSpaces/Hsl.cs
+++ b/src/ImageSharp/ColorSpaces/Hsl.cs
@@ -150,12 +150,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is Hsl)
- {
- return this.Equals((Hsl)obj);
- }
-
- return false;
+ return obj is Hsl other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/Hsv.cs b/src/ImageSharp/ColorSpaces/Hsv.cs
index fdfbfe5dd1..f646eb29d0 100644
--- a/src/ImageSharp/ColorSpaces/Hsv.cs
+++ b/src/ImageSharp/ColorSpaces/Hsv.cs
@@ -202,12 +202,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is Hsv)
- {
- return this.Equals((Hsv)obj);
- }
-
- return false;
+ return obj is Hsv other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/HunterLab.cs b/src/ImageSharp/ColorSpaces/HunterLab.cs
index de42518d76..4ace27def9 100644
--- a/src/ImageSharp/ColorSpaces/HunterLab.cs
+++ b/src/ImageSharp/ColorSpaces/HunterLab.cs
@@ -190,12 +190,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is HunterLab)
- {
- return this.Equals((HunterLab)obj);
- }
-
- return false;
+ return obj is HunterLab other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/LinearRgb.cs b/src/ImageSharp/ColorSpaces/LinearRgb.cs
index b8c446285a..f2dc297a01 100644
--- a/src/ImageSharp/ColorSpaces/LinearRgb.cs
+++ b/src/ImageSharp/ColorSpaces/LinearRgb.cs
@@ -182,12 +182,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is LinearRgb)
- {
- return this.Equals((LinearRgb)obj);
- }
-
- return false;
+ return obj is LinearRgb other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/Lms.cs b/src/ImageSharp/ColorSpaces/Lms.cs
index 72ac16f213..09c20269ab 100644
--- a/src/ImageSharp/ColorSpaces/Lms.cs
+++ b/src/ImageSharp/ColorSpaces/Lms.cs
@@ -149,12 +149,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is Lms)
- {
- return this.Equals((Lms)obj);
- }
-
- return false;
+ return obj is Lms other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/Rgb.cs b/src/ImageSharp/ColorSpaces/Rgb.cs
index ac86cfbf06..1282394670 100644
--- a/src/ImageSharp/ColorSpaces/Rgb.cs
+++ b/src/ImageSharp/ColorSpaces/Rgb.cs
@@ -204,12 +204,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is Rgb)
- {
- return this.Equals((Rgb)obj);
- }
-
- return false;
+ return obj is Rgb other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/ColorSpaces/YCbCr.cs b/src/ImageSharp/ColorSpaces/YCbCr.cs
index 44a0b245d5..a6e27de94b 100644
--- a/src/ImageSharp/ColorSpaces/YCbCr.cs
+++ b/src/ImageSharp/ColorSpaces/YCbCr.cs
@@ -152,12 +152,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
- if (obj is YCbCr)
- {
- return this.Equals((YCbCr)obj);
- }
-
- return false;
+ return obj is YCbCr other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/Common/Extensions/ByteExtensions.cs b/src/ImageSharp/Common/Extensions/ByteExtensions.cs
index f6c7207950..b5b868deaa 100644
--- a/src/ImageSharp/Common/Extensions/ByteExtensions.cs
+++ b/src/ImageSharp/Common/Extensions/ByteExtensions.cs
@@ -12,39 +12,6 @@ namespace SixLabors.ImageSharp
///
internal static class ByteExtensions
{
- ///
- /// Optimized reversal algorithm.
- ///
- /// The byte array.
- public static void ReverseBytes(this byte[] source)
- {
- ReverseBytes(source, 0, source.Length);
- }
-
- ///
- /// Optimized reversal algorithm.
- ///
- /// The byte array.
- /// The index.
- /// The length.
- /// is null.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void ReverseBytes(this byte[] source, int index, int length)
- {
- Guard.NotNull(source, nameof(source));
-
- int i = index;
- int j = index + length - 1;
- while (i < j)
- {
- byte temp = source[i];
- source[i] = source[j];
- source[j] = temp;
- i++;
- j--;
- }
- }
-
///
/// Returns a reference to the given position of the array unsafe casted to .
///
diff --git a/src/ImageSharp/Common/Helpers/Guard.cs b/src/ImageSharp/Common/Helpers/Guard.cs
index 0db5cb7c1d..9f0a46f80c 100644
--- a/src/ImageSharp/Common/Helpers/Guard.cs
+++ b/src/ImageSharp/Common/Helpers/Guard.cs
@@ -230,18 +230,36 @@ namespace SixLabors.ImageSharp
}
///
- /// Verifies, that the `target` span has the length of 'minSpan', or longer.
+ /// Verifies, that the `source` span has the length of 'minSpan', or longer.
///
/// The element type of the spans
- /// The target span.
+ /// The source span.
/// The minimum length.
/// The name of the parameter that is to be checked.
///
- /// is true
+ /// is true
+ ///
+ public static void MustBeSizedAtLeast(ReadOnlySpan source, int minLength, string parameterName)
+ {
+ if (source.Length < minLength)
+ {
+ throw new ArgumentException($"Span-s must be at least of length {minLength}!", parameterName);
+ }
+ }
+
+ ///
+ /// Verifies, that the `source` span has the length of 'minSpan', or longer.
+ ///
+ /// The element type of the spans
+ /// The target span.
+ /// The minimum length.
+ /// The name of the parameter that is to be checked.
+ ///
+ /// is true
///
- public static void MustBeSizedAtLeast(Span target, int minLength, string parameterName)
+ public static void MustBeSizedAtLeast(Span source, int minLength, string parameterName)
{
- if (target.Length < minLength)
+ if (source.Length < minLength)
{
throw new ArgumentException($"Span-s must be at least of length {minLength}!", parameterName);
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs b/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs
index d08487cf27..0029a6b68d 100644
--- a/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs
@@ -16,6 +16,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
/// 32 bits per pixel. Each pixel consists of 4 bytes.
///
- Pixel32 = 4,
+ Pixel32 = 4
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Bmp/BmpCompression.cs b/src/ImageSharp/Formats/Bmp/BmpCompression.cs
index 1280498acb..22b12346fb 100644
--- a/src/ImageSharp/Formats/Bmp/BmpCompression.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpCompression.cs
@@ -58,4 +58,4 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
PNG = 5
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Bmp/BmpConstants.cs b/src/ImageSharp/Formats/Bmp/BmpConstants.cs
index b7291bb99e..99799b619c 100644
--- a/src/ImageSharp/Formats/Bmp/BmpConstants.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpConstants.cs
@@ -20,4 +20,4 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
public static readonly IEnumerable FileExtensions = new[] { "bm", "bmp", "dip" };
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs
index 78a9de6c45..d3cb50d6ba 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs
@@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
where TPixel : struct, IPixel
{
- Guard.NotNull(stream, "stream");
+ Guard.NotNull(stream, nameof(stream));
return new BmpDecoderCore(configuration, this).Decode(stream);
}
@@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
public IImageInfo Identify(Configuration configuration, Stream stream)
{
- Guard.NotNull(stream, "stream");
+ Guard.NotNull(stream, nameof(stream));
return new BmpDecoderCore(configuration, this).Identify(stream);
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index 9f4dba5b4f..dfbd44c046 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
@@ -224,7 +224,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
var color = default(TPixel);
var rgba = new Rgba32(0, 0, 0, 255);
- using (var buffer = this.memoryManager.AllocateClean2D(width, height))
+ using (Buffer2D buffer = this.memoryManager.AllocateClean2D(width, height))
{
this.UncompressRle8(width, buffer.Span);
@@ -398,7 +398,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
var color = default(TPixel);
var rgba = new Rgba32(0, 0, 0, 255);
- using (var buffer = this.memoryManager.AllocateManagedByteBuffer(stride))
+ using (IManagedByteBuffer buffer = this.memoryManager.AllocateManagedByteBuffer(stride))
{
for (int y = 0; y < height; y++)
{
@@ -581,13 +581,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
this.currentStream.Read(data, 0, BmpFileHeader.Size);
- this.fileHeader = new BmpFileHeader
- {
- Type = BitConverter.ToInt16(data, 0),
- FileSize = BitConverter.ToInt32(data, 2),
- Reserved = BitConverter.ToInt32(data, 6),
- Offset = BitConverter.ToInt32(data, 10)
- };
+ this.fileHeader = new BmpFileHeader(
+ type: BitConverter.ToInt16(data, 0),
+ fileSize: BitConverter.ToInt32(data, 2),
+ reserved: BitConverter.ToInt32(data, 6),
+ offset: BitConverter.ToInt32(data, 10));
}
///
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs
index d80e43c63b..9edd0fcd4e 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs
@@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
-using System.Collections.Generic;
using System.IO;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
@@ -28,4 +26,4 @@ namespace SixLabors.ImageSharp.Formats.Bmp
encoder.Encode(image, stream);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
index 66c8b6c086..be7c1d2e55 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
@@ -55,9 +55,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
this.padding = bytesPerLine - (image.Width * (int)this.bitsPerPixel);
// Do not use IDisposable pattern here as we want to preserve the stream.
- EndianBinaryWriter writer = new EndianBinaryWriter(Endianness.LittleEndian, stream);
+ var writer = new EndianBinaryWriter(Endianness.LittleEndian, stream);
- BmpInfoHeader infoHeader = new BmpInfoHeader
+ var infoHeader = new BmpInfoHeader
{
HeaderSize = BmpInfoHeader.BitmapInfoHeaderSize,
Height = image.Height,
@@ -69,12 +69,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
ClrImportant = 0
};
- BmpFileHeader fileHeader = new BmpFileHeader
- {
- Type = 19778, // BM
- Offset = 54,
- FileSize = 54 + infoHeader.ImageSize
- };
+ var fileHeader = new BmpFileHeader(
+ type: 19778, // BM
+ offset: 54,
+ reserved: 0,
+ fileSize: 54 + infoHeader.ImageSize);
WriteHeader(writer, fileHeader);
this.WriteInfo(writer, infoHeader);
@@ -92,7 +91,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
/// The containing the header data.
///
- private static void WriteHeader(EndianBinaryWriter writer, BmpFileHeader fileHeader)
+ private static void WriteHeader(EndianBinaryWriter writer, in BmpFileHeader fileHeader)
{
writer.Write(fileHeader.Type);
writer.Write(fileHeader.FileSize);
diff --git a/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs b/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs
index 4255ecae49..ed17164a22 100644
--- a/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs
@@ -13,35 +13,43 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// All of the other integer values are stored in little-endian format
/// (i.e. least-significant byte first).
///
- internal sealed class BmpFileHeader
+ internal readonly struct BmpFileHeader
{
///
/// Defines of the data structure in the bitmap file.
///
public const int Size = 14;
+ public BmpFileHeader(short type, int fileSize, int reserved, int offset)
+ {
+ this.Type = type;
+ this.FileSize = fileSize;
+ this.Reserved = reserved;
+ this.Offset = offset;
+ }
+
///
- /// Gets or sets the Bitmap identifier.
+ /// Gets the Bitmap identifier.
/// The field used to identify the bitmap file: 0x42 0x4D
/// (Hex code points for B and M)
///
- public short Type { get; set; }
+ public short Type { get; }
///
- /// Gets or sets the size of the bitmap file in bytes.
+ /// Gets the size of the bitmap file in bytes.
///
- public int FileSize { get; set; }
+ public int FileSize { get; }
///
- /// Gets or sets any reserved data; actual value depends on the application
+ /// Gets any reserved data; actual value depends on the application
/// that creates the image.
///
- public int Reserved { get; set; }
+ public int Reserved { get; }
///
- /// Gets or sets the offset, i.e. starting address, of the byte where
+ /// Gets the offset, i.e. starting address, of the byte where
/// the bitmap data can be found.
///
- public int Offset { get; set; }
+ public int Offset { get; }
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/GifConstants.cs b/src/ImageSharp/Formats/Gif/GifConstants.cs
index d448cf7838..ffab45a567 100644
--- a/src/ImageSharp/Formats/Gif/GifConstants.cs
+++ b/src/ImageSharp/Formats/Gif/GifConstants.cs
@@ -21,6 +21,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
public const string FileVersion = "89a";
+ ///
+ /// The ASCII encoded bytes used to identify the GIF file.
+ ///
+ internal static readonly byte[] MagicNumber = Encoding.UTF8.GetBytes(FileType + FileVersion);
+
///
/// The extension block introducer !.
///
@@ -41,6 +46,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
public const string ApplicationIdentification = "NETSCAPE2.0";
+ ///
+ /// The ASCII encoded application identification bytes.
+ ///
+ internal static readonly byte[] ApplicationIdentificationBytes = Encoding.UTF8.GetBytes(ApplicationIdentification);
+
///
/// The application block size.
///
diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
index 57bb3d09a7..436db636d8 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
@@ -157,7 +157,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// The writer to write to the stream with.
private void WriteHeader(EndianBinaryWriter writer)
{
- writer.Write((GifConstants.FileType + GifConstants.FileVersion).ToCharArray());
+ writer.Write(GifConstants.MagicNumber);
}
///
@@ -213,7 +213,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
writer.Write(this.buffer, 0, 3);
- writer.Write(GifConstants.ApplicationIdentification.ToCharArray()); // NETSCAPE2.0
+ writer.Write(GifConstants.ApplicationIdentificationBytes); // NETSCAPE2.0
writer.Write((byte)3); // Application block length
writer.Write((byte)1); // Data sub-block index (always 1)
diff --git a/src/ImageSharp/Formats/Gif/PackedField.cs b/src/ImageSharp/Formats/Gif/PackedField.cs
index 28a415e2b8..969449a9f9 100644
--- a/src/ImageSharp/Formats/Gif/PackedField.cs
+++ b/src/ImageSharp/Formats/Gif/PackedField.cs
@@ -169,9 +169,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
public override bool Equals(object obj)
{
- PackedField? field = obj as PackedField?;
-
- return this.Byte == field?.Byte;
+ return obj is PackedField other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs b/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs
index 11a456ef9b..8a571fa6b7 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs
@@ -241,19 +241,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
///
public override string ToString()
{
- var bld = new StringBuilder();
- bld.Append('[');
+ var sb = new StringBuilder();
+ sb.Append('[');
for (int i = 0; i < Size; i++)
{
- bld.Append(this[i]);
+ sb.Append(this[i]);
if (i < Size - 1)
{
- bld.Append(',');
+ sb.Append(',');
}
}
- bld.Append(']');
- return bld.ToString();
+ sb.Append(']');
+ return sb.ToString();
}
///
@@ -273,12 +273,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
- {
- return false;
- }
-
- return obj is Block8x8 && this.Equals((Block8x8)obj);
+ return obj is Block8x8 other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
index f45b5df4eb..3f71c498b2 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
@@ -496,19 +496,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
///
public override string ToString()
{
- var bld = new StringBuilder();
- bld.Append('[');
+ var sb = new StringBuilder();
+ sb.Append('[');
for (int i = 0; i < Size; i++)
{
- bld.Append(this[i]);
+ sb.Append(this[i]);
if (i < Size - 1)
{
- bld.Append(',');
+ sb.Append(',');
}
}
- bld.Append(']');
- return bld.ToString();
+ sb.Append(']');
+ return sb.ToString();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/AdobeMarker.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/AdobeMarker.cs
index d55e36bd48..40059c5a0f 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/AdobeMarker.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/AdobeMarker.cs
@@ -94,12 +94,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
- {
- return false;
- }
-
- return obj is AdobeMarker && this.Equals((AdobeMarker)obj);
+ return obj is AdobeMarker other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JFifMarker.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JFifMarker.cs
index c856fd04a6..afe4794a23 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JFifMarker.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JFifMarker.cs
@@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
}
}
- marker = default(JFifMarker);
+ marker = default;
return false;
}
@@ -104,12 +104,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
- {
- return false;
- }
-
- return obj is JFifMarker && this.Equals((JFifMarker)obj);
+ return obj is JFifMarker other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
index 0125d2703b..a4fbb17be3 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
@@ -427,10 +427,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
{
if (this.isExif)
{
- ExifValue horizontal = this.MetaData.ExifProfile.GetValue(ExifTag.XResolution);
- ExifValue vertical = this.MetaData.ExifProfile.GetValue(ExifTag.YResolution);
- double horizontalValue = horizontal != null ? ((Rational)horizontal.Value).ToDouble() : 0;
- double verticalValue = vertical != null ? ((Rational)vertical.Value).ToDouble() : 0;
+ double horizontalValue = this.MetaData.ExifProfile.TryGetValue(ExifTag.XResolution, out ExifValue horizonalTag)
+ ? ((Rational)horizonalTag.Value).ToDouble()
+ : 0;
+
+ double verticalValue = this.MetaData.ExifProfile.TryGetValue(ExifTag.YResolution, out ExifValue verticalTag)
+ ? ((Rational)verticalTag.Value).ToDouble()
+ : 0;
if (horizontalValue > 0 && verticalValue > 0)
{
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFileMarker.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFileMarker.cs
index d6ff1e9eda..8e51c0b7cc 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFileMarker.cs
+++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFileMarker.cs
@@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
///
/// Represents a jpeg file marker
///
- internal struct PdfJsFileMarker
+ internal readonly struct PdfJsFileMarker
{
///
/// Initializes a new instance of the struct.
@@ -34,9 +34,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
///
- /// Gets or sets a value indicating whether the current marker is invalid
+ /// Gets a value indicating whether the current marker is invalid
///
- public bool Invalid { get; set; }
+ public bool Invalid { get; }
///
/// Gets the position of the marker within a stream
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs
index a600658b02..30b8158e73 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs
@@ -380,10 +380,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
{
if (this.isExif)
{
- ExifValue horizontal = image.MetaData.ExifProfile.GetValue(ExifTag.XResolution);
- ExifValue vertical = image.MetaData.ExifProfile.GetValue(ExifTag.YResolution);
- double horizontalValue = horizontal != null ? ((Rational)horizontal.Value).ToDouble() : 0;
- double verticalValue = vertical != null ? ((Rational)vertical.Value).ToDouble() : 0;
+ double horizontalValue = image.MetaData.ExifProfile.TryGetValue(ExifTag.XResolution, out ExifValue horizontalTag)
+ ? ((Rational)horizontalTag.Value).ToDouble()
+ : 0;
+
+ double verticalValue = image.MetaData.ExifProfile.TryGetValue(ExifTag.YResolution, out ExifValue verticalTag)
+ ? ((Rational)verticalTag.Value).ToDouble()
+ : 0;
if (horizontalValue > 0 && verticalValue > 0)
{
diff --git a/src/ImageSharp/Formats/Png/PngChunk.cs b/src/ImageSharp/Formats/Png/PngChunk.cs
index 2483a3ad9d..b944b43a34 100644
--- a/src/ImageSharp/Formats/Png/PngChunk.cs
+++ b/src/ImageSharp/Formats/Png/PngChunk.cs
@@ -10,13 +10,18 @@ namespace SixLabors.ImageSharp.Formats.Png
///
internal sealed class PngChunk
{
+ public PngChunk(int length)
+ {
+ this.Length = length;
+ }
+
///
- /// Gets or sets the length.
+ /// Gets the length.
/// An unsigned integer giving the number of bytes in the chunk's
/// data field. The length counts only the data field, not itself,
/// the chunk type code, or the CRC. Zero is a valid length
///
- public int Length { get; set; }
+ public int Length { get; }
///
/// Gets or sets the chunk type as string with 4 chars.
diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index dba4eaa15c..234ed6bbd0 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -3,6 +3,7 @@
using System;
using System.Buffers;
+using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -216,19 +217,18 @@ namespace SixLabors.ImageSharp.Formats.Png
{
using (var deframeStream = new ZlibInflateStream(this.currentStream))
{
- PngChunk currentChunk;
- while (!this.isEndChunkReached && (currentChunk = this.ReadChunk()) != null)
+ while (!this.isEndChunkReached && this.TryReadChunk(out PngChunk chunk))
{
try
{
- switch (currentChunk.Type)
+ switch (chunk.Type)
{
case PngChunkTypes.Header:
- this.ReadHeaderChunk(currentChunk.Data.Array);
+ this.ReadHeaderChunk(chunk.Data.Array);
this.ValidateHeader();
break;
case PngChunkTypes.Physical:
- this.ReadPhysicalChunk(metadata, currentChunk.Data.Array);
+ this.ReadPhysicalChunk(metadata, chunk.Data.Array);
break;
case PngChunkTypes.Data:
if (image == null)
@@ -236,23 +236,23 @@ namespace SixLabors.ImageSharp.Formats.Png
this.InitializeImage(metadata, out image);
}
- deframeStream.AllocateNewBytes(currentChunk.Length);
+ deframeStream.AllocateNewBytes(chunk.Length);
this.ReadScanlines(deframeStream.CompressedStream, image.Frames.RootFrame);
this.currentStream.Read(this.crcBuffer, 0, 4);
break;
case PngChunkTypes.Palette:
- byte[] pal = new byte[currentChunk.Length];
- Buffer.BlockCopy(currentChunk.Data.Array, 0, pal, 0, currentChunk.Length);
+ byte[] pal = new byte[chunk.Length];
+ Buffer.BlockCopy(chunk.Data.Array, 0, pal, 0, chunk.Length);
this.palette = pal;
break;
case PngChunkTypes.PaletteAlpha:
- byte[] alpha = new byte[currentChunk.Length];
- Buffer.BlockCopy(currentChunk.Data.Array, 0, alpha, 0, currentChunk.Length);
+ byte[] alpha = new byte[chunk.Length];
+ Buffer.BlockCopy(chunk.Data.Array, 0, alpha, 0, chunk.Length);
this.paletteAlpha = alpha;
this.AssignTransparentMarkers(alpha);
break;
case PngChunkTypes.Text:
- this.ReadTextChunk(metadata, currentChunk.Data.Array, currentChunk.Length);
+ this.ReadTextChunk(metadata, chunk.Data.Array, chunk.Length);
break;
case PngChunkTypes.End:
this.isEndChunkReached = true;
@@ -262,10 +262,10 @@ namespace SixLabors.ImageSharp.Formats.Png
finally
{
// Data is rented in ReadChunkData()
- if (currentChunk.Data != null)
+ if (chunk.Data != null)
{
- currentChunk.Data.Dispose();
- currentChunk.Data = null;
+ chunk.Data.Dispose();
+ chunk.Data = null;
}
}
}
@@ -296,25 +296,24 @@ namespace SixLabors.ImageSharp.Formats.Png
this.currentStream.Skip(8);
try
{
- PngChunk currentChunk;
- while (!this.isEndChunkReached && (currentChunk = this.ReadChunk()) != null)
+ while (!this.isEndChunkReached && this.TryReadChunk(out PngChunk chunk))
{
try
{
- switch (currentChunk.Type)
+ switch (chunk.Type)
{
case PngChunkTypes.Header:
- this.ReadHeaderChunk(currentChunk.Data.Array);
+ this.ReadHeaderChunk(chunk.Data.Array);
this.ValidateHeader();
break;
case PngChunkTypes.Physical:
- this.ReadPhysicalChunk(metadata, currentChunk.Data.Array);
+ this.ReadPhysicalChunk(metadata, chunk.Data.Array);
break;
case PngChunkTypes.Data:
- this.SkipChunkDataAndCrc(currentChunk);
+ this.SkipChunkDataAndCrc(chunk);
break;
case PngChunkTypes.Text:
- this.ReadTextChunk(metadata, currentChunk.Data.Array, currentChunk.Length);
+ this.ReadTextChunk(metadata, chunk.Data.Array, chunk.Length);
break;
case PngChunkTypes.End:
this.isEndChunkReached = true;
@@ -324,9 +323,9 @@ namespace SixLabors.ImageSharp.Formats.Png
finally
{
// Data is rented in ReadChunkData()
- if (currentChunk.Data != null)
+ if (chunk.Data != null)
{
- ArrayPool.Shared.Return(currentChunk.Data.Array);
+ ArrayPool.Shared.Return(chunk.Data.Array);
}
}
}
@@ -337,7 +336,7 @@ namespace SixLabors.ImageSharp.Formats.Png
this.previousScanline?.Dispose();
}
- if (this.header == null)
+ if (this.header.Width == 0 && this.header.Height == 0)
{
throw new ImageFormatException("PNG Image does not contain a header chunk");
}
@@ -348,13 +347,12 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// Converts a byte array to a new array where each value in the original array is represented by the specified number of bits.
///
- /// The bytes to convert from. Cannot be null.
+ /// The bytes to convert from. Cannot be empty.
/// The number of bytes per scanline
/// The number of bits per value.
- /// The resulting array. Is never null.
- /// is null.
+ /// The resulting array.
/// is less than or equals than zero.
- private static Span ToArrayByBitsLength(Span source, int bytesPerScanline, int bits)
+ private static ReadOnlySpan ToArrayByBitsLength(ReadOnlySpan source, int bytesPerScanline, int bits)
{
Guard.MustBeGreaterThan(source.Length, 0, nameof(source));
Guard.MustBeGreaterThan(bits, 0, nameof(bits));
@@ -414,14 +412,11 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// The metadata to read to.
/// The data containing physical data.
- private void ReadPhysicalChunk(ImageMetaData metadata, byte[] data)
+ private void ReadPhysicalChunk(ImageMetaData metadata, ReadOnlySpan data)
{
- data.ReverseBytes(0, 4);
- data.ReverseBytes(4, 4);
-
// 39.3700787 = inches in a meter.
- metadata.HorizontalResolution = BitConverter.ToInt32(data, 0) / 39.3700787d;
- metadata.VerticalResolution = BitConverter.ToInt32(data, 4) / 39.3700787d;
+ metadata.HorizontalResolution = BinaryPrimitives.ReadInt32BigEndian(data.Slice(0, 4)) / 39.3700787d;
+ metadata.VerticalResolution = BinaryPrimitives.ReadInt32BigEndian(data.Slice(4, 4)) / 39.3700787d;
}
///
@@ -671,7 +666,7 @@ namespace SixLabors.ImageSharp.Formats.Png
}
Span rowSpan = image.GetPixelRowSpan(this.currentRow);
- this.ProcessInterlacedDefilteredScanline(this.scanline.Array, rowSpan, Adam7FirstColumn[this.pass], Adam7ColumnIncrement[this.pass]);
+ this.ProcessInterlacedDefilteredScanline(this.scanline.Span, rowSpan, Adam7FirstColumn[this.pass], Adam7ColumnIncrement[this.pass]);
this.SwapBuffers();
@@ -699,20 +694,20 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The pixel format.
/// The de-filtered scanline
/// The image
- private void ProcessDefilteredScanline(byte[] defilteredScanline, ImageFrame pixels)
+ private void ProcessDefilteredScanline(ReadOnlySpan defilteredScanline, ImageFrame pixels)
where TPixel : struct, IPixel
{
var color = default(TPixel);
Span rowSpan = pixels.GetPixelRowSpan(this.currentRow);
// Trim the first marker byte from the buffer
- var scanlineBuffer = new Span(defilteredScanline, 1, defilteredScanline.Length - 1);
+ ReadOnlySpan scanlineBuffer = defilteredScanline.Slice(1, defilteredScanline.Length - 1);
switch (this.pngColorType)
{
case PngColorType.Grayscale:
int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1);
- Span newScanline1 = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth);
+ ReadOnlySpan newScanline1 = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth);
for (int x = 0; x < this.header.Width; x++)
{
@@ -796,10 +791,10 @@ namespace SixLabors.ImageSharp.Formats.Png
}
else
{
- Span rgb24Span = scanlineBuffer.NonPortableCast();
+ ReadOnlySpan rgb24Span = scanlineBuffer.NonPortableCast();
for (int x = 0; x < this.header.Width; x++)
{
- ref Rgb24 rgb24 = ref rgb24Span[x];
+ ref readonly Rgb24 rgb24 = ref rgb24Span[x];
var rgba32 = default(Rgba32);
rgba32.Rgb = rgb24;
rgba32.A = (byte)(rgb24.Equals(this.rgb24Trans) ? 0 : 255);
@@ -840,7 +835,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The target buffer
/// The target length
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void From16BitTo8Bit(Span source, Span target, int length)
+ private void From16BitTo8Bit(ReadOnlySpan source, Span target, int length)
{
for (int i = 0, j = 0; i < length; i++, j += 2)
{
@@ -881,10 +876,10 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The type of pixel we are expanding to
/// The scanline
/// Thecurrent output image row
- private void ProcessScanlineFromPalette(Span defilteredScanline, Span row)
+ private void ProcessScanlineFromPalette(ReadOnlySpan defilteredScanline, Span row)
where TPixel : struct, IPixel
{
- Span newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth);
+ ReadOnlySpan newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth);
byte[] pal = this.palette;
var color = default(TPixel);
@@ -931,19 +926,19 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The current image row.
/// The column start index. Always 0 for none interlaced images.
/// The column increment. Always 1 for none interlaced images.
- private void ProcessInterlacedDefilteredScanline(byte[] defilteredScanline, Span rowSpan, int pixelOffset = 0, int increment = 1)
+ private void ProcessInterlacedDefilteredScanline(ReadOnlySpan defilteredScanline, Span rowSpan, int pixelOffset = 0, int increment = 1)
where TPixel : struct, IPixel
{
var color = default(TPixel);
// Trim the first marker byte from the buffer
- var scanlineBuffer = new Span(defilteredScanline, 1, defilteredScanline.Length - 1);
+ ReadOnlySpan scanlineBuffer = defilteredScanline.Slice(1, defilteredScanline.Length - 1);
switch (this.pngColorType)
{
case PngColorType.Grayscale:
int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1);
- Span newScanline1 = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth);
+ ReadOnlySpan newScanline1 = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth);
for (int x = pixelOffset, o = 0; x < this.header.Width; x += increment, o++)
{
@@ -976,7 +971,7 @@ namespace SixLabors.ImageSharp.Formats.Png
case PngColorType.Palette:
- Span newScanline = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth);
+ ReadOnlySpan newScanline = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth);
var rgba = default(Rgba32);
if (this.paletteAlpha != null && this.paletteAlpha.Length > 0)
@@ -1159,22 +1154,17 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// Reads a header chunk from the data.
///
- /// The containing data.
- private void ReadHeaderChunk(byte[] data)
+ /// The containing data.
+ private void ReadHeaderChunk(ReadOnlySpan data)
{
- this.header = new PngHeader();
-
- data.ReverseBytes(0, 4);
- data.ReverseBytes(4, 4);
-
- this.header.Width = BitConverter.ToInt32(data, 0);
- this.header.Height = BitConverter.ToInt32(data, 4);
-
- this.header.BitDepth = data[8];
- this.header.ColorType = (PngColorType)data[9];
- this.header.CompressionMethod = data[10];
- this.header.FilterMethod = data[11];
- this.header.InterlaceMethod = (PngInterlaceMode)data[12];
+ this.header = new PngHeader(
+ width: BinaryPrimitives.ReadInt32BigEndian(data.Slice(0, 4)),
+ height: BinaryPrimitives.ReadInt32BigEndian(data.Slice(4, 4)),
+ bitDepth: data[8],
+ colorType: (PngColorType)data[9],
+ compressionMethod: data[10],
+ filterMethod: data[11],
+ interlaceMethod: (PngInterlaceMode)data[12]);
}
///
@@ -1214,36 +1204,40 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// The .
///
- private PngChunk ReadChunk()
+ private bool TryReadChunk(out PngChunk chunk)
{
- var chunk = new PngChunk();
- this.ReadChunkLength(chunk);
+ int length = this.ReadChunkLength();
- if (chunk.Length == -1)
+ if (length == -1)
{
+ chunk = default;
+
// IEND
- return null;
+ return false;
}
+ chunk = new PngChunk(length);
+
if (chunk.Length < 0 || chunk.Length > this.currentStream.Length - this.currentStream.Position)
{
// Not a valid chunk so we skip back all but one of the four bytes we have just read.
// That lets us read one byte at a time until we reach a known chunk.
this.currentStream.Position -= 3;
- return chunk;
+
+ return true;
}
this.ReadChunkType(chunk);
if (chunk.Type == PngChunkTypes.Data)
{
- return chunk;
+ return true;
}
this.ReadChunkData(chunk);
this.ReadChunkCrc(chunk);
- return chunk;
+ return true;
}
///
@@ -1256,18 +1250,17 @@ namespace SixLabors.ImageSharp.Formats.Png
private void ReadChunkCrc(PngChunk chunk)
{
int numBytes = this.currentStream.Read(this.crcBuffer, 0, 4);
+
if (numBytes >= 1 && numBytes <= 3)
{
throw new ImageFormatException("Image stream is not valid!");
}
- this.crcBuffer.ReverseBytes();
-
- chunk.Crc = BitConverter.ToUInt32(this.crcBuffer, 0);
+ chunk.Crc = BinaryPrimitives.ReadUInt32BigEndian(this.crcBuffer);
this.crc.Reset();
this.crc.Update(this.chunkTypeBuffer);
- this.crc.Update(chunk.Data.Array, 0, chunk.Length);
+ this.crc.Update(new ReadOnlySpan(chunk.Data.Array, 0, chunk.Length));
if (this.crc.Value != chunk.Crc && IsCriticalChunk(chunk))
{
@@ -1321,22 +1314,19 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// Calculates the length of the given chunk.
///
- /// The chunk.
///
/// Thrown if the input stream is not valid.
///
- private void ReadChunkLength(PngChunk chunk)
+ private int ReadChunkLength()
{
int numBytes = this.currentStream.Read(this.chunkLengthBuffer, 0, 4);
+
if (numBytes < 4)
{
- chunk.Length = -1;
- return;
+ return -1;
}
- this.chunkLengthBuffer.ReverseBytes();
-
- chunk.Length = BitConverter.ToInt32(this.chunkLengthBuffer, 0);
+ return BinaryPrimitives.ReadInt32BigEndian(this.chunkLengthBuffer);
}
///
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index 2735164996..17aae17620 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -2,8 +2,10 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers.Binary;
using System.IO;
using System.Linq;
+using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats.Png.Filters;
using SixLabors.ImageSharp.Formats.Png.Zlib;
@@ -35,6 +37,11 @@ namespace SixLabors.ImageSharp.Formats.Png
///
private readonly byte[] chunkDataBuffer = new byte[16];
+ ///
+ /// Reusable buffer for writing int data.
+ ///
+ private readonly byte[] intBuffer = new byte[4];
+
///
/// Reusable crc for validating chunks.
///
@@ -205,16 +212,14 @@ namespace SixLabors.ImageSharp.Formats.Png
this.bytesPerPixel = this.CalculateBytesPerPixel();
- var header = new PngHeader
- {
- Width = image.Width,
- Height = image.Height,
- ColorType = this.pngColorType,
- BitDepth = this.bitDepth,
- FilterMethod = 0, // None
- CompressionMethod = 0,
- InterlaceMethod = 0
- };
+ var header = new PngHeader(
+ width: image.Width,
+ height: image.Height,
+ colorType: this.pngColorType,
+ bitDepth: this.bitDepth,
+ filterMethod: 0, // None
+ compressionMethod: 0,
+ interlaceMethod: 0);
this.WriteHeaderChunk(stream, header);
@@ -243,52 +248,12 @@ namespace SixLabors.ImageSharp.Formats.Png
this.paeth?.Dispose();
}
- ///
- /// Writes an integer to the byte array.
- ///
- /// The containing image data.
- /// The amount to offset by.
- /// The value to write.
- private static void WriteInteger(byte[] data, int offset, int value)
- {
- byte[] buffer = BitConverter.GetBytes(value);
-
- buffer.ReverseBytes();
- Buffer.BlockCopy(buffer, 0, data, offset, 4);
- }
-
- ///
- /// Writes an integer to the stream.
- ///
- /// The containing image data.
- /// The value to write.
- private static void WriteInteger(Stream stream, int value)
- {
- byte[] buffer = BitConverter.GetBytes(value);
-
- buffer.ReverseBytes();
- stream.Write(buffer, 0, 4);
- }
-
- ///
- /// Writes an unsigned integer to the stream.
- ///
- /// The containing image data.
- /// The value to write.
- private static void WriteInteger(Stream stream, uint value)
- {
- byte[] buffer = BitConverter.GetBytes(value);
-
- buffer.ReverseBytes();
- stream.Write(buffer, 0, 4);
- }
-
///
/// Collects a row of grayscale pixels.
///
/// The pixel format.
/// The image row span.
- private void CollectGrayscaleBytes(Span rowSpan)
+ private void CollectGrayscaleBytes(ReadOnlySpan rowSpan)
where TPixel : struct, IPixel
{
byte[] rawScanlineArray = this.rawScanline.Array;
@@ -323,7 +288,7 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// The pixel format.
/// The row span.
- private void CollecTPixelBytes(Span rowSpan)
+ private void CollecTPixelBytes(ReadOnlySpan rowSpan)
where TPixel : struct, IPixel
{
if (this.bytesPerPixel == 4)
@@ -344,7 +309,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The row span.
/// The row.
/// The
- private IManagedByteBuffer EncodePixelRow(Span rowSpan, int row)
+ private IManagedByteBuffer EncodePixelRow(ReadOnlySpan rowSpan, int row)
where TPixel : struct, IPixel
{
switch (this.pngColorType)
@@ -448,10 +413,10 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// The containing image data.
/// The .
- private void WriteHeaderChunk(Stream stream, PngHeader header)
+ private void WriteHeaderChunk(Stream stream, in PngHeader header)
{
- WriteInteger(this.chunkDataBuffer, 0, header.Width);
- WriteInteger(this.chunkDataBuffer, 4, header.Height);
+ BinaryPrimitives.WriteInt32BigEndian(new Span(this.chunkDataBuffer, 0, 4), header.Width);
+ BinaryPrimitives.WriteInt32BigEndian(new Span(this.chunkDataBuffer, 4, 4), header.Height);
this.chunkDataBuffer[8] = header.BitDepth;
this.chunkDataBuffer[9] = (byte)header.ColorType;
@@ -469,7 +434,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The containing image data.
/// The .
/// The quantized frame.
- private void WritePaletteChunk(Stream stream, PngHeader header, QuantizedFrame quantized)
+ private void WritePaletteChunk(Stream stream, in PngHeader header, QuantizedFrame quantized)
where TPixel : struct, IPixel
{
// Grab the palette and write it to the stream.
@@ -535,8 +500,8 @@ namespace SixLabors.ImageSharp.Formats.Png
int dpmX = (int)Math.Round(image.MetaData.HorizontalResolution * 39.3700787D);
int dpmY = (int)Math.Round(image.MetaData.VerticalResolution * 39.3700787D);
- WriteInteger(this.chunkDataBuffer, 0, dpmX);
- WriteInteger(this.chunkDataBuffer, 4, dpmY);
+ BinaryPrimitives.WriteInt32BigEndian(new Span(this.chunkDataBuffer, 0, 4), dpmX);
+ BinaryPrimitives.WriteInt32BigEndian(new Span(this.chunkDataBuffer, 4, 4), dpmY);
this.chunkDataBuffer[8] = 1;
@@ -552,14 +517,10 @@ namespace SixLabors.ImageSharp.Formats.Png
{
if (this.writeGamma)
{
- int gammaValue = (int)(this.gamma * 100000F);
+ // 4-byte unsigned integer of gamma * 100,000.
+ uint gammaValue = (uint)(this.gamma * 100_000F);
- byte[] size = BitConverter.GetBytes(gammaValue);
-
- this.chunkDataBuffer[0] = size[3];
- this.chunkDataBuffer[1] = size[2];
- this.chunkDataBuffer[2] = size[1];
- this.chunkDataBuffer[3] = size[0];
+ BinaryPrimitives.WriteUInt32BigEndian(new Span(this.chunkDataBuffer, 0, 4), gammaValue);
this.WriteChunk(stream, PngChunkTypes.Gamma, this.chunkDataBuffer, 0, 4);
}
@@ -591,15 +552,14 @@ namespace SixLabors.ImageSharp.Formats.Png
byte[] buffer;
int bufferLength;
- MemoryStream memoryStream = null;
- try
+
+ using (var memoryStream = new MemoryStream())
{
- memoryStream = new MemoryStream();
using (var deflateStream = new ZlibDeflateStream(memoryStream, this.compressionLevel))
{
for (int y = 0; y < this.height; y++)
{
- IManagedByteBuffer r = this.EncodePixelRow(pixels.GetPixelRowSpan(y), y);
+ IManagedByteBuffer r = this.EncodePixelRow(pixels.GetPixelRowSpan(y).AsReadOnlySpan(), y);
deflateStream.Write(r.Array, 0, resultLength);
IManagedByteBuffer temp = this.rawScanline;
@@ -611,10 +571,6 @@ namespace SixLabors.ImageSharp.Formats.Png
buffer = memoryStream.ToArray();
bufferLength = buffer.Length;
}
- finally
- {
- memoryStream?.Dispose();
- }
// Store the chunks in repeated 64k blocks.
// This reduces the memory load for decoding the image for many decoders.
@@ -668,7 +624,9 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The of the data to write.
private void WriteChunk(Stream stream, string type, byte[] data, int offset, int length)
{
- WriteInteger(stream, length);
+ BinaryPrimitives.WriteInt32BigEndian(this.intBuffer, length);
+
+ stream.Write(this.intBuffer, 0, 4); // write the length
this.chunkTypeBuffer[0] = (byte)type[0];
this.chunkTypeBuffer[1] = (byte)type[1];
@@ -677,20 +635,20 @@ namespace SixLabors.ImageSharp.Formats.Png
stream.Write(this.chunkTypeBuffer, 0, 4);
- if (data != null)
- {
- stream.Write(data, offset, length);
- }
-
this.crc.Reset();
+
this.crc.Update(this.chunkTypeBuffer);
if (data != null && length > 0)
{
- this.crc.Update(data, offset, length);
+ stream.Write(data, offset, length);
+
+ this.crc.Update(new ReadOnlySpan(data, offset, length));
}
- WriteInteger(stream, (uint)this.crc.Value);
+ BinaryPrimitives.WriteUInt32BigEndian(this.intBuffer, (uint)this.crc.Value);
+
+ stream.Write(this.intBuffer, 0, 4); // write the crc
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/PngHeader.cs b/src/ImageSharp/Formats/Png/PngHeader.cs
index a70032ce3c..df85642bed 100644
--- a/src/ImageSharp/Formats/Png/PngHeader.cs
+++ b/src/ImageSharp/Formats/Png/PngHeader.cs
@@ -6,55 +6,73 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// Represents the png header chunk.
///
- internal sealed class PngHeader
+ internal readonly struct PngHeader
{
+ public PngHeader(
+ int width,
+ int height,
+ byte bitDepth,
+ PngColorType colorType,
+ byte compressionMethod,
+ byte filterMethod,
+ PngInterlaceMode interlaceMethod)
+ {
+ this.Width = width;
+ this.Height = height;
+ this.BitDepth = bitDepth;
+ this.ColorType = colorType;
+ this.CompressionMethod = compressionMethod;
+ this.FilterMethod = filterMethod;
+ this.InterlaceMethod = interlaceMethod;
+ }
+
///
- /// Gets or sets the dimension in x-direction of the image in pixels.
+ /// Gets the dimension in x-direction of the image in pixels.
///
- public int Width { get; set; }
+ public int Width { get; }
///
- /// Gets or sets the dimension in y-direction of the image in pixels.
+ /// Gets the dimension in y-direction of the image in pixels.
///
- public int Height { get; set; }
+ public int Height { get; }
///
- /// Gets or sets the bit depth.
+ /// Gets the bit depth.
/// Bit depth is a single-byte integer giving the number of bits per sample
/// or per palette index (not per pixel). Valid values are 1, 2, 4, 8, and 16,
/// although not all values are allowed for all color types.
///
- public byte BitDepth { get; set; }
+ public byte BitDepth { get; }
///
- /// Gets or sets the color type.
+ /// Gets the color type.
/// Color type is a integer that describes the interpretation of the
/// image data. Color type codes represent sums of the following values:
/// 1 (palette used), 2 (color used), and 4 (alpha channel used).
///
- public PngColorType ColorType { get; set; }
+ public PngColorType ColorType { get; }
///
- /// Gets or sets the compression method.
+ /// Gets the compression method.
/// Indicates the method used to compress the image data. At present,
/// only compression method 0 (deflate/inflate compression with a sliding
/// window of at most 32768 bytes) is defined.
///
- public byte CompressionMethod { get; set; }
+ public byte CompressionMethod { get; }
///
- /// Gets or sets the preprocessing method.
+ /// Gets the preprocessing method.
/// Indicates the preprocessing method applied to the image
/// data before compression. At present, only filter method 0
/// (adaptive filtering with five basic filter types) is defined.
///
- public byte FilterMethod { get; set; }
+ public byte FilterMethod { get; }
///
- /// Gets or sets the transmission order.
+ /// Gets the transmission order.
/// Indicates the transmission order of the image data.
/// Two values are currently defined: 0 (no interlace) or 1 (Adam7 interlace).
///
- public PngInterlaceMode InterlaceMethod { get; set; }
+ public PngInterlaceMode InterlaceMethod { get; }
}
}
diff --git a/src/ImageSharp/Formats/Png/Zlib/Adler32.cs b/src/ImageSharp/Formats/Png/Zlib/Adler32.cs
index 1cce90c0b7..9c4e9e4b99 100644
--- a/src/ImageSharp/Formats/Png/Zlib/Adler32.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/Adler32.cs
@@ -113,30 +113,15 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Update(byte[] buffer)
+ public void Update(ReadOnlySpan data)
{
- if (buffer == null)
- {
- throw new ArgumentNullException(nameof(buffer));
- }
-
- this.Update(buffer, 0, buffer.Length);
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Update(byte[] buffer, int offset, int count)
- {
- DebugGuard.NotNull(buffer, nameof(buffer));
- DebugGuard.MustBeGreaterThanOrEqualTo(offset, 0, nameof(offset));
- DebugGuard.MustBeGreaterThanOrEqualTo(count, 0, nameof(count));
- DebugGuard.MustBeLessThan(offset, buffer.Length, nameof(offset));
- DebugGuard.MustBeLessThanOrEqualTo(offset + count, buffer.Length, nameof(count));
-
// (By Per Bothner)
uint s1 = this.checksum & 0xFFFF;
uint s2 = this.checksum >> 16;
+ int count = data.Length;
+ int offset = 0;
+
while (count > 0)
{
// We can defer the modulo operation:
@@ -151,7 +136,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
count -= n;
while (--n >= 0)
{
- s1 = s1 + (uint)(buffer[offset++] & 0xff);
+ s1 = s1 + (uint)(data[offset++] & 0xff);
s2 = s2 + s1;
}
diff --git a/src/ImageSharp/Formats/Png/Zlib/Crc32.cs b/src/ImageSharp/Formats/Png/Zlib/Crc32.cs
index bd686f2b9f..d1588c384f 100644
--- a/src/ImageSharp/Formats/Png/Zlib/Crc32.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/Crc32.cs
@@ -137,30 +137,13 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Update(byte[] buffer)
+ public void Update(ReadOnlySpan data)
{
- if (buffer == null)
- {
- throw new ArgumentNullException(nameof(buffer));
- }
-
- this.Update(buffer, 0, buffer.Length);
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Update(byte[] buffer, int offset, int count)
- {
- DebugGuard.NotNull(buffer, nameof(buffer));
- DebugGuard.MustBeGreaterThanOrEqualTo(count, 0, nameof(count));
- DebugGuard.MustBeGreaterThanOrEqualTo(offset, 0, nameof(offset));
- DebugGuard.MustBeLessThanOrEqualTo(offset + count, buffer.Length, nameof(count));
-
this.crc ^= CrcSeed;
- while (--count >= 0)
+ for (int i = 0; i < data.Length; i++)
{
- this.crc = CrcTable[(this.crc ^ buffer[offset++]) & 0xFF] ^ (this.crc >> 8);
+ this.crc = CrcTable[(this.crc ^ data[i]) & 0xFF] ^ (this.crc >> 8);
}
this.crc ^= CrcSeed;
diff --git a/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs b/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs
index 9d84258cae..a2a57332b1 100644
--- a/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs
@@ -1,6 +1,8 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using System;
+
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{
///
@@ -34,25 +36,11 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
void Update(int value);
///
- /// Updates the data checksum with the bytes taken from the array.
+ /// Updates the data checksum with the bytes taken from the span.
///
- ///
+ ///
/// buffer an array of bytes
///
- void Update(byte[] buffer);
-
- ///
- /// Adds the byte array to the data checksum.
- ///
- ///
- /// The buffer which contains the data
- ///
- ///
- /// The offset in the buffer where the data starts
- ///
- ///
- /// the number of data bytes to add.
- ///
- void Update(byte[] buffer, int offset, int count);
+ void Update(ReadOnlySpan data);
}
}
diff --git a/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs b/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs
index dd20886ff7..51e6b4859e 100644
--- a/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs
@@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
public override void Write(byte[] buffer, int offset, int count)
{
this.deflateStream.Write(buffer, offset, count);
- this.adler32.Update(buffer, offset, count);
+ this.adler32.Update(new ReadOnlySpan(buffer, offset, count));
}
///
diff --git a/src/ImageSharp/IImageFrameCollection.cs b/src/ImageSharp/IImageFrameCollection.cs
index 81b512e221..c9232c7780 100644
--- a/src/ImageSharp/IImageFrameCollection.cs
+++ b/src/ImageSharp/IImageFrameCollection.cs
@@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.Collections;
using System.Collections.Generic;
using SixLabors.ImageSharp.PixelFormats;
diff --git a/src/ImageSharp/IO/BigEndianBitConverter.cs b/src/ImageSharp/IO/BigEndianBitConverter.cs
deleted file mode 100644
index 2fcfd966c3..0000000000
--- a/src/ImageSharp/IO/BigEndianBitConverter.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.IO
-{
- ///
- /// Implementation of EndianBitConverter which converts to/from big-endian byte arrays.
- ///
- internal sealed class BigEndianBitConverter : EndianBitConverter
- {
- ///
- public override Endianness Endianness
- {
- get { return Endianness.BigEndian; }
- }
-
- ///
- public override bool IsLittleEndian
- {
- get { return false; }
- }
-
- ///
- public override void CopyBytes(short value, byte[] buffer, int index)
- {
- CheckByteArgument(buffer, index, 2);
-
- buffer[index] = (byte)(value >> 8);
- buffer[index + 1] = (byte)value;
- }
-
- ///
- 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;
- }
-
- ///
- 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;
- }
-
- ///
- public override short ToInt16(byte[] value, int startIndex)
- {
- CheckByteArgument(value, startIndex, 2);
-
- return (short)((value[startIndex] << 8) | value[startIndex + 1]);
- }
-
- ///
- 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];
- }
-
- ///
- public override long ToInt64(byte[] value, int startIndex)
- {
- CheckByteArgument(value, startIndex, 8);
-
- 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 & 0xFFFFFFFF) | (p1 << 32);
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/IO/EndianBinaryReader.cs b/src/ImageSharp/IO/EndianBinaryReader.cs
index 0d660c68d5..6454ff2506 100644
--- a/src/ImageSharp/IO/EndianBinaryReader.cs
+++ b/src/ImageSharp/IO/EndianBinaryReader.cs
@@ -2,57 +2,32 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers.Binary;
using System.IO;
using System.Text;
namespace SixLabors.ImageSharp.IO
{
///
- /// Equivalent of , but with either endianness, depending on the it is constructed with.
+ /// Equivalent of , but with either endianness.
/// No data is buffered in the reader; the client may seek within the stream at will.
///
internal class EndianBinaryReader : IDisposable
{
- ///
- /// Decoder to use for string conversions.
- ///
- private readonly Decoder decoder;
-
///
/// Buffer used for temporary storage before conversion into primitives
///
private readonly byte[] storageBuffer = new byte[16];
- ///
- /// Buffer used for temporary storage when reading a single character
- ///
- private readonly char[] charBuffer = new char[1];
-
- ///
- /// Minimum number of bytes used to encode a character
- ///
- private readonly int minBytesPerChar;
-
///
/// Whether or not this reader has been disposed yet.
///
private bool disposed;
///
- /// Initializes a new instance of the class.
- /// Equivalent of , but with either endianness, depending on
- /// the EndianBitConverter it is constructed with.
+ /// The endianness used to read data
///
- ///
- /// Endianness to use when reading data
- ///
- ///
- /// Stream to read data from
- ///
- public EndianBinaryReader(Endianness endianness, Stream stream)
- : this(endianness, stream, Encoding.UTF8)
- {
- }
+ private readonly Endianness endianness;
///
/// Initializes a new instance of the class.
@@ -61,40 +36,20 @@ namespace SixLabors.ImageSharp.IO
///
/// Endianness to use when reading data
/// Stream to read data from
- /// Encoding to use when reading character data
- public EndianBinaryReader(Endianness endianness, Stream stream, Encoding encoding)
+ public EndianBinaryReader(Endianness endianness, Stream stream)
{
Guard.NotNull(stream, nameof(stream));
- Guard.NotNull(encoding, nameof(encoding));
Guard.IsTrue(stream.CanRead, nameof(stream), "Stream isn't readable");
this.BaseStream = stream;
- this.BitConverter = EndianBitConverter.GetConverter(endianness);
- this.Encoding = encoding;
- this.decoder = encoding.GetDecoder();
- this.minBytesPerChar = 1;
-
- if (encoding is UnicodeEncoding)
- {
- this.minBytesPerChar = 2;
- }
+ this.endianness = endianness;
}
- ///
- /// Gets the encoding used to read strings
- ///
- public Encoding Encoding { get; }
-
///
/// Gets the underlying stream of the EndianBinaryReader.
///
public Stream BaseStream { get; }
- ///
- /// Gets the bit converter used to read values from the stream.
- ///
- internal EndianBitConverter BitConverter { get; }
-
///
/// Closes the reader, including the underlying stream.
///
@@ -141,7 +96,8 @@ namespace SixLabors.ImageSharp.IO
public bool ReadBoolean()
{
this.ReadInternal(this.storageBuffer, 1);
- return this.BitConverter.ToBoolean(this.storageBuffer, 0);
+
+ return this.storageBuffer[0] != 0;
}
///
@@ -152,7 +108,10 @@ namespace SixLabors.ImageSharp.IO
public short ReadInt16()
{
this.ReadInternal(this.storageBuffer, 2);
- return this.BitConverter.ToInt16(this.storageBuffer, 0);
+
+ return (this.endianness == Endianness.BigEndian)
+ ? BinaryPrimitives.ReadInt16BigEndian(this.storageBuffer)
+ : BinaryPrimitives.ReadInt16LittleEndian(this.storageBuffer);
}
///
@@ -163,7 +122,10 @@ namespace SixLabors.ImageSharp.IO
public int ReadInt32()
{
this.ReadInternal(this.storageBuffer, 4);
- return this.BitConverter.ToInt32(this.storageBuffer, 0);
+
+ return (this.endianness == Endianness.BigEndian)
+ ? BinaryPrimitives.ReadInt32BigEndian(this.storageBuffer)
+ : BinaryPrimitives.ReadInt32LittleEndian(this.storageBuffer);
}
///
@@ -174,7 +136,10 @@ namespace SixLabors.ImageSharp.IO
public long ReadInt64()
{
this.ReadInternal(this.storageBuffer, 8);
- return this.BitConverter.ToInt64(this.storageBuffer, 0);
+
+ return (this.endianness == Endianness.BigEndian)
+ ? BinaryPrimitives.ReadInt64BigEndian(this.storageBuffer)
+ : BinaryPrimitives.ReadInt64LittleEndian(this.storageBuffer);
}
///
@@ -185,7 +150,10 @@ namespace SixLabors.ImageSharp.IO
public ushort ReadUInt16()
{
this.ReadInternal(this.storageBuffer, 2);
- return this.BitConverter.ToUInt16(this.storageBuffer, 0);
+
+ return (this.endianness == Endianness.BigEndian)
+ ? BinaryPrimitives.ReadUInt16BigEndian(this.storageBuffer)
+ : BinaryPrimitives.ReadUInt16LittleEndian(this.storageBuffer);
}
///
@@ -196,7 +164,10 @@ namespace SixLabors.ImageSharp.IO
public uint ReadUInt32()
{
this.ReadInternal(this.storageBuffer, 4);
- return this.BitConverter.ToUInt32(this.storageBuffer, 0);
+
+ return (this.endianness == Endianness.BigEndian)
+ ? BinaryPrimitives.ReadUInt32BigEndian(this.storageBuffer)
+ : BinaryPrimitives.ReadUInt32LittleEndian(this.storageBuffer);
}
///
@@ -207,7 +178,10 @@ namespace SixLabors.ImageSharp.IO
public ulong ReadUInt64()
{
this.ReadInternal(this.storageBuffer, 8);
- return this.BitConverter.ToUInt64(this.storageBuffer, 0);
+
+ return (this.endianness == Endianness.BigEndian)
+ ? BinaryPrimitives.ReadUInt64BigEndian(this.storageBuffer)
+ : BinaryPrimitives.ReadUInt64LittleEndian(this.storageBuffer);
}
///
@@ -215,10 +189,11 @@ namespace SixLabors.ImageSharp.IO
/// for this reader. 4 bytes are read.
///
/// The floating point value read
- public float ReadSingle()
+ public unsafe float ReadSingle()
{
- this.ReadInternal(this.storageBuffer, 4);
- return this.BitConverter.ToSingle(this.storageBuffer, 0);
+ int intValue = this.ReadInt32();
+
+ return *((float*)&intValue);
}
///
@@ -226,107 +201,11 @@ namespace SixLabors.ImageSharp.IO
/// for this reader. 8 bytes are read.
///
/// The floating point value read
- public double ReadDouble()
+ public unsafe double ReadDouble()
{
- this.ReadInternal(this.storageBuffer, 8);
- return this.BitConverter.ToDouble(this.storageBuffer, 0);
- }
+ long value = this.ReadInt64();
- ///
- /// Reads a decimal value from the stream, using the bit converter
- /// for this reader. 16 bytes are read.
- ///
- /// The decimal value read
- public decimal ReadDecimal()
- {
- this.ReadInternal(this.storageBuffer, 16);
- return this.BitConverter.ToDecimal(this.storageBuffer, 0);
- }
-
- ///
- /// Reads a single character from the stream, using the character encoding for
- /// this reader. If no characters have been fully read by the time the stream ends,
- /// -1 is returned.
- ///
- /// The character read, or -1 for end of stream.
- public int Read()
- {
- int charsRead = this.Read(this.charBuffer, 0, 1);
- if (charsRead == 0)
- {
- return -1;
- }
- else
- {
- return this.charBuffer[0];
- }
- }
-
- ///
- /// Reads the specified number of characters into the given buffer, starting at
- /// the given index.
- ///
- /// The buffer to copy data into
- /// The first index to copy data into
- /// The number of characters to read
- /// The number of characters actually read. This will only be less than
- /// the requested number of characters if the end of the stream is reached.
- ///
- public int Read(char[] data, int index, int count)
- {
- this.CheckDisposed();
-
- Guard.NotNull(this.storageBuffer, nameof(this.storageBuffer));
- Guard.MustBeGreaterThanOrEqualTo(index, 0, nameof(index));
- Guard.MustBeGreaterThanOrEqualTo(count, 0, nameof(count));
- Guard.IsFalse(count + index > data.Length, nameof(data.Length), "Not enough space in buffer for specified number of characters starting at specified index.");
-
- int read = 0;
- bool firstTime = true;
-
- // Use the normal buffer if we're only reading a small amount, otherwise
- // use at most 4K at a time.
- byte[] byteBuffer = this.storageBuffer;
-
- if (byteBuffer.Length < count * this.minBytesPerChar)
- {
- byteBuffer = new byte[4096];
- }
-
- while (read < count)
- {
- int amountToRead;
-
- // First time through we know we haven't previously read any data
- if (firstTime)
- {
- amountToRead = count * this.minBytesPerChar;
- firstTime = false;
- }
- else
- {
- // After that we can only assume we need to fully read 'chars left -1' characters
- // and a single byte of the character we may be in the middle of
- amountToRead = ((count - read - 1) * this.minBytesPerChar) + 1;
- }
-
- if (amountToRead > byteBuffer.Length)
- {
- amountToRead = byteBuffer.Length;
- }
-
- int bytesRead = this.TryReadInternal(byteBuffer, amountToRead);
- if (bytesRead == 0)
- {
- return read;
- }
-
- int decoded = this.decoder.GetChars(byteBuffer, 0, bytesRead, data, index);
- read += decoded;
- index += decoded;
- }
-
- return read;
+ return *((double*)&value);
}
///
@@ -411,84 +290,6 @@ namespace SixLabors.ImageSharp.IO
return ret;
}
- ///
- /// Reads a 7-bit encoded integer from the stream. This is stored with the least significant
- /// information first, with 7 bits of information per byte of value, and the top
- /// bit as a continuation flag. This method is not affected by the endianness
- /// of the bit converter.
- ///
- /// The 7-bit encoded integer read from the stream.
- public int Read7BitEncodedInt()
- {
- this.CheckDisposed();
-
- int ret = 0;
- for (int shift = 0; shift < 35; shift += 7)
- {
- int b = this.BaseStream.ReadByte();
- if (b == -1)
- {
- throw new EndOfStreamException();
- }
-
- ret = ret | ((b & 0x7f) << shift);
- if ((b & 0x80) == 0)
- {
- return ret;
- }
- }
-
- // Still haven't seen a byte with the high bit unset? Dodgy data.
- throw new IOException("Invalid 7-bit encoded integer in stream.");
- }
-
- ///
- /// Reads a 7-bit encoded integer from the stream. This is stored with the most significant
- /// information first, with 7 bits of information per byte of value, and the top
- /// bit as a continuation flag. This method is not affected by the endianness
- /// of the bit converter.
- ///
- /// The 7-bit encoded integer read from the stream.
- public int ReadBigEndian7BitEncodedInt()
- {
- this.CheckDisposed();
-
- int ret = 0;
- for (int i = 0; i < 5; i++)
- {
- int b = this.BaseStream.ReadByte();
- if (b == -1)
- {
- throw new EndOfStreamException();
- }
-
- ret = (ret << 7) | (b & 0x7f);
- if ((b & 0x80) == 0)
- {
- return ret;
- }
- }
-
- // Still haven't seen a byte with the high bit unset? Dodgy data.
- throw new IOException("Invalid 7-bit encoded integer in stream.");
- }
-
- ///
- /// Reads a length-prefixed string from the stream, using the encoding for this reader.
- /// A 7-bit encoded integer is first read, which specifies the number of bytes
- /// to read from the stream. These bytes are then converted into a string with
- /// the encoding for this reader.
- ///
- /// The string read from the stream.
- public string ReadString()
- {
- int bytesToRead = this.Read7BitEncodedInt();
-
- byte[] data = new byte[bytesToRead];
- this.ReadInternal(data, bytesToRead);
- return this.Encoding.GetString(data, 0, data.Length);
- }
-
///
/// Disposes of the underlying stream.
///
diff --git a/src/ImageSharp/IO/EndianBinaryWriter.cs b/src/ImageSharp/IO/EndianBinaryWriter.cs
index dd87faf455..9c42f0b694 100644
--- a/src/ImageSharp/IO/EndianBinaryWriter.cs
+++ b/src/ImageSharp/IO/EndianBinaryWriter.cs
@@ -2,14 +2,13 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers.Binary;
using System.IO;
-using System.Text;
namespace SixLabors.ImageSharp.IO
{
///
- /// Equivalent of , but with either endianness, depending on
- /// the it is constructed with.
+ /// Equivalent of , but with either endianness
///
internal class EndianBinaryWriter : IDisposable
{
@@ -19,61 +18,35 @@ namespace SixLabors.ImageSharp.IO
private readonly byte[] buffer = new byte[16];
///
- /// Buffer used for Write(char)
+ /// The endianness used to write the data
///
- private readonly char[] charBuffer = new char[1];
+ private readonly Endianness endianness;
///
/// Whether or not this writer has been disposed yet.
///
private bool disposed;
- ///
- /// Initializes a new instance of the class
- /// with the given bit converter, writing to the given stream, using UTF-8 encoding.
- ///
- /// Endianness to use when writing data
- /// Stream to write data to
- public EndianBinaryWriter(Endianness endianness, Stream stream)
- : this(endianness, stream, Encoding.UTF8)
- {
- }
-
///
/// Initializes a new instance of the class
/// with the given bit converter, writing to the given stream, using the given encoding.
///
/// Endianness to use when writing data
/// Stream to write data to
- ///
- /// Encoding to use when writing character data
- ///
- public EndianBinaryWriter(Endianness endianness, Stream stream, Encoding encoding)
+ public EndianBinaryWriter(Endianness endianness, Stream 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 = EndianBitConverter.GetConverter(endianness);
- this.Encoding = encoding;
+ this.endianness = endianness;
}
- ///
- /// Gets the encoding used to write strings
- ///
- public Encoding Encoding { get; }
-
///
/// Gets the underlying stream of the EndianBinaryWriter.
///
public Stream BaseStream { get; }
- ///
- /// Gets the bit converter used to write values to the stream
- ///
- internal EndianBitConverter BitConverter { get; }
-
///
/// Closes the writer, including the underlying stream.
///
@@ -108,7 +81,8 @@ namespace SixLabors.ImageSharp.IO
/// The value to write
public void Write(bool value)
{
- this.BitConverter.CopyBytes(value, this.buffer, 0);
+ this.buffer[0] = value ? (byte)1 : (byte)0;
+
this.WriteInternal(this.buffer, 1);
}
@@ -119,7 +93,15 @@ namespace SixLabors.ImageSharp.IO
/// The value to write
public void Write(short value)
{
- this.BitConverter.CopyBytes(value, this.buffer, 0);
+ if (this.endianness == Endianness.BigEndian)
+ {
+ BinaryPrimitives.WriteInt16BigEndian(this.buffer, value);
+ }
+ else
+ {
+ BinaryPrimitives.WriteInt16LittleEndian(this.buffer, value);
+ }
+
this.WriteInternal(this.buffer, 2);
}
@@ -130,7 +112,15 @@ namespace SixLabors.ImageSharp.IO
/// The value to write
public void Write(int value)
{
- this.BitConverter.CopyBytes(value, this.buffer, 0);
+ if (this.endianness == Endianness.BigEndian)
+ {
+ BinaryPrimitives.WriteInt32BigEndian(this.buffer, value);
+ }
+ else
+ {
+ BinaryPrimitives.WriteInt32LittleEndian(this.buffer, value);
+ }
+
this.WriteInternal(this.buffer, 4);
}
@@ -141,7 +131,15 @@ namespace SixLabors.ImageSharp.IO
/// The value to write
public void Write(long value)
{
- this.BitConverter.CopyBytes(value, this.buffer, 0);
+ if (this.endianness == Endianness.BigEndian)
+ {
+ BinaryPrimitives.WriteInt64BigEndian(this.buffer, value);
+ }
+ else
+ {
+ BinaryPrimitives.WriteInt64LittleEndian(this.buffer, value);
+ }
+
this.WriteInternal(this.buffer, 8);
}
@@ -152,7 +150,15 @@ namespace SixLabors.ImageSharp.IO
/// The value to write
public void Write(ushort value)
{
- this.BitConverter.CopyBytes(value, this.buffer, 0);
+ if (this.endianness == Endianness.BigEndian)
+ {
+ BinaryPrimitives.WriteUInt16BigEndian(this.buffer, value);
+ }
+ else
+ {
+ BinaryPrimitives.WriteUInt16LittleEndian(this.buffer, value);
+ }
+
this.WriteInternal(this.buffer, 2);
}
@@ -163,7 +169,15 @@ namespace SixLabors.ImageSharp.IO
/// The value to write
public void Write(uint value)
{
- this.BitConverter.CopyBytes(value, this.buffer, 0);
+ if (this.endianness == Endianness.BigEndian)
+ {
+ BinaryPrimitives.WriteUInt32BigEndian(this.buffer, value);
+ }
+ else
+ {
+ BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, value);
+ }
+
this.WriteInternal(this.buffer, 4);
}
@@ -174,7 +188,15 @@ namespace SixLabors.ImageSharp.IO
/// The value to write
public void Write(ulong value)
{
- this.BitConverter.CopyBytes(value, this.buffer, 0);
+ if (this.endianness == Endianness.BigEndian)
+ {
+ BinaryPrimitives.WriteUInt64BigEndian(this.buffer, value);
+ }
+ else
+ {
+ BinaryPrimitives.WriteUInt64LittleEndian(this.buffer, value);
+ }
+
this.WriteInternal(this.buffer, 8);
}
@@ -183,10 +205,9 @@ namespace SixLabors.ImageSharp.IO
/// for this writer. 4 bytes are written.
///
/// The value to write
- public void Write(float value)
+ public unsafe void Write(float value)
{
- this.BitConverter.CopyBytes(value, this.buffer, 0);
- this.WriteInternal(this.buffer, 4);
+ this.Write(*((int*)&value));
}
///
@@ -194,21 +215,9 @@ namespace SixLabors.ImageSharp.IO
/// for this writer. 8 bytes are written.
///
/// The value to write
- public void Write(double value)
- {
- this.BitConverter.CopyBytes(value, this.buffer, 0);
- this.WriteInternal(this.buffer, 8);
- }
-
- ///
- /// Writes a decimal value to the stream, using the bit converter for this writer.
- /// 16 bytes are written.
- ///
- /// The value to write
- public void Write(decimal value)
+ public unsafe void Write(double value)
{
- this.BitConverter.CopyBytes(value, this.buffer, 0);
- this.WriteInternal(this.buffer, 16);
+ this.Write(*((long*)&value));
}
///
@@ -255,71 +264,6 @@ namespace SixLabors.ImageSharp.IO
this.BaseStream.Write(value, offset, count);
}
- ///
- /// Writes a single character to the stream, using the encoding for this writer.
- ///
- /// The value to write
- public void Write(char value)
- {
- this.charBuffer[0] = value;
- this.Write(this.charBuffer);
- }
-
- ///
- /// Writes an array of characters to the stream, using the encoding for this writer.
- ///
- /// An array containing the characters to write
- /// value is null
- public void Write(char[] value)
- {
- Guard.NotNull(value, nameof(value));
-
- this.CheckDisposed();
- byte[] data = this.Encoding.GetBytes(value, 0, value.Length);
- this.WriteInternal(data, data.Length);
- }
-
- ///
- /// Writes a length-prefixed string to the stream, using the encoding for this writer.
- ///
- /// The value to write. Must not be null.
- /// value is null
- public void Write(string value)
- {
- Guard.NotNull(value, nameof(value));
-
- this.CheckDisposed();
- byte[] data = this.Encoding.GetBytes(value);
- this.Write7BitEncodedInt(data.Length);
- this.WriteInternal(data, data.Length);
- }
-
- ///
- /// Writes a 7-bit encoded integer from the stream. This is stored with the least significant
- /// information first, with 7 bits of information per byte of value, and the top
- /// bit as a continuation flag.
- ///
- /// The 7-bit encoded integer to write to the stream
- public void Write7BitEncodedInt(int value)
- {
- this.CheckDisposed();
- if (value < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(value), "Value must be greater than or equal to 0.");
- }
-
- int index = 0;
- while (value >= 128)
- {
- this.buffer[index++] = (byte)((value & 0x7f) | 0x80);
- value = value >> 7;
- index++;
- }
-
- this.buffer[index++] = (byte)value;
- this.BaseStream.Write(this.buffer, 0, index);
- }
-
///
/// Disposes of the underlying stream.
///
diff --git a/src/ImageSharp/IO/EndianBitConverter.Conversion.cs b/src/ImageSharp/IO/EndianBitConverter.Conversion.cs
deleted file mode 100644
index 844c81cc9e..0000000000
--- a/src/ImageSharp/IO/EndianBitConverter.Conversion.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-
-namespace SixLabors.ImageSharp.IO
-{
- ///
- /// Equivalent of , but with either endianness.
- ///
- internal abstract partial class EndianBitConverter
- {
- ///
- /// 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.
- ///
- /// The number to convert.
- /// A 64-bit signed integer whose value is equivalent to value.
- public unsafe long DoubleToInt64Bits(double value)
- {
- return *((long*)&value);
- }
-
- ///
- /// 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.
- ///
- /// The number to convert.
- /// A double-precision floating point number whose value is equivalent to value.
- public unsafe double Int64BitsToDouble(long value)
- {
- return *((double*)&value);
- }
-
- ///
- /// 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.
- ///
- /// The number to convert.
- /// A 32-bit signed integer whose value is equivalent to value.
- public unsafe int SingleToInt32Bits(float value)
- {
- return *((int*)&value);
- }
-
- ///
- /// 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.
- ///
- /// The number to convert.
- /// A single-precision floating point number whose value is equivalent to value.
- public unsafe float Int32BitsToSingle(int value)
- {
- return *((float*)&value);
- }
- }
-}
diff --git a/src/ImageSharp/IO/EndianBitConverter.CopyBytes.cs b/src/ImageSharp/IO/EndianBitConverter.CopyBytes.cs
deleted file mode 100644
index ea1d7aa5ac..0000000000
--- a/src/ImageSharp/IO/EndianBitConverter.CopyBytes.cs
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-
-namespace SixLabors.ImageSharp.IO
-{
- ///
- /// Equivalent of , but with either endianness.
- ///
- internal abstract partial class EndianBitConverter
- {
- ///
- /// Copies the specified 16-bit signed integer value into the specified byte array,
- /// beginning at the specified index.
- ///
- /// The number to convert.
- /// The byte array to copy the bytes into
- /// The first index into the array to copy the bytes into
- public abstract void CopyBytes(short value, byte[] buffer, int index);
-
- ///
- /// Copies the specified 32-bit signed integer value into the specified byte array,
- /// beginning at the specified index.
- ///
- /// The number to convert.
- /// The byte array to copy the bytes into
- /// The first index into the array to copy the bytes into
- public abstract void CopyBytes(int value, byte[] buffer, int index);
-
- ///
- /// Copies the specified 64-bit signed integer value into the specified byte array,
- /// beginning at the specified index.
- ///
- /// The number to convert.
- /// The byte array to copy the bytes into
- /// The first index into the array to copy the bytes into
- public abstract void CopyBytes(long value, byte[] buffer, int index);
-
- ///
- /// Copies the specified 16-bit unsigned integer value into the specified byte array,
- /// beginning at the specified index.
- ///
- /// The number to convert.
- /// The byte array to copy the bytes into
- /// The first index into the array to copy the bytes into
- public void CopyBytes(ushort value, byte[] buffer, int index)
- {
- this.CopyBytes(unchecked((short)value), buffer, index);
- }
-
- ///
- /// Copies the specified 32-bit unsigned integer value into the specified byte array,
- /// beginning at the specified index.
- ///
- /// The number to convert.
- /// The byte array to copy the bytes into
- /// The first index into the array to copy the bytes into
- public void CopyBytes(uint value, byte[] buffer, int index)
- {
- this.CopyBytes(unchecked((int)value), buffer, index);
- }
-
- ///
- /// Copies the specified 64-bit unsigned integer value into the specified byte array,
- /// beginning at the specified index.
- ///
- /// The number to convert.
- /// The byte array to copy the bytes into
- /// The first index into the array to copy the bytes into
- public void CopyBytes(ulong value, byte[] buffer, int index)
- {
- this.CopyBytes(unchecked((long)value), buffer, index);
- }
-
- ///
- /// Copies the specified Boolean value into the specified byte array,
- /// beginning at the specified index.
- ///
- /// A Boolean value.
- /// The byte array to copy the bytes into
- /// The first index into the array to copy the bytes into
- public void CopyBytes(bool value, byte[] buffer, int index)
- {
- CheckByteArgument(buffer, index, 1);
- buffer[index] = value ? (byte)1 : (byte)0;
- }
-
- ///
- /// Copies the specified Unicode character value into the specified byte array,
- /// beginning at the specified index.
- ///
- /// A character to convert.
- /// The byte array to copy the bytes into
- /// The first index into the array to copy the bytes into
- public void CopyBytes(char value, byte[] buffer, int index)
- {
- this.CopyBytes(unchecked((short)value), buffer, index);
- }
-
- ///
- /// Copies the specified double-precision floating point value into the specified byte array,
- /// beginning at the specified index.
- ///
- /// The number to convert.
- /// The byte array to copy the bytes into
- /// The first index into the array to copy the bytes into
- public unsafe void CopyBytes(double value, byte[] buffer, int index)
- {
- this.CopyBytes(*((long*)&value), buffer, index);
- }
-
- ///
- /// Copies the specified single-precision floating point value into the specified byte array,
- /// beginning at the specified index.
- ///
- /// The number to convert.
- /// The byte array to copy the bytes into
- /// The first index into the array to copy the bytes into
- public unsafe void CopyBytes(float value, byte[] buffer, int index)
- {
- this.CopyBytes(*((int*)&value), buffer, index);
- }
-
- ///
- /// Copies the specified decimal value into the specified byte array,
- /// beginning at the specified index.
- ///
- /// A character to convert.
- /// The byte array to copy the bytes into
- /// The first index into the array to copy the bytes into
- 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);
- }
- }
-}
diff --git a/src/ImageSharp/IO/EndianBitConverter.GetBytes.cs b/src/ImageSharp/IO/EndianBitConverter.GetBytes.cs
deleted file mode 100644
index 5686c829c4..0000000000
--- a/src/ImageSharp/IO/EndianBitConverter.GetBytes.cs
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-
-namespace SixLabors.ImageSharp.IO
-{
- ///
- /// Equivalent of , but with either endianness.
- ///
- internal abstract partial class EndianBitConverter
- {
- ///
- /// Returns the specified 16-bit signed integer value as an array of bytes.
- ///
- /// The number to convert.
- /// An array of bytes with length 2.
- public byte[] GetBytes(short value)
- {
- byte[] result = new byte[2];
- this.CopyBytes(value, result, 0);
- return result;
- }
-
- ///
- /// Returns the specified 32-bit signed integer value as an array of bytes.
- ///
- /// The number to convert.
- /// An array of bytes with length 4.
- public byte[] GetBytes(int value)
- {
- byte[] result = new byte[4];
- this.CopyBytes(value, result, 0);
- return result;
- }
-
- ///
- /// Returns the specified 64-bit signed integer value as an array of bytes.
- ///
- /// The number to convert.
- /// An array of bytes with length 8.
- public byte[] GetBytes(long value)
- {
- byte[] result = new byte[8];
- this.CopyBytes(value, result, 0);
- return result;
- }
-
- ///
- /// Returns the specified 16-bit unsigned integer value as an array of bytes.
- ///
- /// The number to convert.
- /// An array of bytes with length 2.
- public byte[] GetBytes(ushort value)
- {
- return this.GetBytes(unchecked((short)value));
- }
-
- ///
- /// Returns the specified 32-bit unsigned integer value as an array of bytes.
- ///
- /// The number to convert.
- /// An array of bytes with length 4.
- public byte[] GetBytes(uint value)
- {
- return this.GetBytes(unchecked((int)value));
- }
-
- ///
- /// Returns the specified 64-bit unsigned integer value as an array of bytes.
- ///
- /// The number to convert.
- /// An array of bytes with length 8.
- public byte[] GetBytes(ulong value)
- {
- return this.GetBytes(unchecked((long)value));
- }
-
- ///
- /// Returns the specified Boolean value as an array of bytes.
- ///
- /// A Boolean value.
- /// An array of bytes with length 1.
- ///
- /// The .
- ///
- public byte[] GetBytes(bool value)
- {
- return new byte[1] { value ? (byte)1 : (byte)0 };
- }
-
- ///
- /// Returns the specified Unicode character value as an array of bytes.
- ///
- /// A character to convert.
- /// An array of bytes with length 2.
- ///
- /// The .
- ///
- public byte[] GetBytes(char value)
- {
- return this.GetBytes((short)value);
- }
-
- ///
- /// Returns the specified double-precision floating point value as an array of bytes.
- ///
- /// The number to convert.
- /// An array of bytes with length 8.
- public unsafe byte[] GetBytes(double value)
- {
- return this.GetBytes(*((long*)&value));
- }
-
- ///
- /// Returns the specified single-precision floating point value as an array of bytes.
- ///
- /// The number to convert.
- /// An array of bytes with length 4.
- public unsafe byte[] GetBytes(float value)
- {
- return this.GetBytes(*((int*)&value));
- }
-
- ///
- /// Returns the specified decimal value as an array of bytes.
- ///
- /// The number to convert.
- /// An array of bytes with length 16.
- public byte[] GetBytes(decimal value)
- {
- byte[] result = new byte[16];
- this.CopyBytes(value, result, 0);
- return result;
- }
- }
-}
diff --git a/src/ImageSharp/IO/EndianBitConverter.ToType.cs b/src/ImageSharp/IO/EndianBitConverter.ToType.cs
deleted file mode 100644
index 0c0e49911b..0000000000
--- a/src/ImageSharp/IO/EndianBitConverter.ToType.cs
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-
-namespace SixLabors.ImageSharp.IO
-{
- ///
- /// Equivalent of , but with either endianness.
- ///
- internal abstract partial class EndianBitConverter
- {
- ///
- /// Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// A 16-bit signed integer formed by two bytes beginning at startIndex.
- public abstract short ToInt16(byte[] value, int startIndex);
-
- ///
- /// Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// A 32-bit signed integer formed by four bytes beginning at startIndex.
- public abstract int ToInt32(byte[] value, int startIndex);
-
- ///
- /// Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// A 64-bit signed integer formed by eight bytes beginning at startIndex.
- public abstract long ToInt64(byte[] value, int startIndex);
-
- ///
- /// Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// A 16-bit unsigned integer formed by two bytes beginning at startIndex.
- public ushort ToUInt16(byte[] value, int startIndex)
- {
- return unchecked((ushort)this.ToInt16(value, startIndex));
- }
-
- ///
- /// Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// A 32-bit unsigned integer formed by four bytes beginning at startIndex.
- public uint ToUInt32(byte[] value, int startIndex)
- {
- return unchecked((uint)this.ToInt32(value, startIndex));
- }
-
- ///
- /// Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// A 64-bit unsigned integer formed by eight bytes beginning at startIndex.
- public ulong ToUInt64(byte[] value, int startIndex)
- {
- return unchecked((ulong)this.ToInt64(value, startIndex));
- }
-
- ///
- /// Returns a Boolean value converted from one byte at a specified position in a byte array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// true if the byte at startIndex in value is nonzero; otherwise, false.
- public bool ToBoolean(byte[] value, int startIndex)
- {
- CheckByteArgument(value, startIndex, 1);
- return value[startIndex] != 0;
- }
-
- ///
- /// Returns a Unicode character converted from two bytes at a specified position in a byte array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// A character formed by two bytes beginning at startIndex.
- public char ToChar(byte[] value, int startIndex)
- {
- return unchecked((char)this.ToInt16(value, startIndex));
- }
-
- ///
- /// Returns a double-precision floating point number converted from eight bytes
- /// at a specified position in a byte array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// A double precision floating point number formed by eight bytes beginning at startIndex.
- public unsafe double ToDouble(byte[] value, int startIndex)
- {
- long intValue = this.ToInt64(value, startIndex);
- return *((double*)&intValue);
- }
-
- ///
- /// Returns a single-precision floating point number converted from four bytes
- /// at a specified position in a byte array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// A single precision floating point number formed by four bytes beginning at startIndex.
- public unsafe float ToSingle(byte[] value, int startIndex)
- {
- int intValue = this.ToInt32(value, startIndex);
- return *((float*)&intValue);
- }
-
- ///
- /// Returns a decimal value converted from sixteen bytes
- /// at a specified position in a byte array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// A decimal formed by sixteen bytes beginning at startIndex.
- 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;
- }
- }
-}
diff --git a/src/ImageSharp/IO/EndianBitConverter.cs b/src/ImageSharp/IO/EndianBitConverter.cs
deleted file mode 100644
index b563a09cb8..0000000000
--- a/src/ImageSharp/IO/EndianBitConverter.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Runtime.CompilerServices;
-
-namespace SixLabors.ImageSharp.IO
-{
- ///
- /// Equivalent of , but with either endianness.
- ///
- internal abstract partial class EndianBitConverter
- {
- ///
- /// The little-endian bit converter.
- ///
- public static readonly LittleEndianBitConverter LittleEndianConverter = new LittleEndianBitConverter();
-
- ///
- /// The big-endian bit converter.
- ///
- public static readonly BigEndianBitConverter BigEndianConverter = new BigEndianBitConverter();
-
- ///
- /// Gets the byte order ("endianness") in which data is converted using this class.
- ///
- public abstract Endianness Endianness { get; }
-
- ///
- /// Gets a value indicating whether the byte order ("endianness") in which data is converted is little endian.
- ///
- ///
- /// 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.
- ///
- public abstract bool IsLittleEndian { get; }
-
- ///
- /// Gets the converter.
- ///
- /// The endianness.
- /// an
- /// Not a valid form of Endianness - endianness
- public static EndianBitConverter GetConverter(Endianness endianness)
- {
- switch (endianness)
- {
- case Endianness.LittleEndian:
- return LittleEndianConverter;
- case Endianness.BigEndian:
- return BigEndianConverter;
- default:
- throw new ArgumentException("Not a valid form of Endianness", nameof(endianness));
- }
- }
-
- ///
- /// Returns a String converted from the elements of a byte array.
- ///
- /// An array of bytes.
- /// All the elements of value are converted.
- ///
- /// A String of hexadecimal pairs separated by hyphens, where each pair
- /// represents the corresponding element in value; for example, "7F-2C-4A".
- ///
- public static string ToString(byte[] value)
- {
- return BitConverter.ToString(value);
- }
-
- ///
- /// Returns a String converted from the elements of a byte array starting at a specified array position.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// The elements from array position startIndex to the end of the array are converted.
- ///
- /// A String of hexadecimal pairs separated by hyphens, where each pair
- /// represents the corresponding element in value; for example, "7F-2C-4A".
- ///
- public static string ToString(byte[] value, int startIndex)
- {
- return BitConverter.ToString(value, startIndex);
- }
-
- ///
- /// Returns a String converted from a specified number of bytes at a specified position in a byte array.
- ///
- /// An array of bytes.
- /// The starting position within value.
- /// The number of bytes to convert.
- /// The length elements from array position startIndex are converted.
- ///
- /// A String of hexadecimal pairs separated by hyphens, where each pair
- /// represents the corresponding element in value; for example, "7F-2C-4A".
- ///
- public static string ToString(byte[] value, int startIndex, int length)
- {
- return BitConverter.ToString(value, startIndex, length);
- }
-
- ///
- /// Checks the given argument for validity.
- ///
- /// The byte array passed in
- /// The start index passed in
- /// The number of bytes required
- /// value is a null reference
- ///
- /// startIndex is less than zero or greater than the length of value minus bytesRequired.
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- protected 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));
- }
- }
- }
-}
diff --git a/src/ImageSharp/IO/LittleEndianBitConverter.cs b/src/ImageSharp/IO/LittleEndianBitConverter.cs
deleted file mode 100644
index a69831586a..0000000000
--- a/src/ImageSharp/IO/LittleEndianBitConverter.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.IO
-{
- ///
- /// Implementation of EndianBitConverter which converts to/from little-endian byte arrays.
- ///
- internal sealed class LittleEndianBitConverter : EndianBitConverter
- {
- ///
- public override Endianness Endianness
- {
- get { return Endianness.LittleEndian; }
- }
-
- ///
- public override bool IsLittleEndian
- {
- get { return true; }
- }
-
- ///
- public override void CopyBytes(short value, byte[] buffer, int index)
- {
- CheckByteArgument(buffer, index, 2);
-
- buffer[index + 1] = (byte)(value >> 8);
- buffer[index] = (byte)value;
- }
-
- ///
- 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;
- }
-
- ///
- public override void CopyBytes(long value, byte[] buffer, int index)
- {
- 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;
- }
-
- ///
- public unsafe override short ToInt16(byte[] value, int startIndex)
- {
- CheckByteArgument(value, startIndex, 2);
- return (short)((value[startIndex + 1] << 8) | value[startIndex]);
- }
-
- ///
- 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];
- }
-
- ///
- 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 & 0xFFFFFFFF) | (p1 << 32);
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs
index 9061c334dc..3236e00072 100644
--- a/src/ImageSharp/Image.FromStream.cs
+++ b/src/ImageSharp/Image.FromStream.cs
@@ -183,15 +183,15 @@ namespace SixLabors.ImageSharp
return data.img;
}
- var stringBuilder = new StringBuilder();
- stringBuilder.AppendLine("Image cannot be loaded. Available decoders:");
+ var sb = new StringBuilder();
+ sb.AppendLine("Image cannot be loaded. Available decoders:");
foreach (KeyValuePair val in config.ImageFormatsManager.ImageDecoders)
{
- stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
+ sb.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
}
- throw new NotSupportedException(stringBuilder.ToString());
+ throw new NotSupportedException(sb.ToString());
}
private static T WithSeekableStream(Configuration config, Stream stream, Func action)
diff --git a/src/ImageSharp/Image.LoadPixelData.cs b/src/ImageSharp/Image.LoadPixelData.cs
index 5f1a1617f2..f90f4c8953 100644
--- a/src/ImageSharp/Image.LoadPixelData.cs
+++ b/src/ImageSharp/Image.LoadPixelData.cs
@@ -2,12 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.IO;
-using System.Runtime.CompilerServices;
-using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Formats;
-using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp
@@ -103,13 +98,7 @@ namespace SixLabors.ImageSharp
public static Image LoadPixelData(Configuration config, TPixel[] data, int width, int height)
where TPixel : struct, IPixel
{
- int count = width * height;
- Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data));
-
- var image = new Image(config, width, height);
- SpanHelper.Copy(data, image.GetPixelSpan(), count);
-
- return image;
+ return LoadPixelData(config, new Span(data), width, height);
}
///
@@ -128,7 +117,8 @@ namespace SixLabors.ImageSharp
Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data));
var image = new Image(config, width, height);
- SpanHelper.Copy(data, image.Frames.RootFrame.GetPixelSpan(), count);
+
+ data.Slice(0, count).CopyTo(image.Frames.RootFrame.GetPixelSpan());
return image;
}
diff --git a/src/ImageSharp/ImageExtensions.cs b/src/ImageSharp/ImageExtensions.cs
index 7d23d95d9c..294da3dc40 100644
--- a/src/ImageSharp/ImageExtensions.cs
+++ b/src/ImageSharp/ImageExtensions.cs
@@ -35,28 +35,28 @@ namespace SixLabors.ImageSharp
IImageFormat format = source.GetConfiguration().ImageFormatsManager.FindFormatByFileExtension(ext);
if (format == null)
{
- var stringBuilder = new StringBuilder();
- stringBuilder.AppendLine($"Can't find a format that is associated with the file extention '{ext}'. Registered formats with there extensions include:");
+ var sb = new StringBuilder();
+ sb.AppendLine($"Can't find a format that is associated with the file extention '{ext}'. Registered formats with there extensions include:");
foreach (IImageFormat fmt in source.GetConfiguration().ImageFormats)
{
- stringBuilder.AppendLine($" - {fmt.Name} : {string.Join(", ", fmt.FileExtensions)}");
+ sb.AppendLine($" - {fmt.Name} : {string.Join(", ", fmt.FileExtensions)}");
}
- throw new NotSupportedException(stringBuilder.ToString());
+ throw new NotSupportedException(sb.ToString());
}
IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
if (encoder == null)
{
- var stringBuilder = new StringBuilder();
- stringBuilder.AppendLine($"Can't find encoder for file extention '{ext}' using image format '{format.Name}'. Registered encoders include:");
+ var sb = new StringBuilder();
+ sb.AppendLine($"Can't find encoder for file extention '{ext}' using image format '{format.Name}'. Registered encoders include:");
foreach (KeyValuePair enc in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
{
- stringBuilder.AppendLine($" - {enc.Key} : {enc.Value.GetType().Name}");
+ sb.AppendLine($" - {enc.Key} : {enc.Value.GetType().Name}");
}
- throw new NotSupportedException(stringBuilder.ToString());
+ throw new NotSupportedException(sb.ToString());
}
source.Save(filePath, encoder);
@@ -97,15 +97,15 @@ namespace SixLabors.ImageSharp
if (encoder == null)
{
- var stringBuilder = new StringBuilder();
- stringBuilder.AppendLine("Can't find encoder for provided mime type. Available encoded:");
+ var sb = new StringBuilder();
+ sb.AppendLine("Can't find encoder for provided mime type. Available encoded:");
foreach (KeyValuePair val in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
{
- stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
+ sb.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
}
- throw new NotSupportedException(stringBuilder.ToString());
+ throw new NotSupportedException(sb.ToString());
}
source.Save(stream, encoder);
diff --git a/src/ImageSharp/ImageFrame.LoadPixelData.cs b/src/ImageSharp/ImageFrame.LoadPixelData.cs
index b9341a1b24..9a733fb536 100644
--- a/src/ImageSharp/ImageFrame.LoadPixelData.cs
+++ b/src/ImageSharp/ImageFrame.LoadPixelData.cs
@@ -2,11 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.IO;
-using System.Runtime.CompilerServices;
-using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
@@ -46,7 +42,8 @@ namespace SixLabors.ImageSharp
Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data));
var image = new ImageFrame(memoryManager, width, height);
- SpanHelper.Copy(data, image.GetPixelSpan(), count);
+
+ data.Slice(0, count).CopyTo(image.GetPixelSpan());
return image;
}
diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs
index 888aff905e..cf7a1ae4fc 100644
--- a/src/ImageSharp/ImageFrame{TPixel}.cs
+++ b/src/ImageSharp/ImageFrame{TPixel}.cs
@@ -181,7 +181,7 @@ namespace SixLabors.ImageSharp
throw new ArgumentException("ImageFrame.CopyTo(): target must be of the same size!", nameof(target));
}
- SpanHelper.Copy(this.GetPixelSpan(), target.Span);
+ this.GetPixelSpan().CopyTo(target.Span);
}
///
@@ -246,27 +246,23 @@ namespace SixLabors.ImageSharp
return this.Clone() as ImageFrame;
}
- Func scaleFunc = PackedPixelConverterHelper.ComputeScaleFunction();
-
var target = new ImageFrame(this.MemoryManager, this.Width, this.Height, this.MetaData.Clone());
- using (PixelAccessor pixels = this.Lock())
- using (PixelAccessor targetPixels = target.Lock())
- {
- Parallel.For(
- 0,
- target.Height,
- Configuration.Default.ParallelOptions,
- y =>
- {
- for (int x = 0; x < target.Width; x++)
- {
- var color = default(TPixel2);
- color.PackFromVector4(scaleFunc(pixels[x, y].ToVector4()));
- targetPixels[x, y] = color;
- }
- });
- }
+ // TODO: ImageFrame has no visibility of the current configuration. It should have.
+ ParallelFor.WithTemporaryBuffer(
+ 0,
+ this.Height,
+ Configuration.Default,
+ this.Width,
+ (int y, IBuffer tempRowBuffer) =>
+ {
+ Span sourceRow = this.GetPixelRowSpan(y);
+ Span targetRow = target.GetPixelRowSpan(y);
+ Span tempRowSpan = tempRowBuffer.Span;
+
+ PixelOperations.Instance.ToScaledVector4(sourceRow, tempRowSpan, sourceRow.Length);
+ PixelOperations.Instance.PackFromScaledVector4(tempRowSpan, targetRow, targetRow.Length);
+ });
return target;
}
diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj
index 4433836793..db1de7b6c2 100644
--- a/src/ImageSharp/ImageSharp.csproj
+++ b/src/ImageSharp/ImageSharp.csproj
@@ -11,7 +11,7 @@
SixLabors.ImageSharp
SixLabors.ImageSharp
Image Resize Crop Gif Jpg Jpeg Bitmap Png Core
- https://raw.githubusercontent.com/SixLabors/ImageSharp/master/build/icons/imagesharp-logo-128.png
+ https://raw.githubusercontent.com/SixLabors/Branding/master/icons/imagesharp/sixlabors.imagesharp.128.png
https://github.com/SixLabors/ImageSharp
http://www.apache.org/licenses/LICENSE-2.0
git
@@ -35,7 +35,7 @@
-
+
All
diff --git a/src/ImageSharp/Memory/BasicArrayBuffer.cs b/src/ImageSharp/Memory/BasicArrayBuffer.cs
index 30ca210ac4..a4810d0379 100644
--- a/src/ImageSharp/Memory/BasicArrayBuffer.cs
+++ b/src/ImageSharp/Memory/BasicArrayBuffer.cs
@@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Memory
public int Length { get; }
- public Span Span => this.Array.AsSpan().Slice(0, this.Length);
+ public Span Span => new Span(this.Array, 0, this.Length);
///
/// Returns a reference to specified element of the buffer.
diff --git a/src/ImageSharp/Memory/SpanHelper.cs b/src/ImageSharp/Memory/SpanHelper.cs
index 0c327484a0..592e2a885b 100644
--- a/src/ImageSharp/Memory/SpanHelper.cs
+++ b/src/ImageSharp/Memory/SpanHelper.cs
@@ -2,9 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.Numerics;
using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Memory
{
@@ -13,52 +11,6 @@ namespace SixLabors.ImageSharp.Memory
///
internal static class SpanHelper
{
- ///
- /// Fetches a from the beginning of the span.
- ///
- /// The value type
- /// The span to fetch the vector from
- /// A reference to the beginning of the span
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ref Vector FetchVector(this Span span)
- where T : struct
- {
- return ref Unsafe.As>(ref MemoryMarshal.GetReference(span));
- }
-
- ///
- /// Copy 'count' number of elements of the same type from 'source' to 'dest'
- ///
- /// The element type.
- /// The to copy elements from.
- /// The destination .
- /// The number of elements to copy
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static unsafe void Copy(Span source, Span destination, int count)
- where T : struct
- {
- DebugGuard.MustBeLessThanOrEqualTo(count, source.Length, nameof(count));
- DebugGuard.MustBeLessThanOrEqualTo(count, destination.Length, nameof(count));
-
- ref byte srcRef = ref Unsafe.As(ref MemoryMarshal.GetReference(source));
- ref byte destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destination));
-
- int byteCount = Unsafe.SizeOf() * count;
-
- // TODO: Use unfixed Unsafe.CopyBlock(ref T, ref T, int) for small blocks, when it gets available!
- // This is now available. Check with Anton re intent. Do we replace both ifdefs?
- fixed (byte* pSrc = &srcRef)
- fixed (byte* pDest = &destRef)
- {
-#if NETSTANDARD1_1
- Unsafe.CopyBlock(pDest, pSrc, (uint)byteCount);
-#else
- int destLength = destination.Length * Unsafe.SizeOf();
- Buffer.MemoryCopy(pSrc, pDest, destLength, byteCount);
-#endif
- }
- }
-
///
/// Copy all elements of 'source' into 'destination'.
///
@@ -66,10 +18,10 @@ namespace SixLabors.ImageSharp.Memory
/// The to copy elements from.
/// The destination .
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void Copy(Span source, Span destination)
+ public static void Copy(ReadOnlySpan source, Span destination)
where T : struct
{
- Copy(source, destination, Math.Min(source.Length, destination.Length));
+ source.Slice(0, Math.Min(source.Length, destination.Length)).CopyTo(destination);
}
///
diff --git a/src/ImageSharp/MetaData/ImageProperty.cs b/src/ImageSharp/MetaData/ImageProperty.cs
index c60aaecfba..e4f60e8b33 100644
--- a/src/ImageSharp/MetaData/ImageProperty.cs
+++ b/src/ImageSharp/MetaData/ImageProperty.cs
@@ -10,10 +10,10 @@ namespace SixLabors.ImageSharp.MetaData
/// the copyright information, the date, where the image was created
/// or some other information.
///
- public class ImageProperty : IEquatable
+ public readonly struct ImageProperty : IEquatable
{
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the struct.
///
/// The name of the property.
/// The value of the property.
@@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.MetaData
}
///
- /// Initializes a new instance of the class
+ /// Initializes a new instance of the struct
/// by making a copy from another property.
///
///
@@ -71,11 +71,6 @@ namespace SixLabors.ImageSharp.MetaData
///
public static bool operator ==(ImageProperty left, ImageProperty right)
{
- if (ReferenceEquals(left, right))
- {
- return true;
- }
-
return left.Equals(right);
}
@@ -110,9 +105,7 @@ namespace SixLabors.ImageSharp.MetaData
///
public override bool Equals(object obj)
{
- ImageProperty other = obj as ImageProperty;
-
- return this.Equals(other);
+ return obj is ImageProperty other && this.Equals(other);
}
///
@@ -155,16 +148,6 @@ namespace SixLabors.ImageSharp.MetaData
/// An object to compare with this object.
public bool Equals(ImageProperty other)
{
- if (ReferenceEquals(other, null))
- {
- return false;
- }
-
- if (ReferenceEquals(this, other))
- {
- return true;
- }
-
return this.Name.Equals(other.Name) && Equals(this.Value, other.Value);
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifDataType.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifDataType.cs
index 8c3c1171c7..5bd38b195d 100644
--- a/src/ImageSharp/MetaData/Profiles/Exif/ExifDataType.cs
+++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifDataType.cs
@@ -11,66 +11,66 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
/// Unknown
///
- Unknown,
+ Unknown = 0,
///
- /// Byte
+ /// An 8-bit unsigned integer.
///
- Byte,
+ Byte = 1,
///
- /// Ascii
+ /// An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated with NULL.
///
- Ascii,
+ Ascii = 2,
///
- /// Short
+ /// A 16-bit (2-byte) unsigned integer.
///
- Short,
+ Short = 3,
///
- /// Long
+ /// A 32-bit (4-byte) unsigned integer.
///
- Long,
+ Long = 4,
///
- /// Rational
+ /// Two LONGs. The first LONG is the numerator and the second LONG expresses the denominator.
///
- Rational,
+ Rational = 5,
///
- /// SignedByte
+ /// An 8-bit signed integer.
///
- SignedByte,
+ SignedByte = 6,
///
- /// Undefined
+ /// An 8-bit byte that can take any value depending on the field definition.
///
- Undefined,
+ Undefined = 7,
///
- /// SignedShort
+ /// A 16-bit (2-byte) signed integer.
///
- SignedShort,
+ SignedShort = 8,
///
- /// SignedLong
+ /// A 32-bit (4-byte) signed integer (2's complement notation).
///
- SignedLong,
+ SignedLong = 9,
///
- /// SignedRational
+ /// Two SLONGs. The first SLONG is the numerator and the second SLONG is the denominator.
///
- SignedRational,
+ SignedRational = 10,
///
- /// SingleFloat
+ /// A 32-bit floating point value.
///
- SingleFloat,
+ SingleFloat = 11,
///
- /// DoubleFloat
+ /// A 64-bit floating point value.
///
- DoubleFloat
+ DoubleFloat = 12
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs
index 7cd2d002d7..0f19083e53 100644
--- a/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs
+++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs
@@ -23,12 +23,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
/// The collection of EXIF values
///
- private Collection values;
+ private List values;
///
/// The list of invalid EXIF tags
///
- private List invalidTags;
+ private IReadOnlyList invalidTags;
///
/// The thumbnail offset position in the byte stream
@@ -75,8 +75,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
this.invalidTags = new List(other.invalidTags);
if (other.values != null)
{
- this.values = new Collection();
- foreach (ExifValue value in other.values)
+ this.values = new List(other.Values.Count);
+
+ foreach (ExifValue value in other.Values)
{
this.values.Add(new ExifValue(value));
}
@@ -92,21 +93,17 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
/// Gets or sets which parts will be written when the profile is added to an image.
///
- public ExifParts Parts
- {
- get;
- set;
- }
+ public ExifParts Parts { get; set; }
///
/// Gets the tags that where found but contained an invalid value.
///
- public IEnumerable InvalidTags => this.invalidTags;
+ public IReadOnlyList InvalidTags => this.invalidTags;
///
/// Gets the values of this EXIF profile.
///
- public IEnumerable Values
+ public IReadOnlyList Values
{
get
{
@@ -163,6 +160,31 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
return null;
}
+ ///
+ /// Conditionally returns the value of the tag if it exists.
+ ///
+ /// The tag of the EXIF value.
+ /// The value of the tag, if found.
+ ///
+ /// The .
+ ///
+ public bool TryGetValue(ExifTag tag, out ExifValue value)
+ {
+ foreach (ExifValue exifValue in this.Values)
+ {
+ if (exifValue.Tag == tag)
+ {
+ value = exifValue;
+
+ return true;
+ }
+ }
+
+ value = default;
+
+ return false;
+ }
+
///
/// Removes the value with the specified tag.
///
@@ -193,16 +215,18 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
/// The value.
public void SetValue(ExifTag tag, object value)
{
- foreach (ExifValue exifValue in this.Values)
+ for (int i = 0; i < this.Values.Count; i++)
{
- if (exifValue.Tag == tag)
+ if (this.values[i].Tag == tag)
{
- exifValue.Value = value;
+ this.values[i] = this.values[i].WithValue(value);
+
return;
}
}
var newExifValue = ExifValue.Create(tag, value);
+
this.values.Add(newExifValue);
}
@@ -262,12 +286,14 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
if (this.data == null)
{
- this.values = new Collection();
+ this.values = new List();
return;
}
- var reader = new ExifReader();
- this.values = reader.Read(this.data);
+ var reader = new ExifReader(this.data);
+
+ this.values = reader.ReadValues();
+
this.invalidTags = new List(reader.InvalidTags);
this.thumbnailOffset = (int)reader.ThumbnailOffset;
this.thumbnailLength = (int)reader.ThumbnailLength;
diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs
index 8a7b1f7d7e..c00eec6010 100644
--- a/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs
+++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs
@@ -2,10 +2,13 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers.Binary;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
+using System.Runtime.InteropServices;
using System.Text;
+using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
@@ -15,38 +18,37 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
internal sealed class ExifReader
{
- private readonly Collection invalidTags = new Collection();
- private byte[] exifData;
- private uint currentIndex;
- private bool isLittleEndian;
+ private readonly List invalidTags = new List();
+ private readonly byte[] exifData;
+ private int position;
+ private Endianness endianness = Endianness.BigEndian;
private uint exifOffset;
private uint gpsOffset;
- private uint startIndex;
+ private int startIndex;
- private delegate TDataType ConverterMethod(byte[] data);
+ public ExifReader(byte[] exifData)
+ {
+ DebugGuard.NotNull(exifData, nameof(exifData));
+
+ this.exifData = exifData;
+ }
+
+ private delegate TDataType ConverterMethod(ReadOnlySpan data);
///
/// Gets the invalid tags.
///
- public IEnumerable InvalidTags => this.invalidTags;
+ public IReadOnlyList InvalidTags => this.invalidTags;
///
/// Gets the thumbnail length in the byte stream
///
- public uint ThumbnailLength
- {
- get;
- private set;
- }
+ public uint ThumbnailLength { get; private set; }
///
/// Gets the thumbnail offset position in the byte stream
///
- public uint ThumbnailOffset
- {
- get;
- private set;
- }
+ public uint ThumbnailOffset { get; private set; }
///
/// Gets the remaining length.
@@ -55,81 +57,78 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
{
get
{
- if (this.currentIndex >= this.exifData.Length)
+ if (this.position >= this.exifData.Length)
{
return 0;
}
- return this.exifData.Length - (int)this.currentIndex;
+ return this.exifData.Length - this.position;
}
}
///
/// Reads and returns the collection of EXIF values.
///
- /// The data.
///
/// The .
///
- public Collection Read(byte[] data)
+ public List ReadValues()
{
- DebugGuard.NotNull(data, nameof(data));
-
- var result = new Collection();
+ var values = new List();
- this.exifData = data;
-
- if (this.GetString(4) == "Exif")
+ if (this.ReadString(4) == "Exif")
{
- if (this.GetShort() != 0)
+ if (this.ReadUInt16() != 0)
{
- return result;
+ return values;
}
this.startIndex = 6;
}
else
{
- this.currentIndex = 0;
+ this.position = 0;
}
- this.isLittleEndian = this.GetString(2) == "II";
+ if (this.ReadString(2) == "II")
+ {
+ this.endianness = Endianness.LittleEndian;
+ }
- if (this.GetShort() != 0x002A)
+ if (this.ReadUInt16() != 0x002A)
{
- return result;
+ return values;
}
- uint ifdOffset = this.GetLong();
- this.AddValues(result, ifdOffset);
+ uint ifdOffset = this.ReadUInt32();
+ this.AddValues(values, (int)ifdOffset);
- uint thumbnailOffset = this.GetLong();
- this.GetThumbnail(thumbnailOffset);
+ uint thumbnailOffset = this.ReadUInt32();
+ this.GetThumbnail((int)thumbnailOffset);
if (this.exifOffset != 0)
{
- this.AddValues(result, this.exifOffset);
+ this.AddValues(values, (int)this.exifOffset);
}
if (this.gpsOffset != 0)
{
- this.AddValues(result, this.gpsOffset);
+ this.AddValues(values, (int)this.gpsOffset);
}
- return result;
+ return values;
}
- private static TDataType[] ToArray(ExifDataType dataType, byte[] data, ConverterMethod converter)
+ private static TDataType[] ToArray(ExifDataType dataType, ReadOnlySpan data, ConverterMethod converter)
{
int dataTypeSize = (int)ExifValue.GetSize(dataType);
int length = data.Length / dataTypeSize;
- TDataType[] result = new TDataType[length];
- byte[] buffer = new byte[dataTypeSize];
+ var result = new TDataType[length];
for (int i = 0; i < length; i++)
{
- Array.Copy(data, i * dataTypeSize, buffer, 0, dataTypeSize);
+ ReadOnlySpan buffer = data.Slice(i * dataTypeSize, dataTypeSize);
result.SetValue(converter(buffer), i);
}
@@ -137,14 +136,23 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
return result;
}
- private static byte ToByte(byte[] data)
- {
- return data[0];
- }
+ private byte ConvertToByte(ReadOnlySpan buffer) => buffer[0];
- private static string ToString(byte[] data)
+ private unsafe string ConvertToString(ReadOnlySpan buffer)
{
- string result = Encoding.UTF8.GetString(data, 0, data.Length);
+#if NETSTANDARD1_1
+ byte[] bytes = buffer.ToArray();
+
+ string result = Encoding.UTF8.GetString(bytes, 0, buffer.Length);
+
+#else
+ string result;
+
+ fixed (byte* pointer = &MemoryMarshal.GetReference(buffer))
+ {
+ result = Encoding.UTF8.GetString(pointer, buffer.Length);
+ }
+#endif
int nullCharIndex = result.IndexOf('\0');
if (nullCharIndex != -1)
{
@@ -159,15 +167,14 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
/// The values.
/// The index.
- private void AddValues(Collection values, uint index)
+ private void AddValues(List values, int index)
{
- this.currentIndex = this.startIndex + index;
- ushort count = this.GetShort();
+ this.position = this.startIndex + index;
+ int count = this.ReadUInt16();
- for (ushort i = 0; i < count; i++)
+ for (int i = 0; i < count; i++)
{
- ExifValue value = this.CreateValue();
- if (value == null)
+ if (!this.TryReadValue(out ExifValue value))
{
continue;
}
@@ -208,9 +215,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
}
}
- private object ConvertValue(ExifDataType dataType, byte[] data, uint numberOfComponents)
+ private object ConvertValue(ExifDataType dataType, ReadOnlySpan buffer, uint numberOfComponents)
{
- if (data == null || data.Length == 0)
+ if (buffer == null || buffer.Length == 0)
{
return null;
}
@@ -220,106 +227,116 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
case ExifDataType.Unknown:
return null;
case ExifDataType.Ascii:
- return ToString(data);
+ return this.ConvertToString(buffer);
case ExifDataType.Byte:
if (numberOfComponents == 1)
{
- return ToByte(data);
+ return this.ConvertToByte(buffer);
}
- return data;
+ return buffer.ToArray();
case ExifDataType.DoubleFloat:
if (numberOfComponents == 1)
{
- return this.ToDouble(data);
+ return this.ConvertToDouble(buffer);
}
- return ToArray(dataType, data, this.ToDouble);
+ return ToArray(dataType, buffer, this.ConvertToDouble);
case ExifDataType.Long:
if (numberOfComponents == 1)
{
- return this.ToLong(data);
+ return this.ConvertToUInt32(buffer);
}
- return ToArray(dataType, data, this.ToLong);
+ return ToArray(dataType, buffer, this.ConvertToUInt32);
case ExifDataType.Rational:
if (numberOfComponents == 1)
{
- return this.ToRational(data);
+ return this.ToRational(buffer);
}
- return ToArray(dataType, data, this.ToRational);
+ return ToArray(dataType, buffer, this.ToRational);
case ExifDataType.Short:
if (numberOfComponents == 1)
{
- return this.ToShort(data);
+ return this.ConvertToShort(buffer);
}
- return ToArray(dataType, data, this.ToShort);
+ return ToArray(dataType, buffer, this.ConvertToShort);
case ExifDataType.SignedByte:
if (numberOfComponents == 1)
{
- return this.ToSignedByte(data);
+ return this.ConvertToSignedByte(buffer);
}
- return ToArray(dataType, data, this.ToSignedByte);
+ return ToArray(dataType, buffer, this.ConvertToSignedByte);
case ExifDataType.SignedLong:
if (numberOfComponents == 1)
{
- return this.ToSignedLong(data);
+ return this.ConvertToInt32(buffer);
}
- return ToArray(dataType, data, this.ToSignedLong);
+ return ToArray(dataType, buffer, this.ConvertToInt32);
case ExifDataType.SignedRational:
if (numberOfComponents == 1)
{
- return this.ToSignedRational(data);
+ return this.ToSignedRational(buffer);
}
- return ToArray(dataType, data, this.ToSignedRational);
+ return ToArray(dataType, buffer, this.ToSignedRational);
case ExifDataType.SignedShort:
if (numberOfComponents == 1)
{
- return this.ToSignedShort(data);
+ return this.ConvertToSignedShort(buffer);
}
- return ToArray(dataType, data, this.ToSignedShort);
+ return ToArray(dataType, buffer, this.ConvertToSignedShort);
case ExifDataType.SingleFloat:
if (numberOfComponents == 1)
{
- return this.ToSingle(data);
+ return this.ConvertToSingle(buffer);
}
- return ToArray(dataType, data, this.ToSingle);
+ return ToArray(dataType, buffer, this.ConvertToSingle);
case ExifDataType.Undefined:
if (numberOfComponents == 1)
{
- return ToByte(data);
+ return this.ConvertToByte(buffer);
}
- return data;
+ return buffer.ToArray();
default:
throw new NotSupportedException();
}
}
- private ExifValue CreateValue()
+ private bool TryReadValue(out ExifValue exifValue)
{
+ // 2 | 2 | 4 | 4
+ // tag | type | count | value offset
if (this.RemainingLength < 12)
{
- return null;
+ exifValue = default;
+
+ return false;
}
- ExifTag tag = this.ToEnum(this.GetShort(), ExifTag.Unknown);
- ExifDataType dataType = this.ToEnum(this.GetShort(), ExifDataType.Unknown);
- object value;
+ ExifTag tag = this.ToEnum(this.ReadUInt16(), ExifTag.Unknown);
+ uint type = this.ReadUInt16();
- if (dataType == ExifDataType.Unknown)
+ // Ensure that the data type is valid
+ if (type == 0 || type > 12)
{
- return new ExifValue(tag, dataType, null, false);
+ exifValue = new ExifValue(tag, ExifDataType.Unknown, null, false);
+
+ return true;
}
- uint numberOfComponents = this.GetLong();
+ var dataType = (ExifDataType)type;
+
+ object value;
+
+ uint numberOfComponents = this.ReadUInt32();
// 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)
@@ -329,29 +346,50 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
}
uint size = numberOfComponents * ExifValue.GetSize(dataType);
- byte[] data = this.GetBytes(4);
+
+ this.TryReadSpan(4, out ReadOnlySpan offsetBuffer);
if (size > 4)
{
- uint oldIndex = this.currentIndex;
- this.currentIndex = this.ToLong(data) + this.startIndex;
+ int oldIndex = this.position;
+
+ uint newIndex = this.ConvertToUInt32(offsetBuffer) + (uint)this.startIndex;
+
+ // Ensure that the new index does not overrun the data
+ if (newIndex > int.MaxValue)
+ {
+ this.invalidTags.Add(tag);
+
+ exifValue = default;
+
+ return false;
+ }
+
+ this.position = (int)newIndex;
+
if (this.RemainingLength < size)
{
this.invalidTags.Add(tag);
- this.currentIndex = oldIndex;
- return null;
+ this.position = oldIndex;
+
+ exifValue = default;
+
+ return false;
}
- value = this.ConvertValue(dataType, this.GetBytes(size), numberOfComponents);
- this.currentIndex = oldIndex;
+ this.TryReadSpan((int)size, out ReadOnlySpan dataBuffer);
+
+ value = this.ConvertValue(dataType, dataBuffer, numberOfComponents);
+ this.position = oldIndex;
}
else
{
- value = this.ConvertValue(dataType, data, numberOfComponents);
+ value = this.ConvertValue(dataType, offsetBuffer, numberOfComponents);
}
- bool isArray = value != null && numberOfComponents > 1;
- return new ExifValue(tag, dataType, value, isArray);
+ exifValue = new ExifValue(tag, dataType, value, isArray: value != null && numberOfComponents > 1);
+
+ return true;
}
private TEnum ToEnum(int value, TEnum defaultValue)
@@ -366,51 +404,57 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
return defaultValue;
}
- private byte[] GetBytes(uint length)
+ private bool TryReadSpan(int length, out ReadOnlySpan span)
{
- if (this.currentIndex + length > (uint)this.exifData.Length)
+ if (this.RemainingLength < length)
{
- return null;
+ span = default;
+
+ return false;
}
- byte[] data = new byte[length];
- Array.Copy(this.exifData, (int)this.currentIndex, data, 0, (int)length);
- this.currentIndex += length;
+ span = new ReadOnlySpan(this.exifData, this.position, length);
- return data;
+ this.position += length;
+
+ return true;
}
- private uint GetLong()
+ private uint ReadUInt32()
{
- return this.ToLong(this.GetBytes(4));
+ // Known as Long in Exif Specification
+ return this.TryReadSpan(4, out ReadOnlySpan span)
+ ? this.ConvertToUInt32(span)
+ : default;
}
- private ushort GetShort()
+ private ushort ReadUInt16()
{
- return this.ToShort(this.GetBytes(2));
+ return this.TryReadSpan(2, out ReadOnlySpan span)
+ ? this.ConvertToShort(span)
+ : default;
}
- private string GetString(uint length)
+ private string ReadString(int length)
{
- byte[] data = this.GetBytes(length);
- if (data == null || data.Length == 0)
+ if (this.TryReadSpan(length, out ReadOnlySpan span) && span.Length != 0)
{
- return null;
+ return this.ConvertToString(span);
}
- return ToString(data);
+ return null;
}
- private void GetThumbnail(uint offset)
+ private void GetThumbnail(int offset)
{
- var values = new Collection();
+ var values = new List();
this.AddValues(values, offset);
foreach (ExifValue value in values)
{
if (value.Tag == ExifTag.JPEGInterchangeFormat && (value.DataType == ExifDataType.Long))
{
- this.ThumbnailOffset = (uint)value.Value + this.startIndex;
+ this.ThumbnailOffset = (uint)value.Value + (uint)this.startIndex;
}
else if (value.Tag == ExifTag.JPEGInterchangeFormatLength && value.DataType == ExifDataType.Long)
{
@@ -419,120 +463,112 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
}
}
- private double ToDouble(byte[] data)
+ private unsafe double ConvertToDouble(ReadOnlySpan buffer)
{
- if (!this.ValidateArray(data, 8))
+ if (buffer.Length < 8)
{
- return default(double);
+ return default;
}
- return BitConverter.ToDouble(data, 0);
+ long intValue = this.endianness == Endianness.BigEndian
+ ? BinaryPrimitives.ReadInt64BigEndian(buffer)
+ : BinaryPrimitives.ReadInt64LittleEndian(buffer);
+
+ return *((double*)&intValue);
}
- private uint ToLong(byte[] data)
+ private uint ConvertToUInt32(ReadOnlySpan buffer)
{
- if (!this.ValidateArray(data, 4))
+ // Known as Long in Exif Specification
+ if (buffer.Length < 4)
{
- return default(uint);
+ return default;
}
- return BitConverter.ToUInt32(data, 0);
+ return this.endianness == Endianness.BigEndian
+ ? BinaryPrimitives.ReadUInt32BigEndian(buffer)
+ : BinaryPrimitives.ReadUInt32LittleEndian(buffer);
}
- private ushort ToShort(byte[] data)
+ private ushort ConvertToShort(ReadOnlySpan buffer)
{
- if (!this.ValidateArray(data, 2))
+ if (buffer.Length < 2)
{
- return default(ushort);
+ return default;
}
- return BitConverter.ToUInt16(data, 0);
+ return this.endianness == Endianness.BigEndian
+ ? BinaryPrimitives.ReadUInt16BigEndian(buffer)
+ : BinaryPrimitives.ReadUInt16LittleEndian(buffer);
}
- private float ToSingle(byte[] data)
+ private unsafe float ConvertToSingle(ReadOnlySpan buffer)
{
- if (!this.ValidateArray(data, 4))
+ if (buffer.Length < 4)
{
- return default(float);
+ return default;
}
- return BitConverter.ToSingle(data, 0);
+ int intValue = this.endianness == Endianness.BigEndian
+ ? BinaryPrimitives.ReadInt32BigEndian(buffer)
+ : BinaryPrimitives.ReadInt32LittleEndian(buffer);
+
+ return *((float*)&intValue);
}
- private Rational ToRational(byte[] data)
+ private Rational ToRational(ReadOnlySpan buffer)
{
- if (!this.ValidateArray(data, 8, 4))
+ if (buffer.Length < 8)
{
- return default(Rational);
+ return default;
}
- uint numerator = BitConverter.ToUInt32(data, 0);
- uint denominator = BitConverter.ToUInt32(data, 4);
+ uint numerator = this.ConvertToUInt32(buffer.Slice(0, 4));
+ uint denominator = this.ConvertToUInt32(buffer.Slice(4, 4));
return new Rational(numerator, denominator, false);
}
- private sbyte ToSignedByte(byte[] data)
+ private sbyte ConvertToSignedByte(ReadOnlySpan buffer)
{
- return unchecked((sbyte)data[0]);
+ return unchecked((sbyte)buffer[0]);
}
- private int ToSignedLong(byte[] data)
+ private int ConvertToInt32(ReadOnlySpan buffer) // SignedLong in Exif Specification
{
- if (!this.ValidateArray(data, 4))
+ if (buffer.Length < 4)
{
- return default(int);
+ return default;
}
- return BitConverter.ToInt32(data, 0);
+ return this.endianness == Endianness.BigEndian
+ ? BinaryPrimitives.ReadInt32BigEndian(buffer)
+ : BinaryPrimitives.ReadInt32LittleEndian(buffer);
}
- private SignedRational ToSignedRational(byte[] data)
+ private SignedRational ToSignedRational(ReadOnlySpan buffer)
{
- if (!this.ValidateArray(data, 8, 4))
+ if (buffer.Length < 8)
{
- return default(SignedRational);
+ return default;
}
- int numerator = BitConverter.ToInt32(data, 0);
- int denominator = BitConverter.ToInt32(data, 4);
+ int numerator = this.ConvertToInt32(buffer.Slice(0, 4));
+ int denominator = this.ConvertToInt32(buffer.Slice(4, 4));
return new SignedRational(numerator, denominator, false);
}
- private short ToSignedShort(byte[] data)
+ private short ConvertToSignedShort(ReadOnlySpan buffer)
{
- if (!this.ValidateArray(data, 2))
+ if (buffer.Length < 2)
{
- return default(short);
+ return default;
}
- return BitConverter.ToInt16(data, 0);
- }
-
- private bool ValidateArray(byte[] data, int size)
- {
- return this.ValidateArray(data, size, size);
- }
-
- private bool ValidateArray(byte[] data, int size, int stepSize)
- {
- if (data == null || data.Length < size)
- {
- return false;
- }
-
- if (this.isLittleEndian == BitConverter.IsLittleEndian)
- {
- return true;
- }
-
- for (int i = 0; i < data.Length; i += stepSize)
- {
- Array.Reverse(data, i, stepSize);
- }
-
- return true;
+ return this.endianness == Endianness.BigEndian
+ ? BinaryPrimitives.ReadInt16BigEndian(buffer)
+ : BinaryPrimitives.ReadInt16LittleEndian(buffer);
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifTags.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifTags.cs
new file mode 100644
index 0000000000..e497fc7fa4
--- /dev/null
+++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifTags.cs
@@ -0,0 +1,281 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using static SixLabors.ImageSharp.MetaData.Profiles.Exif.ExifTag;
+
+namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
+{
+ internal static class ExifTags
+ {
+ ///
+ /// The collection if Image File Directory tags
+ ///
+ public static readonly ExifTag[] Ifd =
+ {
+ SubfileType,
+ OldSubfileType,
+ ImageWidth,
+ ImageLength,
+ BitsPerSample,
+ Compression,
+ PhotometricInterpretation,
+ Thresholding,
+ CellWidth,
+ CellLength,
+ FillOrder,
+ DocumentName,
+ ImageDescription,
+ Make,
+ Model,
+ StripOffsets,
+ Orientation,
+ SamplesPerPixel,
+ RowsPerStrip,
+ StripByteCounts,
+ MinSampleValue,
+ MaxSampleValue,
+ XResolution,
+ YResolution,
+ PlanarConfiguration,
+ PageName,
+ XPosition,
+ YPosition,
+ FreeOffsets,
+ FreeByteCounts,
+ GrayResponseUnit,
+ GrayResponseCurve,
+ T4Options,
+ T6Options,
+ ResolutionUnit,
+ PageNumber,
+ ColorResponseUnit,
+ TransferFunction,
+ Software,
+ DateTime,
+ Artist,
+ HostComputer,
+ Predictor,
+ WhitePoint,
+ PrimaryChromaticities,
+ ColorMap,
+ HalftoneHints,
+ TileWidth,
+ TileLength,
+ TileOffsets,
+ TileByteCounts,
+ BadFaxLines,
+ CleanFaxData,
+ ConsecutiveBadFaxLines,
+ InkSet,
+ InkNames,
+ NumberOfInks,
+ DotRange,
+ TargetPrinter,
+ ExtraSamples,
+ SampleFormat,
+ SMinSampleValue,
+ SMaxSampleValue,
+ TransferRange,
+ ClipPath,
+ XClipPathUnits,
+ YClipPathUnits,
+ Indexed,
+ JPEGTables,
+ OPIProxy,
+ ProfileType,
+ FaxProfile,
+ CodingMethods,
+ VersionYear,
+ ModeNumber,
+ Decode,
+ DefaultImageColor,
+ T82ptions,
+ JPEGProc,
+ JPEGInterchangeFormat,
+ JPEGInterchangeFormatLength,
+ JPEGRestartInterval,
+ JPEGLosslessPredictors,
+ JPEGPointTransforms,
+ JPEGQTables,
+ JPEGDCTables,
+ JPEGACTables,
+ YCbCrCoefficients,
+ YCbCrSubsampling,
+ YCbCrSubsampling,
+ YCbCrPositioning,
+ ReferenceBlackWhite,
+ StripRowCounts,
+ XMP,
+ Rating,
+ RatingPercent,
+ ImageID,
+ CFARepeatPatternDim,
+ CFAPattern2,
+ BatteryLevel,
+ Copyright,
+ MDFileTag,
+ MDScalePixel,
+ MDLabName,
+ MDSampleInfo,
+ MDPrepDate,
+ MDPrepTime,
+ MDFileUnits,
+ PixelScale,
+ IntergraphPacketData,
+ IntergraphRegisters,
+ IntergraphMatrix,
+ ModelTiePoint,
+ SEMInfo,
+ ModelTransform,
+ ImageLayer,
+ FaxRecvParams,
+ FaxSubaddress,
+ FaxRecvTime,
+ ImageSourceData,
+ XPTitle,
+ XPComment,
+ XPAuthor,
+ XPKeywords,
+ XPSubject,
+ GDALMetadata,
+ GDALNoData
+ };
+
+ ///
+ /// The collection of Exif tags
+ ///
+ public static readonly ExifTag[] Exif =
+ {
+ ExposureTime,
+ FNumber,
+ ExposureProgram,
+ SpectralSensitivity,
+ ISOSpeedRatings,
+ OECF,
+ Interlace,
+ TimeZoneOffset,
+ SelfTimerMode,
+ SensitivityType,
+ StandardOutputSensitivity,
+ RecommendedExposureIndex,
+ ISOSpeed,
+ ISOSpeedLatitudeyyy,
+ ISOSpeedLatitudezzz,
+ ExifVersion,
+ DateTimeOriginal,
+ DateTimeDigitized,
+ OffsetTime,
+ OffsetTimeOriginal,
+ OffsetTimeDigitized,
+ ComponentsConfiguration,
+ CompressedBitsPerPixel,
+ ShutterSpeedValue,
+ ApertureValue,
+ BrightnessValue,
+ ExposureBiasValue,
+ MaxApertureValue,
+ SubjectDistance,
+ MeteringMode,
+ LightSource,
+ Flash,
+ FocalLength,
+ FlashEnergy2,
+ SpatialFrequencyResponse2,
+ Noise,
+ FocalPlaneXResolution2,
+ FocalPlaneYResolution2,
+ FocalPlaneResolutionUnit2,
+ ImageNumber,
+ SecurityClassification,
+ ImageHistory,
+ SubjectArea,
+ ExposureIndex2,
+ TIFFEPStandardID,
+ SensingMethod2,
+ MakerNote,
+ UserComment,
+ SubsecTime,
+ SubsecTimeOriginal,
+ SubsecTimeDigitized,
+ AmbientTemperature,
+ Humidity,
+ Pressure,
+ WaterDepth,
+ Acceleration,
+ CameraElevationAngle,
+ FlashpixVersion,
+ ColorSpace,
+ PixelXDimension,
+ PixelYDimension,
+ RelatedSoundFile,
+ FlashEnergy,
+ SpatialFrequencyResponse,
+ FocalPlaneXResolution,
+ FocalPlaneYResolution,
+ FocalPlaneResolutionUnit,
+ SubjectLocation,
+ ExposureIndex,
+ SensingMethod,
+ FileSource,
+ SceneType,
+ CFAPattern,
+ CustomRendered,
+ ExposureMode,
+ WhiteBalance,
+ DigitalZoomRatio,
+ FocalLengthIn35mmFilm,
+ SceneCaptureType,
+ GainControl,
+ Contrast,
+ Saturation,
+ Sharpness,
+ DeviceSettingDescription,
+ SubjectDistanceRange,
+ ImageUniqueID,
+ OwnerName,
+ SerialNumber,
+ LensInfo,
+ LensMake,
+ LensModel,
+ LensSerialNumber
+ };
+
+ ///
+ /// The collection of GPS tags
+ ///
+ public static readonly ExifTag[] Gps =
+ {
+ GPSVersionID,
+ GPSLatitudeRef,
+ GPSLatitude,
+ GPSLongitudeRef,
+ GPSLongitude,
+ GPSAltitudeRef,
+ GPSAltitude,
+ GPSTimestamp,
+ GPSSatellites,
+ GPSStatus,
+ GPSMeasureMode,
+ GPSDOP,
+ GPSSpeedRef,
+ GPSSpeed,
+ GPSTrackRef,
+ GPSTrack,
+ GPSImgDirectionRef,
+ GPSImgDirection,
+ GPSMapDatum,
+ GPSDestLatitudeRef,
+ GPSDestLatitude,
+ GPSDestLongitudeRef,
+ GPSDestLongitude,
+ GPSDestBearingRef,
+ GPSDestBearing,
+ GPSDestDistanceRef,
+ GPSDestDistance,
+ GPSProcessingMethod,
+ GPSAreaInformation,
+ GPSDateStamp,
+ GPSDifferential
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs
index 3c2b23f37f..bdd902e239 100644
--- a/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs
+++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs
@@ -13,11 +13,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
public sealed class ExifValue : IEquatable
{
- ///
- /// The exif value.
- ///
- private object exifValue;
-
///
/// Initializes a new instance of the class
/// by making a copy from another exif value.
@@ -34,30 +29,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
if (!other.IsArray)
{
- this.exifValue = other.exifValue;
+ this.Value = other.Value;
}
else
{
- var array = (Array)other.exifValue;
- this.exifValue = array.Clone();
- }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The tag.
- /// The data type.
- /// Whether the value is an array.
- internal ExifValue(ExifTag tag, ExifDataType dataType, bool isArray)
- {
- this.Tag = tag;
- this.DataType = dataType;
- this.IsArray = isArray;
-
- if (dataType == ExifDataType.Ascii)
- {
- this.IsArray = false;
+ var array = (Array)other.Value;
+ this.Value = array.Clone();
}
}
@@ -69,51 +46,32 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
/// The value.
/// Whether the value is an array.
internal ExifValue(ExifTag tag, ExifDataType dataType, object value, bool isArray)
- : this(tag, dataType, isArray)
{
- this.exifValue = value;
+ this.Tag = tag;
+ this.DataType = dataType;
+ this.IsArray = isArray && dataType != ExifDataType.Ascii;
+ this.Value = value;
}
///
/// Gets the data type of the exif value.
///
- public ExifDataType DataType
- {
- get;
- }
+ public ExifDataType DataType { get; }
///
/// Gets a value indicating whether the value is an array.
///
- public bool IsArray
- {
- get;
- }
+ public bool IsArray { get; }
///
/// Gets the tag of the exif value.
///
- public ExifTag Tag
- {
- get;
- }
+ public ExifTag Tag { get; }
///
- /// Gets or sets the value.
+ /// Gets the value.
///
- public object Value
- {
- get
- {
- return this.exifValue;
- }
-
- set
- {
- this.CheckValue(value);
- this.exifValue = value;
- }
- }
+ public object Value { get; }
///
/// Gets a value indicating whether the EXIF value has a value.
@@ -122,14 +80,14 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
{
get
{
- if (this.exifValue == null)
+ if (this.Value == null)
{
return false;
}
if (this.DataType == ExifDataType.Ascii)
{
- return ((string)this.exifValue).Length > 0;
+ return ((string)this.Value).Length > 0;
}
return true;
@@ -143,7 +101,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
{
get
{
- if (this.exifValue == null)
+ if (this.Value == null)
{
return 4;
}
@@ -163,12 +121,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
{
if (this.DataType == ExifDataType.Ascii)
{
- return Encoding.UTF8.GetBytes((string)this.exifValue).Length;
+ return Encoding.UTF8.GetBytes((string)this.Value).Length;
}
if (this.IsArray)
{
- return ((Array)this.exifValue).Length;
+ return ((Array)this.Value).Length;
}
return 1;
@@ -217,12 +175,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(this, obj))
- {
- return true;
- }
-
- return this.Equals(obj as ExifValue);
+ return obj is ExifValue other && this.Equals(other);
}
///
@@ -241,7 +194,19 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
return
this.Tag == other.Tag &&
this.DataType == other.DataType &&
- object.Equals(this.exifValue, other.exifValue);
+ object.Equals(this.Value, other.Value);
+ }
+
+ ///
+ /// Clones the current value, overwriting the value.
+ ///
+ /// The value to overwrite.
+ ///
+ public ExifValue WithValue(object value)
+ {
+ this.CheckValue(value);
+
+ return new ExifValue(this.Tag, this.DataType, value, this.IsArray);
}
///
@@ -253,26 +218,26 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
public override string ToString()
{
- if (this.exifValue == null)
+ if (this.Value == null)
{
return null;
}
if (this.DataType == ExifDataType.Ascii)
{
- return (string)this.exifValue;
+ return (string)this.Value;
}
if (!this.IsArray)
{
- return this.ToString(this.exifValue);
+ return this.ToString(this.Value);
}
var sb = new StringBuilder();
- foreach (object value in (Array)this.exifValue)
+ foreach (object value in (Array)this.Value)
{
sb.Append(this.ToString(value));
- sb.Append(" ");
+ sb.Append(' ');
}
return sb.ToString();
@@ -293,13 +258,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
{
Guard.IsFalse(tag == ExifTag.Unknown, nameof(tag), "Invalid Tag");
- ExifValue exifValue;
- Type type = value?.GetType();
- if (type != null && type.IsArray)
- {
- type = type.GetElementType();
- }
-
switch (tag)
{
case ExifTag.ImageDescription:
@@ -355,8 +313,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
case ExifTag.GPSDestBearingRef:
case ExifTag.GPSDestDistanceRef:
case ExifTag.GPSDateStamp:
- exifValue = new ExifValue(tag, ExifDataType.Ascii, true);
- break;
+ return new ExifValue(tag, ExifDataType.Ascii, value, true);
case ExifTag.ClipPath:
case ExifTag.VersionYear:
@@ -369,13 +326,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
case ExifTag.XPKeywords:
case ExifTag.XPSubject:
case ExifTag.GPSVersionID:
- exifValue = new ExifValue(tag, ExifDataType.Byte, true);
- break;
+ return new ExifValue(tag, ExifDataType.Byte, value, true);
+
case ExifTag.FaxProfile:
case ExifTag.ModeNumber:
case ExifTag.GPSAltitudeRef:
- exifValue = new ExifValue(tag, ExifDataType.Byte, false);
- break;
+ return new ExifValue(tag, ExifDataType.Byte, value, false);
case ExifTag.FreeOffsets:
case ExifTag.FreeByteCounts:
@@ -389,8 +345,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
case ExifTag.StripRowCounts:
case ExifTag.IntergraphRegisters:
case ExifTag.TimeZoneOffset:
- exifValue = new ExifValue(tag, ExifDataType.Long, true);
- break;
+ return new ExifValue(tag, ExifDataType.Long, value, true);
case ExifTag.SubfileType:
case ExifTag.SubIFDOffset:
case ExifTag.GPSIFDOffset:
@@ -412,8 +367,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
case ExifTag.FaxRecvParams:
case ExifTag.FaxRecvTime:
case ExifTag.ImageNumber:
- exifValue = new ExifValue(tag, ExifDataType.Long, false);
- break;
+ return new ExifValue(tag, ExifDataType.Long, value, false);
case ExifTag.WhitePoint:
case ExifTag.PrimaryChromaticities:
@@ -428,8 +382,8 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
case ExifTag.GPSTimestamp:
case ExifTag.GPSDestLatitude:
case ExifTag.GPSDestLongitude:
- exifValue = new ExifValue(tag, ExifDataType.Rational, true);
- break;
+ return new ExifValue(tag, ExifDataType.Rational, value, true);
+
case ExifTag.XPosition:
case ExifTag.YPosition:
case ExifTag.XResolution:
@@ -463,8 +417,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
case ExifTag.GPSImgDirection:
case ExifTag.GPSDestBearing:
case ExifTag.GPSDestDistance:
- exifValue = new ExifValue(tag, ExifDataType.Rational, false);
- break;
+ return new ExifValue(tag, ExifDataType.Rational, value, false);
case ExifTag.BitsPerSample:
case ExifTag.MinSampleValue:
@@ -487,8 +440,8 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
case ExifTag.ISOSpeedRatings:
case ExifTag.SubjectArea:
case ExifTag.SubjectLocation:
- exifValue = new ExifValue(tag, ExifDataType.Short, true);
- break;
+ return new ExifValue(tag, ExifDataType.Short, value, true);
+
case ExifTag.OldSubfileType:
case ExifTag.Compression:
case ExifTag.PhotometricInterpretation:
@@ -535,20 +488,18 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
case ExifTag.Sharpness:
case ExifTag.SubjectDistanceRange:
case ExifTag.GPSDifferential:
- exifValue = new ExifValue(tag, ExifDataType.Short, false);
- break;
+ return new ExifValue(tag, ExifDataType.Short, value, false);
case ExifTag.Decode:
- exifValue = new ExifValue(tag, ExifDataType.SignedRational, true);
- break;
+ return new ExifValue(tag, ExifDataType.SignedRational, value, true);
+
case ExifTag.ShutterSpeedValue:
case ExifTag.BrightnessValue:
case ExifTag.ExposureBiasValue:
case ExifTag.AmbientTemperature:
case ExifTag.WaterDepth:
case ExifTag.CameraElevationAngle:
- exifValue = new ExifValue(tag, ExifDataType.SignedRational, false);
- break;
+ return new ExifValue(tag, ExifDataType.SignedRational, value, false);
case ExifTag.JPEGTables:
case ExifTag.OECF:
@@ -565,18 +516,17 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
case ExifTag.ImageSourceData:
case ExifTag.GPSProcessingMethod:
case ExifTag.GPSAreaInformation:
- exifValue = new ExifValue(tag, ExifDataType.Undefined, true);
- break;
+ return new ExifValue(tag, ExifDataType.Undefined, value, true);
+
case ExifTag.FileSource:
case ExifTag.SceneType:
- exifValue = new ExifValue(tag, ExifDataType.Undefined, false);
- break;
+ return new ExifValue(tag, ExifDataType.Undefined, value, false);
case ExifTag.StripOffsets:
case ExifTag.TileByteCounts:
case ExifTag.ImageLayer:
- exifValue = CreateNumber(tag, type, true);
- break;
+ return CreateNumber(tag, value, true);
+
case ExifTag.ImageWidth:
case ExifTag.ImageLength:
case ExifTag.TileWidth:
@@ -585,15 +535,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
case ExifTag.ConsecutiveBadFaxLines:
case ExifTag.PixelXDimension:
case ExifTag.PixelYDimension:
- exifValue = CreateNumber(tag, type, false);
- break;
+ return CreateNumber(tag, value, false);
default:
throw new NotSupportedException();
}
-
- exifValue.Value = value;
- return exifValue;
}
///
@@ -635,29 +581,35 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
/// Returns an EXIF value with a numeric type for the given tag.
///
/// The tag.
- /// The numeric type.
+ /// The value.
/// Whether the value is an array.
///
/// The .
///
- private static ExifValue CreateNumber(ExifTag tag, Type type, bool isArray)
+ private static ExifValue CreateNumber(ExifTag tag, object value, bool isArray)
{
+ Type type = value?.GetType();
+ if (type != null && type.IsArray)
+ {
+ type = type.GetElementType();
+ }
+
if (type == null || type == typeof(ushort))
{
- return new ExifValue(tag, ExifDataType.Short, isArray);
+ return new ExifValue(tag, ExifDataType.Short, value, isArray);
}
if (type == typeof(short))
{
- return new ExifValue(tag, ExifDataType.SignedShort, isArray);
+ return new ExifValue(tag, ExifDataType.SignedShort, value, isArray);
}
if (type == typeof(uint))
{
- return new ExifValue(tag, ExifDataType.Long, isArray);
+ return new ExifValue(tag, ExifDataType.Long, value, isArray);
}
- return new ExifValue(tag, ExifDataType.SignedLong, isArray);
+ return new ExifValue(tag, ExifDataType.SignedLong, value, isArray);
}
///
@@ -739,8 +691,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
/// The
private string ToString(object value)
{
- string description = ExifTagDescriptionAttribute.GetDescription(this.Tag, value);
- if (description != null)
+ if (ExifTagDescriptionAttribute.GetDescription(this.Tag, value) is string description)
{
return description;
}
@@ -788,7 +739,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
private int GetHashCode(ExifValue exif)
{
int hashCode = exif.Tag.GetHashCode() ^ exif.DataType.GetHashCode();
- return hashCode ^ exif.exifValue?.GetHashCode() ?? hashCode;
+ return hashCode ^ exif.Value?.GetHashCode() ?? hashCode;
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs
index a4cfc7e13e..f7363ef314 100644
--- a/src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs
+++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs
@@ -2,8 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers.Binary;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.Text;
using SixLabors.ImageSharp.Primitives;
@@ -19,299 +19,28 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
private const int StartIndex = 6;
- ///
- /// The collection if Image File Directory tags
- ///
- private static readonly ExifTag[] IfdTags =
- {
- ExifTag.SubfileType,
- ExifTag.OldSubfileType,
- ExifTag.ImageWidth,
- ExifTag.ImageLength,
- ExifTag.BitsPerSample,
- ExifTag.Compression,
- ExifTag.PhotometricInterpretation,
- ExifTag.Thresholding,
- ExifTag.CellWidth,
- ExifTag.CellLength,
- ExifTag.FillOrder,
- ExifTag.DocumentName,
- ExifTag.ImageDescription,
- ExifTag.Make,
- ExifTag.Model,
- ExifTag.StripOffsets,
- ExifTag.Orientation,
- ExifTag.SamplesPerPixel,
- ExifTag.RowsPerStrip,
- ExifTag.StripByteCounts,
- ExifTag.MinSampleValue,
- ExifTag.MaxSampleValue,
- ExifTag.XResolution,
- ExifTag.YResolution,
- ExifTag.PlanarConfiguration,
- ExifTag.PageName,
- ExifTag.XPosition,
- ExifTag.YPosition,
- ExifTag.FreeOffsets,
- ExifTag.FreeByteCounts,
- ExifTag.GrayResponseUnit,
- ExifTag.GrayResponseCurve,
- ExifTag.T4Options,
- ExifTag.T6Options,
- ExifTag.ResolutionUnit,
- ExifTag.PageNumber,
- ExifTag.ColorResponseUnit,
- ExifTag.TransferFunction,
- ExifTag.Software,
- ExifTag.DateTime,
- ExifTag.Artist,
- ExifTag.HostComputer,
- ExifTag.Predictor,
- ExifTag.WhitePoint,
- ExifTag.PrimaryChromaticities,
- ExifTag.ColorMap,
- ExifTag.HalftoneHints,
- ExifTag.TileWidth,
- ExifTag.TileLength,
- ExifTag.TileOffsets,
- ExifTag.TileByteCounts,
- ExifTag.BadFaxLines,
- ExifTag.CleanFaxData,
- ExifTag.ConsecutiveBadFaxLines,
- ExifTag.InkSet,
- ExifTag.InkNames,
- ExifTag.NumberOfInks,
- ExifTag.DotRange,
- ExifTag.TargetPrinter,
- ExifTag.ExtraSamples,
- ExifTag.SampleFormat,
- ExifTag.SMinSampleValue,
- ExifTag.SMaxSampleValue,
- ExifTag.TransferRange,
- ExifTag.ClipPath,
- ExifTag.XClipPathUnits,
- ExifTag.YClipPathUnits,
- ExifTag.Indexed,
- ExifTag.JPEGTables,
- ExifTag.OPIProxy,
- ExifTag.ProfileType,
- ExifTag.FaxProfile,
- ExifTag.CodingMethods,
- ExifTag.VersionYear,
- ExifTag.ModeNumber,
- ExifTag.Decode,
- ExifTag.DefaultImageColor,
- ExifTag.T82ptions,
- ExifTag.JPEGProc,
- ExifTag.JPEGInterchangeFormat,
- ExifTag.JPEGInterchangeFormatLength,
- ExifTag.JPEGRestartInterval,
- ExifTag.JPEGLosslessPredictors,
- ExifTag.JPEGPointTransforms,
- ExifTag.JPEGQTables,
- ExifTag.JPEGDCTables,
- ExifTag.JPEGACTables,
- ExifTag.YCbCrCoefficients,
- ExifTag.YCbCrSubsampling,
- ExifTag.YCbCrSubsampling,
- ExifTag.YCbCrPositioning,
- ExifTag.ReferenceBlackWhite,
- ExifTag.StripRowCounts,
- ExifTag.XMP,
- ExifTag.Rating,
- ExifTag.RatingPercent,
- ExifTag.ImageID,
- ExifTag.CFARepeatPatternDim,
- ExifTag.CFAPattern2,
- ExifTag.BatteryLevel,
- ExifTag.Copyright,
- ExifTag.MDFileTag,
- ExifTag.MDScalePixel,
- ExifTag.MDLabName,
- ExifTag.MDSampleInfo,
- ExifTag.MDPrepDate,
- ExifTag.MDPrepTime,
- ExifTag.MDFileUnits,
- ExifTag.PixelScale,
- ExifTag.IntergraphPacketData,
- ExifTag.IntergraphRegisters,
- ExifTag.IntergraphMatrix,
- ExifTag.ModelTiePoint,
- ExifTag.SEMInfo,
- ExifTag.ModelTransform,
- ExifTag.ImageLayer,
- ExifTag.FaxRecvParams,
- ExifTag.FaxSubaddress,
- ExifTag.FaxRecvTime,
- ExifTag.ImageSourceData,
- ExifTag.XPTitle,
- ExifTag.XPComment,
- ExifTag.XPAuthor,
- ExifTag.XPKeywords,
- ExifTag.XPSubject,
- ExifTag.GDALMetadata,
- ExifTag.GDALNoData
- };
-
- ///
- /// The collection of Exif tags
- ///
- private static readonly ExifTag[] ExifTags =
- {
- ExifTag.ExposureTime,
- ExifTag.FNumber,
- ExifTag.ExposureProgram,
- ExifTag.SpectralSensitivity,
- ExifTag.ISOSpeedRatings,
- ExifTag.OECF,
- ExifTag.Interlace,
- ExifTag.TimeZoneOffset,
- ExifTag.SelfTimerMode,
- ExifTag.SensitivityType,
- ExifTag.StandardOutputSensitivity,
- ExifTag.RecommendedExposureIndex,
- ExifTag.ISOSpeed,
- ExifTag.ISOSpeedLatitudeyyy,
- ExifTag.ISOSpeedLatitudezzz,
- ExifTag.ExifVersion,
- ExifTag.DateTimeOriginal,
- ExifTag.DateTimeDigitized,
- ExifTag.OffsetTime,
- ExifTag.OffsetTimeOriginal,
- ExifTag.OffsetTimeDigitized,
- ExifTag.ComponentsConfiguration,
- ExifTag.CompressedBitsPerPixel,
- ExifTag.ShutterSpeedValue,
- ExifTag.ApertureValue,
- ExifTag.BrightnessValue,
- ExifTag.ExposureBiasValue,
- ExifTag.MaxApertureValue,
- ExifTag.SubjectDistance,
- ExifTag.MeteringMode,
- ExifTag.LightSource,
- ExifTag.Flash,
- ExifTag.FocalLength,
- ExifTag.FlashEnergy2,
- ExifTag.SpatialFrequencyResponse2,
- ExifTag.Noise,
- ExifTag.FocalPlaneXResolution2,
- ExifTag.FocalPlaneYResolution2,
- ExifTag.FocalPlaneResolutionUnit2,
- ExifTag.ImageNumber,
- ExifTag.SecurityClassification,
- ExifTag.ImageHistory,
- ExifTag.SubjectArea,
- ExifTag.ExposureIndex2,
- ExifTag.TIFFEPStandardID,
- ExifTag.SensingMethod2,
- ExifTag.MakerNote,
- ExifTag.UserComment,
- ExifTag.SubsecTime,
- ExifTag.SubsecTimeOriginal,
- ExifTag.SubsecTimeDigitized,
- ExifTag.AmbientTemperature,
- ExifTag.Humidity,
- ExifTag.Pressure,
- ExifTag.WaterDepth,
- ExifTag.Acceleration,
- ExifTag.CameraElevationAngle,
- ExifTag.FlashpixVersion,
- ExifTag.ColorSpace,
- ExifTag.PixelXDimension,
- ExifTag.PixelYDimension,
- ExifTag.RelatedSoundFile,
- ExifTag.FlashEnergy,
- ExifTag.SpatialFrequencyResponse,
- ExifTag.FocalPlaneXResolution,
- ExifTag.FocalPlaneYResolution,
- ExifTag.FocalPlaneResolutionUnit,
- ExifTag.SubjectLocation,
- ExifTag.ExposureIndex,
- ExifTag.SensingMethod,
- ExifTag.FileSource,
- ExifTag.SceneType,
- ExifTag.CFAPattern,
- ExifTag.CustomRendered,
- ExifTag.ExposureMode,
- ExifTag.WhiteBalance,
- ExifTag.DigitalZoomRatio,
- ExifTag.FocalLengthIn35mmFilm,
- ExifTag.SceneCaptureType,
- ExifTag.GainControl,
- ExifTag.Contrast,
- ExifTag.Saturation,
- ExifTag.Sharpness,
- ExifTag.DeviceSettingDescription,
- ExifTag.SubjectDistanceRange,
- ExifTag.ImageUniqueID,
- ExifTag.OwnerName,
- ExifTag.SerialNumber,
- ExifTag.LensInfo,
- ExifTag.LensMake,
- ExifTag.LensModel,
- ExifTag.LensSerialNumber
- };
-
- ///
- /// The collection of GPS tags
- ///
- private static readonly ExifTag[] GPSTags =
- {
- ExifTag.GPSVersionID,
- ExifTag.GPSLatitudeRef,
- ExifTag.GPSLatitude,
- ExifTag.GPSLongitudeRef,
- ExifTag.GPSLongitude,
- ExifTag.GPSAltitudeRef,
- ExifTag.GPSAltitude,
- ExifTag.GPSTimestamp,
- ExifTag.GPSSatellites,
- ExifTag.GPSStatus,
- ExifTag.GPSMeasureMode,
- ExifTag.GPSDOP,
- ExifTag.GPSSpeedRef,
- ExifTag.GPSSpeed,
- ExifTag.GPSTrackRef,
- ExifTag.GPSTrack,
- ExifTag.GPSImgDirectionRef,
- ExifTag.GPSImgDirection,
- ExifTag.GPSMapDatum,
- ExifTag.GPSDestLatitudeRef,
- ExifTag.GPSDestLatitude,
- ExifTag.GPSDestLongitudeRef,
- ExifTag.GPSDestLongitude,
- ExifTag.GPSDestBearingRef,
- ExifTag.GPSDestBearing,
- ExifTag.GPSDestDistanceRef,
- ExifTag.GPSDestDistance,
- ExifTag.GPSProcessingMethod,
- ExifTag.GPSAreaInformation,
- ExifTag.GPSDateStamp,
- ExifTag.GPSDifferential
- };
-
///
/// Which parts will be written.
///
private ExifParts allowedParts;
- private Collection values;
- private Collection dataOffsets;
- private Collection ifdIndexes;
- private Collection exifIndexes;
- private Collection gpsIndexes;
+ private IList values;
+ private List dataOffsets;
+ private List ifdIndexes;
+ private List exifIndexes;
+ private List gpsIndexes;
///
/// Initializes a new instance of the class.
///
/// The values.
/// The allowed parts.
- public ExifWriter(Collection values, ExifParts allowedParts)
+ public ExifWriter(IList values, ExifParts allowedParts)
{
this.values = values;
this.allowedParts = allowedParts;
- this.ifdIndexes = this.GetIndexes(ExifParts.IfdTags, IfdTags);
- this.exifIndexes = this.GetIndexes(ExifParts.ExifTags, ExifTags);
- this.gpsIndexes = this.GetIndexes(ExifParts.GPSTags, GPSTags);
+ this.ifdIndexes = this.GetIndexes(ExifParts.IfdTags, ExifTags.Ifd);
+ this.exifIndexes = this.GetIndexes(ExifParts.ExifTags, ExifTags.Exif);
+ this.gpsIndexes = this.GetIndexes(ExifParts.GPSTags, ExifTags.Gps);
}
///
@@ -360,6 +89,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
length += 10 + 4 + 2;
byte[] result = new byte[length];
+
result[0] = (byte)'E';
result[1] = (byte)'x';
result[2] = (byte)'i';
@@ -377,17 +107,17 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
if (exifLength > 0)
{
- this.values[exifIndex].Value = ifdOffset + ifdLength;
+ this.values[exifIndex] = this.values[exifIndex].WithValue(ifdOffset + ifdLength);
}
if (gpsLength > 0)
{
- this.values[gpsIndex].Value = ifdOffset + ifdLength + exifLength;
+ this.values[gpsIndex] = this.values[gpsIndex].WithValue(ifdOffset + ifdLength + exifLength);
}
- i = Write(BitConverter.GetBytes(ifdOffset), result, i);
+ i = WriteUInt32(ifdOffset, result, i);
i = this.WriteHeaders(this.ifdIndexes, result, i);
- i = Write(BitConverter.GetBytes(thumbnailOffset), result, i);
+ i = WriteUInt32(thumbnailOffset, result, i);
i = this.WriteData(this.ifdIndexes, result, i);
if (exifLength > 0)
@@ -402,19 +132,61 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
i = this.WriteData(this.gpsIndexes, result, i);
}
- Write(BitConverter.GetBytes((ushort)0), result, i);
+ WriteUInt16((ushort)0, result, i);
return result;
}
- private static int Write(byte[] source, byte[] destination, int offset)
+ private static unsafe int WriteSingle(float value, Span destination, int offset)
+ {
+ BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(offset, 4), *((int*)&value));
+
+ return offset + 4;
+ }
+
+ private static unsafe int WriteDouble(double value, Span destination, int offset)
+ {
+ BinaryPrimitives.WriteInt64LittleEndian(destination.Slice(offset, 8), *((long*)&value));
+
+ return offset + 8;
+ }
+
+ private static int Write(ReadOnlySpan source, Span destination, int offset)
{
- Buffer.BlockCopy(source, 0, destination, offset, source.Length);
+ source.CopyTo(destination.Slice(offset, source.Length));
return offset + source.Length;
}
- private int GetIndex(Collection indexes, ExifTag tag)
+ private static int WriteInt16(short value, Span destination, int offset)
+ {
+ BinaryPrimitives.WriteInt16LittleEndian(destination.Slice(offset, 2), value);
+
+ return offset + 2;
+ }
+
+ private static int WriteUInt16(ushort value, Span destination, int offset)
+ {
+ BinaryPrimitives.WriteUInt16LittleEndian(destination.Slice(offset, 2), value);
+
+ return offset + 2;
+ }
+
+ private static int WriteUInt32(uint value, Span destination, int offset)
+ {
+ BinaryPrimitives.WriteUInt32LittleEndian(destination.Slice(offset, 4), value);
+
+ return offset + 4;
+ }
+
+ private static int WriteInt32(int value, Span destination, int offset)
+ {
+ BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(offset, 4), value);
+
+ return offset + 4;
+ }
+
+ private int GetIndex(IList indexes, ExifTag tag)
{
foreach (int index in indexes)
{
@@ -430,14 +202,14 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
return newIndex;
}
- private Collection GetIndexes(ExifParts part, ExifTag[] tags)
+ private List GetIndexes(ExifParts part, ExifTag[] tags)
{
if (((int)this.allowedParts & (int)part) == 0)
{
- return new Collection();
+ return new List();
}
- Collection result = new Collection();
+ var result = new List();
for (int i = 0; i < this.values.Count; i++)
{
ExifValue value = this.values[i];
@@ -457,7 +229,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
return result;
}
- private uint GetLength(IEnumerable indexes)
+ private uint GetLength(IList indexes)
{
uint length = 0;
@@ -494,7 +266,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
return newOffset;
}
- private int WriteData(Collection indexes, byte[] destination, int offset)
+ private int WriteData(List indexes, byte[] destination, int offset)
{
if (this.dataOffsets.Count == 0)
{
@@ -509,7 +281,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
ExifValue value = this.values[index];
if (value.Length > 4)
{
- Write(BitConverter.GetBytes(newOffset - StartIndex), destination, this.dataOffsets[i++]);
+ WriteUInt32((uint)(newOffset - StartIndex), destination, this.dataOffsets[i++]);
newOffset = this.WriteValue(value, destination, newOffset);
}
}
@@ -517,11 +289,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
return newOffset;
}
- private int WriteHeaders(Collection indexes, byte[] destination, int offset)
+ private int WriteHeaders(List indexes, byte[] destination, int offset)
{
- this.dataOffsets = new Collection();
+ this.dataOffsets = new List();
- int newOffset = Write(BitConverter.GetBytes((ushort)indexes.Count), destination, offset);
+ int newOffset = WriteUInt16((ushort)indexes.Count, destination, offset);
if (indexes.Count == 0)
{
@@ -531,9 +303,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
foreach (int index in indexes)
{
ExifValue value = this.values[index];
- newOffset = Write(BitConverter.GetBytes((ushort)value.Tag), destination, newOffset);
- newOffset = Write(BitConverter.GetBytes((ushort)value.DataType), destination, newOffset);
- newOffset = Write(BitConverter.GetBytes((uint)value.NumberOfComponents), destination, newOffset);
+ newOffset = WriteUInt16((ushort)value.Tag, destination, newOffset);
+ newOffset = WriteUInt16((ushort)value.DataType, destination, newOffset);
+ newOffset = WriteUInt32((uint)value.NumberOfComponents, destination, newOffset);
if (value.Length > 4)
{
@@ -550,23 +322,19 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
return newOffset;
}
- private int WriteRational(Rational value, byte[] destination, int offset)
+ private static void WriteRational(Span destination, in Rational value)
{
- Write(BitConverter.GetBytes(value.Numerator), destination, offset);
- Write(BitConverter.GetBytes(value.Denominator), destination, offset + 4);
-
- return offset + 8;
+ BinaryPrimitives.WriteUInt32LittleEndian(destination.Slice(0, 4), value.Numerator);
+ BinaryPrimitives.WriteUInt32LittleEndian(destination.Slice(4, 4), value.Denominator);
}
- private int WriteSignedRational(SignedRational value, byte[] destination, int offset)
+ private static void WriteSignedRational(Span destination, in SignedRational value)
{
- Write(BitConverter.GetBytes(value.Numerator), destination, offset);
- Write(BitConverter.GetBytes(value.Denominator), destination, offset + 4);
-
- return offset + 8;
+ BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(0, 4), value.Numerator);
+ BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(4, 4), value.Denominator);
}
- private int WriteValue(ExifDataType dataType, object value, byte[] destination, int offset)
+ private int WriteValue(ExifDataType dataType, object value, Span destination, int offset)
{
switch (dataType)
{
@@ -577,24 +345,26 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
destination[offset] = (byte)value;
return offset + 1;
case ExifDataType.DoubleFloat:
- return Write(BitConverter.GetBytes((double)value), destination, offset);
+ return WriteDouble((double)value, destination, offset);
case ExifDataType.Short:
- return Write(BitConverter.GetBytes((ushort)value), destination, offset);
+ return WriteUInt16((ushort)value, destination, offset);
case ExifDataType.Long:
- return Write(BitConverter.GetBytes((uint)value), destination, offset);
+ return WriteUInt32((uint)value, destination, offset);
case ExifDataType.Rational:
- return this.WriteRational((Rational)value, destination, offset);
+ WriteRational(destination.Slice(offset, 8), (Rational)value);
+ return offset + 8;
case ExifDataType.SignedByte:
destination[offset] = unchecked((byte)((sbyte)value));
return offset + 1;
case ExifDataType.SignedLong:
- return Write(BitConverter.GetBytes((int)value), destination, offset);
+ return WriteInt32((int)value, destination, offset);
case ExifDataType.SignedShort:
- return Write(BitConverter.GetBytes((short)value), destination, offset);
+ return WriteInt16((short)value, destination, offset);
case ExifDataType.SignedRational:
- return this.WriteSignedRational((SignedRational)value, destination, offset);
+ WriteSignedRational(destination.Slice(offset, 8), (SignedRational)value);
+ return offset + 8;
case ExifDataType.SingleFloat:
- return Write(BitConverter.GetBytes((float)value), destination, offset);
+ return WriteSingle((float)value, destination, offset);
default:
throw new NotImplementedException();
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs
index 46aec49be6..ee8b4c731e 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs
@@ -158,7 +158,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccParametricCurve && this.Equals((IccParametricCurve)obj);
+ return obj is IccParametricCurve other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs
index ae9cd84b47..8a7162198b 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs
@@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccResponseCurve && this.Equals((IccResponseCurve)obj);
+ return obj is IccResponseCurve other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs
index 14f7f95703..794d77ba19 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers.Binary;
using System.Text;
namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
@@ -17,7 +18,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// the value
public ushort ReadUInt16()
{
- return this.converter.ToUInt16(this.data, this.AddIndex(2));
+ return BinaryPrimitives.ReadUInt16BigEndian(new Span(this.data, this.AddIndex(2), 2));
}
///
@@ -26,7 +27,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// the value
public short ReadInt16()
{
- return this.converter.ToInt16(this.data, this.AddIndex(2));
+ return BinaryPrimitives.ReadInt16BigEndian(new Span(this.data, this.AddIndex(2), 2));
}
///
@@ -35,7 +36,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// the value
public uint ReadUInt32()
{
- return this.converter.ToUInt32(this.data, this.AddIndex(4));
+ return BinaryPrimitives.ReadUInt32BigEndian(new Span(this.data, this.AddIndex(4), 4));
}
///
@@ -44,7 +45,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// the value
public int ReadInt32()
{
- return this.converter.ToInt32(this.data, this.AddIndex(4));
+ return BinaryPrimitives.ReadInt32BigEndian(new Span(this.data, this.AddIndex(4), 4));
}
///
@@ -53,7 +54,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// the value
public ulong ReadUInt64()
{
- return this.converter.ToUInt64(this.data, this.AddIndex(8));
+ return BinaryPrimitives.ReadUInt64BigEndian(new Span(this.data, this.AddIndex(8), 8));
}
///
@@ -62,25 +63,29 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// the value
public long ReadInt64()
{
- return this.converter.ToInt64(this.data, this.AddIndex(8));
+ return BinaryPrimitives.ReadInt64BigEndian(new Span(this.data, this.AddIndex(8), 8));
}
///
/// Reads a float
///
/// the value
- public float ReadSingle()
+ public unsafe float ReadSingle()
{
- return this.converter.ToSingle(this.data, this.AddIndex(4));
+ int intValue = this.ReadInt32();
+
+ return *((float*)&intValue);
}
///
/// Reads a double
///
/// the value
- public double ReadDouble()
+ public unsafe double ReadDouble()
{
- return this.converter.ToDouble(this.data, this.AddIndex(8));
+ long intValue = this.ReadInt64();
+
+ return *((double*)&intValue);
}
///
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs
index 1fecd761a6..c4a6a9039a 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs
@@ -3,7 +3,6 @@
using System;
using System.Text;
-using SixLabors.ImageSharp.IO;
namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
@@ -20,11 +19,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
private readonly byte[] data;
- ///
- /// The bit converter
- ///
- private readonly EndianBitConverter converter = new BigEndianBitConverter();
-
///
/// The current reading position
///
diff --git a/src/ImageSharp/PixelAccessor{TPixel}.cs b/src/ImageSharp/PixelAccessor{TPixel}.cs
index 63e4c015c1..1e789f0a68 100644
--- a/src/ImageSharp/PixelAccessor{TPixel}.cs
+++ b/src/ImageSharp/PixelAccessor{TPixel}.cs
@@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp
/// The target pixel buffer accessor.
internal void CopyTo(PixelAccessor target)
{
- SpanHelper.Copy(this.PixelBuffer.Span, target.PixelBuffer.Span);
+ this.PixelBuffer.Span.CopyTo(target.PixelBuffer.Span);
}
///
diff --git a/src/ImageSharp/PixelFormats/Alpha8.cs b/src/ImageSharp/PixelFormats/Alpha8.cs
index c266035a6b..57e2e984be 100644
--- a/src/ImageSharp/PixelFormats/Alpha8.cs
+++ b/src/ImageSharp/PixelFormats/Alpha8.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Packed pixel type containing a single 8 bit normalized W values.
///
- /// Ranges from <0, 0, 0, 0> to <0, 0, 0, 1> in vector form.
+ /// Ranges from [0, 0, 0, 0] to [0, 0, 0, 1] in vector form.
///
///
public struct Alpha8 : IPixel, IPackedVector
@@ -62,6 +62,20 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ return this.ToVector4();
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
@@ -124,7 +138,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// True if the object is equal to the packed vector.
public override bool Equals(object obj)
{
- return (obj is Alpha8) && this.Equals((Alpha8)obj);
+ return obj is Alpha8 other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/PixelFormats/Argb32.cs b/src/ImageSharp/PixelFormats/Argb32.cs
index 33294838e6..7030006f61 100644
--- a/src/ImageSharp/PixelFormats/Argb32.cs
+++ b/src/ImageSharp/PixelFormats/Argb32.cs
@@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255.
/// The color components are stored in alpha, red, green, and blue order.
///
- /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form.
+ /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form.
///
///
///
@@ -237,6 +237,20 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ return this.ToVector4();
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
@@ -321,7 +335,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(float x, float y, float z, float w)
{
- Vector4 value = new Vector4(x, y, z, w);
+ var value = new Vector4(x, y, z, w);
return Pack(ref value);
}
@@ -347,7 +361,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(ref Vector3 vector)
{
- Vector4 value = new Vector4(vector, 1);
+ var value = new Vector4(vector, 1);
return Pack(ref value);
}
diff --git a/src/ImageSharp/PixelFormats/Bgr24.cs b/src/ImageSharp/PixelFormats/Bgr24.cs
index e210856b36..61b447b882 100644
--- a/src/ImageSharp/PixelFormats/Bgr24.cs
+++ b/src/ImageSharp/PixelFormats/Bgr24.cs
@@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -11,6 +10,9 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Pixel type containing three 8-bit unsigned normalized values ranging from 0 to 255.
/// The color components are stored in blue, green, red order.
+ ///
+ /// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form.
+ ///
///
[StructLayout(LayoutKind.Sequential)]
public struct Bgr24 : IPixel
@@ -57,7 +59,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public override bool Equals(object obj)
{
- return obj?.GetType() == typeof(Bgr24) && this.Equals((Bgr24)obj);
+ return obj is Bgr24 other && this.Equals(other);
}
///
@@ -80,6 +82,20 @@ namespace SixLabors.ImageSharp.PixelFormats
this = source.Bgr;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ return this.ToVector4();
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
diff --git a/src/ImageSharp/PixelFormats/Bgr565.cs b/src/ImageSharp/PixelFormats/Bgr565.cs
index b4e7aad583..54e29e21e6 100644
--- a/src/ImageSharp/PixelFormats/Bgr565.cs
+++ b/src/ImageSharp/PixelFormats/Bgr565.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Packed pixel type containing unsigned normalized values ranging from 0 to 1. The x and z components use 5 bits, and the y component uses 6 bits.
///
- /// Ranges from <0, 0, 0, 1> to <1, 1, 1, 1> in vector form.
+ /// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form.
///
///
public struct Bgr565 : IPixel, IPackedVector
@@ -85,6 +85,20 @@ namespace SixLabors.ImageSharp.PixelFormats
(this.PackedValue & 0x1F) * (1F / 31F));
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ return this.ToVector4();
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
diff --git a/src/ImageSharp/PixelFormats/Bgra32.cs b/src/ImageSharp/PixelFormats/Bgra32.cs
index e8469414d3..ad5efa2578 100644
--- a/src/ImageSharp/PixelFormats/Bgra32.cs
+++ b/src/ImageSharp/PixelFormats/Bgra32.cs
@@ -11,6 +11,9 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255.
/// The color components are stored in blue, green, red, and alpha order.
+ ///
+ /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form.
+ ///
///
[StructLayout(LayoutKind.Sequential)]
public struct Bgra32 : IPixel, IPackedVector
@@ -101,7 +104,7 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- public override bool Equals(object obj) => obj?.GetType() == typeof(Bgra32) && this.Equals((Bgra32)obj);
+ public override bool Equals(object obj) => obj is Bgra32 other && this.Equals(other);
///
public override int GetHashCode()
@@ -116,6 +119,20 @@ namespace SixLabors.ImageSharp.PixelFormats
}
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ return this.ToVector4();
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
diff --git a/src/ImageSharp/PixelFormats/Bgra4444.cs b/src/ImageSharp/PixelFormats/Bgra4444.cs
index c51a872d1a..0f52d00687 100644
--- a/src/ImageSharp/PixelFormats/Bgra4444.cs
+++ b/src/ImageSharp/PixelFormats/Bgra4444.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Packed pixel type containing unsigned normalized values, ranging from 0 to 1, using 4 bits each for x, y, z, and w.
///
- /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form.
+ /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form.
///
///
public struct Bgra4444 : IPixel, IPackedVector
@@ -70,6 +70,20 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ return this.ToVector4();
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
@@ -142,7 +156,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public override bool Equals(object obj)
{
- return (obj is Bgra4444) && this.Equals((Bgra4444)obj);
+ return obj is Bgra4444 other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/PixelFormats/Bgra5551.cs b/src/ImageSharp/PixelFormats/Bgra5551.cs
index 8be4ce82c9..d24bab848e 100644
--- a/src/ImageSharp/PixelFormats/Bgra5551.cs
+++ b/src/ImageSharp/PixelFormats/Bgra5551.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Packed pixel type containing unsigned normalized values ranging from 0 to 1. The x , y and z components use 5 bits, and the w component uses 1 bit.
///
- /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form.
+ /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form.
///
///
public struct Bgra5551 : IPixel, IPackedVector
@@ -72,6 +72,20 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ return this.ToVector4();
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
@@ -101,7 +115,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -111,7 +125,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -122,7 +136,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -132,7 +146,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -142,7 +156,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public override bool Equals(object obj)
{
- return (obj is Bgra5551) && this.Equals((Bgra5551)obj);
+ return obj is Bgra5551 other && this.Equals(other);
}
///
@@ -190,6 +204,6 @@ namespace SixLabors.ImageSharp.PixelFormats
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private Vector4 ToScaledVector4() => this.ToVector4() * 255f;
+ private Vector4 ToByteScaledVector4() => this.ToVector4() * 255f;
}
}
diff --git a/src/ImageSharp/PixelFormats/Byte4.cs b/src/ImageSharp/PixelFormats/Byte4.cs
index 829937c8ad..d7aae5df9a 100644
--- a/src/ImageSharp/PixelFormats/Byte4.cs
+++ b/src/ImageSharp/PixelFormats/Byte4.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Packed pixel type containing four 8-bit unsigned integer values, ranging from 0 to 255.
///
- /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form.
+ /// Ranges from [0, 0, 0, 0] to [255, 255, 255, 255] in vector form.
///
///
public struct Byte4 : IPixel, IPackedVector
@@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The w-component
public Byte4(float x, float y, float z, float w)
{
- Vector4 vector = new Vector4(x, y, z, w);
+ var vector = new Vector4(x, y, z, w);
this.PackedValue = Pack(ref vector);
}
@@ -73,6 +73,20 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ this.PackFromVector4(vector * 255F);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ return this.ToVector4() / 255F;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
@@ -95,14 +109,14 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
- this.PackFromVector4(source.ToUnscaledVector4());
+ this.PackFromVector4(source.ToByteScaledVector4());
}
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
- Vector4 vector = this.ToVector4();
+ var vector = this.ToVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -112,7 +126,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
- Vector4 vector = this.ToVector4();
+ var vector = this.ToVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -123,7 +137,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
- Vector4 vector = this.ToVector4();
+ var vector = this.ToVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -133,7 +147,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
- Vector4 vector = this.ToVector4();
+ var vector = this.ToVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
diff --git a/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs b/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs
index c646d804ac..184928d0e4 100644
--- a/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs
+++ b/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs
@@ -32,8 +32,8 @@ namespace SixLabors.ImageSharp.PixelFormats
throw new ArgumentException("Hexadecimal string is not in the correct format.", nameof(hex));
}
- TPixel result = default(TPixel);
- Rgba32 rgba = new Rgba32(
+ TPixel result = default;
+ var rgba = new Rgba32(
(byte)(packedValue >> 24),
(byte)(packedValue >> 16),
(byte)(packedValue >> 8),
@@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// Returns a that represents the color defined by the provided RGBA values.
public static TPixel FromRGBA(byte red, byte green, byte blue, byte alpha)
{
- TPixel color = default(TPixel);
+ TPixel color = default;
color.PackFromRgba32(new Rgba32(red, green, blue, alpha));
return color;
}
diff --git a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs
index 9505ee6cf7..c8fe5ab88e 100644
--- a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs
+++ b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The source of data.
/// The to the destination pixels.
/// The number of pixels to convert.
- internal virtual void PackFromRgba32(Span source, Span destPixels, int count)
+ internal virtual void PackFromRgba32(ReadOnlySpan source, Span destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
@@ -35,14 +35,14 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- /// A helper for that expects a byte span.
+ /// A helper for that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with layout.
///
- /// The to the source bytes.
+ /// The to the source bytes.
/// The to the destination pixels.
/// The number of pixels to convert.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void PackFromRgba32Bytes(Span sourceBytes, Span destPixels, int count)
+ internal void PackFromRgba32Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count)
{
this.PackFromRgba32(sourceBytes.NonPortableCast(), destPixels, count);
}
@@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The span of source pixels
/// The destination span of data.
/// The number of pixels to convert.
- internal virtual void ToRgba32(Span sourcePixels, Span dest, int count)
+ internal virtual void ToRgba32(ReadOnlySpan sourcePixels, Span dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
@@ -70,14 +70,14 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- /// A helper for that expects a byte span as destination.
+ /// A helper for that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with layout.
///
/// The to the source colors.
/// The to the destination bytes.
/// The number of pixels to convert.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void ToRgba32Bytes(Span sourceColors, Span destBytes, int count)
+ internal void ToRgba32Bytes(ReadOnlySpan sourceColors, Span destBytes, int count)
{
this.ToRgba32(sourceColors, destBytes.NonPortableCast(), count);
}
@@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The source of data.
/// The to the destination pixels.
/// The number of pixels to convert.
- internal virtual void PackFromBgra32(Span source, Span destPixels, int count)
+ internal virtual void PackFromBgra32(ReadOnlySpan source, Span destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
@@ -106,14 +106,14 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- /// A helper for that expects a byte span.
+ /// A helper for that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with layout.
///
- /// The to the source bytes.
+ /// The to the source bytes.
/// The to the destination pixels.
/// The number of pixels to convert.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void PackFromBgra32Bytes(Span sourceBytes, Span destPixels, int count)
+ internal void PackFromBgra32Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count)
{
this.PackFromBgra32(sourceBytes.NonPortableCast(), destPixels, count);
}
@@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The span of source pixels
/// The destination span of data.
/// The number of pixels to convert.
- internal virtual void ToBgra32(Span sourcePixels, Span dest, int count)
+ internal virtual void ToBgra32(ReadOnlySpan sourcePixels, Span dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
@@ -141,14 +141,14 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- /// A helper for that expects a byte span as destination.
+ /// A helper for that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with layout.
///
/// The to the source colors.
/// The to the destination bytes.
/// The number of pixels to convert.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void ToBgra32Bytes(Span sourceColors, Span destBytes, int count)
+ internal void ToBgra32Bytes(ReadOnlySpan sourceColors, Span destBytes, int count)
{
this.ToBgra32(sourceColors, destBytes.NonPortableCast(), count);
}
@@ -159,7 +159,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The source of data.
/// The to the destination pixels.
/// The number of pixels to convert.
- internal virtual void PackFromRgb24(Span source, Span destPixels, int count)
+ internal virtual void PackFromRgb24(ReadOnlySpan source, Span destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
@@ -177,14 +177,14 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- /// A helper for that expects a byte span.
+ /// A helper for that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with layout.
///
- /// The to the source bytes.
+ /// The to the source bytes.
/// The to the destination pixels.
/// The number of pixels to convert.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void PackFromRgb24Bytes(Span sourceBytes, Span destPixels, int count)
+ internal void PackFromRgb24Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count)
{
this.PackFromRgb24(sourceBytes.NonPortableCast(), destPixels, count);
}
@@ -196,7 +196,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The span of source pixels
/// The destination span of data.
/// The number of pixels to convert.
- internal virtual void ToRgb24(Span sourcePixels, Span dest, int count)
+ internal virtual void ToRgb24(ReadOnlySpan sourcePixels, Span dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
@@ -212,14 +212,14 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- /// A helper for that expects a byte span as destination.
+ /// A helper for that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with layout.
///
/// The to the source colors.
/// The to the destination bytes.
/// The number of pixels to convert.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void ToRgb24Bytes(Span sourceColors, Span destBytes, int count)
+ internal void ToRgb24Bytes(ReadOnlySpan sourceColors, Span destBytes, int count)
{
this.ToRgb24(sourceColors, destBytes.NonPortableCast(), count);
}
@@ -230,7 +230,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The source of data.
/// The to the destination pixels.
/// The number of pixels to convert.
- internal virtual void PackFromBgr24(Span source, Span destPixels, int count)
+ internal virtual void PackFromBgr24(ReadOnlySpan source, Span destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
@@ -248,14 +248,14 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- /// A helper for that expects a byte span.
+ /// A helper for that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with layout.
///
- /// The to the source bytes.
+ /// The to the source bytes.
/// The to the destination pixels.
/// The number of pixels to convert.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void PackFromBgr24Bytes(Span sourceBytes, Span destPixels, int count)
+ internal void PackFromBgr24Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count)
{
this.PackFromBgr24(sourceBytes.NonPortableCast(), destPixels, count);
}
@@ -267,7 +267,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The span of source pixels
/// The destination span of data.
/// The number of pixels to convert.
- internal virtual void ToBgr24(Span sourcePixels, Span dest, int count)
+ internal virtual void ToBgr24(ReadOnlySpan sourcePixels, Span dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
@@ -283,14 +283,14 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- /// A helper for that expects a byte span as destination.
+ /// A helper for that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with layout.
///
/// The to the source colors.
/// The to the destination bytes.
/// The number of pixels to convert.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void ToBgr24Bytes(Span sourceColors, Span destBytes, int count)
+ internal void ToBgr24Bytes(ReadOnlySpan sourceColors, Span destBytes, int count)
{
this.ToBgr24(sourceColors, destBytes.NonPortableCast(), count);
}
diff --git a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt
index 365f5cb514..d0a05677f9 100644
--- a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt
+++ b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt
@@ -21,7 +21,7 @@
/// The span of source pixels
/// The destination span of data.
/// The number of pixels to convert.
- internal virtual void To<#=pixelType#>(Span sourcePixels, Span<<#=pixelType#>> dest, int count)
+ internal virtual void To<#=pixelType#>(ReadOnlySpan sourcePixels, Span<<#=pixelType#>> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
@@ -37,14 +37,14 @@
}
///
- /// A helper for that expects a byte span as destination.
+ /// A helper for that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with layout.
///
/// The to the source colors.
/// The to the destination bytes.
/// The number of pixels to convert.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void To<#=pixelType#>Bytes(Span sourceColors, Span destBytes, int count)
+ internal void To<#=pixelType#>Bytes(ReadOnlySpan sourceColors, Span destBytes, int count)
{
this.To<#=pixelType#>(sourceColors, destBytes.NonPortableCast>(), count);
}
@@ -61,7 +61,7 @@
/// The source of data.
/// The to the destination pixels.
/// The number of pixels to convert.
- internal virtual void PackFrom<#=pixelType#>(Span<<#=pixelType#>> source, Span destPixels, int count)
+ internal virtual void PackFrom<#=pixelType#>(ReadOnlySpan<<#=pixelType#>> source, Span destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
@@ -79,14 +79,14 @@
}
///
- /// A helper for that expects a byte span.
+ /// A helper for that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with layout.
///
- /// The to the source bytes.
+ /// The to the source bytes.
/// The to the destination pixels.
/// The number of pixels to convert.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void PackFrom<#=pixelType#>Bytes(Span sourceBytes, Span destPixels, int count)
+ internal void PackFrom<#=pixelType#>Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count)
{
this.PackFrom<#=pixelType#>(sourceBytes.NonPortableCast>(), destPixels, count);
}
diff --git a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs
index c5ee6661f7..a8e68e36db 100644
--- a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs
+++ b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
///
- internal override void PackFromRgb24(Span source, Span destPixels, int count)
+ internal override void PackFromRgb24(ReadOnlySpan source, Span destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
@@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- internal override void ToRgb24(Span sourcePixels, Span dest, int count)
+ internal override void ToRgb24(ReadOnlySpan sourcePixels, Span dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
@@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- internal override void PackFromBgr24(Span source, Span destPixels, int count)
+ internal override void PackFromBgr24(ReadOnlySpan source, Span destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
@@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- internal override void ToBgr24(Span sourcePixels, Span dest, int count)
+ internal override void ToBgr24(ReadOnlySpan sourcePixels, Span dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
@@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- internal override void PackFromBgra32(Span source, Span destPixels, int count)
+ internal override void PackFromBgra32(ReadOnlySpan source, Span destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
@@ -97,7 +97,7 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- internal override void ToBgra32(Span sourcePixels, Span dest, int count)
+ internal override void ToBgra32(ReadOnlySpan sourcePixels, Span dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
diff --git a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt
index 9dfec2cf90..4a88bbad7a 100644
--- a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt
+++ b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt
@@ -14,7 +14,7 @@
#>
///
- internal override void PackFrom<#=pixelType#>(Span<<#=pixelType#>> source, Span destPixels, int count)
+ internal override void PackFrom<#=pixelType#>(ReadOnlySpan<<#=pixelType#>> source, Span destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
@@ -36,7 +36,7 @@
#>
///
- internal override void To<#=pixelType#>(Span sourcePixels, Span<<#=pixelType#>> dest, int count)
+ internal override void To<#=pixelType#>(ReadOnlySpan sourcePixels, Span<<#=pixelType#>> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
diff --git a/src/ImageSharp/PixelFormats/HalfSingle.cs b/src/ImageSharp/PixelFormats/HalfSingle.cs
index b4bc491ebd..0569b796d4 100644
--- a/src/ImageSharp/PixelFormats/HalfSingle.cs
+++ b/src/ImageSharp/PixelFormats/HalfSingle.cs
@@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
using System.Numerics;
using System.Runtime.CompilerServices;
@@ -10,7 +9,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Packed pixel type containing a single 16 bit floating point value.
///
- /// Ranges from <0, 0, 0, 1> to <1, 0, 0, 1> in vector form.
+ /// Ranges from [-1, 0, 0, 1] to [1, 0, 0, 1] in vector form.
///
///
public struct HalfSingle : IPixel, IPackedVector
@@ -86,6 +85,25 @@ namespace SixLabors.ImageSharp.PixelFormats
return HalfTypeHelper.Unpack(this.PackedValue);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ float scaled = vector.X;
+ scaled *= 2F;
+ scaled -= 1F;
+ this.PackedValue = HalfTypeHelper.Pack(scaled);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ float single = this.ToSingle() + 1F;
+ single /= 2F;
+ return new Vector4(single, 0, 0, 1);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
@@ -111,7 +129,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -121,7 +139,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -132,7 +150,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -142,7 +160,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -176,7 +194,7 @@ namespace SixLabors.ImageSharp.PixelFormats
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private Vector4 ToScaledVector4()
+ private Vector4 ToByteScaledVector4()
{
var vector = this.ToVector4();
vector *= MaxBytes;
diff --git a/src/ImageSharp/PixelFormats/HalfTypeHelper.cs b/src/ImageSharp/PixelFormats/HalfTypeHelper.cs
index 4d6ef0fb40..cf8b9f4a23 100644
--- a/src/ImageSharp/PixelFormats/HalfTypeHelper.cs
+++ b/src/ImageSharp/PixelFormats/HalfTypeHelper.cs
@@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static ushort Pack(float value)
{
- Uif uif = new Uif { F = value };
+ var uif = new Uif { F = value };
return Pack(uif.I);
}
@@ -113,7 +113,7 @@ namespace SixLabors.ImageSharp.PixelFormats
result = ((((uint)value & 0x8000) << 16) | ((((((uint)value >> 10) & 0x1f) - 15) + 127) << 23)) | (mantissa << 13);
}
- Uif uif = new Uif { U = result };
+ var uif = new Uif { U = result };
return uif.F;
}
diff --git a/src/ImageSharp/PixelFormats/HalfVector2.cs b/src/ImageSharp/PixelFormats/HalfVector2.cs
index aa5f321908..b26ae95983 100644
--- a/src/ImageSharp/PixelFormats/HalfVector2.cs
+++ b/src/ImageSharp/PixelFormats/HalfVector2.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Packed pixel type containing two 16-bit floating-point values.
///
- /// Ranges from <0, 0, 0, 1> to <1, 0, 0, 1> in vector form.
+ /// Ranges from [-1, -1, 0, 1] to [1, 1, 0, 1] in vector form.
///
///
public struct HalfVector2 : IPixel, IPackedVector
@@ -99,6 +99,25 @@ namespace SixLabors.ImageSharp.PixelFormats
return vector;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ Vector2 scaled = new Vector2(vector.X, vector.Y) * 2F;
+ scaled -= Vector2.One;
+ this.PackedValue = Pack(scaled.X, scaled.Y);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ var scaled = this.ToVector2();
+ scaled += Vector2.One;
+ scaled /= 2F;
+ return new Vector4(scaled, 0F, 1F);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
@@ -110,7 +129,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
- Vector2 vector = this.ToVector2();
+ var vector = this.ToVector2();
return new Vector4(vector.X, vector.Y, 0F, 1F);
}
@@ -125,7 +144,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
@@ -135,7 +154,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
@@ -146,7 +165,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
@@ -156,7 +175,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
@@ -204,9 +223,9 @@ namespace SixLabors.ImageSharp.PixelFormats
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private Vector4 ToScaledVector4()
+ private Vector4 ToByteScaledVector4()
{
- Vector4 vector = this.ToVector4();
+ var vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
diff --git a/src/ImageSharp/PixelFormats/HalfVector4.cs b/src/ImageSharp/PixelFormats/HalfVector4.cs
index 87a1c9a498..c92de4ef13 100644
--- a/src/ImageSharp/PixelFormats/HalfVector4.cs
+++ b/src/ImageSharp/PixelFormats/HalfVector4.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Packed pixel type containing four 16-bit floating-point values.
///
- /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form.
+ /// Ranges from [-1, -1, -1, -1] to [1, 1, 1, 1] in vector form.
///
///
public struct HalfVector4 : IPixel, IPackedVector
@@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The w-component.
public HalfVector4(float x, float y, float z, float w)
{
- Vector4 vector = new Vector4(x, y, z, w);
+ var vector = new Vector4(x, y, z, w);
this.PackedValue = Pack(ref vector);
}
@@ -89,6 +89,25 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ vector *= 2F;
+ vector -= Vector4.One;
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ var scaled = this.ToVector4();
+ scaled += Vector4.One;
+ scaled /= 2F;
+ return scaled;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
@@ -118,7 +137,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -128,7 +147,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -139,7 +158,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -149,7 +168,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -172,7 +191,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public override bool Equals(object obj)
{
- return (obj is HalfVector4) && this.Equals((HalfVector4)obj);
+ return obj is HalfVector4 other && this.Equals(other);
}
///
@@ -198,9 +217,9 @@ namespace SixLabors.ImageSharp.PixelFormats
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private Vector4 ToScaledVector4()
+ private Vector4 ToByteScaledVector4()
{
- Vector4 vector = this.ToVector4();
+ var vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
diff --git a/src/ImageSharp/PixelFormats/IPixel.cs b/src/ImageSharp/PixelFormats/IPixel.cs
index 37c505c848..954e14cc09 100644
--- a/src/ImageSharp/PixelFormats/IPixel.cs
+++ b/src/ImageSharp/PixelFormats/IPixel.cs
@@ -32,6 +32,20 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The vector to create the packed representation from.
void PackFromVector4(Vector4 vector);
+ ///
+ /// Sets the packed representation from a scaled .
+ ///
+ /// The vector to create the packed representation from.
+ void PackFromScaledVector4(Vector4 vector);
+
+ ///
+ /// Expands the packed representation into a scaled
+ /// with values clamped between 0 and 1.
+ /// The vector components are typically expanded in least to greatest significance order.
+ ///
+ /// The .
+ Vector4 ToScaledVector4();
+
///
/// Expands the packed representation into a .
/// The vector components are typically expanded in least to greatest significance order.
diff --git a/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs b/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs
index 6a2902f9b1..e27bde8822 100644
--- a/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs
+++ b/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs
@@ -735,7 +735,7 @@ namespace SixLabors.ImageSharp.PixelFormats
private static TPixel[] GetWebSafePalette()
{
Rgba32[] constants = ColorConstants.WebSafeColors;
- TPixel[] safe = new TPixel[constants.Length + 1];
+ var safe = new TPixel[constants.Length + 1];
Span constantsBytes = constants.AsSpan().NonPortableCast();
PixelOperations.Instance.PackFromRgba32Bytes(constantsBytes, safe, constants.Length);
diff --git a/src/ImageSharp/PixelFormats/NormalizedByte2.cs b/src/ImageSharp/PixelFormats/NormalizedByte2.cs
index 9a69f6ab36..9bac828560 100644
--- a/src/ImageSharp/PixelFormats/NormalizedByte2.cs
+++ b/src/ImageSharp/PixelFormats/NormalizedByte2.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Packed packed pixel type containing two 8-bit signed normalized values, ranging from −1 to 1.
///
- /// Ranges from <-1, -1, 0, 1> to <1, 1, 0, 1> in vector form.
+ /// Ranges from [-1, -1, 0, 1] to [1, 1, 0, 1] in vector form.
///
///
public struct NormalizedByte2 : IPixel, IPackedVector
@@ -104,6 +104,25 @@ namespace SixLabors.ImageSharp.PixelFormats
(sbyte)((this.PackedValue >> 8) & 0xFF) / 127F);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ Vector2 scaled = new Vector2(vector.X, vector.Y) * 2F;
+ scaled -= Vector2.One;
+ this.PackedValue = Pack(scaled.X, scaled.Y);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ var scaled = this.ToVector2();
+ scaled += Vector2.One;
+ scaled /= 2F;
+ return new Vector4(scaled, 0F, 1F);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
@@ -122,7 +141,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
- Vector4 vector = source.ToUnscaledVector4();
+ Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
@@ -134,7 +153,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
@@ -144,7 +163,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
@@ -155,7 +174,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
@@ -165,7 +184,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
@@ -175,7 +194,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public override bool Equals(object obj)
{
- return (obj is NormalizedByte2) && this.Equals((NormalizedByte2)obj);
+ return obj is NormalizedByte2 other && this.Equals(other);
}
///
@@ -214,9 +233,9 @@ namespace SixLabors.ImageSharp.PixelFormats
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private Vector4 ToScaledVector4()
+ private Vector4 ToByteScaledVector4()
{
- Vector4 vector = this.ToVector4();
+ var vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
diff --git a/src/ImageSharp/PixelFormats/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/NormalizedByte4.cs
index 920f92cae7..a3aa60fd21 100644
--- a/src/ImageSharp/PixelFormats/NormalizedByte4.cs
+++ b/src/ImageSharp/PixelFormats/NormalizedByte4.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Packed pixel type containing four 8-bit signed normalized values, ranging from −1 to 1.
///
- /// Ranges from <-1, -1, -1, -1> to <1, 1, 1, 1> in vector form.
+ /// Ranges from [-1, -1, -1, -1] to [1, 1, 1, 1] in vector form.
///
///
public struct NormalizedByte4 : IPixel, IPackedVector
@@ -93,6 +93,25 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ vector *= 2F;
+ vector -= Vector4.One;
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ var scaled = this.ToVector4();
+ scaled += Vector4.One;
+ scaled /= 2F;
+ return scaled;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
@@ -115,7 +134,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
- Vector4 vector = source.ToUnscaledVector4();
+ Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
@@ -127,7 +146,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -137,7 +156,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -148,7 +167,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -158,7 +177,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
@@ -168,7 +187,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public override bool Equals(object obj)
{
- return (obj is NormalizedByte4) && this.Equals((NormalizedByte4)obj);
+ return obj is NormalizedByte4 other && this.Equals(other);
}
///
@@ -211,9 +230,9 @@ namespace SixLabors.ImageSharp.PixelFormats
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private Vector4 ToScaledVector4()
+ private Vector4 ToByteScaledVector4()
{
- Vector4 vector = this.ToVector4();
+ var vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
diff --git a/src/ImageSharp/PixelFormats/NormalizedShort2.cs b/src/ImageSharp/PixelFormats/NormalizedShort2.cs
index 6d28f61c25..afea6aaad8 100644
--- a/src/ImageSharp/PixelFormats/NormalizedShort2.cs
+++ b/src/ImageSharp/PixelFormats/NormalizedShort2.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Packed pixel type containing two 16-bit signed normalized values, ranging from −1 to 1.
///
- /// Ranges from <-1, -1, 0, 1> to <1, 1, 0, 1> in vector form.
+ /// Ranges from [-1, -1, 0, 1] to [1, 1, 0, 1] in vector form.
///
///
public struct NormalizedShort2 : IPixel, IPackedVector
@@ -91,6 +91,25 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ Vector2 scaled = new Vector2(vector.X, vector.Y) * 2F;
+ scaled -= Vector2.One;
+ this.PackedValue = Pack(scaled.X, scaled.Y);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ var scaled = this.ToVector2();
+ scaled += Vector2.One;
+ scaled /= 2F;
+ return new Vector4(scaled, 0F, 1F);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
@@ -109,7 +128,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
- Vector4 vector = source.ToUnscaledVector4();
+ Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
@@ -121,7 +140,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
@@ -131,7 +150,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
@@ -142,7 +161,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
@@ -152,7 +171,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
@@ -221,9 +240,9 @@ namespace SixLabors.ImageSharp.PixelFormats
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private Vector4 ToScaledVector4()
+ private Vector4 ToByteScaledVector4()
{
- Vector4 vector = this.ToVector4();
+ var vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
diff --git a/src/ImageSharp/PixelFormats/NormalizedShort4.cs b/src/ImageSharp/PixelFormats/NormalizedShort4.cs
index 45f984da0b..87c92cb73b 100644
--- a/src/ImageSharp/PixelFormats/NormalizedShort4.cs
+++ b/src/ImageSharp/PixelFormats/NormalizedShort4.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// Packed pixel type containing four 16-bit signed normalized values, ranging from −1 to 1.
///
- /// Ranges from <-1, -1, -1, -1> to <1, 1, 1, 1> in vector form.
+ /// Ranges from [-1, -1, -1, -1] to [1, 1, 1, 1] in vector form.
///
///
public struct NormalizedShort4 : IPixel, IPackedVector
@@ -93,6 +93,25 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromScaledVector4(Vector4 vector)
+ {
+ vector *= 2F;
+ vector -= Vector4.One;
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector4 ToScaledVector4()
+ {
+ var scaled = this.ToVector4();
+ scaled += Vector4.One;
+ scaled /= 2F;
+ return scaled;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
@@ -117,7 +136,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
- Vector4 vector = source.ToUnscaledVector4();
+ Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
@@ -129,7 +148,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
@@ -139,7 +158,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
@@ -150,7 +169,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
@@ -160,7 +179,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
- Vector4 vector = this.ToScaledVector4();
+ Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
@@ -170,7 +189,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
public override bool Equals(object obj)
{
- return (obj is NormalizedShort4) && this.Equals((NormalizedShort4)obj);
+ return obj is NormalizedShort4 other && this.Equals(other);
}
///
@@ -217,9 +236,9 @@ namespace SixLabors.ImageSharp.PixelFormats
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private Vector4 ToScaledVector4()
+ private Vector4 ToByteScaledVector4()
{
- Vector4 vector = this.ToVector4();
+ var vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
diff --git a/src/ImageSharp/PixelFormats/PackedPixelConverterHelper.cs b/src/ImageSharp/PixelFormats/PackedPixelConverterHelper.cs
deleted file mode 100644
index ae5f785a96..0000000000
--- a/src/ImageSharp/PixelFormats/PackedPixelConverterHelper.cs
+++ /dev/null
@@ -1,365 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Numerics;
-
-namespace SixLabors.ImageSharp.PixelFormats
-{
- ///
- /// Assists with the conversion of known packed pixel formats from one to another.
- ///
- internal static class PackedPixelConverterHelper
- {
- ///
- /// A non operative function. Simply returns the original vector.
- ///
- private static readonly Func Noop = vector4 => vector4;
-
- ///
- /// Returns the correct scaling function for the given types The compute scale function.
- ///
- /// The source pixel format.
- /// The target pixel format.
- /// The
- public static Func ComputeScaleFunction()
- {
- Type source = typeof(TPixel);
- Type target = typeof(TPixel2);
-
- // Normalized standard
- if (IsStandardNormalizedType(source))
- {
- return FromStandardNormalizedType(target);
- }
-
- // Standard
- if (IsStandardType(source))
- {
- return FromStandardType(target);
- }
-
- // Normalized offsets. All four components.
- if (IsOffsetNormalizedType(source))
- {
- return FromOffsetNormalizedType(target);
- }
-
- // Offset. All four components.
- if (IsOffsetType(source))
- {
- return FromOffsetType(target);
- }
-
- // Normalized offsets. First component pair only.
- if (IsOffsetTwoComponentNormalizedType(source))
- {
- return FromOffsetTwoComponentNormalizedType(target);
- }
-
- // Offsets. First component pair only.
- if (IsOffsetTwoComponentType(source))
- {
- return FromOffsetTwoComponentType(target);
- }
-
- return Noop;
- }
-
- ///
- /// Returns the correct conversion function to convert from types having vector values representing all four components
- /// ranging from 0 to 1.
- ///
- /// The target type
- /// The
- private static Func FromStandardNormalizedType(Type target)
- {
- if (IsStandardType(target))
- {
- return vector4 => 255F * vector4;
- }
-
- if (IsOffsetNormalizedType(target) || IsOffsetTwoComponentNormalizedType(target))
- {
- // Expand the range then offset the center down.
- return vector4 => (2F * vector4) - Vector4.One;
- }
-
- if (IsOffsetType(target) || IsOffsetTwoComponentType(target))
- {
- return vector4 => (65534F * vector4) - new Vector4(32767F);
- }
-
- return Noop;
- }
-
- ///
- /// Returns the correct conversion function to convert from types having vector values representing all four components
- /// ranging from 0 to 255.
- ///
- /// The target type
- /// The
- private static Func FromStandardType(Type target)
- {
- // Scale down
- if (IsStandardNormalizedType(target))
- {
- return vector4 => vector4 / 255F;
- }
-
- if (IsOffsetNormalizedType(target) || IsOffsetTwoComponentNormalizedType(target))
- {
- // Expand the range, divide, then offset the center down.
- return vector4 => ((2F * (vector4 / 255F)) - Vector4.One);
- }
-
- if (IsOffsetType(target) || IsOffsetTwoComponentType(target))
- {
- return vector4 => (65534F * (vector4 / 255F)) - new Vector4(32767F);
- }
-
- return Noop;
- }
-
- ///
- /// Returns the correct conversion function to convert from types having vector values representing all four components
- /// ranging from -1 to 1.
- ///
- /// The target type
- /// The
- private static Func FromOffsetNormalizedType(Type target)
- {
- if (IsStandardNormalizedType(target))
- {
- // Compress the range then offset the center up.
- return vector4 => (vector4 / 2F) + new Vector4(.5F);
- }
-
- if (IsStandardType(target))
- {
- // Compress the range, multiply, then offset the center up.
- return vector4 => ((vector4 / 2F) * 255F) + new Vector4(127.5F);
- }
-
- if (IsOffsetType(target) || IsOffsetTwoComponentType(target))
- {
- // Multiply out the range, two component won't read the last two values.
- return vector4 => (vector4 * 32767F);
- }
-
- return Noop;
- }
-
- ///
- /// Returns the correct conversion function to convert from types having vector values representing all four components
- /// ranging from -32767 to 32767.
- ///
- /// The target type
- /// The
- private static Func FromOffsetType(Type target)
- {
- if (IsStandardNormalizedType(target))
- {
- // Compress the range then offset the center up.
- return vector4 => (vector4 / 65534F) + new Vector4(.5F);
- }
-
- if (IsStandardType(target))
- {
- // Compress the range, multiply, then offset the center up.
- return vector4 => ((vector4 / 65534F) * 255F) + new Vector4(127.5F);
- }
-
- if (IsOffsetNormalizedType(target) || IsOffsetTwoComponentNormalizedType(target))
- {
- // Compress the range. Two component won't read the last two values.
- return vector4 => (vector4 / 32767F);
- }
-
- return Noop;
- }
-
- ///
- /// Returns the correct conversion function to convert from types having vector with the first component pair ranging from -1 to 1.
- /// and the second component pair ranging from 0 to 1.
- ///
- /// The target type
- /// The