From 4c80b16f31834879bf2c6e3d0ad6919d05fe70c9 Mon Sep 17 00:00:00 2001 From: Peter Amrehn Date: Sat, 6 Oct 2018 22:13:58 +0200 Subject: [PATCH] #718: extend IPixel interface and implement it everywhere, ... AND add unit tests AND fix Gray16 implementation (constructor takes ushort, not byte) AND fix Gray8 and Gray16 Pack (do not scale by sum) --- src/ImageSharp/PixelFormats/Alpha8.cs | 16 ++ src/ImageSharp/PixelFormats/Argb32.cs | 30 +++ src/ImageSharp/PixelFormats/Bgr24.cs | 27 +++ src/ImageSharp/PixelFormats/Bgr565.cs | 16 ++ src/ImageSharp/PixelFormats/Bgra32.cs | 29 +++ src/ImageSharp/PixelFormats/Bgra4444.cs | 16 ++ src/ImageSharp/PixelFormats/Bgra5551.cs | 16 ++ src/ImageSharp/PixelFormats/Byte4.cs | 16 ++ src/ImageSharp/PixelFormats/Gray16.cs | 33 ++- src/ImageSharp/PixelFormats/Gray8.cs | 3 +- src/ImageSharp/PixelFormats/HalfSingle.cs | 16 ++ src/ImageSharp/PixelFormats/HalfVector2.cs | 16 ++ src/ImageSharp/PixelFormats/HalfVector4.cs | 16 ++ src/ImageSharp/PixelFormats/IPixel.cs | 24 ++ .../PixelFormats/NormalizedByte2.cs | 16 ++ .../PixelFormats/NormalizedByte4.cs | 16 ++ .../PixelFormats/NormalizedShort2.cs | 16 ++ .../PixelFormats/NormalizedShort4.cs | 16 ++ src/ImageSharp/PixelFormats/Rg32.cs | 16 ++ src/ImageSharp/PixelFormats/Rgb24.cs | 27 +++ src/ImageSharp/PixelFormats/Rgb48.cs | 33 +++ src/ImageSharp/PixelFormats/Rgba1010102.cs | 16 ++ src/ImageSharp/PixelFormats/Rgba32.cs | 35 +++ src/ImageSharp/PixelFormats/Rgba64.cs | 29 +++ src/ImageSharp/PixelFormats/RgbaVector.cs | 16 ++ src/ImageSharp/PixelFormats/Short2.cs | 16 ++ src/ImageSharp/PixelFormats/Short4.cs | 16 ++ .../PixelFormats/Gray16Tests.cs | 211 ++++++++++++++++++ 28 files changed, 748 insertions(+), 5 deletions(-) create mode 100644 tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs diff --git a/src/ImageSharp/PixelFormats/Alpha8.cs b/src/ImageSharp/PixelFormats/Alpha8.cs index a8d97d31a2..d795931af3 100644 --- a/src/ImageSharp/PixelFormats/Alpha8.cs +++ b/src/ImageSharp/PixelFormats/Alpha8.cs @@ -168,6 +168,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.B = 0; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackedValue = 255; + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackedValue = 0; + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackedValue = 255; + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackedValue = 0; + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/Argb32.cs b/src/ImageSharp/PixelFormats/Argb32.cs index 51d3964ef8..0249bb6af9 100644 --- a/src/ImageSharp/PixelFormats/Argb32.cs +++ b/src/ImageSharp/PixelFormats/Argb32.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; using System.Runtime.InteropServices; @@ -289,6 +290,35 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = this.A; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) + { + this.A = 255; + this.R = source.PackedValue; + this.G = source.PackedValue; + this.B = source.PackedValue; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) + { + var val = (byte)(((source.PackedValue * 255) + 32895) >> 16); + this.R = val; + this.G = val; + this.B = val; + this.A = 255; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// /// Converts the pixel to format. /// diff --git a/src/ImageSharp/PixelFormats/Bgr24.cs b/src/ImageSharp/PixelFormats/Bgr24.cs index fc283b5684..bc8e2324ce 100644 --- a/src/ImageSharp/PixelFormats/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/Bgr24.cs @@ -172,6 +172,33 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = byte.MaxValue; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) + { + this.R = source.PackedValue; + this.G = source.PackedValue; + this.B = source.PackedValue; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) + { + var val = (byte)(((source.PackedValue * 255) + 32895) >> 16); + this.R = val; + this.G = val; + this.B = val; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) diff --git a/src/ImageSharp/PixelFormats/Bgr565.cs b/src/ImageSharp/PixelFormats/Bgr565.cs index 570b975dba..53f15ecb3b 100644 --- a/src/ImageSharp/PixelFormats/Bgr565.cs +++ b/src/ImageSharp/PixelFormats/Bgr565.cs @@ -187,6 +187,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = (byte)MathF.Round(vector.W); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/Bgra32.cs b/src/ImageSharp/PixelFormats/Bgra32.cs index 233df2f29e..304f815359 100644 --- a/src/ImageSharp/PixelFormats/Bgra32.cs +++ b/src/ImageSharp/PixelFormats/Bgra32.cs @@ -215,6 +215,35 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) => dest = this; + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) + { + this.R = source.PackedValue; + this.R = source.PackedValue; + this.R = source.PackedValue; + this.A = byte.MaxValue; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) + { + var val = (byte)(((source.PackedValue * 255) + 32895) >> 16); + this.R = val; + this.G = val; + this.B = val; + this.A = byte.MaxValue; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// /// Converts the pixel to format. /// diff --git a/src/ImageSharp/PixelFormats/Bgra4444.cs b/src/ImageSharp/PixelFormats/Bgra4444.cs index 90f967f898..f684bec339 100644 --- a/src/ImageSharp/PixelFormats/Bgra4444.cs +++ b/src/ImageSharp/PixelFormats/Bgra4444.cs @@ -178,6 +178,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = (byte)vector.W; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/Bgra5551.cs b/src/ImageSharp/PixelFormats/Bgra5551.cs index 3a18c03e83..1044a0febf 100644 --- a/src/ImageSharp/PixelFormats/Bgra5551.cs +++ b/src/ImageSharp/PixelFormats/Bgra5551.cs @@ -178,6 +178,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = (byte)vector.W; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/Byte4.cs b/src/ImageSharp/PixelFormats/Byte4.cs index bb1b350f07..aea3aec655 100644 --- a/src/ImageSharp/PixelFormats/Byte4.cs +++ b/src/ImageSharp/PixelFormats/Byte4.cs @@ -179,6 +179,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = (byte)vector.W; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/Gray16.cs b/src/ImageSharp/PixelFormats/Gray16.cs index a7e50e3667..6fda8b0817 100644 --- a/src/ImageSharp/PixelFormats/Gray16.cs +++ b/src/ImageSharp/PixelFormats/Gray16.cs @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Initializes a new instance of the struct. /// /// The gray component - public Gray16(byte gray) + public Gray16(ushort gray) { this.PackedValue = gray; } @@ -185,6 +185,34 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = 255; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) + { + this.PackedValue = (ushort)(source.PackedValue * 255); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) + { + dest.PackedValue = (byte)(((this.PackedValue * 255) + 32895) >> 16); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) + { + this.PackedValue = source.PackedValue; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) + { + dest.PackedValue = this.PackedValue; + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => @@ -252,9 +280,8 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] private static ushort Pack(float r, float g, float b) { - float sum = r + g + b; float val = (r * Rx) + (g * Gx) + (b * Bx); - return (ushort)Math.Round(val * 65535f / sum); // TODO: if this is correct, Rx, Gx, Bx consts could be scaled by 65535f directly! + return (ushort)Math.Round(val * 65535f); } /// diff --git a/src/ImageSharp/PixelFormats/Gray8.cs b/src/ImageSharp/PixelFormats/Gray8.cs index db05395431..1509f8ea9f 100644 --- a/src/ImageSharp/PixelFormats/Gray8.cs +++ b/src/ImageSharp/PixelFormats/Gray8.cs @@ -257,9 +257,8 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] private static byte Pack(float r, float g, float b) { - float sum = r + g + b; float val = (r * Rx) + (g * Gx) + (b * Bx); - return (byte)Math.Round(val * 255 / sum); // TODO: if this is correct, Rx, Gx, Bx consts could be scaled by 255 directly! + return (byte)Math.Round(val * 255); } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/HalfSingle.cs b/src/ImageSharp/PixelFormats/HalfSingle.cs index 09b4636492..b392910a67 100644 --- a/src/ImageSharp/PixelFormats/HalfSingle.cs +++ b/src/ImageSharp/PixelFormats/HalfSingle.cs @@ -192,6 +192,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = (byte)vector.W; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/HalfVector2.cs b/src/ImageSharp/PixelFormats/HalfVector2.cs index befa49736c..ac70f4fbcc 100644 --- a/src/ImageSharp/PixelFormats/HalfVector2.cs +++ b/src/ImageSharp/PixelFormats/HalfVector2.cs @@ -207,6 +207,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = 255; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/HalfVector4.cs b/src/ImageSharp/PixelFormats/HalfVector4.cs index 885e022921..9bdae99abe 100644 --- a/src/ImageSharp/PixelFormats/HalfVector4.cs +++ b/src/ImageSharp/PixelFormats/HalfVector4.cs @@ -200,6 +200,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = (byte)vector.W; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/IPixel.cs b/src/ImageSharp/PixelFormats/IPixel.cs index ae09af626c..382c8541d6 100644 --- a/src/ImageSharp/PixelFormats/IPixel.cs +++ b/src/ImageSharp/PixelFormats/IPixel.cs @@ -126,5 +126,29 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// The destination pixel to write to void ToBgra32(ref Bgra32 dest); + + /// + /// Packs the Pixel from an value. + /// + /// The value. + void PackFromGray8(Gray8 source); + + /// + /// Converts the pixel to format. + /// + /// The destination pixel to write to. + void ToGray8(ref Gray8 dest); + + /// + /// Packs the Pixel from an value. + /// + /// The value. + void PackFromGray16(Gray16 source); + + /// + /// Converts the pixel tgo value. + /// + /// The destination pixel to write to. + void ToGray16(ref Gray16 dest); } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/NormalizedByte2.cs b/src/ImageSharp/PixelFormats/NormalizedByte2.cs index 8592fdd6a7..cd9fa65fbe 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte2.cs @@ -226,6 +226,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = 255; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/NormalizedByte4.cs index 293d536e53..9b53adeccf 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte4.cs @@ -219,6 +219,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = (byte)vector.W; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/NormalizedShort2.cs b/src/ImageSharp/PixelFormats/NormalizedShort2.cs index 1ced412d06..3319a10927 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort2.cs @@ -213,6 +213,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = 255; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/NormalizedShort4.cs b/src/ImageSharp/PixelFormats/NormalizedShort4.cs index 25b26fa7f7..7a74a44349 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort4.cs @@ -221,6 +221,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = (byte)MathF.Round(vector.W); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/Rg32.cs b/src/ImageSharp/PixelFormats/Rg32.cs index e5ceeacec2..e4bed1275b 100644 --- a/src/ImageSharp/PixelFormats/Rg32.cs +++ b/src/ImageSharp/PixelFormats/Rg32.cs @@ -191,6 +191,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = (byte)vector.W; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/Rgb24.cs b/src/ImageSharp/PixelFormats/Rgb24.cs index d7e1c47ec0..4c5aef5438 100644 --- a/src/ImageSharp/PixelFormats/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/Rgb24.cs @@ -166,6 +166,33 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = byte.MaxValue; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) + { + this.R = source.PackedValue; + this.G = source.PackedValue; + this.B = source.PackedValue; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) + { + var val = (byte)(((source.PackedValue * 255) + 32895) >> 16); + this.R = val; + this.G = val; + this.B = val; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) diff --git a/src/ImageSharp/PixelFormats/Rgb48.cs b/src/ImageSharp/PixelFormats/Rgb48.cs index 2d92b0e4e3..7784c49ffb 100644 --- a/src/ImageSharp/PixelFormats/Rgb48.cs +++ b/src/ImageSharp/PixelFormats/Rgb48.cs @@ -210,6 +210,39 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = 255; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) + { + var val = (ushort)(source.PackedValue * 255); + this.R = val; + this.G = val; + this.B = val; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) + { + dest.PackFromRgb48(this); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) + { + this.R = source.PackedValue; + this.G = source.PackedValue; + this.B = source.PackedValue; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) + { + dest.PackFromRgb48(this); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this = source; diff --git a/src/ImageSharp/PixelFormats/Rgba1010102.cs b/src/ImageSharp/PixelFormats/Rgba1010102.cs index 94fb7a41e6..6dd5f7b544 100644 --- a/src/ImageSharp/PixelFormats/Rgba1010102.cs +++ b/src/ImageSharp/PixelFormats/Rgba1010102.cs @@ -185,6 +185,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = (byte)MathF.Round(vector.W); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs index cf66538c52..aab9fad928 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.cs @@ -336,6 +336,41 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = this.A; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) + { + this.R = source.PackedValue; + this.G = source.PackedValue; + this.B = source.PackedValue; + this.A = 0; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) + { + dest.PackFromRgba32(this); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) + { + var val = (byte)(((source.PackedValue * 255) + 32895) >> 16); + this.R = val; + this.G = val; + this.B = val; + this.A = 0; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) + { + dest.PackFromRgba32(this); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromScaledVector4(Vector4 vector) diff --git a/src/ImageSharp/PixelFormats/Rgba64.cs b/src/ImageSharp/PixelFormats/Rgba64.cs index 8e6be1e8c4..5c3187856e 100644 --- a/src/ImageSharp/PixelFormats/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/Rgba64.cs @@ -274,6 +274,35 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = (byte)(((this.A * 255) + 32895) >> 16); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) + { + ushort x = (ushort)(source.PackedValue * 255); + this.R = x; + this.G = x; + this.B = x; + this.A = ushort.MaxValue; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) + { + this.R = source.PackedValue; + this.G = source.PackedValue; + this.B = source.PackedValue; + this.A = ushort.MaxValue; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// public override bool Equals(object obj) { diff --git a/src/ImageSharp/PixelFormats/RgbaVector.cs b/src/ImageSharp/PixelFormats/RgbaVector.cs index dd5f77b80f..3ab45a66ef 100644 --- a/src/ImageSharp/PixelFormats/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/RgbaVector.cs @@ -298,6 +298,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = (byte)MathF.Round(vector.W); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/Short2.cs b/src/ImageSharp/PixelFormats/Short2.cs index 9fc7618b91..331c5fb208 100644 --- a/src/ImageSharp/PixelFormats/Short2.cs +++ b/src/ImageSharp/PixelFormats/Short2.cs @@ -207,6 +207,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = 255; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/Short4.cs b/src/ImageSharp/PixelFormats/Short4.cs index 641f154f94..4a3d89ad8b 100644 --- a/src/ImageSharp/PixelFormats/Short4.cs +++ b/src/ImageSharp/PixelFormats/Short4.cs @@ -213,6 +213,22 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = (byte)MathF.Round(vector.W); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray8(ref Gray8 dest) => dest.PackFromVector4(this.ToVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ToGray16(ref Gray16 dest) => dest.PackFromVector4(this.ToVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); diff --git a/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs new file mode 100644 index 0000000000..2525ee3796 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs @@ -0,0 +1,211 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Numerics; +using SixLabors.ImageSharp.PixelFormats; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.PixelFormats +{ + public class Gray16Tests + { + [Theory] + [InlineData(0)] + [InlineData(65535)] + [InlineData(32767)] + [InlineData(42)] + public void Gray16_PackedValue_EqualsInput(ushort input) + { + Assert.Equal(input, new Gray16(input).PackedValue); + } + + [Theory] + [InlineData(0)] + [InlineData(65535)] + [InlineData(32767)] + public void Gray16_ToVector4(ushort input) + { + // arrange + var gray = new Gray16(input); + + // act + var actual = gray.ToVector4(); + + // assert + Assert.Equal(input, actual.X); + Assert.Equal(input, actual.Y); + Assert.Equal(input, actual.Z); + Assert.Equal(1, actual.W); + } + + [Theory] + [InlineData(0)] + [InlineData(65535)] + [InlineData(32767)] + public void Gray16_ToScaledVector4(ushort input) + { + // arrange + var gray = new Gray16(input); + + // act + var actual = gray.ToScaledVector4(); + + // assert + float scaledInput = input / 65535f; + Assert.Equal(scaledInput, actual.X); + Assert.Equal(scaledInput, actual.Y); + Assert.Equal(scaledInput, actual.Z); + Assert.Equal(1, actual.W); + } + + [Fact] + public void Gray16_PackFromScaledVector4() + { + // arrange + Gray16 gray = default; + int expected = 32767; + Vector4 scaled = new Gray16((ushort)expected).ToScaledVector4(); + + // act + gray.PackFromScaledVector4(scaled); + ushort actual = gray.PackedValue; + + // assert + Assert.Equal(expected, actual); + } + + [Fact] + public void Gray16_PackFromScaledVector4_ToRgb24() + { + // arrange + Rgb24 actual = default; + Gray16 gray = default; + var expected = new Rgb24(128, 128, 128); + Vector4 scaled = new Gray16(32768).ToScaledVector4(); + + // act + gray.PackFromScaledVector4(scaled); + gray.ToRgb24(ref actual); + + // assert + Assert.Equal(expected, actual); + } + + [Fact] + public void Gray16_PackFromScaledVector4_ToRgba32() + { + // arrange + Rgba32 actual = default; + Gray16 gray = default; + var expected = new Rgba32(128, 128, 128, 255); + Vector4 scaled = new Gray16(32768).ToScaledVector4(); + + // act + gray.PackFromScaledVector4(scaled); + gray.ToRgba32(ref actual); + + // assert + Assert.Equal(expected, actual); + } + + [Fact] + public void Gray16_PackFromScaledVector4_ToBgr24() + { + // arrange + Bgr24 actual = default; + Gray16 gray = default; + var expected = new Bgr24(128, 128, 128); + Vector4 scaled = new Gray16(32768).ToScaledVector4(); + + // act + gray.PackFromScaledVector4(scaled); + gray.ToBgr24(ref actual); + + // assert + Assert.Equal(expected, actual); + } + + [Fact] + public void Gray16_PackFromScaledVector4_ToBgra32() + { + // arrange + Bgra32 actual = default; + Gray16 gray = default; + var expected = new Bgra32(128,128,128); + Vector4 scaled = new Gray16(32768).ToScaledVector4(); + + // act + gray.PackFromScaledVector4(scaled); + gray.ToBgra32(ref actual); + + // assert + Assert.Equal(expected, actual); + } + + [Fact] + public void Gray16_PackFromScaledVector4_ToArgb32() + { + // arrange + Gray16 gray = default; + Argb32 actual = default; + var expected = new Argb32(128, 128, 128); + Vector4 scaled = new Gray16(32768).ToScaledVector4(); + + // act + gray.PackFromScaledVector4(scaled); + gray.ToArgb32(ref actual); + + // assert + Assert.Equal(expected, actual); + } + + [Fact] + public void Gray16_PackFromScaledVector4_ToRgba64() + { + // arrange + Gray16 gray = default; + Rgba64 actual = default; + var expected = new Rgba64(65535, 65535, 65535, 65535); + Vector4 scaled = new Gray16(65535).ToScaledVector4(); + + // act + gray.PackFromScaledVector4(scaled); + gray.ToRgba64(ref actual); + + // assert + Assert.Equal(expected, actual); + } + + [Fact] + public void Gray16_PackFromRgb48_ToRgb48() + { + // arrange + var gray = default(Gray16); + var actual = default(Rgb48); + var expected = new Rgb48(0, 0, 0); + + // act + gray.PackFromRgb48(expected); + gray.ToRgb48(ref actual); + + // assert + Assert.Equal(expected, actual); + } + + [Fact] + public void Gray16_PackFromRgba64_ToRgba64() + { + // arrange + var gray = default(Gray16); + var actual = default(Rgba64); + var expected = new Rgba64(0, 0, 0, 65535); + + // act + gray.PackFromRgba64(expected); + gray.ToRgba64(ref actual); + + // assert + Assert.Equal(expected, actual); + } + } +}