mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Former-commit-id: 7240b4fba080dba719b8add3eebba027dd8c350d Former-commit-id: 3129efd3d7f565fffd52e4ce970ad739e58cd636 Former-commit-id: dbaca5b79a4e4d023ee9d508a19a4e83f0f71aadaf/merge-core
22 changed files with 822 additions and 165 deletions
@ -0,0 +1,6 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<configuration> |
||||
|
<solution> |
||||
|
<add key="disableSourceControlIntegration" value="true" /> |
||||
|
</solution> |
||||
|
</configuration> |
||||
@ -0,0 +1 @@ |
|||||
|
9ca66594f912a1fe7aec510819006fb1a80bc1a9 |
||||
@ -0,0 +1,144 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
|
<PropertyGroup> |
||||
|
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir> |
||||
|
|
||||
|
<!-- Enable the restore command to run before builds --> |
||||
|
<RestorePackages Condition=" '$(RestorePackages)' == '' ">false</RestorePackages> |
||||
|
|
||||
|
<!-- Property that enables building a package from a project --> |
||||
|
<BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage> |
||||
|
|
||||
|
<!-- Determines if package restore consent is required to restore packages --> |
||||
|
<RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent> |
||||
|
|
||||
|
<!-- Download NuGet.exe if it does not already exist --> |
||||
|
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup Condition=" '$(PackageSources)' == '' "> |
||||
|
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used --> |
||||
|
<!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list --> |
||||
|
<!-- |
||||
|
<PackageSource Include="https://www.nuget.org/api/v2/" /> |
||||
|
<PackageSource Include="https://my-nuget-source/nuget/" /> |
||||
|
--> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'"> |
||||
|
<!-- Windows specific commands --> |
||||
|
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT'"> |
||||
|
<!-- We need to launch nuget.exe with the mono command if we're not on windows --> |
||||
|
<NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<PackagesProjectConfig Condition=" '$(OS)' == 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config</PackagesProjectConfig> |
||||
|
<PackagesProjectConfig Condition=" '$(OS)' != 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config</PackagesProjectConfig> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<PackagesConfig Condition="Exists('$(MSBuildProjectDirectory)\packages.config')">$(MSBuildProjectDirectory)\packages.config</PackagesConfig> |
||||
|
<PackagesConfig Condition="Exists('$(PackagesProjectConfig)')">$(PackagesProjectConfig)</PackagesConfig> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<!-- NuGet command --> |
||||
|
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\NuGet.exe</NuGetExePath> |
||||
|
<PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources> |
||||
|
|
||||
|
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand> |
||||
|
<NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 "$(NuGetExePath)"</NuGetCommand> |
||||
|
|
||||
|
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir> |
||||
|
|
||||
|
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch> |
||||
|
<NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch> |
||||
|
|
||||
|
<PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir> |
||||
|
<PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir> |
||||
|
|
||||
|
<!-- Commands --> |
||||
|
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand> |
||||
|
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand> |
||||
|
|
||||
|
<!-- We need to ensure packages are restored prior to assembly resolve --> |
||||
|
<BuildDependsOn Condition="$(RestorePackages) == 'true'"> |
||||
|
RestorePackages; |
||||
|
$(BuildDependsOn); |
||||
|
</BuildDependsOn> |
||||
|
|
||||
|
<!-- Make the build depend on restore packages --> |
||||
|
<BuildDependsOn Condition="$(BuildPackage) == 'true'"> |
||||
|
$(BuildDependsOn); |
||||
|
BuildPackage; |
||||
|
</BuildDependsOn> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<Target Name="CheckPrerequisites"> |
||||
|
<!-- Raise an error if we're unable to locate nuget.exe --> |
||||
|
<Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" /> |
||||
|
<!-- |
||||
|
Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once. |
||||
|
This effectively acts as a lock that makes sure that the download operation will only happen once and all |
||||
|
parallel builds will have to wait for it to complete. |
||||
|
--> |
||||
|
<MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" /> |
||||
|
</Target> |
||||
|
|
||||
|
<Target Name="_DownloadNuGet"> |
||||
|
<DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" /> |
||||
|
</Target> |
||||
|
|
||||
|
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites"> |
||||
|
<Exec Command="$(RestoreCommand)" |
||||
|
Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" /> |
||||
|
|
||||
|
<Exec Command="$(RestoreCommand)" |
||||
|
LogStandardErrorAsError="true" |
||||
|
Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" /> |
||||
|
</Target> |
||||
|
|
||||
|
<Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites"> |
||||
|
<Exec Command="$(BuildCommand)" |
||||
|
Condition=" '$(OS)' != 'Windows_NT' " /> |
||||
|
|
||||
|
<Exec Command="$(BuildCommand)" |
||||
|
LogStandardErrorAsError="true" |
||||
|
Condition=" '$(OS)' == 'Windows_NT' " /> |
||||
|
</Target> |
||||
|
|
||||
|
<UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"> |
||||
|
<ParameterGroup> |
||||
|
<OutputFilename ParameterType="System.String" Required="true" /> |
||||
|
</ParameterGroup> |
||||
|
<Task> |
||||
|
<Reference Include="System.Core" /> |
||||
|
<Using Namespace="System" /> |
||||
|
<Using Namespace="System.IO" /> |
||||
|
<Using Namespace="System.Net" /> |
||||
|
<Using Namespace="Microsoft.Build.Framework" /> |
||||
|
<Using Namespace="Microsoft.Build.Utilities" /> |
||||
|
<Code Type="Fragment" Language="cs"> |
||||
|
<![CDATA[ |
||||
|
try { |
||||
|
OutputFilename = Path.GetFullPath(OutputFilename); |
||||
|
|
||||
|
Log.LogMessage("Downloading latest version of NuGet.exe..."); |
||||
|
WebClient webClient = new WebClient(); |
||||
|
webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename); |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
catch (Exception ex) { |
||||
|
Log.LogErrorFromException(ex); |
||||
|
return false; |
||||
|
} |
||||
|
]]> |
||||
|
</Code> |
||||
|
</Task> |
||||
|
</UsingTask> |
||||
|
</Project> |
||||
@ -0,0 +1,223 @@ |
|||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
// <copyright file="YCbCrColor.cs" company="James South">
|
||||
|
// Copyright © James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
// <summary>
|
||||
|
// Represents an YCbCr (luminance, chroma, chroma) color conforming to the
|
||||
|
// ITU-R BT.601 standard used in digital imaging systems.
|
||||
|
// <see href="http://en.wikipedia.org/wiki/YCbCr" />
|
||||
|
// </summary>
|
||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
namespace ImageProcessor |
||||
|
{ |
||||
|
using System; |
||||
|
using System.ComponentModel; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Represents an YCbCr (luminance, chroma, chroma) color conforming to the
|
||||
|
/// ITU-R BT.601 standard used in digital imaging systems.
|
||||
|
/// <see href="http://en.wikipedia.org/wiki/YCbCr"/>
|
||||
|
/// </summary>
|
||||
|
public struct YCbCrColor : IEquatable<YCbCrColor> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Represents a <see cref="YCbCrColor"/> that has Y, Cb, and Cr values set to zero.
|
||||
|
/// </summary>
|
||||
|
public static readonly YCbCrColor Empty = new YCbCrColor(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Holds the Y luminance component.
|
||||
|
/// <remarks>A value ranging between 0 and 255.</remarks>
|
||||
|
/// </summary>
|
||||
|
public float Y; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Holds the Cb chroma component.
|
||||
|
/// <remarks>A value ranging between 0 and 255.</remarks>
|
||||
|
/// </summary>
|
||||
|
public float Cb; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Holds the Cr chroma component.
|
||||
|
/// <remarks>A value ranging between 0 and 255.</remarks>
|
||||
|
/// </summary>
|
||||
|
public float Cr; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The epsilon for comparing floating point numbers.
|
||||
|
/// </summary>
|
||||
|
private const float Epsilon = 0.0001f; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="YCbCrColor"/> struct.
|
||||
|
/// </summary>
|
||||
|
/// <param name="y">The y luminance component.</param>
|
||||
|
/// <param name="cb">The cb chroma component.</param>
|
||||
|
/// <param name="cr">The cr chroma component.</param>
|
||||
|
public YCbCrColor(float y, float cb, float cr) |
||||
|
{ |
||||
|
this.Y = y.Clamp(0, 255); |
||||
|
this.Cb = cb.Clamp(0, 255); |
||||
|
this.Cr = cr.Clamp(0, 255); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a value indicating whether this <see cref="YCbCrColor"/> is empty.
|
||||
|
/// </summary>
|
||||
|
[EditorBrowsable(EditorBrowsableState.Never)] |
||||
|
public bool IsEmpty |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return Math.Abs(this.Y) < Epsilon |
||||
|
&& Math.Abs(this.Cb) < Epsilon |
||||
|
&& Math.Abs(this.Cr) < Epsilon; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Compares two <see cref="YCbCrColor"/> objects. The result specifies whether the values
|
||||
|
/// of the <see cref="YCbCrColor.Y"/>, <see cref="YCbCrColor.Cb"/>, and <see cref="YCbCrColor.Cr"/>
|
||||
|
/// properties of the two <see cref="YCbCrColor"/> objects are equal.
|
||||
|
/// </summary>
|
||||
|
/// <param name="left">
|
||||
|
/// The <see cref="YCbCrColor"/> on the left side of the operand.
|
||||
|
/// </param>
|
||||
|
/// <param name="right">
|
||||
|
/// The <see cref="YCbCrColor"/> on the right side of the operand.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
||||
|
/// </returns>
|
||||
|
public static bool operator ==(YCbCrColor left, YCbCrColor right) |
||||
|
{ |
||||
|
return left.Equals(right); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Compares two <see cref="YCbCrColor"/> objects. The result specifies whether the values
|
||||
|
/// of the <see cref="YCbCrColor.Y"/>, <see cref="YCbCrColor.Cb"/>, and <see cref="YCbCrColor.Cr"/>
|
||||
|
/// properties of the two <see cref="YCbCrColor"/> objects are unequal.
|
||||
|
/// </summary>
|
||||
|
/// <param name="left">
|
||||
|
/// The <see cref="YCbCrColor"/> on the left side of the operand.
|
||||
|
/// </param>
|
||||
|
/// <param name="right">
|
||||
|
/// The <see cref="YCbCrColor"/> on the right side of the operand.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
||||
|
/// </returns>
|
||||
|
public static bool operator !=(YCbCrColor left, YCbCrColor right) |
||||
|
{ |
||||
|
return !left.Equals(right); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
|
||||
|
/// <see cref="YCbCrColor"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="color">
|
||||
|
/// The instance of <see cref="Color"/> to convert.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// An instance of <see cref="YCbCrColor"/>.
|
||||
|
/// </returns>
|
||||
|
public static implicit operator YCbCrColor(Color color) |
||||
|
{ |
||||
|
byte r = color.R; |
||||
|
byte g = color.G; |
||||
|
byte b = color.B; |
||||
|
|
||||
|
float y = (float)((0.299 * r) + (0.587 * g) + (0.114 * b)); |
||||
|
float cb = 128 + (float)((-0.168736 * r) - (0.331264 * g) + (0.5 * b)); |
||||
|
float cr = 128 + (float)((0.5 * r) - (0.418688 * g) - (0.081312 * b)); |
||||
|
|
||||
|
return new YCbCrColor(y, cb, cr); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Indicates whether this instance and a specified object are equal.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
|
||||
|
/// </returns>
|
||||
|
/// <param name="obj">Another object to compare to. </param>
|
||||
|
public override bool Equals(object obj) |
||||
|
{ |
||||
|
if (obj is YCbCrColor) |
||||
|
{ |
||||
|
YCbCrColor color = (YCbCrColor)obj; |
||||
|
|
||||
|
return Math.Abs(this.Y - color.Y) < Epsilon |
||||
|
&& Math.Abs(this.Cb - color.Cb) < Epsilon |
||||
|
&& Math.Abs(this.Cr - color.Cr) < Epsilon; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the hash code for this instance.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// A 32-bit signed integer that is the hash code for this instance.
|
||||
|
/// </returns>
|
||||
|
public override int GetHashCode() |
||||
|
{ |
||||
|
return this.GetHashCode(this); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the fully qualified type name of this instance.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// A <see cref="T:System.String"/> containing a fully qualified type name.
|
||||
|
/// </returns>
|
||||
|
public override string ToString() |
||||
|
{ |
||||
|
if (this.IsEmpty) |
||||
|
{ |
||||
|
return "YCbCrColor [Empty]"; |
||||
|
} |
||||
|
|
||||
|
return string.Format("YCbCrColor [ Y={0:#0.##}, Cb={1:#0.##}, Cr={2:#0.##}]", this.Y, this.Cb, this.Cr); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Indicates whether the current object is equal to another object of the same type.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// True if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
|
||||
|
/// </returns>
|
||||
|
/// <param name="other">An object to compare with this object.</param>
|
||||
|
public bool Equals(YCbCrColor other) |
||||
|
{ |
||||
|
return this.Y.Equals(other.Y) |
||||
|
&& this.Cb.Equals(other.Cb) |
||||
|
&& this.Cr.Equals(other.Cr); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the hash code for the given instance.
|
||||
|
/// </summary>
|
||||
|
/// <param name="color">
|
||||
|
/// The instance of <see cref="Color"/> to return the hash code for.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// A 32-bit signed integer that is the hash code for this instance.
|
||||
|
/// </returns>
|
||||
|
private int GetHashCode(YCbCrColor color) |
||||
|
{ |
||||
|
unchecked |
||||
|
{ |
||||
|
int hashCode = color.Y.GetHashCode(); |
||||
|
hashCode = (hashCode * 397) ^ color.Cb.GetHashCode(); |
||||
|
hashCode = (hashCode * 397) ^ color.Cr.GetHashCode(); |
||||
|
return hashCode; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,89 @@ |
|||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
// <copyright file="ColorConversionTests.cs" company="James South">
|
||||
|
// Copyright © James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
// <summary>
|
||||
|
// Test conversion between the various color structs.
|
||||
|
// </summary>
|
||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
namespace ImageProcessor.Tests |
||||
|
{ |
||||
|
using System.Diagnostics; |
||||
|
using System.Diagnostics.CodeAnalysis; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Test conversion between the various color structs.
|
||||
|
/// </summary>
|
||||
|
public class ColorConversionTests |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Tests the implicit conversion from <see cref="Color"/> to <see cref="YCbCrColor"/>.
|
||||
|
/// </summary>
|
||||
|
[Fact] |
||||
|
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Reviewed. Suppression is OK here.")] |
||||
|
public void ColorToYCbCrColor() |
||||
|
{ |
||||
|
// White
|
||||
|
Color color = new Color(255, 255, 255, 255); |
||||
|
YCbCrColor yCbCrColor = color; |
||||
|
|
||||
|
Assert.Equal(255, yCbCrColor.Y); |
||||
|
Assert.Equal(128, yCbCrColor.Cb); |
||||
|
Assert.Equal(128, yCbCrColor.Cr); |
||||
|
|
||||
|
// Black
|
||||
|
Color color2 = new Color(0, 0, 0, 255); |
||||
|
YCbCrColor yCbCrColor2 = color2; |
||||
|
Assert.Equal(0, yCbCrColor2.Y); |
||||
|
Assert.Equal(128, yCbCrColor2.Cb); |
||||
|
Assert.Equal(128, yCbCrColor2.Cr); |
||||
|
|
||||
|
|
||||
|
// Grey
|
||||
|
Color color3 = new Color(128, 128, 128, 255); |
||||
|
YCbCrColor yCbCrColor3 = color3; |
||||
|
Assert.Equal(128, yCbCrColor3.Y); |
||||
|
Assert.Equal(128, yCbCrColor3.Cb); |
||||
|
Assert.Equal(128, yCbCrColor3.Cr); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Tests the implicit conversion from <see cref="YCbCrColor"/> to <see cref="Color"/>.
|
||||
|
/// </summary>
|
||||
|
[Fact] |
||||
|
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Reviewed. Suppression is OK here.")] |
||||
|
public void YCbCrColorToColor() |
||||
|
{ |
||||
|
// White
|
||||
|
YCbCrColor yCbCrColor = new YCbCrColor(255, 128, 128); |
||||
|
Color color = yCbCrColor; |
||||
|
|
||||
|
Assert.Equal(255, color.B); |
||||
|
Assert.Equal(255, color.G); |
||||
|
Assert.Equal(255, color.R); |
||||
|
Assert.Equal(255, color.A); |
||||
|
|
||||
|
// Black
|
||||
|
YCbCrColor yCbCrColor2 = new YCbCrColor(0, 128, 128); |
||||
|
Color color2 = yCbCrColor2; |
||||
|
|
||||
|
Assert.Equal(0, color2.B); |
||||
|
Assert.Equal(0, color2.G); |
||||
|
Assert.Equal(0, color2.R); |
||||
|
Assert.Equal(255, color2.A); |
||||
|
|
||||
|
// Grey
|
||||
|
YCbCrColor yCbCrColor3 = new YCbCrColor(128, 128, 128); |
||||
|
Color color3 = yCbCrColor3; |
||||
|
|
||||
|
Assert.Equal(128, color3.B); |
||||
|
Assert.Equal(128, color3.G); |
||||
|
Assert.Equal(128, color3.R); |
||||
|
Assert.Equal(255, color3.A); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,60 @@ |
|||||
|
namespace ImageProcessor.Tests |
||||
|
{ |
||||
|
using System.Diagnostics; |
||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
|
||||
|
using ImageProcessor.Formats; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
public class EncoderDecoderTests |
||||
|
{ |
||||
|
[Theory] |
||||
|
//[InlineData("TestImages/Car.bmp")]
|
||||
|
//[InlineData("TestImages/Portrait.png")]
|
||||
|
//[InlineData("TestImages/Backdrop.jpg")]
|
||||
|
//[InlineData("TestImages/Windmill.gif")]
|
||||
|
[InlineData("../../TestImages/Formats/Png/cmyk.png")] |
||||
|
public void DecodeThenEncodeImageFromStreamShouldSucceed(string filename) |
||||
|
{ |
||||
|
if (!Directory.Exists("Encoded")) |
||||
|
{ |
||||
|
Directory.CreateDirectory("Encoded"); |
||||
|
} |
||||
|
|
||||
|
FileStream stream = File.OpenRead(filename); |
||||
|
Stopwatch watch = Stopwatch.StartNew(); |
||||
|
Image image = new Image(stream); |
||||
|
|
||||
|
string encodedFilename = "Encoded/" + Path.GetFileName(filename); |
||||
|
|
||||
|
//if (!image.IsAnimated)
|
||||
|
//{
|
||||
|
using (FileStream output = File.OpenWrite(encodedFilename)) |
||||
|
{ |
||||
|
IImageEncoder encoder = Image.Encoders.First(e => e.IsSupportedFileExtension(Path.GetExtension(filename))); |
||||
|
encoder.Encode(image, output); |
||||
|
} |
||||
|
//}
|
||||
|
//else
|
||||
|
//{
|
||||
|
// using (var output = File.OpenWrite(
|
||||
|
// string.Format("Encoded/{ Path.GetFileNameWithoutExtension(filename) }.jpg"))
|
||||
|
// {
|
||||
|
// image.SaveAsJpeg(output, 40);
|
||||
|
// }
|
||||
|
|
||||
|
// for (int i = 0; i < image.Frames.Count; i++)
|
||||
|
// {
|
||||
|
// using (var output = File.OpenWrite($"Encoded/{ i }_{ Path.GetFileNameWithoutExtension(filename) }.png"))
|
||||
|
// {
|
||||
|
// image.Frames[i].SaveAsPng(output);
|
||||
|
// }
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
Trace.WriteLine(string.Format("{0} : {1}ms", filename, watch.ElapsedMilliseconds)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,3 +1,4 @@ |
|||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> |
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> |
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=colors/@EntryIndexedValue">True</s:Boolean> |
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=colors/@EntryIndexedValue">True</s:Boolean> |
||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=formats/@EntryIndexedValue">True</s:Boolean> |
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=numerics/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> |
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=numerics/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> |
||||
@ -0,0 +1,3 @@ |
|||||
|
version https://git-lfs.github.com/spec/v1 |
||||
|
oid sha256:2e17ba8fac1fd6247ff839ab7e21d715c96b3588d5f4fdb835dbe8c937dbf79d |
||||
|
size 37678 |
||||
Loading…
Reference in new issue