From 1901b3fdc2ac45815387570c22893306de54e0a0 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 5 Jun 2017 03:44:50 +0200 Subject: [PATCH] T4 all the PixelOperations! --- src/ImageSharp/Common/Helpers/Guard.cs | 1 - src/ImageSharp/Formats/Png/PngEncoderCore.cs | 2 +- src/ImageSharp/Image/PixelAccessor{TPixel}.cs | 10 +- src/ImageSharp/ImageSharp.csproj | 9 + .../PixelOperations{TPixel}.Generated.cs | 297 ++++++++++++++++++ .../PixelOperations{TPixel}.Generated.tt | 120 +++++++ .../PixelFormats/PixelOperations{TPixel}.cs | 229 ++------------ .../PixelFormats/Rgba32.PixelOperations.cs | 107 ++----- src/ImageSharp/PixelFormats/Rgba32.cs | 11 + .../RgbaVector.PixelOperations.cs | 5 +- src/Shared/stylecop.json | 12 +- .../Color/Bulk/ToXyzw.cs | 4 +- .../PixelFormats/PixelOperationsTests.cs | 10 +- 13 files changed, 510 insertions(+), 307 deletions(-) create mode 100644 src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs create mode 100644 src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt diff --git a/src/ImageSharp/Common/Helpers/Guard.cs b/src/ImageSharp/Common/Helpers/Guard.cs index a4b392fcf1..8e55c18af8 100644 --- a/src/ImageSharp/Common/Helpers/Guard.cs +++ b/src/ImageSharp/Common/Helpers/Guard.cs @@ -242,7 +242,6 @@ namespace ImageSharp /// is true /// public static void MustBeSizedAtLeast(Span target, int minLength, string parameterName) - where T : struct { if (target.Length < minLength) { diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index a0be82bb0c..645df05481 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -338,7 +338,7 @@ namespace ImageSharp.Formats { if (this.bytesPerPixel == 4) { - PixelOperations.Instance.ToXyzwBytes(rowSpan, this.rawScanline, this.width); + PixelOperations.Instance.ToRgba32Bytes(rowSpan, this.rawScanline, this.width); } else { diff --git a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs index 719c48a8de..3902ba4255 100644 --- a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs +++ b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs @@ -275,7 +275,7 @@ namespace ImageSharp Span source = area.GetRowSpan(y); Span destination = this.GetRowSpan(targetX, targetY + y); - Operations.PackFromZyxBytes(source, destination, width); + Operations.PackFromBgr24Bytes(source, destination, width); } } @@ -295,7 +295,7 @@ namespace ImageSharp Span source = area.GetRowSpan(y); Span destination = this.GetRowSpan(targetX, targetY + y); - Operations.PackFromZyxwBytes(source, destination, width); + Operations.PackFromBgra32Bytes(source, destination, width); } } @@ -353,7 +353,7 @@ namespace ImageSharp { Span source = this.GetRowSpan(sourceX, sourceY + y); Span destination = area.GetRowSpan(y); - Operations.ToZyxBytes(source, destination, width); + Operations.ToBgr24Bytes(source, destination, width); } } @@ -372,7 +372,7 @@ namespace ImageSharp { Span source = this.GetRowSpan(sourceX, sourceY + y); Span destination = area.GetRowSpan(y); - Operations.ToZyxwBytes(source, destination, width); + Operations.ToBgra32Bytes(source, destination, width); } } @@ -410,7 +410,7 @@ namespace ImageSharp { Span source = this.GetRowSpan(sourceX, sourceY + y); Span destination = area.GetRowSpan(y); - Operations.ToXyzwBytes(source, destination, width); + Operations.ToRgba32Bytes(source, destination, width); } } diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 68a1571a32..60f88a79c7 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -55,6 +55,10 @@ TextTemplatingFileGenerator Block8x8F.Generated.cs + + TextTemplatingFileGenerator + PixelOperations{TPixel}.Generated.cs + @@ -65,5 +69,10 @@ True Block8x8F.Generated.tt + + True + True + PixelOperations{TPixel}.Generated.tt + \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs new file mode 100644 index 0000000000..6ae52351ed --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs @@ -0,0 +1,297 @@ +// + +namespace ImageSharp.PixelFormats +{ + using System; + using System.Numerics; + using System.Runtime.CompilerServices; + + public partial class PixelOperations + { + + /// + /// Converts 'count' elements in 'source` span of data to a span of -s. + /// + /// The source of data. + /// The to the destination pixels. + /// The number of pixels to convert. + internal virtual void PackFromRgba32(Span source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref Rgba32 sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); + + for (int i = 0; i < count; i++) + { + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + rgba = Unsafe.Add(ref sourceRef, i); + dp.PackFromRgba32(rgba); + } + } + + /// + /// A helper for that expects a byte span. + /// The layout of the data in 'sourceBytes' must be compatible with layout. + /// + /// The to the source bytes. + /// The to the destination pixels. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void PackFromRgba32Bytes(Span sourceBytes, Span destPixels, int count) + { + this.PackFromRgba32(sourceBytes.NonPortableCast(), destPixels, count); + } + + /// + /// Converts 'count' pixels in 'sourcePixels` span to a span of -s. + /// Bulk version of . + /// + /// The span of source pixels + /// The destination span of data. + /// The number of pixels to convert. + internal virtual void ToRgba32(Span sourcePixels, Span dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Rgba32 destBaseRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref Rgba32 dp = ref Unsafe.Add(ref destBaseRef, i); + sp.ToRgba32(ref dp); + } + } + + /// + /// A helper for that expects a byte span as destination. + /// The layout of the data in 'destBytes' must be compatible with layout. + /// + /// The to the source colors. + /// The to the destination bytes. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void ToRgba32Bytes(Span sourceColors, Span destBytes, int count) + { + this.ToRgba32(sourceColors, destBytes.NonPortableCast(), count); + } + + /// + /// Converts 'count' elements in 'source` span of data to a span of -s. + /// + /// The source of data. + /// The to the destination pixels. + /// The number of pixels to convert. + internal virtual void PackFromBgra32(Span source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); + + for (int i = 0; i < count; i++) + { + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + rgba = Unsafe.Add(ref sourceRef, i).ToRgba32(); + dp.PackFromRgba32(rgba); + } + } + + /// + /// A helper for that expects a byte span. + /// The layout of the data in 'sourceBytes' must be compatible with layout. + /// + /// The to the source bytes. + /// The to the destination pixels. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void PackFromBgra32Bytes(Span sourceBytes, Span destPixels, int count) + { + this.PackFromBgra32(sourceBytes.NonPortableCast(), destPixels, count); + } + + /// + /// Converts 'count' pixels in 'sourcePixels` span to a span of -s. + /// Bulk version of . + /// + /// The span of source pixels + /// The destination span of data. + /// The number of pixels to convert. + internal virtual void ToBgra32(Span sourcePixels, Span dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Bgra32 destBaseRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref Bgra32 dp = ref Unsafe.Add(ref destBaseRef, i); + sp.ToBgra32(ref dp); + } + } + + /// + /// A helper for that expects a byte span as destination. + /// The layout of the data in 'destBytes' must be compatible with layout. + /// + /// The to the source colors. + /// The to the destination bytes. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void ToBgra32Bytes(Span sourceColors, Span destBytes, int count) + { + this.ToBgra32(sourceColors, destBytes.NonPortableCast(), count); + } + + /// + /// Converts 'count' elements in 'source` span of data to a span of -s. + /// + /// The source of data. + /// The to the destination pixels. + /// The number of pixels to convert. + internal virtual void PackFromRgb24(Span source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); + + for (int i = 0; i < count; i++) + { + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + rgba.Rgb = Unsafe.Add(ref sourceRef, i); + dp.PackFromRgba32(rgba); + } + } + + /// + /// A helper for that expects a byte span. + /// The layout of the data in 'sourceBytes' must be compatible with layout. + /// + /// The to the source bytes. + /// The to the destination pixels. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void PackFromRgb24Bytes(Span sourceBytes, Span destPixels, int count) + { + this.PackFromRgb24(sourceBytes.NonPortableCast(), destPixels, count); + } + + /// + /// Converts 'count' pixels in 'sourcePixels` span to a span of -s. + /// Bulk version of . + /// + /// The span of source pixels + /// The destination span of data. + /// The number of pixels to convert. + internal virtual void ToRgb24(Span sourcePixels, Span dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Rgb24 destBaseRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref Rgb24 dp = ref Unsafe.Add(ref destBaseRef, i); + sp.ToRgb24(ref dp); + } + } + + /// + /// A helper for that expects a byte span as destination. + /// The layout of the data in 'destBytes' must be compatible with layout. + /// + /// The to the source colors. + /// The to the destination bytes. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void ToRgb24Bytes(Span sourceColors, Span destBytes, int count) + { + this.ToRgb24(sourceColors, destBytes.NonPortableCast(), count); + } + + /// + /// Converts 'count' elements in 'source` span of data to a span of -s. + /// + /// The source of data. + /// The to the destination pixels. + /// The number of pixels to convert. + internal virtual void PackFromBgr24(Span source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); + + for (int i = 0; i < count; i++) + { + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + rgba.Bgr = Unsafe.Add(ref sourceRef, i); + dp.PackFromRgba32(rgba); + } + } + + /// + /// A helper for that expects a byte span. + /// The layout of the data in 'sourceBytes' must be compatible with layout. + /// + /// The to the source bytes. + /// The to the destination pixels. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void PackFromBgr24Bytes(Span sourceBytes, Span destPixels, int count) + { + this.PackFromBgr24(sourceBytes.NonPortableCast(), destPixels, count); + } + + /// + /// Converts 'count' pixels in 'sourcePixels` span to a span of -s. + /// Bulk version of . + /// + /// The span of source pixels + /// The destination span of data. + /// The number of pixels to convert. + internal virtual void ToBgr24(Span sourcePixels, Span dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Bgr24 destBaseRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref Bgr24 dp = ref Unsafe.Add(ref destBaseRef, i); + sp.ToBgr24(ref dp); + } + } + + /// + /// A helper for that expects a byte span as destination. + /// The layout of the data in 'destBytes' must be compatible with layout. + /// + /// The to the source colors. + /// The to the destination bytes. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void ToBgr24Bytes(Span sourceColors, Span destBytes, int count) + { + this.ToBgr24(sourceColors, destBytes.NonPortableCast(), count); + } + + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt new file mode 100644 index 0000000000..edb74bb0ce --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt @@ -0,0 +1,120 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +<# + + void GenerateToDestFormatMethods(string pixelType) + { + #> + + /// + /// Converts 'count' pixels in 'sourcePixels` span to a span of -s. + /// Bulk version of . + /// + /// The span of source pixels + /// The destination span of data. + /// The number of pixels to convert. + internal virtual void To<#=pixelType#>(Span sourcePixels, Span<<#=pixelType#>> dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); + ref <#=pixelType#> destBaseRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref <#=pixelType#> dp = ref Unsafe.Add(ref destBaseRef, i); + sp.To<#=pixelType#>(ref dp); + } + } + + /// + /// A helper for that expects a byte span as destination. + /// The layout of the data in 'destBytes' must be compatible with layout. + /// + /// The to the source colors. + /// The to the destination bytes. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void To<#=pixelType#>Bytes(Span sourceColors, Span destBytes, int count) + { + this.To<#=pixelType#>(sourceColors, destBytes.NonPortableCast>(), count); + } + <# + } + + void GeneratePackFromMethodUsingPackFromRgba32(string pixelType, string rgbaOperationCode) + { + #> + + /// + /// Converts 'count' elements in 'source` span of data to a span of -s. + /// + /// The source of data. + /// The to the destination pixels. + /// The number of pixels to convert. + internal virtual void PackFrom<#=pixelType#>(Span<<#=pixelType#>> source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref <#=pixelType#> sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); + + for (int i = 0; i < count; i++) + { + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + <#=rgbaOperationCode#> + dp.PackFromRgba32(rgba); + } + } + + /// + /// A helper for that expects a byte span. + /// The layout of the data in 'sourceBytes' must be compatible with layout. + /// + /// The to the source bytes. + /// The to the destination pixels. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void PackFrom<#=pixelType#>Bytes(Span sourceBytes, Span destPixels, int count) + { + this.PackFrom<#=pixelType#>(sourceBytes.NonPortableCast>(), destPixels, count); + } + <# + } + +#> +// + +namespace ImageSharp.PixelFormats +{ + using System; + using System.Numerics; + using System.Runtime.CompilerServices; + + public partial class PixelOperations + { + <# + + GeneratePackFromMethodUsingPackFromRgba32("Rgba32", "rgba = Unsafe.Add(ref sourceRef, i);"); + GenerateToDestFormatMethods("Rgba32"); + + GeneratePackFromMethodUsingPackFromRgba32("Bgra32", "rgba = Unsafe.Add(ref sourceRef, i).ToRgba32();"); + GenerateToDestFormatMethods("Bgra32"); + + GeneratePackFromMethodUsingPackFromRgba32("Rgb24", "rgba.Rgb = Unsafe.Add(ref sourceRef, i);"); + GenerateToDestFormatMethods("Rgb24"); + + GeneratePackFromMethodUsingPackFromRgba32("Bgr24", "rgba.Bgr = Unsafe.Add(ref sourceRef, i);"); + GenerateToDestFormatMethods("Bgr24"); + + #> + + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 8eb44d00b2..a62d14527a 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -30,8 +30,7 @@ namespace ImageSharp.PixelFormats /// The number of pixels to convert. internal virtual void PackFromVector4(Span sourceVectors, Span destColors, int count) { - Guard.MustBeSizedAtLeast(sourceVectors, count, nameof(sourceVectors)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + GuardSpans(sourceVectors, nameof(sourceVectors), destColors, nameof(destColors), count); ref Vector4 sourceRef = ref sourceVectors.DangerousGetPinnableReference(); ref TPixel destRef = ref destColors.DangerousGetPinnableReference(); @@ -52,8 +51,7 @@ namespace ImageSharp.PixelFormats /// The number of pixels to convert. internal virtual void ToVector4(Span sourceColors, Span destVectors, int count) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destVectors, count, nameof(destVectors)); + GuardSpans(sourceColors, nameof(sourceColors), destVectors, nameof(destVectors), count); ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference(); ref Vector4 destRef = ref destVectors.DangerousGetPinnableReference(); @@ -65,216 +63,27 @@ namespace ImageSharp.PixelFormats dp = sp.ToVector4(); } } - - /// - /// Converts 'count' elements in 'source` span of data to a span of -s. - /// - /// The source span of data. - /// The to the destination pixels. - /// The number of pixels to convert. - internal virtual void PackFromRgb24(Span source, Span destPixels, int count) - { - Guard.MustBeSizedAtLeast(source, count, nameof(source)); - Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); - - ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference(); - ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); - - Rgba32 rgba = new Rgba32(0, 0, 0, 255); - - for (int i = 0; i < count; i++) - { - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - rgba.Rgb = Unsafe.Add(ref sourceRef, i); - dp.PackFromRgba32(rgba); - } - } - - /// - /// A version of that expects a byte span to be converted to - /// Bulk version of - /// that converts bytes expected in R->G->B order compatible to layout. - /// - /// The to the source bytes. - /// The to the destination pixels. - /// The number of pixels to convert. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void PackFromRgb24Bytes(Span sourceBytes, Span destPixels, int count) - { - this.PackFromRgb24(sourceBytes.NonPortableCast(), destPixels, count); - } - - internal virtual void ToRgb24(Span sourcePixels, Span dest, int count) - { - Guard.MustBeSizedAtLeast(sourcePixels, count, nameof(sourcePixels)); - Guard.MustBeSizedAtLeast(dest, count, nameof(dest)); - - ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); - ref Rgb24 destBaseRef = ref dest.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); - ref Rgb24 dp = ref Unsafe.Add(ref destBaseRef, i); - sp.ToRgb24(ref dp); - } - } - - /// - /// Bulk version of . - /// - /// The to the source colors. - /// The to the destination bytes. - /// The number of pixels to convert. - internal void ToRgb24Bytes(Span sourceColors, Span destBytes, int count) - { - this.ToRgb24(sourceColors, destBytes.NonPortableCast(), count); - } - - /// - /// Bulk version of that converts data in . - /// - /// The to the source bytes. - /// The to the destination colors. - /// The number of pixels to convert. - internal virtual void PackFromRgba32Bytes(Span sourceBytes, Span destColors, int count) - { - this.PackFromRgba32(sourceBytes.NonPortableCast(), destColors, count); - } - - internal virtual void PackFromRgba32(Span source, Span destPixels, int count) - { - Guard.MustBeSizedAtLeast(source, count, nameof(source)); - Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); - - ref Rgba32 sourceRef = ref source.DangerousGetPinnableReference(); - ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); - - Rgba32 rgba = new Rgba32(0, 0, 0, 255); - - for (int i = 0; i < count; i++) - { - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - rgba = Unsafe.Add(ref sourceRef, i); - dp.PackFromRgba32(rgba); - } - } - - /// - /// Bulk version of - /// - /// The to the source colors. - /// The to the destination bytes. - /// The number of pixels to convert. - internal virtual void ToXyzwBytes(Span sourceColors, Span destBytes, int count) - { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 4, nameof(destBytes)); - - ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - sp.ToXyzwBytes(destBytes, i * 4); - } - } - - /// - /// Bulk version of that converts data in . - /// - /// The to the source bytes. - /// The to the destination colors. - /// The number of pixels to convert. - internal virtual void PackFromZyxBytes(Span sourceBytes, Span destColors, int count) - { - this.PackFromBgr24(sourceBytes.NonPortableCast(), destColors, count); - } - - internal virtual void PackFromBgr24(Span source, Span destPixels, int count) - { - Guard.MustBeSizedAtLeast(source, count, nameof(source)); - Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); - - ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference(); - ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); - - Rgba32 rgba = new Rgba32(0, 0, 0, 255); - - for (int i = 0; i < count; i++) - { - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - rgba.Bgr = Unsafe.Add(ref sourceRef, i); - dp.PackFromRgba32(rgba); - } - } - - /// - /// Bulk version of . - /// - /// The to the source colors. - /// The to the destination bytes. - /// The number of pixels to convert. - internal virtual void ToZyxBytes(Span sourceColors, Span destBytes, int count) - { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 3, nameof(destBytes)); - - ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - sp.ToZyxBytes(destBytes, i * 3); - } - } - - /// - /// Bulk version of that converts data in . - /// - /// The to the source bytes. - /// The to the destination colors. - /// The number of pixels to convert. - internal virtual void PackFromZyxwBytes(Span sourceBytes, Span destColors, int count) - { - this.PackFromBgra32(sourceBytes.NonPortableCast(), destColors, count); - } - - internal virtual void PackFromBgra32(Span source, Span destPixels, int count) - { - Guard.MustBeSizedAtLeast(source, count, nameof(source)); - Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); - - ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference(); - ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); - Rgba32 rgba = new Rgba32(0, 0, 0, 255); - - for (int i = 0; i < count; i++) - { - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - rgba = Unsafe.Add(ref sourceRef, i).ToRgba32(); - dp.PackFromRgba32(rgba); - } - } /// - /// Bulk version of . + /// Verifies that the given 'source' and 'dest' spans are at least of 'minLength' size. + /// Throwing an if the condition is not met. /// - /// The to the source colors. - /// The to the destination bytes. - /// The number of pixels to convert. - internal virtual void ToZyxwBytes(Span sourceColors, Span destBytes, int count) + /// The source element type + /// The destination element type + /// The source span + /// The source parameter name + /// The destination span + /// The destination parameter name + /// The minimum length + protected internal static void GuardSpans( + Span source, + string sourceParamName, + Span dest, + string destParamName, + int minLength) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 4, nameof(destBytes)); - - ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - sp.ToZyxwBytes(destBytes, i * 4); - } + Guard.MustBeSizedAtLeast(source, minLength, sourceParamName); + Guard.MustBeSizedAtLeast(dest, minLength, destParamName); } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs index 0b0663cb51..f10f0ba279 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs @@ -120,6 +120,7 @@ namespace ImageSharp } } + /// internal override void PackFromRgb24(Span source, Span destPixels, int count) { Guard.MustBeSizedAtLeast(source, count, nameof(source)); @@ -138,6 +139,7 @@ namespace ImageSharp } } + /// internal override void ToRgb24(Span sourcePixels, Span dest, int count) { Guard.MustBeSizedAtLeast(sourcePixels, count, nameof(sourcePixels)); @@ -156,129 +158,86 @@ namespace ImageSharp } /// - internal override unsafe void PackFromRgba32Bytes(Span sourceBytes, Span destColors, int count) + internal override void PackFromRgba32(Span source, Span destPixels, int count) { - Guard.MustBeSizedAtLeast(sourceBytes, count * 4, nameof(sourceBytes)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - SpanHelper.Copy(sourceBytes, destColors.AsBytes(), count * sizeof(Rgba32)); + SpanHelper.Copy(source, destPixels, count); } /// - internal override unsafe void ToXyzwBytes(Span sourceColors, Span destBytes, int count) + internal override void ToRgba32(Span sourcePixels, Span dest, int count) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 4, nameof(destBytes)); + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - SpanHelper.Copy(sourceColors.AsBytes(), destBytes, count * sizeof(Rgba32)); + SpanHelper.Copy(sourcePixels, dest, count); } /// - internal override void PackFromZyxBytes(Span sourceBytes, Span destColors, int count) + internal override void PackFromBgr24(Span source, Span destPixels, int count) { - Guard.MustBeSizedAtLeast(sourceBytes, count * 3, nameof(sourceBytes)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - ref RGB24 sourceRef = ref Unsafe.As(ref sourceBytes.DangerousGetPinnableReference()); - ref Rgba32 destRef = ref destColors.DangerousGetPinnableReference(); + ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference(); + ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); for (int i = 0; i < count; i++) { - ref RGB24 sp = ref Unsafe.Add(ref sourceRef, i); + ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i); ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); - - Unsafe.As(ref dp) = sp.ToZyx(); + dp.Bgr = sp; dp.A = 255; } } /// - internal override void ToZyxBytes(Span sourceColors, Span destBytes, int count) + internal override void ToBgr24(Span sourcePixels, Span dest, int count) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 3, nameof(destBytes)); + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - ref Rgba32 sourceRef = ref sourceColors.DangerousGetPinnableReference(); - ref RGB24 destRef = ref Unsafe.As(ref destBytes.DangerousGetPinnableReference()); + ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Bgr24 destRef = ref dest.DangerousGetPinnableReference(); for (int i = 0; i < count; i++) { ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); - ref RGB24 dp = ref Unsafe.Add(ref destRef, i); - - dp = Unsafe.As(ref sp).ToZyx(); + ref Bgr24 dp = ref Unsafe.Add(ref destRef, i); + dp = sp.Bgr; } } /// - internal override void PackFromZyxwBytes(Span sourceBytes, Span destColors, int count) + internal override void PackFromBgra32(Span source, Span destPixels, int count) { - Guard.MustBeSizedAtLeast(sourceBytes, count * 4, nameof(sourceBytes)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - ref RGBA32 sourceRef = ref Unsafe.As(ref sourceBytes.DangerousGetPinnableReference()); - ref Rgba32 destRef = ref destColors.DangerousGetPinnableReference(); + ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference(); + ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); for (int i = 0; i < count; i++) { - ref RGBA32 sp = ref Unsafe.Add(ref sourceRef, i); + ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i); ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); - RGBA32 zyxw = sp.ToZyxw(); - dp = Unsafe.As(ref zyxw); + dp = sp.ToRgba32(); } } /// - internal override void ToZyxwBytes(Span sourceColors, Span destBytes, int count) + internal override void ToBgra32(Span sourcePixels, Span dest, int count) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 4, nameof(destBytes)); + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - ref Rgba32 sourceRef = ref sourceColors.DangerousGetPinnableReference(); - ref RGBA32 destRef = ref Unsafe.As(ref destBytes.DangerousGetPinnableReference()); + ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Bgra32 destRef = ref dest.DangerousGetPinnableReference(); for (int i = 0; i < count; i++) { - ref RGBA32 sp = ref Unsafe.As(ref Unsafe.Add(ref sourceRef, i)); - ref RGBA32 dp = ref Unsafe.Add(ref destRef, i); - dp = sp.ToZyxw(); + ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); + ref Bgra32 dp = ref Unsafe.Add(ref destRef, i); + dp = sp.ToBgra32(); } } - /// - /// Helper struct to manipulate 3-byte RGB data. - /// - [StructLayout(LayoutKind.Sequential)] - private struct RGB24 - { - private byte x; - - private byte y; - - private byte z; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RGB24 ToZyx() => new RGB24 { x = this.z, y = this.y, z = this.x }; - } - - /// - /// Helper struct to manipulate 4-byte RGBA data. - /// - [StructLayout(LayoutKind.Sequential)] - private struct RGBA32 - { - private byte x; - - private byte y; - - private byte z; - - private byte w; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RGBA32 ToZyxw() => new RGBA32 { x = this.z, y = this.y, z = this.x, w = this.w }; - } - /// /// Value type to store -s unpacked into multiple -s. /// diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs index 240a1a296f..85322c7c5c 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.cs @@ -337,6 +337,17 @@ namespace ImageSharp return new Vector4(this.R, this.G, this.B, this.A) / MaxBytes; } + /// + /// Gets the value of this struct as . + /// Useful for changing the component order. + /// + /// A value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Bgra32 ToBgra32() + { + return new Bgra32(this.R, this.G, this.B, this.A); + } + /// public override bool Equals(object obj) { diff --git a/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs index ac25b7f149..00b7461661 100644 --- a/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs @@ -23,10 +23,9 @@ namespace ImageSharp.PixelFormats /// internal override unsafe void ToVector4(Span sourceColors, Span destVectors, int count) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destVectors, count, nameof(destVectors)); + GuardSpans(sourceColors, nameof(sourceColors), destVectors, nameof(destVectors), count); - SpanHelper.Copy(sourceColors.AsBytes(), destVectors.AsBytes(), count * sizeof(Vector4)); + SpanHelper.Copy(sourceColors.NonPortableCast(), destVectors, count); } } } diff --git a/src/Shared/stylecop.json b/src/Shared/stylecop.json index 11ac49a40d..4f8205d063 100644 --- a/src/Shared/stylecop.json +++ b/src/Shared/stylecop.json @@ -4,12 +4,12 @@ "documentationRules": { "companyName": "James Jackson-South", "copyrightText": "Copyright (c) James Jackson-South and contributors.\nLicensed under the Apache License, Version 2.0." - , - "documentInterfaces": false, - "documentInternalElements": false, - "documentExposedElements": false, - "documentPrivateElements": false, - "documentPrivateFields": false + //, + //"documentInterfaces": false, + //"documentInternalElements": false, + //"documentExposedElements": false, + //"documentPrivateElements": false, + //"documentPrivateFields": false } } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs index f64bf561b0..a702e83856 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs @@ -51,13 +51,13 @@ namespace ImageSharp.Benchmarks.Color.Bulk [Benchmark] public void CommonBulk() { - new PixelOperations().ToXyzwBytes(this.source, this.destination, this.Count); + new PixelOperations().ToRgba32Bytes(this.source, this.destination, this.Count); } [Benchmark] public void OptimizedBulk() { - PixelOperations.Instance.ToXyzwBytes(this.source, this.destination, this.Count); + PixelOperations.Instance.ToRgba32Bytes(this.source, this.destination, this.Count); } } diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs index ad5b055468..0a121cfce9 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs @@ -226,7 +226,7 @@ namespace ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToXyzwBytes(s, d, count) + (s, d) => Operations.ToRgba32Bytes(s, d, count) ); } @@ -247,7 +247,7 @@ namespace ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.PackFromZyxBytes(s, d, count) + (s, d) => Operations.PackFromBgr24Bytes(s, d, count) ); } @@ -267,7 +267,7 @@ namespace ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToZyxBytes(s, d, count) + (s, d) => Operations.ToBgr24Bytes(s, d, count) ); } @@ -288,7 +288,7 @@ namespace ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.PackFromZyxwBytes(s, d, count) + (s, d) => Operations.PackFromBgra32Bytes(s, d, count) ); } @@ -308,7 +308,7 @@ namespace ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToZyxwBytes(s, d, count) + (s, d) => Operations.ToBgra32Bytes(s, d, count) ); }