diff --git a/.travis.yml b/.travis.yml index a4f68b1d1..70501a484 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ matrix: - os: linux # Ubuntu 14.04 dist: trusty sudo: required - dotnet: 1.0.1 + dotnet: 1.0.4 mono: latest # - os: osx # OSX 10.11 # osx_image: xcode7.3.1 diff --git a/appveyor.yml b/appveyor.yml index 5c548a71c..832120990 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,14 +4,10 @@ image: Visual Studio 2017 # prevent the double build when a branch has an active PR skip_branch_with_pr: true -install: - - choco install gitversion.portable -pre -y - before_build: - git submodule -q update --init - cmd: dotnet --version - - ps: c:\ProgramData\chocolatey\lib\gitversion.portable\tools\gitversion.exe /l console /output buildserver - + build_script: - cmd: build.cmd @@ -19,8 +15,8 @@ test_script: - tests\CodeCoverage\CodeCoverage.cmd after_test: - - cmd: appveyor PushArtifact "artifacts\SixLabors.ImageSharp.%GitVersion_NuGetVersion%.nupkg" - - cmd: appveyor PushArtifact "artifacts\SixLabors.ImageSharp.Drawing.%GitVersion_NuGetVersion%.nupkg" + - cmd: appveyor PushArtifact "artifacts\SixLabors.ImageSharp.%APPVEYOR_BUILD_VERSION%.nupkg" + - cmd: appveyor PushArtifact "artifacts\SixLabors.ImageSharp.Drawing.%APPVEYOR_BUILD_VERSION%.nupkg" deploy: # MyGet Deployment for builds & releases diff --git a/build.cmd b/build.cmd index 1ba1b3742..6372b4125 100644 --- a/build.cmd +++ b/build.cmd @@ -1,29 +1,7 @@ @echo Off -SET versionCommand= -if not "%GitVersion_NuGetVersion%" == "" ( - SET versionCommand=/p:packageversion=%GitVersion_NuGetVersion% - @echo building with version set to '%GitVersion_NuGetVersion%' -) +PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '.\build.ps1'" -dotnet restore %versionCommand% - -ECHO Building projects -dotnet build -c Release %versionCommand% - -if not "%errorlevel%"=="0" goto failure - -if not "%CI%" == "True" ( - ECHO NOT on CI server running tests - dotnet test ./tests/ImageSharp.Tests/ImageSharp.Tests.csproj --no-build -c Release -) -if not "%errorlevel%"=="0" goto failure - -ECHO Packaging projects -dotnet pack ./src/ImageSharp/ -c Release --output ../../artifacts --no-build %versionCommand% -if not "%errorlevel%"=="0" goto failure - -dotnet pack ./src/ImageSharp.Drawing/ -c Release --output ../../artifacts --no-build %versionCommand% if not "%errorlevel%"=="0" goto failure :success diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 000000000..2f4d1c949 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,113 @@ + +# lets calulat the correct version here +$fallbackVersion = "1.0.0"; +$version = '' + +$tagRegex = '^v?(\d+\.\d+\.\d+)(-([a-zA-Z]+)\.?(\d*))?$' + +# we are running on the build server +$isVersionTag = $env:APPVEYOR_REPO_TAG_NAME -match $tagRegex + + if($isVersionTag){ + + Write-Debug "Building commit tagged with a compatable version number" + + $version = $matches[1] + $postTag = $matches[3] + $count = $matches[4] + Write-Debug "version number: ${version} post tag: ${postTag} count: ${count}" + if("$postTag" -ne ""){ + $version = "${version}-${postTag}" + } + if("$count" -ne ""){ + # for consistancy with previous releases we pad the counter to only 4 places + $padded = $count.Trim().Trim('0').PadLeft(4,"0"); + Write-Debug "count '$count', padded '${padded}'" + + $version = "${version}${padded}" + } + }else { + + Write-Debug "Untagged" + $lastTag = (git tag --list --sort=-taggerdate) | Out-String + $list = $lastTag.Split("`n") + foreach ($tag in $list) { + + Write-Debug "testing ${tag}" + $tag = $tag.Trim(); + if($tag -match $tagRegex){ + Write-Debug "matched ${tag}" + $version = $matches[1]; + break; + } + } + + if("$version" -eq ""){ + $version = $fallbackVersion + Write-Debug "Failed to discover base version Fallback to '${version}'" + }else{ + + Write-Debug "Discovered base version from tags '${version}'" + } + + $buildNumber = $env:APPVEYOR_BUILD_NUMBER + + # build number replacement is padded to 6 places + $buildNumber = "$buildNumber".Trim().Trim('0').PadLeft(6,"0"); + if("$env:APPVEYOR_PULL_REQUEST_NUMBER" -ne ""){ + Write-Debug "building a PR" + + $prNumber = "$env:APPVEYOR_PULL_REQUEST_NUMBER".Trim().Trim('0').PadLeft(5,"0"); + # this is a PR + $version = "${version}-PullRequest${prNumber}${buildNumber}"; + }else{ + Write-Debug "building a branch commit" + + # this is a general branch commit + $branch = $env:APPVEYOR_REPO_BRANCH + + if("$branch" -eq ""){ + $branch = ((git rev-parse --abbrev-ref HEAD) | Out-String).Trim() + + if("$branch" -eq ""){ + $branch = "unknown" + } + } + + $branch = $branch.Replace("/","-").ToLower() + + if($branch.ToLower() -eq "master"){ + $branch = "dev" + } + + $version = "${version}-${branch}${buildNumber}"; + } + } + +if("$env:APPVEYOR_API_URL" -ne ""){ + # update appveyor build number for this build + Invoke-RestMethod -Method "PUT" ` + -Uri "${env:APPVEYOR_API_URL}api/build" ` + -Body "{version:'${version}'}" ` + -ContentType "application/json" +} + +Write-Host "Building version '${version}'" +dotnet restore /p:packageversion=$version + +Write-Host "Building projects" +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 +} +if ($LASTEXITCODE ){ Exit $LASTEXITCODE } + +Write-Host "Packaging projects" +dotnet pack ./src/ImageSharp/ -c Release --output ../../artifacts --no-build /p:packageversion=$version +if ($LASTEXITCODE ){ Exit $LASTEXITCODE } + +dotnet pack ./src/ImageSharp.Drawing/ -c Release --output ../../artifacts --no-build /p:packageversion=$version +if ($LASTEXITCODE ){ Exit $LASTEXITCODE } diff --git a/gitversion.yml b/gitversion.yml deleted file mode 100644 index 9fae0d8c2..000000000 --- a/gitversion.yml +++ /dev/null @@ -1,31 +0,0 @@ -# to create a new package you create a new release/tag -# in github appveyor will build it without the -cixxx tag -# it will then be deployable cleanly to nuget.org - -branches: - master: - tag: ci - mode: ContinuousDeployment - increment: Minor - prevent-increment-of-merged-branch-version: false - track-merge-target: true - pull-request: - regex: (pull|pull\-requests|pr)[/-] - mode: ContinuousDelivery - tag: PullRequest - increment: Inherit - prevent-increment-of-merged-branch-version: false - tag-number-pattern: '[/-](?\d+)[-/]' - track-merge-target: false - tracks-release-branches: false - is-release-branch: false - otherbranches: - regex: '.*' - mode: ContinuousDeployment - tag: ci - increment: Patch - prevent-increment-of-merged-branch-version: false - track-merge-target: true - is-release-branch: false -ignore: - sha: [] \ No newline at end of file diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 6045a9c6a..eb3c29dd9 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -1,54 +1,54 @@  - - An extension to ImageSharp that allows the drawing of images, paths, and text. - SixLabors.ImageSharp.Drawing - $(packageversion) - 0.0.1 - Six Labor and contributors - netstandard1.1 - true - true - 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://github.com/SixLabors/ImageSharp - http://www.apache.org/licenses/LICENSE-2.0 - git - https://github.com/SixLabors/ImageSharp - false - false - false - false - false - false - false - false - false - full - portable - True - - - - - - - - - - - - - - All - - - - ..\..\ImageSharp.ruleset - SixLabors.ImageSharp.Drawing - - - true - + + An extension to ImageSharp that allows the drawing of images, paths, and text. + SixLabors.ImageSharp.Drawing + $(packageversion) + 0.0.1 + SixLabors and contributors + netstandard1.1;netstandard2.0 + true + true + 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://github.com/SixLabors/ImageSharp + http://www.apache.org/licenses/LICENSE-2.0 + git + https://github.com/SixLabors/ImageSharp + false + false + false + false + false + false + false + false + false + full + portable + True + + + + + + + + + + + + + + All + + + + ..\..\ImageSharp.ruleset + SixLabors.ImageSharp.Drawing + + + true + \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs index d867008d7..b6ef4be21 100644 --- a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs +++ b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs @@ -82,8 +82,15 @@ namespace SixLabors.ImageSharp.Drawing.Processors int maxIntersections = region.MaxIntersections; float subpixelCount = 4; + + // we need to offset the pixel grid to account for when we outline a path. + // basically if the line is [1,2] => [3,2] then when outlining at 1 we end up with a region of [0.5,1.5],[1.5, 1.5],[3.5,2.5],[2.5,2.5] + // and this can cause missed fills when not using antialiasing.so we offset the pixel grid by 0.5 in the x & y direction thus causing the# + // region to alline with the pixel grid. + float offset = 0.5f; if (this.Options.Antialias) { + offset = 0f; // we are antialising skip offsetting as real antalising should take care of offset. subpixelCount = this.Options.AntialiasSubpixelDepth; if (subpixelCount < 4) { @@ -117,7 +124,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors float subpixelFractionPoint = subpixelFraction / subpixelCount; for (float subPixel = (float)y; subPixel < y + 1; subPixel += subpixelFraction) { - int pointsFound = region.Scan(subPixel, buffer, 0); + int pointsFound = region.Scan(subPixel + offset, buffer, 0); if (pointsFound == 0) { // nothing on this line skip @@ -131,8 +138,8 @@ namespace SixLabors.ImageSharp.Drawing.Processors // points will be paired up float scanStart = buffer[point] - minX; float scanEnd = buffer[point + 1] - minX; - int startX = (int)MathF.Floor(scanStart); - int endX = (int)MathF.Floor(scanEnd); + int startX = (int)MathF.Floor(scanStart + offset); + int endX = (int)MathF.Floor(scanEnd + offset); if (startX >= 0 && startX < scanline.Length) { @@ -169,7 +176,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors { for (int x = 0; x < scanlineWidth; x++) { - if (scanline[x] > 0.5) + if (scanline[x] >= 0.5) { scanline[x] = 1; } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs index 75689d997..0a5ae3627 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs @@ -1,8 +1,8 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; -using SixLabors.ImageSharp.ColorSpaces; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLabColorSapce { diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs index 33a8dc7c8..22308260c 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.ColorSpaces; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs index 3884d9480..35fae30e8 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.ColorSpaces; @@ -20,7 +21,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchColor // 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; - float hRadians = MathF.DegreeToRadian(hDegrees); + float hRadians = MathFExtensions.DegreeToRadian(hDegrees); float a = c * MathF.Cos(hRadians); float b = c * MathF.Sin(hRadians); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs index 50332ebdc..aa4614f9c 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.ColorSpaces; @@ -22,7 +23,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchColor float l = input.L, a = input.A, b = input.B; float c = MathF.Sqrt((a * a) + (b * b)); float hRadians = MathF.Atan2(b, a); - float hDegrees = MathF.RadianToDegree(hRadians); + float hDegrees = MathFExtensions.RadianToDegree(hRadians); // Wrap the angle round at 360. hDegrees = hDegrees % 360; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs index ceadb0195..fc6554a90 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.ColorSpaces; @@ -20,7 +21,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvCol // Conversion algorithm described here: // https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_.28CIELCH.29 float l = input.L, c = input.C, hDegrees = input.H; - float hRadians = MathF.DegreeToRadian(hDegrees); + float hRadians = MathFExtensions.DegreeToRadian(hDegrees); float u = c * MathF.Cos(hRadians); float v = c * MathF.Sin(hRadians); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs index d30151920..f0d7a80a2 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.ColorSpaces; @@ -22,7 +23,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvCol float l = input.L, a = input.U, b = input.V; float c = MathF.Sqrt((a * a) + (b * b)); float hRadians = MathF.Atan2(b, a); - float hDegrees = MathF.RadianToDegree(hRadians); + float hDegrees = MathFExtensions.RadianToDegree(hRadians); // Wrap the angle round at 360. hDegrees = hDegrees % 360; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs index 4fb8fdc80..50e8335ed 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.ColorSpaces; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs index 82b1b1d3f..709d8d426 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.ColorSpaces; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs index 31868ec11..64fc84b1d 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.ColorSpaces; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs index 917cd3bf8..3de3baddd 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.ColorSpaces; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs index 8905a0a30..7faf03c9a 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.ColorSpaces; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs index 2cd379d85..7e7c536e3 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.ColorSpaces; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs index c73a3486e..132861b47 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs index f393b133c..11761f0e4 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs index ba1b1379e..ccda6bf52 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs index 1e49c1159..ce8ea7c6e 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce diff --git a/src/ImageSharp/Common/Extensions/Vector4Extensions.cs b/src/ImageSharp/Common/Extensions/Vector4Extensions.cs index 5fbc3960a..7cb193e82 100644 --- a/src/ImageSharp/Common/Extensions/Vector4Extensions.cs +++ b/src/ImageSharp/Common/Extensions/Vector4Extensions.cs @@ -1,9 +1,9 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using System.Runtime.CompilerServices; -using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs index 8717fa987..7d781e77f 100644 --- a/src/ImageSharp/Common/Helpers/ImageMaths.cs +++ b/src/ImageSharp/Common/Helpers/ImageMaths.cs @@ -64,6 +64,27 @@ namespace SixLabors.ImageSharp return left * right; } + /// + /// Returns the result of a normalized sine cardinal function for the given value. + /// SinC(x) = sin(pi*x)/(pi*x). + /// + /// A single-precision floating-point number to calculate the result for. + /// + /// The sine cardinal of . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float SinC(float f) + { + if (MathF.Abs(f) > Constants.Epsilon) + { + f *= MathF.PI; + float result = MathF.Sin(f) / f; + return MathF.Abs(result) < Constants.Epsilon ? 0F : result; + } + + return 1F; + } + /// /// Returns the result of a B-C filter against the given value. /// diff --git a/src/ImageSharp/Common/Helpers/MathF.cs b/src/ImageSharp/Common/Helpers/MathF.cs deleted file mode 100644 index 7d2f8063f..000000000 --- a/src/ImageSharp/Common/Helpers/MathF.cs +++ /dev/null @@ -1,291 +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 -{ - /// - /// Provides single-precision floating point constants and static methods for trigonometric, logarithmic, and other common mathematical functions. - /// - // ReSharper disable InconsistentNaming - internal static class MathF - { - /// - /// Represents the ratio of the circumference of a circle to its diameter, specified by the constant, π. - /// - public const float PI = (float)Math.PI; - - /// - /// Returns the absolute value of a single-precision floating-point number. - /// - /// - /// A number that is greater than or equal to , but less than or equal to . - /// - /// - /// A single-precision floating-point number, x, such that 0 ≤ x ≤. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Abs(float f) - { - return Math.Abs(f); - } - - /// - /// Returns the angle whose tangent is the quotient of two specified numbers. - /// - /// The y coordinate of a point. - /// The x coordinate of a point. - /// - /// An angle, θ, measured in radians, such that -π≤θ≤π, and tan(θ) = y / x, where - /// (x, y) is a point in the Cartesian plane. Observe the following: For (x, y) in - /// quadrant 1, 0 < θ < π/2.For (x, y) in quadrant 2, π/2 < θ≤π.For (x, y) in quadrant - /// 3, -π < θ < -π/2.For (x, y) in quadrant 4, -π/2 < θ < 0.For points on the boundaries - /// of the quadrants, the return value is the following:If y is 0 and x is not negative, - /// θ = 0.If y is 0 and x is negative, θ = π.If y is positive and x is 0, θ = π/2.If - /// y is negative and x is 0, θ = -π/2.If y is 0 and x is 0, θ = 0. If x or y is - /// , or if x and y are either or - /// , the method returns . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Atan2(float y, float x) - { - return (float)Math.Atan2(y, x); - } - - /// - /// Returns the smallest integral value that is greater than or equal to the specified single-precision floating-point number. - /// - /// A single-precision floating-point number. - /// - /// The smallest integral value that is greater than or equal to . - /// If is equal to , , - /// or , that value is returned. - /// Note that this method returns a instead of an integral type. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Ceiling(float f) - { - return (float)Math.Ceiling(f); - } - - /// - /// Returns the cosine of the specified angle. - /// - /// An angle, measured in radians. - /// - /// The cosine of . If is equal to , , - /// or , this method returns . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Cos(float f) - { - return (float)Math.Cos(f); - } - - /// - /// Converts a degree (360-periodic) angle to a radian (2*Pi-periodic) angle. - /// - /// The angle in degrees. - /// - /// The representing the degree as radians. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float DegreeToRadian(float degree) - { - return degree * (PI / 180F); - } - - /// - /// Returns e raised to the specified power. - /// - /// A number specifying a power. - /// - /// The number e raised to the power . - /// If equals or , that value is returned. - /// If equals , 0 is returned. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Exp(float f) - { - return (float)Math.Exp(f); - } - - /// - /// Returns the largest integer less than or equal to the specified single-precision floating-point number. - /// - /// A single-precision floating-point number. - /// - /// The largest integer less than or equal to . - /// If is equal to , , - /// or , that value is returned. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Floor(float f) - { - return (float)Math.Floor(f); - } - - /// - /// Returns the larger of two single-precision floating-point numbers. - /// - /// The first of two single-precision floating-point numbers to compare. - /// The second of two single-precision floating-point numbers to compare. - /// - /// Parameter or , whichever is larger. - /// If , or , or both and are - /// equal to , is returned. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Max(float val1, float val2) - { - return Math.Max(val1, val2); - } - - /// - /// Returns the smaller of two single-precision floating-point numbers. - /// - /// The first of two single-precision floating-point numbers to compare. - /// The second of two single-precision floating-point numbers to compare. - /// - /// Parameter or , whichever is smaller. - /// If , , or both and are equal - /// to , is returned. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Min(float val1, float val2) - { - return Math.Min(val1, val2); - } - - /// - /// Returns a specified number raised to the specified power. - /// - /// A single-precision floating-point number to be raised to a power. - /// A single-precision floating-point number that specifies a power. - /// The number raised to the power . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Pow(float x, float y) - { - return (float)Math.Pow(x, y); - } - - /// - /// Converts a radian (2*Pi-periodic) angle to a degree (360-periodic) angle. - /// - /// The angle in radians. - /// - /// The representing the degree as radians. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float RadianToDegree(float radian) - { - return radian / (PI / 180F); - } - - /// - /// Rounds a single-precision floating-point value to the nearest integral value. - /// - /// A single-precision floating-point number to be rounded. - /// - /// The integer nearest . - /// If the fractional component of is halfway between two integers, one of which is even and the other odd, then the even number is returned. - /// Note that this method returns a instead of an integral type. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Round(float f) - { - return (float)Math.Round(f); - } - - /// - /// Rounds a single-precision floating-point value to the nearest integer. - /// A parameter specifies how to round the value if it is midway between two numbers. - /// - /// A single-precision floating-point number to be rounded. - /// Specification for how to round if it is midway between two other numbers. - /// - /// The integer nearest . If is halfway between two integers, one of which is even - /// and the other odd, then determines which of the two is returned. - /// Note that this method returns a instead of an integral type. - /// - /// - /// is not a valid value of . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Round(float f, MidpointRounding mode) - { - return (float)Math.Round(f, mode); - } - - /// - /// Returns the sine of the specified angle. - /// - /// An angle, measured in radians. - /// - /// The sine of . - /// If is equal to , , - /// or , this method returns . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sin(float f) - { - return (float)Math.Sin(f); - } - - /// - /// Returns the result of a normalized sine cardinal function for the given value. - /// SinC(x) = sin(pi*x)/(pi*x). - /// - /// A single-precision floating-point number to calculate the result for. - /// - /// The sine cardinal of . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float SinC(float f) - { - if (Abs(f) > Constants.Epsilon) - { - f *= PI; - return Clean(Sin(f) / f); - } - - return 1F; - } - - /// - /// Returns the square root of a specified number. - /// - /// The number whose square root is to be found. - /// - /// One of the values in the following table. - /// parameter Return value Zero or positive The positive square root of . - /// Negative Equals - /// Equals - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sqrt(float f) - { - return (float)Math.Sqrt(f); - } - - /// - /// Ensures that any passed float is correctly rounded to zero - /// - /// The value to clean. - /// - /// The - /// . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static float Clean(float x) - { - if (Abs(x) < Constants.Epsilon) - { - return 0F; - } - - return x; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs b/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs index e0e11ad9e..689c9a85b 100644 --- a/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs +++ b/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs @@ -17,12 +17,12 @@ namespace SixLabors.ImageSharp.Dithering /// The source pixel /// The color to apply to the pixels above the threshold. /// The color to apply to the pixels below the threshold. - /// The byte array to pack/unpack to. Must have a length of 4. Bytes are unpacked to Xyzw order. + /// The to pack/unpack to. /// The component index to test the threshold against. Must range from 0 to 3. /// The column index. /// The row index. /// The pixel format. - void Dither(ImageFrame image, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y) + void Dither(ImageFrame image, TPixel source, TPixel upper, TPixel lower, ref Rgba32 rgba, int index, int x, int y) where TPixel : struct, IPixel; } } \ No newline at end of file diff --git a/src/ImageSharp/Dithering/Ordered/OrderedDitherBase.cs b/src/ImageSharp/Dithering/Ordered/OrderedDitherBase.cs index 09c30eb27..818a24d5d 100644 --- a/src/ImageSharp/Dithering/Ordered/OrderedDitherBase.cs +++ b/src/ImageSharp/Dithering/Ordered/OrderedDitherBase.cs @@ -1,13 +1,14 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Dithering.Base { /// - /// The base class for performing ordered ditheroing using a 4x4 matrix. + /// The base class for performing ordered dithering using a 4x4 matrix. /// public abstract class OrderedDitherBase : IOrderedDither { @@ -26,14 +27,27 @@ namespace SixLabors.ImageSharp.Dithering.Base } /// - public void Dither(ImageFrame image, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y) + public void Dither(ImageFrame image, TPixel source, TPixel upper, TPixel lower, ref Rgba32 rgba, int index, int x, int y) where TPixel : struct, IPixel { - // TODO: This doesn't really cut it for me. - // I'd rather be using float but we need to add some sort of normalization vector methods to all IPixel implementations - // before we can do that as the vectors all cover different ranges. - source.ToXyzwBytes(bytes, 0); - image[x, y] = this.matrix[y % 3, x % 3] >= bytes[index] ? lower : upper; + source.ToRgba32(ref rgba); + switch (index) + { + case 0: + image[x, y] = this.matrix[y % 3, x % 3] >= rgba.R ? lower : upper; + return; + case 1: + image[x, y] = this.matrix[y % 3, x % 3] >= rgba.G ? lower : upper; + return; + case 2: + image[x, y] = this.matrix[y % 3, x % 3] >= rgba.B ? lower : upper; + return; + case 3: + image[x, y] = this.matrix[y % 3, x % 3] >= rgba.A ? lower : upper; + return; + } + + throw new ArgumentOutOfRangeException(nameof(index), "Index should be between 0 and 3 inclusive."); } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index 453197b0c..ae20be7d5 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -7,6 +7,7 @@ using System.IO; using System.Runtime.CompilerServices; using System.Text; using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.MetaData; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; @@ -38,7 +39,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// The global color table. /// - private byte[] globalColorTable; + private Buffer globalColorTable; /// /// The global color table length @@ -123,10 +124,10 @@ namespace SixLabors.ImageSharp.Formats.Gif if (this.logicalScreenDescriptor.GlobalColorTableFlag) { this.globalColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize * 3; - this.globalColorTable = ArrayPool.Shared.Rent(this.globalColorTableLength); + this.globalColorTable = Buffer.CreateClean(this.globalColorTableLength); // Read the global color table from the stream - stream.Read(this.globalColorTable, 0, this.globalColorTableLength); + stream.Read(this.globalColorTable.Array, 0, this.globalColorTableLength); } // Loop though the respective gif parts and read the data. @@ -154,10 +155,15 @@ namespace SixLabors.ImageSharp.Formats.Gif this.ReadComments(); break; case GifConstants.ApplicationExtensionLabel: - this.Skip(12); // No need to read. + + // The application extension length should be 11 but we've got test images that incorrectly + // set this to 252. + int appLength = stream.ReadByte(); + this.Skip(appLength); // No need to read. break; case GifConstants.PlainTextLabel: - this.Skip(13); // Not supported by any known decoder. + int plainLength = stream.ReadByte(); + this.Skip(plainLength); // Not supported by any known decoder. break; } } @@ -175,10 +181,7 @@ namespace SixLabors.ImageSharp.Formats.Gif } finally { - if (this.globalColorTable != null) - { - ArrayPool.Shared.Return(this.globalColorTable); - } + this.globalColorTable?.Dispose(); } return this.image; @@ -309,19 +312,19 @@ namespace SixLabors.ImageSharp.Formats.Gif { GifImageDescriptor imageDescriptor = this.ReadImageDescriptor(); - byte[] localColorTable = null; - byte[] indices = null; + Buffer localColorTable = null; + Buffer indices = null; try { // Determine the color table for this frame. If there is a local one, use it otherwise use the global color table. if (imageDescriptor.LocalColorTableFlag) { int length = imageDescriptor.LocalColorTableSize * 3; - localColorTable = ArrayPool.Shared.Rent(length); - this.currentStream.Read(localColorTable, 0, length); + localColorTable = Buffer.CreateClean(length); + this.currentStream.Read(localColorTable.Array, 0, length); } - indices = ArrayPool.Shared.Rent(imageDescriptor.Width * imageDescriptor.Height); + indices = Buffer.CreateClean(imageDescriptor.Width * imageDescriptor.Height); this.ReadFrameIndices(imageDescriptor, indices); this.ReadFrameColors(indices, localColorTable ?? this.globalColorTable, imageDescriptor); @@ -331,12 +334,8 @@ namespace SixLabors.ImageSharp.Formats.Gif } finally { - if (localColorTable != null) - { - ArrayPool.Shared.Return(localColorTable); - } - - ArrayPool.Shared.Return(indices); + localColorTable?.Dispose(); + indices?.Dispose(); } } @@ -346,7 +345,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The . /// The pixel array to write to. [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadFrameIndices(GifImageDescriptor imageDescriptor, byte[] indices) + private void ReadFrameIndices(GifImageDescriptor imageDescriptor, Span indices) { int dataSize = this.currentStream.ReadByte(); using (var lzwDecoder = new LzwDecoder(this.currentStream)) @@ -361,7 +360,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The indexed pixels. /// The color table containing the available colors. /// The - private void ReadFrameColors(byte[] indices, byte[] colorTable, GifImageDescriptor descriptor) + private void ReadFrameColors(Span indices, Span colorTable, GifImageDescriptor descriptor) { int imageWidth = this.logicalScreenDescriptor.Width; int imageHeight = this.logicalScreenDescriptor.Height; @@ -444,7 +443,8 @@ namespace SixLabors.ImageSharp.Formats.Gif var rgba = new Rgba32(0, 0, 0, 255); - for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++) + // #403 The left + width value can be larger than the image width + for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < rowSpan.Length; x++) { int index = indices[i]; diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 1b145a79e..41c8e944d 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -351,16 +351,16 @@ namespace SixLabors.ImageSharp.Formats.Gif // Get max colors for bit depth. int colorTableLength = (int)Math.Pow(2, this.bitDepth) * 3; byte[] colorTable = ArrayPool.Shared.Rent(colorTableLength); - + var rgb = default(Rgb24); try { for (int i = 0; i < pixelCount; i++) { int offset = i * 3; - image.Palette[i].ToXyzBytes(this.buffer, 0); - colorTable[offset] = this.buffer[0]; - colorTable[offset + 1] = this.buffer[1]; - colorTable[offset + 2] = this.buffer[2]; + image.Palette[i].ToRgb24(ref rgb); + colorTable[offset] = rgb.R; + colorTable[offset + 1] = rgb.G; + colorTable[offset + 2] = rgb.B; } writer.Write(colorTable, 0, colorTableLength); diff --git a/src/ImageSharp/Formats/Gif/LzwDecoder.cs b/src/ImageSharp/Formats/Gif/LzwDecoder.cs index b8f12f930..3284dad65 100644 --- a/src/ImageSharp/Formats/Gif/LzwDecoder.cs +++ b/src/ImageSharp/Formats/Gif/LzwDecoder.cs @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The height of the pixel index array. /// Size of the data. /// The pixel array to decode to. - public void DecodePixels(int width, int height, int dataSize, byte[] pixels) + public void DecodePixels(int width, int height, int dataSize, Span pixels) { Guard.MustBeLessThan(dataSize, int.MaxValue, nameof(dataSize)); diff --git a/src/ImageSharp/Formats/Jpeg/Common/SizeExtensions.cs b/src/ImageSharp/Formats/Jpeg/Common/SizeExtensions.cs index f6b02bbaf..978688673 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/SizeExtensions.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/SizeExtensions.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using SixLabors.Primitives; diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs index 92c7ebe11..67abba9f3 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs @@ -583,7 +583,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder } zig = this.RefineNonZeroes(ref bp, zig, val0, delta); - if (bp.ReachedEOF) + + if (bp.ReachedEOF || bp.HasError) { return; } diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs index e7ffaa9d1..61b18af55 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs @@ -688,7 +688,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort } int th = this.Temp[0] & 0x0f; - if (th > OrigHuffmanTree.MaxTh || (!this.IsProgressive && (th > 1))) + if (th > OrigHuffmanTree.MaxTh) { throw new ImageFormatException("Bad Th value"); } diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 86a63f5b4..0efd46ec7 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -318,6 +318,7 @@ namespace SixLabors.ImageSharp.Formats.Png where TPixel : struct, IPixel { byte[] rawScanlineArray = this.rawScanline.Array; + var rgba = default(Rgba32); // Copy the pixels across from the image. // Reuse the chunk type buffer. @@ -326,8 +327,8 @@ namespace SixLabors.ImageSharp.Formats.Png // Convert the color to YCbCr and store the luminance // Optionally store the original color alpha. int offset = x * this.bytesPerPixel; - rowSpan[x].ToXyzwBytes(this.chunkTypeBuffer, 0); - byte luminance = (byte)((0.299F * this.chunkTypeBuffer[0]) + (0.587F * this.chunkTypeBuffer[1]) + (0.114F * this.chunkTypeBuffer[2])); + rowSpan[x].ToRgba32(ref rgba); + byte luminance = (byte)((0.299F * rgba.R) + (0.587F * rgba.G) + (0.114F * rgba.B)); for (int i = 0; i < this.bytesPerPixel; i++) { @@ -337,7 +338,7 @@ namespace SixLabors.ImageSharp.Formats.Png } else { - rawScanlineArray[offset + i] = this.chunkTypeBuffer[3]; + rawScanlineArray[offset + i] = rgba.A; } } } @@ -518,7 +519,7 @@ namespace SixLabors.ImageSharp.Formats.Png int colorTableLength = (int)Math.Pow(2, header.BitDepth) * 3; byte[] colorTable = ArrayPool.Shared.Rent(colorTableLength); byte[] alphaTable = ArrayPool.Shared.Rent(pixelCount); - byte[] bytes = ArrayPool.Shared.Rent(4); + var rgba = default(Rgba32); bool anyAlpha = false; try { @@ -527,13 +528,13 @@ namespace SixLabors.ImageSharp.Formats.Png if (quantized.Pixels.Contains(i)) { int offset = i * 3; - palette[i].ToXyzwBytes(bytes, 0); + palette[i].ToRgba32(ref rgba); - byte alpha = bytes[3]; + byte alpha = rgba.A; - colorTable[offset] = bytes[0]; - colorTable[offset + 1] = bytes[1]; - colorTable[offset + 2] = bytes[2]; + colorTable[offset] = rgba.R; + colorTable[offset + 1] = rgba.G; + colorTable[offset + 2] = rgba.B; if (alpha > this.threshold) { @@ -557,7 +558,6 @@ namespace SixLabors.ImageSharp.Formats.Png { ArrayPool.Shared.Return(colorTable); ArrayPool.Shared.Return(alphaTable); - ArrayPool.Shared.Return(bytes); } return quantized; diff --git a/src/ImageSharp/Formats/Png/Zlib/Adler32.cs b/src/ImageSharp/Formats/Png/Zlib/Adler32.cs index 6841c1cb8..1cce90c0b 100644 --- a/src/ImageSharp/Formats/Png/Zlib/Adler32.cs +++ b/src/ImageSharp/Formats/Png/Zlib/Adler32.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.Formats.Png.Zlib { @@ -74,9 +75,17 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib } /// - public long Value => this.checksum; + public long Value + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return this.checksum; + } + } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Reset() { this.checksum = 1; @@ -88,6 +97,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// /// The data value to add. The high byte of the int is ignored. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Update(int value) { // We could make a length 1 byte array and call update again, but I @@ -102,6 +112,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Update(byte[] buffer) { if (buffer == null) @@ -113,32 +124,14 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Update(byte[] buffer, int offset, int count) { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - if (offset < 0) - { - throw new ArgumentOutOfRangeException(nameof(offset), "cannot be negative"); - } - - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count), "cannot be negative"); - } - - if (offset >= buffer.Length) - { - throw new ArgumentOutOfRangeException(nameof(offset), "not a valid index into buffer"); - } - - if (offset + count > buffer.Length) - { - throw new ArgumentOutOfRangeException(nameof(count), "exceeds buffer size"); - } + 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; @@ -169,4 +162,4 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib this.checksum = (s2 << 16) | s1; } } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/Zlib/Crc32.cs b/src/ImageSharp/Formats/Png/Zlib/Crc32.cs index 14a29b7af..bd686f2b9 100644 --- a/src/ImageSharp/Formats/Png/Zlib/Crc32.cs +++ b/src/ImageSharp/Formats/Png/Zlib/Crc32.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.Formats.Png.Zlib { @@ -108,18 +109,15 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// public long Value { - get - { - return this.crc; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => this.crc; - set - { - this.crc = (uint)value; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => this.crc = (uint)value; } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Reset() { this.crc = 0; @@ -129,6 +127,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// Updates the checksum with the given value. /// /// The byte is taken as the lower 8 bits of value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Update(int value) { this.crc ^= CrcSeed; @@ -137,6 +136,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Update(byte[] buffer) { if (buffer == null) @@ -148,22 +148,13 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Update(byte[] buffer, int offset, int count) { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count), "Count cannot be less than zero"); - } - - if (offset < 0 || offset + count > buffer.Length) - { - throw new ArgumentOutOfRangeException(nameof(offset)); - } + 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; diff --git a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs index 36d1d62e7..fd9c4ac63 100644 --- a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs +++ b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs @@ -2,10 +2,8 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Collections.Generic; using System.IO; using System.IO.Compression; -using System.Text; namespace SixLabors.ImageSharp.Formats.Png.Zlib { @@ -14,6 +12,13 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// internal sealed class ZlibInflateStream : Stream { + /// + /// Used to read the Adler-32 and Crc-32 checksums + /// We don't actually use this for anything so it doesn't + /// have to be threadsafe. + /// + private static readonly byte[] ChecksumBuffer = new byte[4]; + /// /// The inner raw memory stream /// @@ -38,9 +43,9 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib private bool isDisposed; /// - /// The read crc data. + /// Whether the crc value has been read. /// - private byte[] crcread; + private bool crcRead; /// /// The current data remaining to be read @@ -149,14 +154,12 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib this.compressedStream.Dispose(); this.compressedStream = null; - if (this.crcread == null) + if (!this.crcRead) { // Consume the trailing 4 bytes - this.crcread = new byte[4]; - for (int i = 0; i < 4; i++) - { - this.crcread[i] = (byte)this.innerStream.ReadByte(); - } + this.innerStream.Read(ChecksumBuffer, 0, 4); + this.currentDataRemaining -= 4; + this.crcRead = true; } } } @@ -171,11 +174,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib private void InitializeInflateStream() { - // The DICT dictionary identifier identifying the used dictionary. - - // The preset dictionary. - bool fdict; - // Read the zlib header : http://tools.ietf.org/html/rfc1950 // CMF(Compression Method and flags) // This byte is divided into a 4 - bit compression method and a @@ -195,30 +193,35 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib return; } - if ((cmf & 0x0f) != 8) + if ((cmf & 0x0F) == 8) { - throw new Exception($"Bad compression method for ZLIB header: cmf={cmf}"); - } + // CINFO is the base-2 logarithm of the LZ77 window size, minus eight. + int cinfo = (cmf & 0xF0) >> 4; - // CINFO is the base-2 logarithm of the LZ77 window size, minus eight. - // int cinfo = ((cmf & (0xf0)) >> 8); - fdict = (flag & 32) != 0; + if (cinfo > 7) + { + // Values of CINFO above 7 are not allowed in RFC1950. + // CINFO is not defined in this specification for CM not equal to 8. + throw new ImageFormatException($"Invalid window size for ZLIB header: cinfo={cinfo}"); + } + } + else + { + throw new ImageFormatException($"Bad method for ZLIB header: cmf={cmf}"); + } + // The preset dictionary. + bool fdict = (flag & 32) != 0; if (fdict) { - // The DICT dictionary identifier identifying the used dictionary. - byte[] dictId = new byte[4]; - - for (int i = 0; i < 4; i++) - { - // We consume but don't use this. - dictId[i] = (byte)this.innerStream.ReadByte(); - this.currentDataRemaining--; - } + // We don't need this for inflate so simply skip by the next four bytes. + // https://tools.ietf.org/html/rfc1950#page-6 + this.innerStream.Read(ChecksumBuffer, 0, 4); + this.currentDataRemaining -= 4; } // Initialize the deflate Stream. this.compressedStream = new DeflateStream(this, CompressionMode.Decompress, true); } } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Image/PixelAccessorExtensions.cs b/src/ImageSharp/Image/PixelAccessorExtensions.cs index 9146ef48d..b628c05f8 100644 --- a/src/ImageSharp/Image/PixelAccessorExtensions.cs +++ b/src/ImageSharp/Image/PixelAccessorExtensions.cs @@ -1,14 +1,8 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; -using Unsafe = System.Runtime.CompilerServices.Unsafe; namespace SixLabors.ImageSharp { diff --git a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs index 3abe28aca..8dcb1f760 100644 --- a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs +++ b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs @@ -7,7 +7,6 @@ using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; -using Unsafe = System.Runtime.CompilerServices.Unsafe; namespace SixLabors.ImageSharp { diff --git a/src/ImageSharp/Image/PixelArea{TPixel}.cs b/src/ImageSharp/Image/PixelArea{TPixel}.cs index e9924f823..1c7256455 100644 --- a/src/ImageSharp/Image/PixelArea{TPixel}.cs +++ b/src/ImageSharp/Image/PixelArea{TPixel}.cs @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp /// /// The underlying buffer containing the raw pixel data. /// - private Buffer byteBuffer; + private readonly Buffer byteBuffer; /// /// Initializes a new instance of the class. @@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp this.RowStride = (width * GetComponentCount(componentOrder)) + padding; this.Length = this.RowStride * height; - this.byteBuffer = new Buffer(this.Length); + this.byteBuffer = Buffer.CreateClean(this.Length); } /// diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 45d0a70b8..8c22237cf 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -1,118 +1,120 @@  - - A cross-platform library for the processing of image files; written in C# - SixLabors.ImageSharp - $(packageversion) - 0.0.1 - Six Labors and contributors - netstandard1.1;netstandard1.3 - true - true - 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://github.com/SixLabors/ImageSharp - http://www.apache.org/licenses/LICENSE-2.0 - git - https://github.com/SixLabors/ImageSharp - false - false - false - false - false - false - false - false - false - full - portable - True - IOperation - - - - - - - - - All - - - - - - - - - - - ..\..\ImageSharp.ruleset - SixLabors.ImageSharp - - - true - - - - TextTemplatingFileGenerator - Block8x8F.Generated.cs - - - TextTemplatingFileGenerator - Block8x8F.Generated.cs - - - TextTemplatingFileGenerator - PixelOperations{TPixel}.Generated.cs - - - TextTemplatingFileGenerator - Rgba32.PixelOperations.Generated.cs - - - PorterDuffFunctions.Generated.cs - TextTemplatingFileGenerator - - - DefaultPixelBlenders.Generated.cs - TextTemplatingFileGenerator - - - - - - - - True - True - Block8x8F.Generated.tt - - - True - True - Block8x8F.Generated.tt - - - True - True - PixelOperations{TPixel}.Generated.tt - - - True - True - Rgba32.PixelOperations.Generated.tt - - - True - True - DefaultPixelBlenders.Generated.tt - - - True - True - PorterDuffFunctions.Generated.tt - - + + A cross-platform library for the processing of image files; written in C# + SixLabors.ImageSharp + $(packageversion) + 0.0.1 + Six Labors and contributors + netstandard1.1;netstandard1.3;netstandard2.0 + true + true + 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://github.com/SixLabors/ImageSharp + http://www.apache.org/licenses/LICENSE-2.0 + git + https://github.com/SixLabors/ImageSharp + false + false + false + false + false + false + false + false + false + full + portable + True + IOperation + + + + + + + + + All + + + + + + + + + + + + + ..\..\ImageSharp.ruleset + SixLabors.ImageSharp + + + true + + + + TextTemplatingFileGenerator + Block8x8F.Generated.cs + + + TextTemplatingFileGenerator + Block8x8F.Generated.cs + + + TextTemplatingFileGenerator + PixelOperations{TPixel}.Generated.cs + + + TextTemplatingFileGenerator + Rgba32.PixelOperations.Generated.cs + + + PorterDuffFunctions.Generated.cs + TextTemplatingFileGenerator + + + DefaultPixelBlenders.Generated.cs + TextTemplatingFileGenerator + + + + + + + + True + True + Block8x8F.Generated.tt + + + True + True + Block8x8F.Generated.tt + + + True + True + PixelOperations{TPixel}.Generated.tt + + + True + True + Rgba32.PixelOperations.Generated.tt + + + True + True + DefaultPixelBlenders.Generated.tt + + + True + True + PorterDuffFunctions.Generated.tt + + \ No newline at end of file diff --git a/src/ImageSharp/Memory/Buffer2DExtensions.cs b/src/ImageSharp/Memory/Buffer2DExtensions.cs index 401003eed..ac5ab09db 100644 --- a/src/ImageSharp/Memory/Buffer2DExtensions.cs +++ b/src/ImageSharp/Memory/Buffer2DExtensions.cs @@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Memory /// /// The element type /// The - /// The rectangel subarea + /// The rectangle subarea /// The public static BufferArea GetArea(this IBuffer2D buffer, Rectangle rectangle) where T : struct => new BufferArea(buffer, rectangle); diff --git a/src/ImageSharp/Memory/SpanHelper.cs b/src/ImageSharp/Memory/SpanHelper.cs index 8b9fad522..73bc5f55d 100644 --- a/src/ImageSharp/Memory/SpanHelper.cs +++ b/src/ImageSharp/Memory/SpanHelper.cs @@ -4,7 +4,6 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; -using Unsafe = System.Runtime.CompilerServices.Unsafe; namespace SixLabors.ImageSharp.Memory { diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs index efdd275b4..21ae335be 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs @@ -2,11 +2,13 @@ // Licensed under the Apache License, Version 2.0. // + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; + namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { - using System.Numerics; - using System.Runtime.CompilerServices; - internal static partial class PorterDuffFunctions { [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt index e6a2ca3eb..c92ab6dd6 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt @@ -12,11 +12,13 @@ // Licensed under the Apache License, Version 2.0. // + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; + namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { - using System.Numerics; - using System.Runtime.CompilerServices; - internal static partial class PorterDuffFunctions { <# diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs index 04c750255..f09d6d51c 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using System.Runtime.CompilerServices; diff --git a/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs b/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs deleted file mode 100644 index 37b225d2e..000000000 --- a/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs +++ /dev/null @@ -1,79 +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.PixelFormats -{ - /// - /// Extension methods for copying single pixel data into byte Spans. - /// TODO: This utility class exists for legacy reasons. Need to do a lot of chore work to remove it (mostly in test classes). - /// - internal static class PixelConversionExtensions - { - /// - /// Expands the packed representation into a given byte array. - /// Output is expanded to X-> Y-> Z order. Equivalent to R-> G-> B in - /// - /// The pixel type. - /// The pixel to copy the data from. - /// The bytes to set the color in. - /// The starting index of the . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ToXyzBytes(this TPixel pixel, Span bytes, int startIndex) - where TPixel : struct, IPixel - { - ref Rgb24 dest = ref bytes.GetRgb24(startIndex); - pixel.ToRgb24(ref dest); - } - - /// - /// Expands the packed representation into a given byte array. - /// Output is expanded to X-> Y-> Z-> W order. Equivalent to R-> G-> B-> A in - /// - /// The pixel type. - /// The pixel to copy the data from. - /// The bytes to set the color in. - /// The starting index of the . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ToXyzwBytes(this TPixel pixel, Span bytes, int startIndex) - where TPixel : struct, IPixel - { - ref Rgba32 dest = ref Unsafe.As(ref bytes[startIndex]); - pixel.ToRgba32(ref dest); - } - - /// - /// Expands the packed representation into a given byte array. - /// Output is expanded to Z-> Y-> X order. Equivalent to B-> G-> R in - /// - /// The pixel type. - /// The pixel to copy the data from. - /// The bytes to set the color in. - /// The starting index of the . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ToZyxBytes(this TPixel pixel, Span bytes, int startIndex) - where TPixel : struct, IPixel - { - ref Bgr24 dest = ref Unsafe.As(ref bytes[startIndex]); - pixel.ToBgr24(ref dest); - } - - /// - /// Expands the packed representation into a given byte array. - /// Output is expanded to Z-> Y-> X-> W order. Equivalent to B-> G-> R-> A in - /// - /// The pixel type. - /// The pixel to copy the data from. - /// The bytes to set the color in. - /// The starting index of the . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ToZyxwBytes(this TPixel pixel, Span bytes, int startIndex) - where TPixel : struct, IPixel - { - ref Bgra32 dest = ref Unsafe.As(ref bytes[startIndex]); - pixel.ToBgra32(ref dest); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs index 203a64cf1..a2fd17c94 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs @@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.Processing.Processors int startX = interest.X; int endX = interest.Right; - byte[] bytes = new byte[4]; + var rgba = default(Rgba32); for (int y = startY; y < endY; y++) { Span row = source.GetPixelRowSpan(y); @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Processors for (int x = startX; x < endX; x++) { TPixel sourceColor = row[x]; - this.Dither.Dither(source, sourceColor, this.UpperColor, this.LowerColor, bytes, this.Index, x, y); + this.Dither.Dither(source, sourceColor, this.UpperColor, this.LowerColor, ref rgba, this.Index, x, y); } } } diff --git a/src/ImageSharp/Processing/Processors/ColorMatrix/HueProcessor.cs b/src/ImageSharp/Processing/Processors/ColorMatrix/HueProcessor.cs index 9a40bfca8..adfdb6a78 100644 --- a/src/ImageSharp/Processing/Processors/ColorMatrix/HueProcessor.cs +++ b/src/ImageSharp/Processing/Processors/ColorMatrix/HueProcessor.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using SixLabors.ImageSharp.PixelFormats; @@ -30,7 +31,7 @@ namespace SixLabors.ImageSharp.Processing.Processors this.Angle = angle; - float radians = MathF.DegreeToRadian(angle); + float radians = MathFExtensions.DegreeToRadian(angle); float cosradians = MathF.Cos(radians); float sinradians = MathF.Sin(radians); diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs index 1169d2ead..22a7c90b7 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Processing.Processors internal abstract partial class ResamplingWeightedProcessor { /// - /// Points to a collection of of weights allocated in . + /// Points to a collection of weights allocated in . /// internal struct WeightsWindow { @@ -153,7 +153,7 @@ namespace SixLabors.ImageSharp.Processing.Processors } /// - /// Holds the values in an optimized contigous memory region. + /// Holds the values in an optimized contiguous memory region. /// internal class WeightsBuffer : IDisposable { @@ -196,4 +196,4 @@ namespace SixLabors.ImageSharp.Processing.Processors } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs index a4fdb1a1b..17b42c504 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs @@ -58,9 +58,9 @@ namespace SixLabors.ImageSharp.Processing.Processors // We will always be creating the clone even for mutate because thats the way this base processor works // ------------ // For resize we know we are going to populate every pixel with fresh data and we want a different target size so - // let's manually clone an empty set of images at the correct target and then have the base class processs them in turn. + // let's manually clone an empty set of images at the correct target and then have the base class process them in turn. IEnumerable> frames = source.Frames.Select(x => new ImageFrame(this.Width, this.Height, x.MetaData.Clone())); // this will create places holders - var image = new Image(config, source.MetaData.Clone(), frames); // base the place holder images in to prevet a extra frame being added + var image = new Image(config, source.MetaData.Clone(), frames); // base the place holder images in to prevent a extra frame being added return image; } diff --git a/src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs b/src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs index 152b451e2..17a0cc428 100644 --- a/src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs +++ b/src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Linq; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos2Resampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos2Resampler.cs index deaa0ccb9..29568db02 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos2Resampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos2Resampler.cs @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Processing if (x < 2F) { - return MathF.SinC(x) * MathF.SinC(x / 2F); + return ImageMaths.SinC(x) * ImageMaths.SinC(x / 2F); } return 0F; diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos3Resampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos3Resampler.cs index 2673c3491..492ef69e4 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos3Resampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos3Resampler.cs @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Processing if (x < 3F) { - return MathF.SinC(x) * MathF.SinC(x / 3F); + return ImageMaths.SinC(x) * ImageMaths.SinC(x / 3F); } return 0F; diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos5Resampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos5Resampler.cs index c52670e2d..cae152a53 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos5Resampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos5Resampler.cs @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Processing if (x < 5F) { - return MathF.SinC(x) * MathF.SinC(x / 5F); + return ImageMaths.SinC(x) * ImageMaths.SinC(x / 5F); } return 0F; diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos8Resampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos8Resampler.cs index 552d3065b..b390c5541 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos8Resampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos8Resampler.cs @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Processing if (x < 8F) { - return MathF.SinC(x) * MathF.SinC(x / 8F); + return ImageMaths.SinC(x) * ImageMaths.SinC(x / 8F); } return 0F; diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/WelchResampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/WelchResampler.cs index e154d5483..acb74a8ec 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/WelchResampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/WelchResampler.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing if (x < 3F) { - return MathF.SinC(x) * (1F - (x * x / 9F)); + return ImageMaths.SinC(x) * (1F - (x * x / 9F)); } return 0F; diff --git a/src/ImageSharp/Processing/Transforms/Resize.cs b/src/ImageSharp/Processing/Transforms/Resize.cs index 7897e8f30..3c7cbca31 100644 --- a/src/ImageSharp/Processing/Transforms/Resize.cs +++ b/src/ImageSharp/Processing/Transforms/Resize.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors; diff --git a/src/ImageSharp/Quantizers/Box.cs b/src/ImageSharp/Quantizers/Box.cs index 4a1e17753..cd1936b65 100644 --- a/src/ImageSharp/Quantizers/Box.cs +++ b/src/ImageSharp/Quantizers/Box.cs @@ -5,9 +5,8 @@ namespace SixLabors.ImageSharp.Quantizers { /// /// Represents a box color cube. - /// TODO: This should be a struct for performance /// - internal sealed class Box + internal struct Box { /// /// Gets or sets the min red value, exclusive. @@ -54,4 +53,4 @@ namespace SixLabors.ImageSharp.Quantizers /// public int Volume { get; set; } } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs index 8ab390f4e..cb9eb9b0e 100644 --- a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs @@ -60,11 +60,6 @@ namespace SixLabors.ImageSharp.Quantizers /// private const int TableLength = IndexCount * IndexCount * IndexCount * IndexAlphaCount; - /// - /// A buffer for storing pixels - /// - private readonly byte[] rgbaBuffer = new byte[4]; - /// /// A lookup table for colors /// @@ -173,20 +168,19 @@ namespace SixLabors.ImageSharp.Quantizers this.palette = new TPixel[this.colors]; for (int k = 0; k < this.colors; k++) { - this.Mark(this.colorCube[k], (byte)k); + this.Mark(ref this.colorCube[k], (byte)k); - float weight = Volume(this.colorCube[k], this.vwt); + float weight = Volume(ref this.colorCube[k], this.vwt); if (MathF.Abs(weight) > Constants.Epsilon) { - float r = Volume(this.colorCube[k], this.vmr) / weight; - float g = Volume(this.colorCube[k], this.vmg) / weight; - float b = Volume(this.colorCube[k], this.vmb) / weight; - float a = Volume(this.colorCube[k], this.vma) / weight; - - var color = default(TPixel); - color.PackFromVector4(new Vector4(r, g, b, a) / 255F); - this.palette[k] = color; + float r = Volume(ref this.colorCube[k], this.vmr); + float g = Volume(ref this.colorCube[k], this.vmg); + float b = Volume(ref this.colorCube[k], this.vmb); + float a = Volume(ref this.colorCube[k], this.vma); + + ref TPixel color = ref this.palette[k]; + color.PackFromVector4(new Vector4(r, g, b, a) / weight / 255F); } } } @@ -199,26 +193,24 @@ namespace SixLabors.ImageSharp.Quantizers { // Add the color to a 3-D color histogram. // Colors are expected in r->g->b->a format - pixel.ToXyzwBytes(this.rgbaBuffer, 0); - - byte r = this.rgbaBuffer[0]; - byte g = this.rgbaBuffer[1]; - byte b = this.rgbaBuffer[2]; - byte a = this.rgbaBuffer[3]; - - int inr = r >> (8 - IndexBits); - int ing = g >> (8 - IndexBits); - int inb = b >> (8 - IndexBits); - int ina = a >> (8 - IndexAlphaBits); - - int ind = GetPaletteIndex(inr + 1, ing + 1, inb + 1, ina + 1); - - this.vwt[ind]++; - this.vmr[ind] += r; - this.vmg[ind] += g; - this.vmb[ind] += b; - this.vma[ind] += a; - this.m2[ind] += (r * r) + (g * g) + (b * b) + (a * a); + var rgba = default(Rgba32); + pixel.ToRgba32(ref rgba); + + int r = rgba.R >> (8 - IndexBits); + int g = rgba.G >> (8 - IndexBits); + int b = rgba.B >> (8 - IndexBits); + int a = rgba.A >> (8 - IndexAlphaBits); + + int index = GetPaletteIndex(r + 1, g + 1, b + 1, a + 1); + + this.vwt[index]++; + this.vmr[index] += rgba.R; + this.vmg[index] += rgba.G; + this.vmb[index] += rgba.B; + this.vma[index] += rgba.A; + + var vector = new Vector4(rgba.R, rgba.G, rgba.B, rgba.A); + this.m2[index] += Vector4.Dot(vector, vector); } /// @@ -310,7 +302,7 @@ namespace SixLabors.ImageSharp.Quantizers /// The cube. /// The moment. /// The result. - private static float Volume(Box cube, long[] moment) + private static float Volume(ref Box cube, long[] moment) { return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)] - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] @@ -337,12 +329,12 @@ namespace SixLabors.ImageSharp.Quantizers /// The direction. /// The moment. /// The result. - private static long Bottom(Box cube, int direction, long[] moment) + private static long Bottom(ref Box cube, int direction, long[] moment) { switch (direction) { // Red - case 0: + case 3: return -moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] @@ -353,7 +345,7 @@ namespace SixLabors.ImageSharp.Quantizers + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; // Green - case 1: + case 2: return -moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] @@ -364,7 +356,7 @@ namespace SixLabors.ImageSharp.Quantizers + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; // Blue - case 2: + case 1: return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] + moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] @@ -375,7 +367,7 @@ namespace SixLabors.ImageSharp.Quantizers + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; // Alpha - case 3: + case 0: return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] + moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] @@ -398,12 +390,12 @@ namespace SixLabors.ImageSharp.Quantizers /// The position. /// The moment. /// The result. - private static long Top(Box cube, int direction, int position, long[] moment) + private static long Top(ref Box cube, int direction, int position, long[] moment) { switch (direction) { // Red - case 0: + case 3: return moment[GetPaletteIndex(position, cube.G1, cube.B1, cube.A1)] - moment[GetPaletteIndex(position, cube.G1, cube.B1, cube.A0)] - moment[GetPaletteIndex(position, cube.G1, cube.B0, cube.A1)] @@ -414,7 +406,7 @@ namespace SixLabors.ImageSharp.Quantizers - moment[GetPaletteIndex(position, cube.G0, cube.B0, cube.A0)]; // Green - case 1: + case 2: return moment[GetPaletteIndex(cube.R1, position, cube.B1, cube.A1)] - moment[GetPaletteIndex(cube.R1, position, cube.B1, cube.A0)] - moment[GetPaletteIndex(cube.R1, position, cube.B0, cube.A1)] @@ -425,7 +417,7 @@ namespace SixLabors.ImageSharp.Quantizers - moment[GetPaletteIndex(cube.R0, position, cube.B0, cube.A0)]; // Blue - case 2: + case 1: return moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A1)] - moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A0)] - moment[GetPaletteIndex(cube.R1, cube.G0, position, cube.A1)] @@ -436,7 +428,7 @@ namespace SixLabors.ImageSharp.Quantizers - moment[GetPaletteIndex(cube.R0, cube.G0, position, cube.A0)]; // Alpha - case 3: + case 0: return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, position)] - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, position)] - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, position)] @@ -562,12 +554,12 @@ namespace SixLabors.ImageSharp.Quantizers /// /// The cube. /// The . - private float Variance(Box cube) + private float Variance(ref Box cube) { - float dr = Volume(cube, this.vmr); - float dg = Volume(cube, this.vmg); - float db = Volume(cube, this.vmb); - float da = Volume(cube, this.vma); + float dr = Volume(ref cube, this.vmr); + float dg = Volume(ref cube, this.vmg); + float db = Volume(ref cube, this.vmb); + float da = Volume(ref cube, this.vma); float xx = this.m2[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)] @@ -587,7 +579,8 @@ namespace SixLabors.ImageSharp.Quantizers - this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] + this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; - return xx - (((dr * dr) + (dg * dg) + (db * db) + (da * da)) / Volume(cube, this.vwt)); + var vector = new Vector4(dr, dg, db, da); + return xx - (Vector4.Dot(vector, vector) / Volume(ref cube, this.vwt)); } /// @@ -608,38 +601,33 @@ namespace SixLabors.ImageSharp.Quantizers /// The whole alpha. /// The whole weight. /// The . - private float Maximize(Box cube, int direction, int first, int last, out int cut, float wholeR, float wholeG, float wholeB, float wholeA, float wholeW) + private float Maximize(ref Box cube, int direction, int first, int last, out int cut, float wholeR, float wholeG, float wholeB, float wholeA, float wholeW) { - long baseR = Bottom(cube, direction, this.vmr); - long baseG = Bottom(cube, direction, this.vmg); - long baseB = Bottom(cube, direction, this.vmb); - long baseA = Bottom(cube, direction, this.vma); - long baseW = Bottom(cube, direction, this.vwt); + long baseR = Bottom(ref cube, direction, this.vmr); + long baseG = Bottom(ref cube, direction, this.vmg); + long baseB = Bottom(ref cube, direction, this.vmb); + long baseA = Bottom(ref cube, direction, this.vma); + long baseW = Bottom(ref cube, direction, this.vwt); float max = 0F; cut = -1; for (int i = first; i < last; i++) { - float halfR = baseR + Top(cube, direction, i, this.vmr); - float halfG = baseG + Top(cube, direction, i, this.vmg); - float halfB = baseB + Top(cube, direction, i, this.vmb); - float halfA = baseA + Top(cube, direction, i, this.vma); - float halfW = baseW + Top(cube, direction, i, this.vwt); - - float temp; + float halfR = baseR + Top(ref cube, direction, i, this.vmr); + float halfG = baseG + Top(ref cube, direction, i, this.vmg); + float halfB = baseB + Top(ref cube, direction, i, this.vmb); + float halfA = baseA + Top(ref cube, direction, i, this.vma); + float halfW = baseW + Top(ref cube, direction, i, this.vwt); if (MathF.Abs(halfW) < Constants.Epsilon) { continue; } - temp = ((halfR * halfR) + (halfG * halfG) + (halfB * halfB) + (halfA * halfA)) / halfW; + var vector = new Vector4(halfR, halfG, halfB, halfA); + float temp = Vector4.Dot(vector, vector) / halfW; - halfR = wholeR - halfR; - halfG = wholeG - halfG; - halfB = wholeB - halfB; - halfA = wholeA - halfA; halfW = wholeW - halfW; if (MathF.Abs(halfW) < Constants.Epsilon) @@ -647,7 +635,14 @@ namespace SixLabors.ImageSharp.Quantizers continue; } - temp += ((halfR * halfR) + (halfG * halfG) + (halfB * halfB) + (halfA * halfA)) / halfW; + halfR = wholeR - halfR; + halfG = wholeG - halfG; + halfB = wholeB - halfB; + halfA = wholeA - halfA; + + vector = new Vector4(halfR, halfG, halfB, halfA); + + temp += Vector4.Dot(vector, vector) / halfW; if (temp > max) { @@ -665,24 +660,24 @@ namespace SixLabors.ImageSharp.Quantizers /// The first set. /// The second set. /// Returns a value indicating whether the box has been split. - private bool Cut(Box set1, Box set2) + private bool Cut(ref Box set1, ref Box set2) { - float wholeR = Volume(set1, this.vmr); - float wholeG = Volume(set1, this.vmg); - float wholeB = Volume(set1, this.vmb); - float wholeA = Volume(set1, this.vma); - float wholeW = Volume(set1, this.vwt); + float wholeR = Volume(ref set1, this.vmr); + float wholeG = Volume(ref set1, this.vmg); + float wholeB = Volume(ref set1, this.vmb); + float wholeA = Volume(ref set1, this.vma); + float wholeW = Volume(ref set1, this.vwt); - float maxr = this.Maximize(set1, 0, set1.R0 + 1, set1.R1, out int cutr, wholeR, wholeG, wholeB, wholeA, wholeW); - float maxg = this.Maximize(set1, 1, set1.G0 + 1, set1.G1, out int cutg, wholeR, wholeG, wholeB, wholeA, wholeW); - float maxb = this.Maximize(set1, 2, set1.B0 + 1, set1.B1, out int cutb, wholeR, wholeG, wholeB, wholeA, wholeW); - float maxa = this.Maximize(set1, 3, set1.A0 + 1, set1.A1, out int cuta, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxr = this.Maximize(ref set1, 3, set1.R0 + 1, set1.R1, out int cutr, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxg = this.Maximize(ref set1, 2, set1.G0 + 1, set1.G1, out int cutg, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxb = this.Maximize(ref set1, 1, set1.B0 + 1, set1.B1, out int cutb, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxa = this.Maximize(ref set1, 0, set1.A0 + 1, set1.A1, out int cuta, wholeR, wholeG, wholeB, wholeA, wholeW); int dir; if ((maxr >= maxg) && (maxr >= maxb) && (maxr >= maxa)) { - dir = 0; + dir = 3; if (cutr < 0) { @@ -691,15 +686,15 @@ namespace SixLabors.ImageSharp.Quantizers } else if ((maxg >= maxr) && (maxg >= maxb) && (maxg >= maxa)) { - dir = 1; + dir = 2; } else if ((maxb >= maxr) && (maxb >= maxg) && (maxb >= maxa)) { - dir = 2; + dir = 1; } else { - dir = 3; + dir = 0; } set2.R1 = set1.R1; @@ -710,7 +705,7 @@ namespace SixLabors.ImageSharp.Quantizers switch (dir) { // Red - case 0: + case 3: set2.R0 = set1.R1 = cutr; set2.G0 = set1.G0; set2.B0 = set1.B0; @@ -718,7 +713,7 @@ namespace SixLabors.ImageSharp.Quantizers break; // Green - case 1: + case 2: set2.G0 = set1.G1 = cutg; set2.R0 = set1.R0; set2.B0 = set1.B0; @@ -726,7 +721,7 @@ namespace SixLabors.ImageSharp.Quantizers break; // Blue - case 2: + case 1: set2.B0 = set1.B1 = cutb; set2.R0 = set1.R0; set2.G0 = set1.G0; @@ -734,7 +729,7 @@ namespace SixLabors.ImageSharp.Quantizers break; // Alpha - case 3: + case 0: set2.A0 = set1.A1 = cuta; set2.R0 = set1.R0; set2.G0 = set1.G0; @@ -753,7 +748,7 @@ namespace SixLabors.ImageSharp.Quantizers /// /// The cube. /// A label. - private void Mark(Box cube, byte label) + private void Mark(ref Box cube, byte label) { for (int r = cube.R0 + 1; r <= cube.R1; r++) { @@ -778,23 +773,21 @@ namespace SixLabors.ImageSharp.Quantizers this.colorCube = new Box[this.colors]; float[] vv = new float[this.colors]; - for (int i = 0; i < this.colors; i++) - { - this.colorCube[i] = new Box(); - } - - this.colorCube[0].R0 = this.colorCube[0].G0 = this.colorCube[0].B0 = this.colorCube[0].A0 = 0; - this.colorCube[0].R1 = this.colorCube[0].G1 = this.colorCube[0].B1 = IndexCount - 1; - this.colorCube[0].A1 = IndexAlphaCount - 1; + ref var cube = ref this.colorCube[0]; + cube.R0 = cube.G0 = cube.B0 = cube.A0 = 0; + cube.R1 = cube.G1 = cube.B1 = IndexCount - 1; + cube.A1 = IndexAlphaCount - 1; int next = 0; for (int i = 1; i < this.colors; i++) { - if (this.Cut(this.colorCube[next], this.colorCube[i])) + ref var nextCube = ref this.colorCube[next]; + ref var currentCube = ref this.colorCube[i]; + if (this.Cut(ref nextCube, ref currentCube)) { - vv[next] = this.colorCube[next].Volume > 1 ? this.Variance(this.colorCube[next]) : 0F; - vv[i] = this.colorCube[i].Volume > 1 ? this.Variance(this.colorCube[i]) : 0F; + vv[next] = nextCube.Volume > 1 ? this.Variance(ref nextCube) : 0F; + vv[i] = currentCube.Volume > 1 ? this.Variance(ref currentCube) : 0F; } else { @@ -814,7 +807,7 @@ namespace SixLabors.ImageSharp.Quantizers } } - if (temp <= 0.0) + if (temp <= 0F) { this.colors = i + 1; break; @@ -840,12 +833,13 @@ namespace SixLabors.ImageSharp.Quantizers } // Expected order r->g->b->a - pixel.ToXyzwBytes(this.rgbaBuffer, 0); + var rgba = default(Rgba32); + pixel.ToRgba32(ref rgba); - int r = this.rgbaBuffer[0] >> (8 - IndexBits); - int g = this.rgbaBuffer[1] >> (8 - IndexBits); - int b = this.rgbaBuffer[2] >> (8 - IndexBits); - int a = this.rgbaBuffer[3] >> (8 - IndexAlphaBits); + int r = rgba.R >> (8 - IndexBits); + int g = rgba.G >> (8 - IndexBits); + int b = rgba.B >> (8 - IndexBits); + int a = rgba.A >> (8 - IndexAlphaBits); return this.tag[GetPaletteIndex(r + 1, g + 1, b + 1, a + 1)]; } diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs index e1f5e6106..2d624c19f 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs @@ -35,11 +35,16 @@ namespace SixLabors.ImageSharp.Benchmarks.Color.Bulk { TPixel[] s = this.source.Array; byte[] d = this.destination.Array; + var rgb = default(Rgb24); for (int i = 0; i < this.Count; i++) { TPixel c = s[i]; - c.ToXyzBytes(d, i * 4); + int i3 = i * 3; + c.ToRgb24(ref rgb); + d[i3] = rgb.R; + d[i3 + 1] = rgb.G; + d[i3 + 2] = rgb.B; } } diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs index 603289763..150b55aed 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs @@ -40,11 +40,17 @@ namespace SixLabors.ImageSharp.Benchmarks.Color.Bulk { TPixel[] s = this.source.Array; byte[] d = this.destination.Array; + var rgba = default(Rgba32); for (int i = 0; i < this.Count; i++) { TPixel c = s[i]; - c.ToXyzwBytes(d, i * 4); + int i4 = i * 4; + c.ToRgba32(ref rgba); + d[i4] = rgba.R; + d[i4 + 1] = rgba.G; + d[i4 + 2] = rgba.B; + d[i4 + 3] = rgba.A; } } diff --git a/tests/ImageSharp.Benchmarks/General/Block8x8F_Round.cs b/tests/ImageSharp.Benchmarks/General/Block8x8F_Round.cs index 2739877a6..d101bf050 100644 --- a/tests/ImageSharp.Benchmarks/General/Block8x8F_Round.cs +++ b/tests/ImageSharp.Benchmarks/General/Block8x8F_Round.cs @@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General for (int i = 0; i < Block8x8F.Size; i++) { ref float v = ref Unsafe.Add(ref b, i); - v = MathF.Round(v); + v = (float)Math.Round(v); } } diff --git a/tests/ImageSharp.Benchmarks/Image/DecodePng.cs b/tests/ImageSharp.Benchmarks/Image/DecodePng.cs index b9a9d5cfa..eb13cf929 100644 --- a/tests/ImageSharp.Benchmarks/Image/DecodePng.cs +++ b/tests/ImageSharp.Benchmarks/Image/DecodePng.cs @@ -10,29 +10,39 @@ namespace SixLabors.ImageSharp.Benchmarks.Image using BenchmarkDotNet.Attributes; + using SixLabors.ImageSharp.Tests; + using CoreImage = ImageSharp.Image; using CoreSize = SixLabors.Primitives.Size; + [Config(typeof(Config.ShortClr))] public class DecodePng : BenchmarkBase { private byte[] pngBytes; + private string TestImageFullPath => Path.Combine( + TestEnvironment.InputImagesDirectoryFullPath, + this.TestImage); + + [Params(TestImages.Png.Splash)] + public string TestImage { get; set; } + [GlobalSetup] public void ReadImages() { if (this.pngBytes == null) { - this.pngBytes = File.ReadAllBytes("../ImageSharp.Tests/TestImages/Formats/Png/splash.png"); + this.pngBytes = File.ReadAllBytes(this.TestImageFullPath); } } [Benchmark(Baseline = true, Description = "System.Drawing Png")] public Size PngSystemDrawing() { - using (MemoryStream memoryStream = new MemoryStream(this.pngBytes)) + using (var memoryStream = new MemoryStream(this.pngBytes)) { - using (Image image = Image.FromStream(memoryStream)) + using (var image = Image.FromStream(memoryStream)) { return image.Size; } @@ -42,9 +52,9 @@ namespace SixLabors.ImageSharp.Benchmarks.Image [Benchmark(Description = "ImageSharp Png")] public CoreSize PngCore() { - using (MemoryStream memoryStream = new MemoryStream(this.pngBytes)) + using (var memoryStream = new MemoryStream(this.pngBytes)) { - using (Image image = CoreImage.Load(memoryStream)) + using (var image = CoreImage.Load(memoryStream)) { return new CoreSize(image.Width, image.Height); } diff --git a/tests/ImageSharp.Benchmarks/Samplers/Glow.cs b/tests/ImageSharp.Benchmarks/Samplers/Glow.cs index 884ae3501..1f88c4fbf 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Glow.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Glow.cs @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Benchmarks int endX = sourceRectangle.Right; TPixel glowColor = this.GlowColor; Vector2 centre = Rectangle.Center(sourceRectangle); - float maxDistance = this.Radius > 0 ? MathF.Min(this.Radius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F; + float maxDistance = this.Radius > 0 ? Math.Min(this.Radius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F; // Align start/end positions. int minX = Math.Max(0, startX); @@ -136,13 +136,13 @@ namespace SixLabors.ImageSharp.Benchmarks amount = amount.Clamp(0, 1); // Santize on zero alpha - if (MathF.Abs(backdrop.W) < Constants.Epsilon) + if (Math.Abs(backdrop.W) < Constants.Epsilon) { source.W *= amount; return source; } - if (MathF.Abs(source.W) < Constants.Epsilon) + if (Math.Abs(source.W) < Constants.Epsilon) { return backdrop; } diff --git a/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs b/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs index 15a794144..8014925e2 100644 --- a/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs +++ b/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs @@ -22,9 +22,9 @@ namespace SixLabors.ImageSharp.Tests.Common this.Output = output; } - private static int R(float f) => (int)MathF.Round(f, MidpointRounding.AwayFromZero); + private static int R(float f) => (int)Math.Round(f, MidpointRounding.AwayFromZero); - private static int Re(float f) => (int)MathF.Round(f, MidpointRounding.ToEven); + private static int Re(float f) => (int)Math.Round(f, MidpointRounding.ToEven); // TODO: Move this to a proper test class! [Theory] @@ -168,7 +168,7 @@ namespace SixLabors.ImageSharp.Tests.Common Assert.Equal(expected, dest); } - private static float Clamp255(float x) => MathF.Min(255f, MathF.Max(0f, x)); + private static float Clamp255(float x) => Math.Min(255f, Math.Max(0f, x)); [Theory] [InlineData(1, 0)] diff --git a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs index c210b66ed..be7c8adb0 100644 --- a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs @@ -81,13 +81,13 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (PixelAccessor sourcePixels = image.Lock()) { - Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); + Assert.True(Rgba32.HotPink == sourcePixels[11, 11], "[11, 11] wrong"); - Assert.Equal(Rgba32.HotPink, sourcePixels[199, 150]); + Assert.True(Rgba32.HotPink == sourcePixels[199, 149], "[199, 149] wrong"); - Assert.Equal(Rgba32.HotPink, sourcePixels[50, 50]); + Assert.True(Rgba32.HotPink == sourcePixels[50, 50], "[50, 50] wrong"); - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); + Assert.True(Rgba32.Blue == sourcePixels[2, 2], "[2, 2] wrong"); } } } diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs index cd78add75..76a31c186 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs @@ -10,12 +10,16 @@ using Xunit; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests { + using SixLabors.ImageSharp.Advanced; + public class GifDecoderTests { private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32 | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32; public static readonly string[] TestFiles = { TestImages.Gif.Giphy, TestImages.Gif.Rings, TestImages.Gif.Trans }; + public static readonly string[] BadAppExtFiles = { TestImages.Gif.Issues.BadAppExtLength, TestImages.Gif.Issues.BadAppExtLength_2 }; + [Theory] [WithFileCollection(nameof(TestFiles), PixelTypes)] public void DecodeAndReSave(TestImageProvider imageProvider) @@ -27,6 +31,7 @@ namespace SixLabors.ImageSharp.Tests imageProvider.Utility.SaveTestOutputFile(image, "gif"); } } + [Theory] [WithFileCollection(nameof(TestFiles), PixelTypes)] public void DecodeResizeAndSave(TestImageProvider imageProvider) @@ -113,5 +118,43 @@ namespace SixLabors.ImageSharp.Tests Assert.True(image.Frames.Count > 1); } } + + [Fact] + public void CanDecodeIntermingledImages() + { + using (var kumin1 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes)) + using (var icon = Image.Load(TestFile.Create(TestImages.Png.Icon).Bytes)) + using (var kumin2 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes)) + { + for (int i = 0; i < kumin1.Frames.Count; i++) + { + ImageFrame first = kumin1.Frames[i]; + ImageFrame second = kumin2.Frames[i]; + first.ComparePixelBufferTo(second.GetPixelSpan()); + } + } + } + + [Theory] + [WithFileCollection(nameof(BadAppExtFiles), PixelTypes.Rgba32)] + public void DecodeBadApplicationExtensionLength(TestImageProvider imageProvider) + where TPixel : struct, IPixel + { + using (Image image = imageProvider.GetImage()) + { + imageProvider.Utility.SaveTestOutputFile(image, "bmp"); + } + } + + [Theory] + [WithFile(TestImages.Gif.Issues.BadDescriptorWidth, PixelTypes.Rgba32)] + public void DecodeBadDescriptorDimensionsLength(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + provider.Utility.SaveTestOutputFile(image, "bmp"); + } + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs index bf5507676..8c12b0050 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs @@ -335,7 +335,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg for (int i = 0; i < 64; i++) { - float expected = MathF.Round(s[i]); + float expected = (float)Math.Round(s[i]); float actual = d[i]; Assert.Equal(expected, actual); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index 46f137f81..7e0dc915c 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -236,11 +236,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg float cr = values.Component2[i] - 128F; float k = values.Component3[i] / 255F; - v.X = (255F - MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; - v.Y = (255F - MathF.Round( + v.X = (255F - (float)Math.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; + v.Y = (255F - (float)Math.Round( y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero)) * k; - v.Z = (255F - MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; + v.Z = (255F - (float)Math.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; v.W = 1F; v *= scale; diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs index e26ab2cc9..d529bbaeb 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -42,6 +42,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Baseline.Jpeg444, TestImages.Jpeg.Baseline.Bad.BadEOF, TestImages.Jpeg.Baseline.Bad.ExifUndefType, + TestImages.Jpeg.Issues.MultiHuffmanBaseline394, }; public static string[] ProgressiveTestJpegs = @@ -50,6 +51,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Progressive.Festzug, TestImages.Jpeg.Progressive.Bad.BadEOF, TestImages.Jpeg.Issues.BadCoeffsProgressive178, TestImages.Jpeg.Issues.MissingFF00ProgressiveGirl159, + TestImages.Jpeg.Issues.BadZigZagProgressive385 }; private static readonly Dictionary CustomToleranceValues = new Dictionary @@ -67,6 +69,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [TestImages.Jpeg.Progressive.Festzug] = 0.02f / 100, [TestImages.Jpeg.Progressive.Fb] = 0.16f / 100, [TestImages.Jpeg.Progressive.Progress] = 0.31f / 100, + [TestImages.Jpeg.Issues.BadZigZagProgressive385] = 0.23f / 100, }; public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.RgbaVector; diff --git a/tests/ImageSharp.Tests/Helpers/MathFTests.cs b/tests/ImageSharp.Tests/Helpers/MathFTests.cs deleted file mode 100644 index f865353c4..000000000 --- a/tests/ImageSharp.Tests/Helpers/MathFTests.cs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Helpers -{ - public class MathFTests - { - [Fact] - public void MathF_PI_Is_Equal() - { - Assert.Equal(MathF.PI, (float)Math.PI); - } - - [Fact] - public void MathF_Ceililng_Is_Equal() - { - Assert.Equal(MathF.Ceiling(0.3333F), (float)Math.Ceiling(0.3333F)); - } - - [Fact] - public void MathF_Cos_Is_Equal() - { - Assert.Equal(MathF.Cos(0.3333F), (float)Math.Cos(0.3333F)); - } - - [Fact] - public void MathF_Abs_Is_Equal() - { - Assert.Equal(MathF.Abs(-0.3333F), (float)Math.Abs(-0.3333F)); - } - - [Fact] - public void MathF_Atan2_Is_Equal() - { - Assert.Equal(MathF.Atan2(1.2345F, 1.2345F), (float)Math.Atan2(1.2345F, 1.2345F)); - } - - [Fact] - public void MathF_Exp_Is_Equal() - { - Assert.Equal(MathF.Exp(1.2345F), (float)Math.Exp(1.2345F)); - } - - [Fact] - public void MathF_Floor_Is_Equal() - { - Assert.Equal(MathF.Floor(1.2345F), (float)Math.Floor(1.2345F)); - } - - [Fact] - public void MathF_Min_Is_Equal() - { - Assert.Equal(MathF.Min(1.2345F, 5.4321F), (float)Math.Min(1.2345F, 5.4321F)); - } - - [Fact] - public void MathF_Max_Is_Equal() - { - Assert.Equal(MathF.Max(1.2345F, 5.4321F), (float)Math.Max(1.2345F, 5.4321F)); - } - - [Fact] - public void MathF_Pow_Is_Equal() - { - Assert.Equal(MathF.Pow(1.2345F, 5.4321F), (float)Math.Pow(1.2345F, 5.4321F)); - } - - [Fact] - public void MathF_Round_Is_Equal() - { - Assert.Equal(MathF.Round(1.2345F), (float)Math.Round(1.2345F)); - } - - [Fact] - public void MathF_Round_With_Midpoint_Is_Equal() - { - Assert.Equal(MathF.Round(1.2345F, MidpointRounding.AwayFromZero), (float)Math.Round(1.2345F, MidpointRounding.AwayFromZero)); - } - - [Fact] - public void MathF_Sin_Is_Equal() - { - Assert.Equal(MathF.Sin(1.2345F), (float)Math.Sin(1.2345F)); - } - - [Fact] - public void MathF_SinC_Is_Equal() - { - float f = 1.2345F; - float expected = 1F; - if (Math.Abs(f) > Constants.Epsilon) - { - f *= (float)Math.PI; - float sinC = (float)Math.Sin(f) / f; - - expected = Math.Abs(sinC) < Constants.Epsilon ? 0F : sinC; - } - - Assert.Equal(MathF.SinC(1.2345F), expected); - } - - [Fact] - public void MathF_Sqrt_Is_Equal() - { - Assert.Equal(MathF.Sqrt(2F), (float)Math.Sqrt(2F)); - } - - [Fact] - public void Convert_Degree_To_Radian() - { - Assert.Equal((float)(Math.PI / 2D), MathF.DegreeToRadian(90F), new FloatRoundingComparer(6)); - } - - [Fact] - public void Convert_Radian_To_Degree() - { - Assert.Equal(60F, MathF.RadianToDegree((float)(Math.PI / 3D)), new FloatRoundingComparer(5)); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Issues/Issue412.cs b/tests/ImageSharp.Tests/Issues/Issue412.cs new file mode 100644 index 000000000..b77112ba6 --- /dev/null +++ b/tests/ImageSharp.Tests/Issues/Issue412.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Text; +using SixLabors.Primitives; +using SixLabors.ImageSharp.Advanced; +using Xunit; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Tests.Issues +{ + public class Issue412 + { + [Theory] + [WithBlankImages(40, 30, PixelTypes.Rgba32)] + public void AllPixelsExpectedToBeRedWhenAntialisedDisabled(TestImageProvider provider) where TPixel : struct, IPixel + { + using (var image = provider.GetImage()) + { + image.Mutate( + context => + { + for (var i = 0; i < 40; ++i) + { + context.DrawLines( + NamedColors.Black, + 1, + new[] + { + new PointF(i, 0.1066f), + new PointF(i, 10.1066f) + }, + new GraphicsOptions(true)); + + context.DrawLines( + NamedColors.Red, + 1, + new[] + { + new PointF(i, 15.1066f), + new PointF(i, 25.1066f) + }, + new GraphicsOptions(false)); + } + }); + + image.DebugSave(provider); + for (var y = 15; y < 25; y++) + { + for (var x = 0; x < 40; x++) + { + + Assert.True(NamedColors.Red.Equals(image[x, y]), $"expected {NamedColors.Red} but found {image[x, y]} at [{x}, {y}]"); + } + } + } + } + } +} diff --git a/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs b/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs index 303905baf..9b6d53fd9 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Diagnostics; using System.Numerics; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -34,29 +33,29 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.Equal(26, new Alpha8(0.1F).PackedValue); // Test ordering - Vector4 vector = new Alpha8(.5F).ToVector4(); + var vector = new Alpha8(.5F).ToVector4(); Assert.Equal(0, vector.X); Assert.Equal(0, vector.Y); Assert.Equal(0, vector.Z); Assert.Equal(.5F, vector.W, 2); - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new Alpha8(.5F).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 0, 0, 0 }); + new Alpha8(.5F).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(0, 0, 0)); - new Alpha8(.5F).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 0, 0, 0, 128 }); + new Alpha8(.5F).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(0, 0, 0, 128)); - new Alpha8(.5F).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 0, 0, 0 }); + new Alpha8(.5F).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(0, 0, 0)); - new Alpha8(.5F).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 0, 0, 0, 128 }); + new Alpha8(.5F).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(0, 0, 0, 128)); } [Fact] @@ -82,26 +81,26 @@ namespace SixLabors.ImageSharp.Tests.Colors float y = -0.3f; float z = +0.5f; float w = -0.7f; - Argb32 argb = new Argb32(x, y, z, w); + var argb = new Argb32(x, y, z, w); Assert.Equal(0x001a0080u, argb.PackedValue); // Test ordering - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - argb.ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 0x1a, 0, 0x80 }); + argb.ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(0x1a, 0, 0x80)); - argb.ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 0x1a, 0, 0x80, 0 }); + argb.ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(0x1a, 0, 0x80, 0)); - argb.ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 0x80, 0, 0x1a }); + argb.ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(0x1a, 0, 0x80)); - argb.ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 0x80, 0, 0x1a, 0 }); + argb.ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(0x1a, 0, 0x80, 0)); } [Fact] @@ -133,22 +132,22 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.Equal(6160, new Bgr565(x, y, z).PackedValue); // Test ordering - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new Bgr565(x, y, z).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 25, 0, 132 }); + new Bgr565(x, y, z).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(25, 0, 132)); - new Bgr565(x, y, z).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 25, 0, 132, 255 }); + new Bgr565(x, y, z).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(25, 0, 132, 255)); - new Bgr565(x, y, z).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 132, 0, 25 }); + new Bgr565(x, y, z).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(25, 0, 132)); - new Bgr565(x, y, z).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 132, 0, 25, 255 }); + new Bgr565(x, y, z).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(25, 0, 132, 255)); } [Fact] @@ -183,22 +182,22 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.Equal(520, new Bgra4444(x, y, z, w).PackedValue); // Test ordering - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new Bgra4444(x, y, z, w).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 34, 0, 136 }); + new Bgra4444(x, y, z, w).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(34, 0, 136)); - new Bgra4444(x, y, z, w).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 34, 0, 136, 0 }); + new Bgra4444(x, y, z, w).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(34, 0, 136, 0)); - new Bgra4444(x, y, z, w).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 136, 0, 34 }); + new Bgra4444(x, y, z, w).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(34, 0, 136)); - new Bgra4444(x, y, z, w).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 136, 0, 34, 0 }); + new Bgra4444(x, y, z, w).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(34, 0, 136, 0)); } [Fact] @@ -229,22 +228,22 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.Equal(3088, new Bgra5551(x, y, z, w).PackedValue); // Test ordering - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new Bgra5551(x, y, z, w).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 24, 0, 131 }); + new Bgra5551(x, y, z, w).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(24, 0, 131)); - new Bgra5551(x, y, z, w).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 24, 0, 131, 0 }); + new Bgra5551(x, y, z, w).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(24, 0, 131, 0)); - new Bgra5551(x, y, z, w).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 131, 0, 24 }); + new Bgra5551(x, y, z, w).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(24, 0, 131)); - new Bgra5551(x, y, z, w).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 131, 0, 24, 0 }); + new Bgra5551(x, y, z, w).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(24, 0, 131, 0)); } [Fact] @@ -280,27 +279,27 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.Equal((uint)128, new Byte4(x, y, z, w).PackedValue); // Test ordering - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new Byte4(x, y, z, w).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 128, 0, 0 }); + new Byte4(x, y, z, w).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(128, 0, 0)); - new Byte4(x, y, z, w).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 128, 0, 0, 0 }); + new Byte4(x, y, z, w).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(128, 0, 0, 0)); - new Byte4(x, y, z, w).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 0, 0, 128 }); + new Byte4(x, y, z, w).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(128, 0, 0)); - new Byte4(x, y, z, w).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 0, 0, 128, 0 }); + new Byte4(x, y, z, w).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(128, 0, 0, 0)); - Byte4 r = new Byte4(); + var r = new Byte4(); r.PackFromRgba32(new Rgba32(20, 38, 0, 255)); - r.ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 }); + r.ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(20, 38, 0, 255)); } [Fact] @@ -319,22 +318,22 @@ namespace SixLabors.ImageSharp.Tests.Colors float x = .5F; Assert.True(Equal(new Vector4(x, 0, 0, 1), new HalfSingle(x).ToVector4())); - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new HalfSingle(x).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 128, 0, 0 }); + new HalfSingle(x).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(128, 0, 0)); - new HalfSingle(x).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 128, 0, 0, 255 }); + new HalfSingle(x).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(128, 0, 0, 255)); - new HalfSingle(x).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 0, 0, 128 }); + new HalfSingle(x).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(128, 0, 0)); - new HalfSingle(x).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 0, 0, 128, 255 }); + new HalfSingle(x).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(128, 0, 0, 255)); } [Fact] @@ -356,22 +355,22 @@ namespace SixLabors.ImageSharp.Tests.Colors float y = .25F; Assert.True(Equal(new Vector4(x, y, 0, 1), new HalfVector2(x, y).ToVector4())); - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new HalfVector2(x, y).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 128, 64, 0 }); + new HalfVector2(x, y).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(128, 64, 0)); - new HalfVector2(x, y).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 128, 64, 0, 255 }); + new HalfVector2(x, y).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(128, 64, 0, 255)); - new HalfVector2(x, y).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 0, 64, 128 }); + new HalfVector2(x, y).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(128, 64, 0)); - new HalfVector2(x, y).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 0, 64, 128, 255 }); + new HalfVector2(x, y).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(128, 64, 0, 255)); } [Fact] @@ -402,22 +401,22 @@ namespace SixLabors.ImageSharp.Tests.Colors float z = .75F; float w = 1F; - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new HalfVector4(x, y, z, w).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 64, 128, 191 }); + new HalfVector4(x, y, z, w).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(64, 128, 191)); - new HalfVector4(x, y, z, w).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 64, 128, 191, 255 }); + new HalfVector4(x, y, z, w).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(64, 128, 191, 255)); - new HalfVector4(x, y, z, w).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 191, 128, 64 }); + new HalfVector4(x, y, z, w).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(64, 128, 191)); - new HalfVector4(x, y, z, w).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 191, 128, 64, 255 }); + new HalfVector4(x, y, z, w).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(64, 128, 191, 255)); } [Fact] @@ -443,26 +442,26 @@ namespace SixLabors.ImageSharp.Tests.Colors float x = 0.1f; float y = -0.3f; Assert.Equal(0xda0d, new NormalizedByte2(x, y).PackedValue); - NormalizedByte2 n = new NormalizedByte2(); + var n = new NormalizedByte2(); n.PackFromRgba32(new Rgba32(141, 90, 0, 0)); Assert.Equal(0xda0d, n.PackedValue); - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new NormalizedByte2(x, y).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 141, 90, 0 }); + new NormalizedByte2(x, y).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(141, 90, 0)); - new NormalizedByte2(x, y).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 141, 90, 0, 255 }); + new NormalizedByte2(x, y).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(141, 90, 0, 255)); - new NormalizedByte2(x, y).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 0, 90, 141 }); + new NormalizedByte2(x, y).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(141, 90, 0)); - new NormalizedByte2(x, y).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 0, 90, 141, 255 }); + new NormalizedByte2(x, y).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(141, 90, 0, 255)); } [Fact] @@ -486,38 +485,38 @@ namespace SixLabors.ImageSharp.Tests.Colors float z = 0.5f; float w = -0.7f; Assert.Equal(0xA740DA0D, new NormalizedByte4(x, y, z, w).PackedValue); - NormalizedByte4 n = new NormalizedByte4(); + var n = new NormalizedByte4(); n.PackFromRgba32(new Rgba32(141, 90, 192, 39)); Assert.Equal(0xA740DA0D, n.PackedValue); Assert.Equal((uint)958796544, new NormalizedByte4(0.0008f, 0.15f, 0.30f, 0.45f).PackedValue); - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new NormalizedByte4(x, y, z, w).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 141, 90, 192 }); + new NormalizedByte4(x, y, z, w).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(141, 90, 192)); - new NormalizedByte4(x, y, z, w).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 141, 90, 192, 39 }); + new NormalizedByte4(x, y, z, w).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(141, 90, 192, 39)); - new NormalizedByte4(x, y, z, w).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 192, 90, 141 }); + new NormalizedByte4(x, y, z, w).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(141, 90, 192)); - new NormalizedByte4(x, y, z, w).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 192, 90, 141, 39 }); + new NormalizedByte4(x, y, z, w).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(141, 90, 192, 39)); // http://community.monogame.net/t/normalizedbyte4-texture2d-gives-different-results-from-xna/8012/8 - NormalizedByte4 r = new NormalizedByte4(); + var r = new NormalizedByte4(); r.PackFromRgba32(new Rgba32(9, 115, 202, 127)); - r.ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 9, 115, 202, 127 }); + r.ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(9, 115, 202, 127)); r.PackedValue = 0xff4af389; - r.ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 9, 115, 202, 127 }); + r.ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(9, 115, 202, 127)); } [Fact] @@ -544,30 +543,30 @@ namespace SixLabors.ImageSharp.Tests.Colors y = -0.3f; Assert.Equal(3650751693, new NormalizedShort2(x, y).PackedValue); - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - NormalizedShort2 n = new NormalizedShort2(); + var n = new NormalizedShort2(); n.PackFromRgba32(new Rgba32(141, 90, 0, 0)); - n.ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 141, 90, 0 }); + n.ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(141, 90, 0)); // TODO: I don't think this can ever pass since the bytes are already truncated. // Assert.Equal(3650751693, n.PackedValue); - new NormalizedShort2(x, y).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 141, 90, 0 }); + new NormalizedShort2(x, y).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(141, 90, 0)); - new NormalizedShort2(x, y).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 141, 90, 0, 255 }); + new NormalizedShort2(x, y).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(141, 90, 0, 255)); - new NormalizedShort2(x, y).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 0, 90, 141 }); + new NormalizedShort2(x, y).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(141, 90, 0)); - new NormalizedShort2(x, y).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 0, 90, 141, 255 }); + new NormalizedShort2(x, y).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(141, 90, 0, 255)); } [Fact] @@ -593,27 +592,27 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.Equal(0xa6674000d99a0ccd, new NormalizedShort4(x, y, z, w).PackedValue); Assert.Equal((ulong)4150390751449251866, new NormalizedShort4(0.0008f, 0.15f, 0.30f, 0.45f).PackedValue); - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new NormalizedShort4(x, y, z, w).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 141, 90, 192 }); + new NormalizedShort4(x, y, z, w).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(141, 90, 192)); - new NormalizedShort4(x, y, z, w).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 141, 90, 192, 39 }); + new NormalizedShort4(x, y, z, w).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(141, 90, 192, 39)); - new NormalizedShort4(x, y, z, w).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 192, 90, 141 }); + new NormalizedShort4(x, y, z, w).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(141, 90, 192)); - new NormalizedShort4(x, y, z, w).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 192, 90, 141, 39 }); + new NormalizedShort4(x, y, z, w).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(141, 90, 192, 39)); - NormalizedShort4 r = new NormalizedShort4(); + var r = new NormalizedShort4(); r.PackFromRgba32(new Rgba32(9, 115, 202, 127)); - r.ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 9, 115, 202, 127 }); + r.ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(9, 115, 202, 127)); } [Fact] @@ -640,22 +639,22 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.Equal((uint)6554, new Rg32(x, y).PackedValue); // Test ordering - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new Rg32(x, y).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 25, 0, 0 }); + new Rg32(x, y).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(25, 0, 0)); - new Rg32(x, y).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 25, 0, 0, 255 }); + new Rg32(x, y).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(25, 0, 0, 255)); - new Rg32(x, y).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 0, 0, 25 }); + new Rg32(x, y).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(25, 0, 0)); - new Rg32(x, y).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 0, 0, 25, 255 }); + new Rg32(x, y).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(25, 0, 0, 255)); } [Fact] @@ -685,28 +684,28 @@ namespace SixLabors.ImageSharp.Tests.Colors w = -0.7f; Assert.Equal((uint)536871014, new Rgba1010102(x, y, z, w).PackedValue); - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new Rgba1010102(x, y, z, w).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 25, 0, 128 }); + new Rgba1010102(x, y, z, w).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(25, 0, 128)); - new Rgba1010102(x, y, z, w).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 25, 0, 128, 0 }); + new Rgba1010102(x, y, z, w).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(25, 0, 128, 0)); - new Rgba1010102(x, y, z, w).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 128, 0, 25 }); + new Rgba1010102(x, y, z, w).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(25, 0, 128)); - new Rgba1010102(x, y, z, w).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 128, 0, 25, 0 }); + new Rgba1010102(x, y, z, w).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(25, 0, 128, 0)); // Alpha component accuracy will be awful. - Rgba1010102 r = new Rgba1010102(); + var r = new Rgba1010102(); r.PackFromRgba32(new Rgba32(25, 0, 128, 0)); - r.ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 25, 0, 128, 0 }); + r.ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(25, 0, 128, 0)); } [Fact] @@ -732,26 +731,26 @@ namespace SixLabors.ImageSharp.Tests.Colors float y = -0.3f; float z = +0.5f; float w = -0.7f; - Rgba32 rgba32 = new Rgba32(x, y, z, w); + var rgba32 = new Rgba32(x, y, z, w); Assert.Equal(0x80001Au, rgba32.PackedValue); // Test ordering - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - rgba32.ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 0x1a, 0, 0x80 }); + rgba32.ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(0x1a, 0, 0x80)); - rgba32.ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 0x1a, 0, 0x80, 0 }); + rgba32.ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(0x1a, 0, 0x80, 0)); - rgba32.ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 0x80, 0, 0x1a }); + rgba32.ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(0x1a, 0, 0x80)); - rgba32.ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 0x80, 0, 0x1a, 0 }); + rgba32.ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(0x1a, 0, 0x80, 0)); } [Fact] @@ -779,27 +778,27 @@ namespace SixLabors.ImageSharp.Tests.Colors float w = 0.45f; Assert.Equal((ulong)0x73334CCC2666147B, new Rgba64(x, y, z, w).PackedValue); - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new Rgba64(x, y, z, w).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 20, 38, 76 }); + new Rgba64(x, y, z, w).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(20, 38, 76)); - new Rgba64(x, y, z, w).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 20, 38, 76, 115 }); + new Rgba64(x, y, z, w).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(20, 38, 76, 115)); - new Rgba64(x, y, z, w).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 76, 38, 20 }); + new Rgba64(x, y, z, w).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(20, 38, 76)); - new Rgba64(x, y, z, w).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 76, 38, 20, 115 }); + new Rgba64(x, y, z, w).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(20, 38, 76, 115)); - Rgba64 r = new Rgba64(); + var r = new Rgba64(); r.PackFromRgba32(new Rgba32(20, 38, 76, 115)); - r.ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 20, 38, 76, 115 }); + r.ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(20, 38, 76, 115)); } [Fact] @@ -834,27 +833,27 @@ namespace SixLabors.ImageSharp.Tests.Colors y = -5.3f; Assert.Equal(4294639744, new Short2(x, y).PackedValue); - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new Short2(x, y).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 128, 127, 0 }); + new Short2(x, y).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(128, 127, 0)); - new Short2(x, y).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 128, 127, 0, 255 }); + new Short2(x, y).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(128, 127, 0, 255)); - new Short2(x, y).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 0, 127, 128 }); + new Short2(x, y).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(128, 127, 0)); - new Short2(x, y).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 0, 127, 128, 255 }); + new Short2(x, y).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(128, 127, 0, 255)); - Short2 r = new Short2(); + var r = new Short2(); r.PackFromRgba32(new Rgba32(20, 38, 0, 255)); - r.ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 }); + r.ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(20, 38, 0, 255)); } [Fact] @@ -891,27 +890,27 @@ namespace SixLabors.ImageSharp.Tests.Colors w = 193; Assert.Equal((ulong)0x00c173b7316d2d1b, new Short4(x, y, z, w).PackedValue); - byte[] rgb = new byte[3]; - byte[] rgba = new byte[4]; - byte[] bgr = new byte[3]; - byte[] bgra = new byte[4]; + var rgb = default(Rgb24); + var rgba = default(Rgba32); + var bgr = default(Bgr24); + var bgra = default(Bgra32); - new Short4(x, y, z, w).ToXyzBytes(rgb, 0); - Assert.Equal(rgb, new byte[] { 172, 177, 243 }); + new Short4(x, y, z, w).ToRgb24(ref rgb); + Assert.Equal(rgb, new Rgb24(172, 177, 243)); - new Short4(x, y, z, w).ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 172, 177, 243, 128 }); + new Short4(x, y, z, w).ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(172, 177, 243, 128)); - new Short4(x, y, z, w).ToZyxBytes(bgr, 0); - Assert.Equal(bgr, new byte[] { 243, 177, 172 }); + new Short4(x, y, z, w).ToBgr24(ref bgr); + Assert.Equal(bgr, new Bgr24(172, 177, 243)); - new Short4(x, y, z, w).ToZyxwBytes(bgra, 0); - Assert.Equal(bgra, new byte[] { 243, 177, 172, 128 }); + new Short4(x, y, z, w).ToBgra32(ref bgra); + Assert.Equal(bgra, new Bgra32(172, 177, 243, 128)); - Short4 r = new Short4(); + var r = new Short4(); r.PackFromRgba32(new Rgba32(20, 38, 0, 255)); - r.ToXyzwBytes(rgba, 0); - Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 }); + r.ToRgba32(ref rgba); + Assert.Equal(rgba, new Rgba32(20, 38, 0, 255)); } // Comparison helpers with small tolerance to allow for floating point rounding during computations. diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs index dbb9a6c24..0fde67d28 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs @@ -173,11 +173,15 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { TPixel[] source = CreatePixelTestData(count); byte[] expected = new byte[count * 3]; + var rgb = default(Rgb24); for (int i = 0; i < count; i++) { int i3 = i * 3; - source[i].ToXyzBytes(expected, i3); + source[i].ToRgb24(ref rgb); + expected[i3] = rgb.R; + expected[i3 + 1] = rgb.G; + expected[i3 + 2] = rgb.B; } TestOperation( @@ -214,11 +218,16 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { TPixel[] source = CreatePixelTestData(count); byte[] expected = new byte[count * 4]; + var rgba = default(Rgba32); for (int i = 0; i < count; i++) { int i4 = i * 4; - source[i].ToXyzwBytes(expected, i4); + source[i].ToRgba32(ref rgba); + expected[i4] = rgba.R; + expected[i4 + 1] = rgba.G; + expected[i4 + 2] = rgba.B; + expected[i4 + 3] = rgba.A; } TestOperation( @@ -255,11 +264,15 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { TPixel[] source = CreatePixelTestData(count); byte[] expected = new byte[count * 3]; + var bgr = default(Bgr24); for (int i = 0; i < count; i++) { int i3 = i * 3; - source[i].ToZyxBytes(expected, i3); + source[i].ToBgr24(ref bgr); + expected[i3] = bgr.B; + expected[i3 + 1] = bgr.G; + expected[i3 + 2] = bgr.R; } TestOperation( @@ -296,11 +309,16 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { TPixel[] source = CreatePixelTestData(count); byte[] expected = new byte[count * 4]; + var bgra = default(Bgra32); for (int i = 0; i < count; i++) { int i4 = i * 4; - source[i].ToZyxwBytes(expected, i4); + source[i].ToBgra32(ref bgra); + expected[i4] = bgra.B; + expected[i4 + 1] = bgra.G; + expected[i4 + 2] = bgra.R; + expected[i4 + 3] = bgra.A; } TestOperation( diff --git a/tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs b/tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs index b5d46ba76..1fca398fc 100644 --- a/tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs @@ -12,8 +12,8 @@ namespace SixLabors.ImageSharp.Tests.Colors [Fact] public void Color_Types_From_Bytes_Produce_Equal_Scaled_Component_OutPut() { - Rgba32 color = new Rgba32(24, 48, 96, 192); - RgbaVector colorVector = new RgbaVector(24, 48, 96, 192); + var color = new Rgba32(24, 48, 96, 192); + var colorVector = new RgbaVector(24, 48, 96, 192); Assert.Equal(color.R, (byte)(colorVector.R * 255)); Assert.Equal(color.G, (byte)(colorVector.G * 255)); @@ -24,8 +24,8 @@ namespace SixLabors.ImageSharp.Tests.Colors [Fact] public void Color_Types_From_Floats_Produce_Equal_Scaled_Component_OutPut() { - Rgba32 color = new Rgba32(24 / 255F, 48 / 255F, 96 / 255F, 192 / 255F); - RgbaVector colorVector = new RgbaVector(24 / 255F, 48 / 255F, 96 / 255F, 192 / 255F); + var color = new Rgba32(24 / 255F, 48 / 255F, 96 / 255F, 192 / 255F); + var colorVector = new RgbaVector(24 / 255F, 48 / 255F, 96 / 255F, 192 / 255F); Assert.Equal(color.R, (byte)(colorVector.R * 255)); Assert.Equal(color.G, (byte)(colorVector.G * 255)); @@ -36,8 +36,8 @@ namespace SixLabors.ImageSharp.Tests.Colors [Fact] public void Color_Types_From_Vector4_Produce_Equal_Scaled_Component_OutPut() { - Rgba32 color = new Rgba32(new Vector4(24 / 255F, 48 / 255F, 96 / 255F, 192 / 255F)); - RgbaVector colorVector = new RgbaVector(new Vector4(24 / 255F, 48 / 255F, 96 / 255F, 192 / 255F)); + var color = new Rgba32(new Vector4(24 / 255F, 48 / 255F, 96 / 255F, 192 / 255F)); + var colorVector = new RgbaVector(new Vector4(24 / 255F, 48 / 255F, 96 / 255F, 192 / 255F)); Assert.Equal(color.R, (byte)(colorVector.R * 255)); Assert.Equal(color.G, (byte)(colorVector.G * 255)); @@ -48,8 +48,8 @@ namespace SixLabors.ImageSharp.Tests.Colors [Fact] public void Color_Types_From_Vector3_Produce_Equal_Scaled_Component_OutPut() { - Rgba32 color = new Rgba32(new Vector3(24 / 255F, 48 / 255F, 96 / 255F)); - RgbaVector colorVector = new RgbaVector(new Vector3(24 / 255F, 48 / 255F, 96 / 255F)); + var color = new Rgba32(new Vector3(24 / 255F, 48 / 255F, 96 / 255F)); + var colorVector = new RgbaVector(new Vector3(24 / 255F, 48 / 255F, 96 / 255F)); Assert.Equal(color.R, (byte)(colorVector.R * 255)); Assert.Equal(color.G, (byte)(colorVector.G * 255)); @@ -60,8 +60,8 @@ namespace SixLabors.ImageSharp.Tests.Colors [Fact] public void Color_Types_From_Hex_Produce_Equal_Scaled_Component_OutPut() { - Rgba32 color = Rgba32.FromHex("183060C0"); - RgbaVector colorVector = RgbaVector.FromHex("183060C0"); + var color = Rgba32.FromHex("183060C0"); + var colorVector = RgbaVector.FromHex("183060C0"); Assert.Equal(color.R, (byte)(colorVector.R * 255)); Assert.Equal(color.G, (byte)(colorVector.G * 255)); @@ -72,8 +72,8 @@ namespace SixLabors.ImageSharp.Tests.Colors [Fact] public void Color_Types_To_Vector4_Produce_Equal_OutPut() { - Rgba32 color = new Rgba32(24, 48, 96, 192); - RgbaVector colorVector = new RgbaVector(24, 48, 96, 192); + var color = new Rgba32(24, 48, 96, 192); + var colorVector = new RgbaVector(24, 48, 96, 192); Assert.Equal(color.ToVector4(), colorVector.ToVector4()); } @@ -81,14 +81,14 @@ namespace SixLabors.ImageSharp.Tests.Colors [Fact] public void Color_Types_To_RgbBytes_Produce_Equal_OutPut() { - Rgba32 color = new Rgba32(24, 48, 96, 192); - RgbaVector colorVector = new RgbaVector(24, 48, 96, 192); + var color = new Rgba32(24, 48, 96, 192); + var colorVector = new RgbaVector(24, 48, 96, 192); - byte[] rgb = new byte[3]; - byte[] rgbVector = new byte[3]; + var rgb = default(Rgb24); + var rgbVector = default(Rgb24); - color.ToXyzBytes(rgb, 0); - colorVector.ToXyzBytes(rgbVector, 0); + color.ToRgb24(ref rgb); + colorVector.ToRgb24(ref rgbVector); Assert.Equal(rgb, rgbVector); } @@ -96,14 +96,14 @@ namespace SixLabors.ImageSharp.Tests.Colors [Fact] public void Color_Types_To_RgbaBytes_Produce_Equal_OutPut() { - Rgba32 color = new Rgba32(24, 48, 96, 192); - RgbaVector colorVector = new RgbaVector(24, 48, 96, 192); + var color = new Rgba32(24, 48, 96, 192); + var colorVector = new RgbaVector(24, 48, 96, 192); - byte[] rgba = new byte[4]; - byte[] rgbaVector = new byte[4]; + var rgba = default(Rgba32); + var rgbaVector = default(Rgba32); - color.ToXyzwBytes(rgba, 0); - colorVector.ToXyzwBytes(rgbaVector, 0); + color.ToRgba32(ref rgba); + colorVector.ToRgba32(ref rgbaVector); Assert.Equal(rgba, rgbaVector); } @@ -111,14 +111,14 @@ namespace SixLabors.ImageSharp.Tests.Colors [Fact] public void Color_Types_To_BgrBytes_Produce_Equal_OutPut() { - Rgba32 color = new Rgba32(24, 48, 96, 192); - RgbaVector colorVector = new RgbaVector(24, 48, 96, 192); + var color = new Rgba32(24, 48, 96, 192); + var colorVector = new RgbaVector(24, 48, 96, 192); - byte[] bgr = new byte[3]; - byte[] bgrVector = new byte[3]; + var bgr = default(Bgr24); + var bgrVector = default(Bgr24); - color.ToZyxBytes(bgr, 0); - colorVector.ToZyxBytes(bgrVector, 0); + color.ToBgr24(ref bgr); + colorVector.ToBgr24(ref bgrVector); Assert.Equal(bgr, bgrVector); } @@ -126,14 +126,14 @@ namespace SixLabors.ImageSharp.Tests.Colors [Fact] public void Color_Types_To_BgraBytes_Produce_Equal_OutPut() { - Rgba32 color = new Rgba32(24, 48, 96, 192); - RgbaVector colorVector = new RgbaVector(24, 48, 96, 192); + var color = new Rgba32(24, 48, 96, 192); + var colorVector = new RgbaVector(24, 48, 96, 192); - byte[] bgra = new byte[4]; - byte[] bgraVector = new byte[4]; + var bgra = default(Bgra32); + var bgraVector = default(Bgra32); - color.ToZyxwBytes(bgra, 0); - colorVector.ToZyxwBytes(bgraVector, 0); + color.ToBgra32(ref bgra); + colorVector.ToBgra32(ref bgraVector); Assert.Equal(bgra, bgraVector); } @@ -141,8 +141,8 @@ namespace SixLabors.ImageSharp.Tests.Colors [Fact] public void Color_Types_To_Hex_Produce_Equal_OutPut() { - Rgba32 color = new Rgba32(24, 48, 96, 192); - RgbaVector colorVector = new RgbaVector(24, 48, 96, 192); + var color = new Rgba32(24, 48, 96, 192); + var colorVector = new RgbaVector(24, 48, 96, 192); // 183060C0 Assert.Equal(color.ToHex(), colorVector.ToHex()); diff --git a/tests/ImageSharp.Tests/Processing/Processors/ColorMatrix/GrayscaleTest.cs b/tests/ImageSharp.Tests/Processing/Processors/ColorMatrix/GrayscaleTest.cs index fe003da32..0fbc54b8f 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/ColorMatrix/GrayscaleTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/ColorMatrix/GrayscaleTest.cs @@ -31,13 +31,13 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.ColorMatrix using (Image image = provider.GetImage()) { image.Mutate(x => x.Grayscale(value)); - byte[] data = new byte[3]; + var rgb = default(Rgb24); System.Span span = image.Frames.RootFrame.GetPixelSpan(); for (int i = 0; i < span.Length; i++) { - span[i].ToXyzBytes(data, 0); - Assert.Equal(data[0], data[1]); - Assert.Equal(data[1], data[2]); + span[i].ToRgb24(ref rgb); + Assert.Equal(rgb.R, rgb.B); + Assert.Equal(rgb.B, rgb.G); } image.DebugSave(provider, value.ToString()); @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.ColorMatrix where TPixel : struct, IPixel { using (Image source = provider.GetImage()) - using (var image = source.Clone()) + using (Image image = source.Clone()) { var bounds = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2); image.Mutate(x => x.Grayscale(value, bounds)); diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index ed643c820..a5e21b8ef 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; + using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; @@ -245,7 +247,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { var options = new ResizeOptions { - Size = new Size((int)MathF.Round(image.Width * .75F), (int)MathF.Round(image.Height * .95F)), + Size = new Size((int)Math.Round(image.Width * .75F), (int)Math.Round(image.Height * .95F)), Mode = ResizeMode.Min }; diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 9137049ee..365aea04a 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -31,6 +31,7 @@ namespace SixLabors.ImageSharp.Tests public const string BikeGrayscale = "Png/BikeGrayscale.png"; public const string Rgb48BppInterlaced = "Png/rgb-48bpp-interlaced.png"; public const string SnakeGame = "Png/SnakeGame.png"; + public const string Icon = "Png/icon.png"; // Filtered test images from http://www.schaik.com/pngsuite/pngsuite_fil_png.html public const string Filter0 = "Png/filter0.png"; @@ -122,6 +123,8 @@ namespace SixLabors.ImageSharp.Tests public const string CriticalEOF214 = "Jpg/issues/Issue214-CriticalEOF.jpg"; public const string MissingFF00ProgressiveGirl159 = "Jpg/issues/Issue159-MissingFF00-Progressive-Girl.jpg"; public const string BadCoeffsProgressive178 = "Jpg/issues/Issue178-BadCoeffsProgressive-Lemon.jpg"; + public const string BadZigZagProgressive385 = "Jpg/issues/Issue385-BadZigZag-Progressive.jpg"; + public const string MultiHuffmanBaseline394 = "Jpg/issues/Issue394-MultiHuffmanBaseline-Speakers.jpg"; } public static readonly string[] All = Baseline.All.Concat(Progressive.All).ToArray(); @@ -152,8 +155,16 @@ namespace SixLabors.ImageSharp.Tests public const string Giphy = "Gif/giphy.gif"; public const string Cheers = "Gif/cheers.gif"; public const string Trans = "Gif/trans.gif"; + public const string Kumin = "Gif/kumin.gif"; - public static readonly string[] All = { Rings, Giphy, Cheers, Trans }; + public class Issues + { + public const string BadAppExtLength = "Gif/issues/issue405_badappextlength252.gif"; + public const string BadAppExtLength_2 = "Gif/issues/issue405_badappextlength252-2.gif"; + public const string BadDescriptorWidth = "Gif/issues/issue403_baddescriptorwidth.gif"; + } + + public static readonly string[] All = { Rings, Giphy, Cheers, Trans, Kumin }; } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 505cdc172..2b3cb1bcc 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -29,7 +29,6 @@ namespace SixLabors.ImageSharp.Tests /// The image provider /// Details to be concatenated to the test output file, describing the parameters of the test. /// The extension - /// A boolean indicating whether we should save a smaller in size. /// A boolean indicating whether to append the pixel type to the output file name. public static Image DebugSave( this Image image, diff --git a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs index 83997841a..a468c2116 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs @@ -54,8 +54,8 @@ namespace SixLabors.ImageSharp.Tests return false; } - byte[] bytesA = new byte[3]; - byte[] bytesB = new byte[3]; + var rgb1 = default(Rgb24); + var rgb2 = default(Rgb24); using (PixelAccessor pixA = a.Lock()) { @@ -77,12 +77,12 @@ namespace SixLabors.ImageSharp.Tests } else { - ca.ToXyzBytes(bytesA, 0); - cb.ToXyzBytes(bytesB, 0); + ca.ToRgb24(ref rgb1); + cb.ToRgb24(ref rgb2); - if (bytesA[0] != bytesB[0] || - bytesA[1] != bytesB[1] || - bytesA[2] != bytesB[2]) + if (rgb1.R != rgb2.R || + rgb1.G != rgb2.G || + rgb1.B != rgb2.B) { return false; } @@ -109,7 +109,7 @@ namespace SixLabors.ImageSharp.Tests /// public static PixelTypes GetPixelType(this Type colorStructClrType) => ClrTypes2PixelTypes[colorStructClrType]; - + public static IEnumerable> ExpandAllTypes(this PixelTypes pixelTypes) { diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs index 88d7fa2b8..e3249fae9 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Tests { Assert.Equal(expected, provider.PixelType); } - + [Theory] [WithFile(TestImages.Bmp.Car, PixelTypes.All, 88)] [WithFile(TestImages.Bmp.F, PixelTypes.All, 88)] @@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Tests } internal static int GetInvocationCount(string callerName) => invocationCounts[callerName]; - + private static readonly object Monitor = new object(); public static void DoTestThreadSafe(Action action) @@ -156,7 +156,7 @@ namespace SixLabors.ImageSharp.Tests } internal static int GetInvocationCount(string callerName) => invocationCounts[callerName]; - + private static readonly object Monitor = new object(); public static void DoTestThreadSafe(Action action) @@ -234,7 +234,7 @@ namespace SixLabors.ImageSharp.Tests Image image = provider.GetImage(); provider.Utility.SaveTestOutputFile(image, "png"); } - + [Theory] [WithSolidFilledImages(10, 20, 255, 100, 50, 200, PixelTypes.Rgba32 | PixelTypes.Argb32)] public void Use_WithSolidFilledImagesAttribute(TestImageProvider provider) @@ -244,7 +244,7 @@ namespace SixLabors.ImageSharp.Tests Assert.Equal(10, img.Width); Assert.Equal(20, img.Height); - byte[] colors = new byte[4]; + var rgba = default(Rgba32); using (PixelAccessor pixels = img.Lock()) { @@ -252,12 +252,12 @@ namespace SixLabors.ImageSharp.Tests { for (int x = 0; x < pixels.Width; x++) { - pixels[x, y].ToXyzwBytes(colors, 0); + pixels[x, y].ToRgba32(ref rgba); - Assert.Equal(255, colors[0]); - Assert.Equal(100, colors[1]); - Assert.Equal(50, colors[2]); - Assert.Equal(200, colors[3]); + Assert.Equal(255, rgba.R); + Assert.Equal(100, rgba.G); + Assert.Equal(50, rgba.B); + Assert.Equal(200, rgba.A); } } } diff --git a/tests/Images/External b/tests/Images/External index f99c2ea41..dc5479d00 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit f99c2ea41419cb3b3e80e5beeab611682252df78 +Subproject commit dc5479d00b2312f691e6249b9f7765e2316d4a30 diff --git a/tests/Images/Input/Gif/issues/issue403_baddescriptorwidth.gif b/tests/Images/Input/Gif/issues/issue403_baddescriptorwidth.gif new file mode 100644 index 000000000..0dce4b0ee --- /dev/null +++ b/tests/Images/Input/Gif/issues/issue403_baddescriptorwidth.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c108091ffddd87178378656e37a7e975aa69be56376b9105adbbc14fe8d9a010 +size 707660 diff --git a/tests/Images/Input/Gif/issues/issue405_badappextlength252-2.gif b/tests/Images/Input/Gif/issues/issue405_badappextlength252-2.gif new file mode 100644 index 000000000..98738c511 --- /dev/null +++ b/tests/Images/Input/Gif/issues/issue405_badappextlength252-2.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:151d394c7c57a1696fedc32116514b667ad70c4a2c7d34db7c489c17d5755eed +size 24724 diff --git a/tests/Images/Input/Gif/issues/issue405_badappextlength252.gif b/tests/Images/Input/Gif/issues/issue405_badappextlength252.gif new file mode 100644 index 000000000..6fbc3713f --- /dev/null +++ b/tests/Images/Input/Gif/issues/issue405_badappextlength252.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0549f4500693cdf7eac8351d8cd64d1093da9e9eaaed923e8c6f00476e350f43 +size 41721 diff --git a/tests/Images/Input/Gif/kumin.gif b/tests/Images/Input/Gif/kumin.gif new file mode 100644 index 000000000..31efda7d8 --- /dev/null +++ b/tests/Images/Input/Gif/kumin.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:345556b9a0e064412acc3b2ee87a9226113eb65c0a1791c2f855ac3fa1e6b7ad +size 868269 diff --git a/tests/Images/Input/Jpg/issues/Issue385-BadZigZag-Progressive.jpg b/tests/Images/Input/Jpg/issues/Issue385-BadZigZag-Progressive.jpg new file mode 100644 index 000000000..963cb3d97 --- /dev/null +++ b/tests/Images/Input/Jpg/issues/Issue385-BadZigZag-Progressive.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1052660c765aaad52f7bbad779778b5d15fdc3c92ff4b114c89e579c749c7f6b +size 388517 diff --git a/tests/Images/Input/Jpg/issues/Issue394-MultiHuffmanBaseline-Speakers.jpg b/tests/Images/Input/Jpg/issues/Issue394-MultiHuffmanBaseline-Speakers.jpg new file mode 100644 index 000000000..6e4dc0d0f --- /dev/null +++ b/tests/Images/Input/Jpg/issues/Issue394-MultiHuffmanBaseline-Speakers.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e90cf157d8e2599598c1bea1b8e2bf262651b004cc6261d87bbb49bd6131034 +size 257401 diff --git a/tests/Images/Input/Png/icon.png b/tests/Images/Input/Png/icon.png new file mode 100644 index 000000000..bc355712b --- /dev/null +++ b/tests/Images/Input/Png/icon.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18f1eb7c5019153f4a0b2de90e7e0f0521193f003fabd6ac31c2f58c2562ae42 +size 4040