From b44625e9d17c55462c086eec20c7f084dc5cc428 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Tue, 20 Mar 2018 18:05:12 -0700 Subject: [PATCH 01/34] Use ReadOnlySpans and BinaryPrimitives --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 41 ++++++++----------- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 23 +++-------- src/ImageSharp/Memory/SpanHelper.cs | 4 +- .../PixelOperations{TPixel}.Generated.cs | 32 +++++++-------- .../PixelOperations{TPixel}.Generated.tt | 8 ++-- .../Rgba32.PixelOperations.Generated.cs | 12 +++--- .../PixelFormats/PixelOperations{TPixel}.cs | 10 ++--- .../PixelFormats/Rgba32.PixelOperations.cs | 12 +++--- .../RgbaVector.PixelOperations.cs | 2 +- 9 files changed, 63 insertions(+), 81 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index dba4eaa15..fbb5c29a4 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -3,6 +3,7 @@ using System; using System.Buffers; +using System.Buffers.Binary; using System.Collections.Generic; using System.IO; using System.Linq; @@ -414,14 +415,11 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// The metadata to read to. /// The data containing physical data. - private void ReadPhysicalChunk(ImageMetaData metadata, byte[] data) + private void ReadPhysicalChunk(ImageMetaData metadata, ReadOnlySpan data) { - data.ReverseBytes(0, 4); - data.ReverseBytes(4, 4); - // 39.3700787 = inches in a meter. - metadata.HorizontalResolution = BitConverter.ToInt32(data, 0) / 39.3700787d; - metadata.VerticalResolution = BitConverter.ToInt32(data, 4) / 39.3700787d; + metadata.HorizontalResolution = BinaryPrimitives.ReadInt32BigEndian(data.Slice(0, 4)) / 39.3700787d; + metadata.VerticalResolution = BinaryPrimitives.ReadInt32BigEndian(data.Slice(4, 4)) / 39.3700787d; } /// @@ -699,14 +697,14 @@ namespace SixLabors.ImageSharp.Formats.Png /// The pixel format. /// The de-filtered scanline /// The image - private void ProcessDefilteredScanline(byte[] defilteredScanline, ImageFrame pixels) + private void ProcessDefilteredScanline(Span defilteredScanline, ImageFrame pixels) where TPixel : struct, IPixel { var color = default(TPixel); Span rowSpan = pixels.GetPixelRowSpan(this.currentRow); // Trim the first marker byte from the buffer - var scanlineBuffer = new Span(defilteredScanline, 1, defilteredScanline.Length - 1); + Span scanlineBuffer = defilteredScanline.Slice(1, defilteredScanline.Length - 1); switch (this.pngColorType) { @@ -1159,22 +1157,19 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Reads a header chunk from the data. /// - /// The containing data. - private void ReadHeaderChunk(byte[] data) + /// The containing data. + private void ReadHeaderChunk(ReadOnlySpan data) { - this.header = new PngHeader(); - - data.ReverseBytes(0, 4); - data.ReverseBytes(4, 4); - - this.header.Width = BitConverter.ToInt32(data, 0); - this.header.Height = BitConverter.ToInt32(data, 4); - - this.header.BitDepth = data[8]; - this.header.ColorType = (PngColorType)data[9]; - this.header.CompressionMethod = data[10]; - this.header.FilterMethod = data[11]; - this.header.InterlaceMethod = (PngInterlaceMode)data[12]; + this.header = new PngHeader + { + Width = BinaryPrimitives.ReadInt32BigEndian(data.Slice(0, 4)), + Height = BinaryPrimitives.ReadInt32BigEndian(data.Slice(4, 4)), + BitDepth = data[8], + ColorType = (PngColorType)data[9], + CompressionMethod = data[10], + FilterMethod = data[11], + InterlaceMethod = (PngInterlaceMode)data[12] + }; } /// diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 273516499..7ae075569 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers.Binary; using System.IO; using System.Linq; using SixLabors.ImageSharp.Advanced; @@ -243,20 +244,6 @@ namespace SixLabors.ImageSharp.Formats.Png this.paeth?.Dispose(); } - /// - /// Writes an integer to the byte array. - /// - /// The containing image data. - /// The amount to offset by. - /// The value to write. - private static void WriteInteger(byte[] data, int offset, int value) - { - byte[] buffer = BitConverter.GetBytes(value); - - buffer.ReverseBytes(); - Buffer.BlockCopy(buffer, 0, data, offset, 4); - } - /// /// Writes an integer to the stream. /// @@ -450,8 +437,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// The . private void WriteHeaderChunk(Stream stream, PngHeader header) { - WriteInteger(this.chunkDataBuffer, 0, header.Width); - WriteInteger(this.chunkDataBuffer, 4, header.Height); + BinaryPrimitives.WriteInt32BigEndian(new Span(this.chunkDataBuffer, 0, 4), header.Width); + BinaryPrimitives.WriteInt32BigEndian(new Span(this.chunkDataBuffer, 4, 4), header.Height); this.chunkDataBuffer[8] = header.BitDepth; this.chunkDataBuffer[9] = (byte)header.ColorType; @@ -535,8 +522,8 @@ namespace SixLabors.ImageSharp.Formats.Png int dpmX = (int)Math.Round(image.MetaData.HorizontalResolution * 39.3700787D); int dpmY = (int)Math.Round(image.MetaData.VerticalResolution * 39.3700787D); - WriteInteger(this.chunkDataBuffer, 0, dpmX); - WriteInteger(this.chunkDataBuffer, 4, dpmY); + BinaryPrimitives.WriteInt32BigEndian(this.chunkDataBuffer.AsSpan().Slice(0, 4), dpmX); + BinaryPrimitives.WriteInt32BigEndian(this.chunkDataBuffer.AsSpan().Slice(4, 4), dpmY); this.chunkDataBuffer[8] = 1; diff --git a/src/ImageSharp/Memory/SpanHelper.cs b/src/ImageSharp/Memory/SpanHelper.cs index 0c327484a..3bad54a12 100644 --- a/src/ImageSharp/Memory/SpanHelper.cs +++ b/src/ImageSharp/Memory/SpanHelper.cs @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Memory /// The destination . /// The number of elements to copy [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe void Copy(Span source, Span destination, int count) + public static unsafe void Copy(ReadOnlySpan source, Span destination, int count) where T : struct { DebugGuard.MustBeLessThanOrEqualTo(count, source.Length, nameof(count)); @@ -66,7 +66,7 @@ namespace SixLabors.ImageSharp.Memory /// The to copy elements from. /// The destination . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Copy(Span source, Span destination) + public static void Copy(ReadOnlySpan source, Span destination) where T : struct { Copy(source, destination, Math.Min(source.Length, destination.Length)); diff --git a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs index 9505ee6cf..904e27c7f 100644 --- a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs +++ b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The source of data. /// The to the destination pixels. /// The number of pixels to convert. - internal virtual void PackFromRgba32(Span source, Span destPixels, int count) + internal virtual void PackFromRgba32(ReadOnlySpan source, Span destPixels, int count) { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void PackFromRgba32Bytes(Span sourceBytes, Span destPixels, int count) + internal void PackFromRgba32Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) { this.PackFromRgba32(sourceBytes.NonPortableCast(), destPixels, count); } @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The span of source pixels /// The destination span of data. /// The number of pixels to convert. - internal virtual void ToRgba32(Span sourcePixels, Span dest, int count) + internal virtual void ToRgba32(ReadOnlySpan sourcePixels, Span dest, int count) { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); @@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ToRgba32Bytes(Span sourceColors, Span destBytes, int count) + internal void ToRgba32Bytes(ReadOnlySpan sourceColors, Span destBytes, int count) { this.ToRgba32(sourceColors, destBytes.NonPortableCast(), count); } @@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The source of data. /// The to the destination pixels. /// The number of pixels to convert. - internal virtual void PackFromBgra32(Span source, Span destPixels, int count) + internal virtual void PackFromBgra32(ReadOnlySpan source, Span destPixels, int count) { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); @@ -113,7 +113,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void PackFromBgra32Bytes(Span sourceBytes, Span destPixels, int count) + internal void PackFromBgra32Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) { this.PackFromBgra32(sourceBytes.NonPortableCast(), destPixels, count); } @@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The span of source pixels /// The destination span of data. /// The number of pixels to convert. - internal virtual void ToBgra32(Span sourcePixels, Span dest, int count) + internal virtual void ToBgra32(ReadOnlySpan sourcePixels, Span dest, int count) { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); @@ -148,7 +148,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ToBgra32Bytes(Span sourceColors, Span destBytes, int count) + internal void ToBgra32Bytes(ReadOnlySpan sourceColors, Span destBytes, int count) { this.ToBgra32(sourceColors, destBytes.NonPortableCast(), count); } @@ -159,7 +159,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The source of data. /// The to the destination pixels. /// The number of pixels to convert. - internal virtual void PackFromRgb24(Span source, Span destPixels, int count) + internal virtual void PackFromRgb24(ReadOnlySpan source, Span destPixels, int count) { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); @@ -184,7 +184,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void PackFromRgb24Bytes(Span sourceBytes, Span destPixels, int count) + internal void PackFromRgb24Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) { this.PackFromRgb24(sourceBytes.NonPortableCast(), destPixels, count); } @@ -196,7 +196,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The span of source pixels /// The destination span of data. /// The number of pixels to convert. - internal virtual void ToRgb24(Span sourcePixels, Span dest, int count) + internal virtual void ToRgb24(ReadOnlySpan sourcePixels, Span dest, int count) { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); @@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ToRgb24Bytes(Span sourceColors, Span destBytes, int count) + internal void ToRgb24Bytes(ReadOnlySpan sourceColors, Span destBytes, int count) { this.ToRgb24(sourceColors, destBytes.NonPortableCast(), count); } @@ -230,7 +230,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The source of data. /// The to the destination pixels. /// The number of pixels to convert. - internal virtual void PackFromBgr24(Span source, Span destPixels, int count) + internal virtual void PackFromBgr24(ReadOnlySpan source, Span destPixels, int count) { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); @@ -255,7 +255,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void PackFromBgr24Bytes(Span sourceBytes, Span destPixels, int count) + internal void PackFromBgr24Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) { this.PackFromBgr24(sourceBytes.NonPortableCast(), destPixels, count); } @@ -267,7 +267,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The span of source pixels /// The destination span of data. /// The number of pixels to convert. - internal virtual void ToBgr24(Span sourcePixels, Span dest, int count) + internal virtual void ToBgr24(ReadOnlySpan sourcePixels, Span dest, int count) { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); @@ -290,7 +290,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ToBgr24Bytes(Span sourceColors, Span destBytes, int count) + internal void ToBgr24Bytes(ReadOnlySpan sourceColors, Span destBytes, int count) { this.ToBgr24(sourceColors, destBytes.NonPortableCast(), count); } diff --git a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt index 365f5cb51..999fe6610 100644 --- a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt +++ b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt @@ -21,7 +21,7 @@ /// The span of source pixels /// The destination span of data. /// The number of pixels to convert. - internal virtual void To<#=pixelType#>(Span sourcePixels, Span<<#=pixelType#>> dest, int count) + internal virtual void To<#=pixelType#>(ReadOnlySpan sourcePixels, Span<<#=pixelType#>> dest, int count) { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); @@ -44,7 +44,7 @@ /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void To<#=pixelType#>Bytes(Span sourceColors, Span destBytes, int count) + internal void To<#=pixelType#>Bytes(ReadOnlySpan sourceColors, Span destBytes, int count) { this.To<#=pixelType#>(sourceColors, destBytes.NonPortableCast>(), count); } @@ -61,7 +61,7 @@ /// The source of data. /// The to the destination pixels. /// The number of pixels to convert. - internal virtual void PackFrom<#=pixelType#>(Span<<#=pixelType#>> source, Span destPixels, int count) + internal virtual void PackFrom<#=pixelType#>(ReadOnlySpan<<#=pixelType#>> source, Span destPixels, int count) { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); @@ -86,7 +86,7 @@ /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void PackFrom<#=pixelType#>Bytes(Span sourceBytes, Span destPixels, int count) + internal void PackFrom<#=pixelType#>Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) { this.PackFrom<#=pixelType#>(sourceBytes.NonPortableCast>(), destPixels, count); } diff --git a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs index c5ee6661f..a8e68e36d 100644 --- a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.PixelFormats { /// - internal override void PackFromRgb24(Span source, Span destPixels, int count) + internal override void PackFromRgb24(ReadOnlySpan source, Span destPixels, int count) { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb24(Span sourcePixels, Span dest, int count) + internal override void ToRgb24(ReadOnlySpan sourcePixels, Span dest, int count) { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); @@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void PackFromBgr24(Span source, Span destPixels, int count) + internal override void PackFromBgr24(ReadOnlySpan source, Span destPixels, int count) { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); @@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgr24(Span sourcePixels, Span dest, int count) + internal override void ToBgr24(ReadOnlySpan sourcePixels, Span dest, int count) { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); @@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void PackFromBgra32(Span source, Span destPixels, int count) + internal override void PackFromBgra32(ReadOnlySpan source, Span destPixels, int count) { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); @@ -97,7 +97,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgra32(Span sourcePixels, Span dest, int count) + internal override void ToBgra32(ReadOnlySpan sourcePixels, Span dest, int count) { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 6f7975240..e6238bf5a 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The to the source vectors. /// The to the destination colors. /// The number of pixels to convert. - internal virtual void PackFromVector4(Span sourceVectors, Span destColors, int count) + internal virtual void PackFromVector4(ReadOnlySpan sourceVectors, Span destColors, int count) { GuardSpans(sourceVectors, nameof(sourceVectors), destColors, nameof(destColors), count); @@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The to the source colors. /// The to the destination vectors. /// The number of pixels to convert. - internal virtual void ToVector4(Span sourceColors, Span destVectors, int count) + internal virtual void ToVector4(ReadOnlySpan sourceColors, Span destVectors, int count) { GuardSpans(sourceColors, nameof(sourceColors), destVectors, nameof(destVectors), count); @@ -75,14 +75,14 @@ namespace SixLabors.ImageSharp.PixelFormats /// The destination parameter name /// The minimum length protected internal static void GuardSpans( - Span source, + ReadOnlySpan source, string sourceParamName, Span dest, string destParamName, int minLength) { - Guard.MustBeSizedAtLeast(source, minLength, sourceParamName); - Guard.MustBeSizedAtLeast(dest, minLength, destParamName); + 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 d87820f84..a7e5736b0 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// https://github.com/dotnet/corefx/issues/15957 /// /// - internal static void ToVector4SimdAligned(Span sourceColors, Span destVectors, int count) + internal static void ToVector4SimdAligned(ReadOnlySpan sourceColors, Span destVectors, int count) { if (!Vector.IsHardwareAccelerated) { @@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToVector4(Span sourceColors, Span destVectors, int count) + internal override void ToVector4(ReadOnlySpan sourceColors, Span destVectors, int count) { Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); Guard.MustBeSizedAtLeast(destVectors, count, nameof(destVectors)); @@ -115,7 +115,7 @@ namespace SixLabors.ImageSharp.PixelFormats } } - internal override void PackFromVector4(Span sourceVectors, Span destColors, int count) + internal override void PackFromVector4(ReadOnlySpan sourceVectors, Span destColors, int count) { GuardSpans(sourceVectors, nameof(sourceVectors), destColors, nameof(destColors), count); @@ -130,7 +130,7 @@ namespace SixLabors.ImageSharp.PixelFormats if (alignedCount > 0) { - Span flatSrc = sourceVectors.Slice(0, alignedCount).NonPortableCast(); + ReadOnlySpan flatSrc = sourceVectors.Slice(0, alignedCount).NonPortableCast(); Span flatDest = destColors.NonPortableCast(); SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows(flatSrc, flatDest); @@ -145,7 +145,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void PackFromRgba32(Span source, Span destPixels, int count) + internal override void PackFromRgba32(ReadOnlySpan source, Span destPixels, int count) { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); @@ -153,7 +153,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba32(Span sourcePixels, Span dest, int count) + internal override void ToRgba32(ReadOnlySpan sourcePixels, Span dest, int count) { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); diff --git a/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs index 1886df29f..f038eaa91 100644 --- a/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.PixelFormats internal class PixelOperations : PixelOperations { /// - internal override unsafe void ToVector4(Span sourceColors, Span destVectors, int count) + internal override unsafe void ToVector4(ReadOnlySpan sourceColors, Span destVectors, int count) { GuardSpans(sourceColors, nameof(sourceColors), destVectors, nameof(destVectors), count); From 6095e44eded31f7f0d42cd65d38d8bf6990bc887 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Tue, 20 Mar 2018 18:07:49 -0700 Subject: [PATCH 02/34] Add source & destination gaurds --- src/ImageSharp/Common/Helpers/Guard.cs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/Guard.cs b/src/ImageSharp/Common/Helpers/Guard.cs index 0db5cb7c1..e0a4e9bca 100644 --- a/src/ImageSharp/Common/Helpers/Guard.cs +++ b/src/ImageSharp/Common/Helpers/Guard.cs @@ -233,15 +233,33 @@ namespace SixLabors.ImageSharp /// Verifies, that the `target` span has the length of 'minSpan', or longer. /// /// The element type of the spans - /// The target span. + /// The source span. /// The minimum length. /// The name of the parameter that is to be checked. /// - /// is true + /// is true + /// + public static void MustBeSizedAtLeast(ReadOnlySpan source, int minLength, string parameterName) + { + if (source.Length < minLength) + { + throw new ArgumentException($"Span-s must be at least of length {minLength}!", parameterName); + } + } + + /// + /// Verifies, that the `target` span has the length of 'minSpan', or longer. + /// + /// The element type of the spans + /// The target span. + /// The minimum length. + /// The name of the parameter that is to be checked. + /// + /// is true /// - public static void MustBeSizedAtLeast(Span target, int minLength, string parameterName) + public static void MustBeSizedAtLeast(Span dest, int minLength, string parameterName) { - if (target.Length < minLength) + if (dest.Length < minLength) { throw new ArgumentException($"Span-s must be at least of length {minLength}!", parameterName); } From fac6d076017fd5cbca1fa2e2d9f2a4751b553712 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Wed, 21 Mar 2018 08:28:30 -0700 Subject: [PATCH 03/34] Improve parameters names Use corefx naming --- src/ImageSharp/Common/Helpers/Guard.cs | 12 ++++---- .../PixelFormats/PixelOperations{TPixel}.cs | 30 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/Guard.cs b/src/ImageSharp/Common/Helpers/Guard.cs index e0a4e9bca..9f0a46f80 100644 --- a/src/ImageSharp/Common/Helpers/Guard.cs +++ b/src/ImageSharp/Common/Helpers/Guard.cs @@ -230,7 +230,7 @@ namespace SixLabors.ImageSharp } /// - /// Verifies, that the `target` span has the length of 'minSpan', or longer. + /// Verifies, that the `source` span has the length of 'minSpan', or longer. /// /// The element type of the spans /// The source span. @@ -248,18 +248,18 @@ namespace SixLabors.ImageSharp } /// - /// Verifies, that the `target` span has the length of 'minSpan', or longer. + /// Verifies, that the `source` span has the length of 'minSpan', or longer. /// /// The element type of the spans - /// The target span. + /// The target span. /// The minimum length. /// The name of the parameter that is to be checked. /// - /// is true + /// is true /// - public static void MustBeSizedAtLeast(Span dest, int minLength, string parameterName) + public static void MustBeSizedAtLeast(Span source, int minLength, string parameterName) { - if (dest.Length < minLength) + if (source.Length < minLength) { throw new ArgumentException($"Span-s must be at least of length {minLength}!", parameterName); } diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index e6238bf5a..6d25fe9f4 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -25,14 +25,14 @@ namespace SixLabors.ImageSharp.PixelFormats /// Bulk version of /// /// The to the source vectors. - /// The to the destination colors. + /// The to the destination colors. /// The number of pixels to convert. - internal virtual void PackFromVector4(ReadOnlySpan sourceVectors, Span destColors, int count) + internal virtual void PackFromVector4(ReadOnlySpan sourceVectors, Span destinationColors, int count) { - GuardSpans(sourceVectors, nameof(sourceVectors), destColors, nameof(destColors), count); + GuardSpans(sourceVectors, nameof(sourceVectors), destinationColors, nameof(destinationColors), count); ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); - ref TPixel destRef = ref MemoryMarshal.GetReference(destColors); + ref TPixel destRef = ref MemoryMarshal.GetReference(destinationColors); for (int i = 0; i < count; i++) { @@ -46,14 +46,14 @@ namespace SixLabors.ImageSharp.PixelFormats /// Bulk version of . /// /// The to the source colors. - /// The to the destination vectors. + /// The to the destination vectors. /// The number of pixels to convert. - internal virtual void ToVector4(ReadOnlySpan sourceColors, Span destVectors, int count) + internal virtual void ToVector4(ReadOnlySpan sourceColors, Span destinationVectors, int count) { - GuardSpans(sourceColors, nameof(sourceColors), destVectors, nameof(destVectors), count); + GuardSpans(sourceColors, nameof(sourceColors), destinationVectors, nameof(destinationVectors), count); ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors); - ref Vector4 destRef = ref MemoryMarshal.GetReference(destVectors); + ref Vector4 destRef = ref MemoryMarshal.GetReference(destinationVectors); for (int i = 0; i < count; i++) { @@ -64,25 +64,25 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// Verifies that the given 'source' and 'dest' spans are at least of 'minLength' size. + /// Verifies that the given 'source' and 'destination' spans are at least of 'minLength' size. /// Throwing an if the condition is not met. /// /// The source element type /// The destination element type /// The source span /// The source parameter name - /// The destination span - /// The destination parameter name + /// The destination span + /// The destination parameter name /// The minimum length protected internal static void GuardSpans( ReadOnlySpan source, string sourceParamName, - Span dest, - string destParamName, + Span destination, + string destinationParamName, int minLength) { - Guard.MustBeSizedAtLeast(source, minLength, sourceParamName); - Guard.MustBeSizedAtLeast(dest, minLength, destParamName); + Guard.MustBeSizedAtLeast(source, minLength, sourceParamName); + Guard.MustBeSizedAtLeast(destination, minLength, destinationParamName); } } } \ No newline at end of file From 14f7ff8fb74a7cd20eb799e70328439fac3c075d Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Wed, 21 Mar 2018 08:41:47 -0700 Subject: [PATCH 04/34] Remove ReverseBytes (replacing with faster BinaryPrimitives calls) --- .../Common/Extensions/ByteExtensions.cs | 33 ------------------- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 12 +++---- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 11 ++++--- 3 files changed, 12 insertions(+), 44 deletions(-) diff --git a/src/ImageSharp/Common/Extensions/ByteExtensions.cs b/src/ImageSharp/Common/Extensions/ByteExtensions.cs index f6c720795..b5b868dea 100644 --- a/src/ImageSharp/Common/Extensions/ByteExtensions.cs +++ b/src/ImageSharp/Common/Extensions/ByteExtensions.cs @@ -12,39 +12,6 @@ namespace SixLabors.ImageSharp /// internal static class ByteExtensions { - /// - /// Optimized reversal algorithm. - /// - /// The byte array. - public static void ReverseBytes(this byte[] source) - { - ReverseBytes(source, 0, source.Length); - } - - /// - /// Optimized reversal algorithm. - /// - /// The byte array. - /// The index. - /// The length. - /// is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ReverseBytes(this byte[] source, int index, int length) - { - Guard.NotNull(source, nameof(source)); - - int i = index; - int j = index + length - 1; - while (i < j) - { - byte temp = source[i]; - source[i] = source[j]; - source[j] = temp; - i++; - j--; - } - } - /// /// Returns a reference to the given position of the array unsafe casted to . /// diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index fbb5c29a4..349fa7745 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -1251,14 +1251,13 @@ namespace SixLabors.ImageSharp.Formats.Png private void ReadChunkCrc(PngChunk chunk) { int numBytes = this.currentStream.Read(this.crcBuffer, 0, 4); + if (numBytes >= 1 && numBytes <= 3) { throw new ImageFormatException("Image stream is not valid!"); } - - this.crcBuffer.ReverseBytes(); - - chunk.Crc = BitConverter.ToUInt32(this.crcBuffer, 0); + + chunk.Crc = BinaryPrimitives.ReadUInt32BigEndian(this.crcBuffer); this.crc.Reset(); this.crc.Update(this.chunkTypeBuffer); @@ -1323,15 +1322,14 @@ namespace SixLabors.ImageSharp.Formats.Png private void ReadChunkLength(PngChunk chunk) { int numBytes = this.currentStream.Read(this.chunkLengthBuffer, 0, 4); + if (numBytes < 4) { chunk.Length = -1; return; } - this.chunkLengthBuffer.ReverseBytes(); - - chunk.Length = BitConverter.ToInt32(this.chunkLengthBuffer, 0); + chunk.Length = BinaryPrimitives.ReadInt32BigEndian(this.chunkLengthBuffer); } /// diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 7ae075569..55bf1bbec 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -5,6 +5,7 @@ using System; using System.Buffers.Binary; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats.Png.Filters; using SixLabors.ImageSharp.Formats.Png.Zlib; @@ -251,9 +252,10 @@ namespace SixLabors.ImageSharp.Formats.Png /// The value to write. private static void WriteInteger(Stream stream, int value) { - byte[] buffer = BitConverter.GetBytes(value); + byte[] buffer = new byte[4]; + + BinaryPrimitives.WriteInt32BigEndian(buffer, value); - buffer.ReverseBytes(); stream.Write(buffer, 0, 4); } @@ -264,9 +266,10 @@ namespace SixLabors.ImageSharp.Formats.Png /// The value to write. private static void WriteInteger(Stream stream, uint value) { - byte[] buffer = BitConverter.GetBytes(value); + byte[] buffer = new byte[4]; + + BinaryPrimitives.WriteUInt32BigEndian(buffer, value); - buffer.ReverseBytes(); stream.Write(buffer, 0, 4); } From 5216e286b80675ffa411b1f8df816f4358be67ab Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Wed, 21 Mar 2018 09:05:25 -0700 Subject: [PATCH 05/34] Remove unnesssary abstraction and validation for bools. Booleans don't have Endianness. --- src/ImageSharp/IO/EndianBinaryReader.cs | 10 +++++++++- src/ImageSharp/IO/EndianBitConverter.ToType.cs | 12 ------------ .../IO/BigEndianBitConverter.ToTypeTests.cs | 18 ------------------ .../IO/LittleEndianBitConverter.ToTypeTests.cs | 16 ---------------- 4 files changed, 9 insertions(+), 47 deletions(-) diff --git a/src/ImageSharp/IO/EndianBinaryReader.cs b/src/ImageSharp/IO/EndianBinaryReader.cs index 0d660c68d..2b2a79c7e 100644 --- a/src/ImageSharp/IO/EndianBinaryReader.cs +++ b/src/ImageSharp/IO/EndianBinaryReader.cs @@ -38,6 +38,11 @@ namespace SixLabors.ImageSharp.IO /// private bool disposed; + /// + /// The endianness used to read data + /// + private Endianness endianness; + /// /// Initializes a new instance of the class. /// Equivalent of , but with either endianness, depending on @@ -72,6 +77,7 @@ namespace SixLabors.ImageSharp.IO this.BitConverter = EndianBitConverter.GetConverter(endianness); this.Encoding = encoding; this.decoder = encoding.GetDecoder(); + this.endianness = endianness; this.minBytesPerChar = 1; if (encoding is UnicodeEncoding) @@ -141,7 +147,9 @@ namespace SixLabors.ImageSharp.IO public bool ReadBoolean() { this.ReadInternal(this.storageBuffer, 1); - return this.BitConverter.ToBoolean(this.storageBuffer, 0); + + return this.storageBuffer[0] != 0; + } /// diff --git a/src/ImageSharp/IO/EndianBitConverter.ToType.cs b/src/ImageSharp/IO/EndianBitConverter.ToType.cs index 0c0e49911..ee14ef33e 100644 --- a/src/ImageSharp/IO/EndianBitConverter.ToType.cs +++ b/src/ImageSharp/IO/EndianBitConverter.ToType.cs @@ -67,18 +67,6 @@ namespace SixLabors.ImageSharp.IO return unchecked((ulong)this.ToInt64(value, startIndex)); } - /// - /// Returns a Boolean value converted from one byte at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// true if the byte at startIndex in value is nonzero; otherwise, false. - public bool ToBoolean(byte[] value, int startIndex) - { - CheckByteArgument(value, startIndex, 1); - return value[startIndex] != 0; - } - /// /// Returns a Unicode character converted from two bytes at a specified position in a byte array. /// diff --git a/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs b/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs index 19ef24c79..67fb7e2cc 100644 --- a/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs +++ b/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs @@ -15,7 +15,6 @@ namespace SixLabors.ImageSharp.Tests.IO [Fact] public void CopyToWithNullBufferThrowsException() { - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToBoolean(null, 0)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt16(null, 0)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt16(null, 0)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt32(null, 0)); @@ -27,7 +26,6 @@ namespace SixLabors.ImageSharp.Tests.IO [Fact] public void CopyToWithIndexTooBigThrowsException() { - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToBoolean(new byte[1], 1)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt16(new byte[2], 1)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt16(new byte[2], 1)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt32(new byte[4], 1)); @@ -39,7 +37,6 @@ namespace SixLabors.ImageSharp.Tests.IO [Fact] public void CopyToWithBufferTooSmallThrowsException() { - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToBoolean(new byte[0], 0)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt16(new byte[1], 0)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt16(new byte[1], 0)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt32(new byte[3], 0)); @@ -48,21 +45,6 @@ namespace SixLabors.ImageSharp.Tests.IO Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt64(new byte[7], 0)); } - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToBoolean() - { - Assert.False(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0 }, 0)); - Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1 }, 0)); - Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 42 }, 0)); - - Assert.False(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1)); - Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1)); - Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 42 }, 1)); - } - /// /// Tests that passing a returns the correct bytes. /// diff --git a/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs b/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs index 0e09d1d07..4c890b367 100644 --- a/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs +++ b/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs @@ -15,7 +15,6 @@ namespace SixLabors.ImageSharp.Tests.IO [Fact] public void CopyToWithNullBufferThrowsException() { - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToBoolean(null, 0)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt16(null, 0)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt16(null, 0)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt32(null, 0)); @@ -27,7 +26,6 @@ namespace SixLabors.ImageSharp.Tests.IO [Fact] public void CopyToWithIndexTooBigThrowsException() { - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[1], 1)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt16(new byte[2], 1)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[2], 1)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt32(new byte[4], 1)); @@ -39,7 +37,6 @@ namespace SixLabors.ImageSharp.Tests.IO [Fact] public void CopyToWithBufferTooSmallThrowsException() { - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[0], 0)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt16(new byte[1], 0)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[1], 0)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt32(new byte[3], 0)); @@ -48,19 +45,6 @@ namespace SixLabors.ImageSharp.Tests.IO Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[7], 0)); } - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToBoolean() - { - Assert.False(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0 }, 0)); - Assert.True(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1 }, 0)); - - Assert.False(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1)); - Assert.True(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1)); - } - /// /// Tests that passing a returns the correct bytes. /// From 267b6f05d0349a6914af844f560d88c38c5fed4d Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Wed, 21 Mar 2018 09:23:35 -0700 Subject: [PATCH 06/34] Use BinaryPrimitives in BitConverters --- src/ImageSharp/IO/BigEndianBitConverter.cs | 17 ++++++---------- src/ImageSharp/IO/LittleEndianBitConverter.cs | 20 +++++++++---------- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/ImageSharp/IO/BigEndianBitConverter.cs b/src/ImageSharp/IO/BigEndianBitConverter.cs index 2fcfd966c..a9a713e1a 100644 --- a/src/ImageSharp/IO/BigEndianBitConverter.cs +++ b/src/ImageSharp/IO/BigEndianBitConverter.cs @@ -1,6 +1,9 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; +using System.Buffers.Binary; + namespace SixLabors.ImageSharp.IO { /// @@ -58,27 +61,19 @@ namespace SixLabors.ImageSharp.IO /// public override short ToInt16(byte[] value, int startIndex) { - CheckByteArgument(value, startIndex, 2); - - return (short)((value[startIndex] << 8) | value[startIndex + 1]); + return BinaryPrimitives.ReadInt16BigEndian(value.AsReadOnlySpan().Slice(startIndex)); } /// public override int ToInt32(byte[] value, int startIndex) { - CheckByteArgument(value, startIndex, 4); - - return (value[startIndex] << 24) | (value[startIndex + 1] << 16) | (value[startIndex + 2] << 8) | value[startIndex + 3]; + return BinaryPrimitives.ReadInt32BigEndian(value.AsReadOnlySpan().Slice(startIndex)); } /// public override long ToInt64(byte[] value, int startIndex) { - CheckByteArgument(value, startIndex, 8); - - long p1 = (value[startIndex] << 24) | (value[startIndex + 1] << 16) | (value[startIndex + 2] << 8) | value[startIndex + 3]; - long p2 = (value[startIndex + 4] << 24) | (value[startIndex + 5] << 16) | (value[startIndex + 6] << 8) | value[startIndex + 7]; - return (p2 & 0xFFFFFFFF) | (p1 << 32); + return BinaryPrimitives.ReadInt64BigEndian(value.AsReadOnlySpan().Slice(startIndex)); } } } \ No newline at end of file diff --git a/src/ImageSharp/IO/LittleEndianBitConverter.cs b/src/ImageSharp/IO/LittleEndianBitConverter.cs index a69831586..b9db34f90 100644 --- a/src/ImageSharp/IO/LittleEndianBitConverter.cs +++ b/src/ImageSharp/IO/LittleEndianBitConverter.cs @@ -1,6 +1,9 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; +using System.Buffers.Binary; + namespace SixLabors.ImageSharp.IO { /// @@ -56,26 +59,21 @@ namespace SixLabors.ImageSharp.IO } /// - public unsafe override short ToInt16(byte[] value, int startIndex) + public override short ToInt16(byte[] value, int startIndex) { - CheckByteArgument(value, startIndex, 2); - return (short)((value[startIndex + 1] << 8) | value[startIndex]); + return BinaryPrimitives.ReadInt16LittleEndian(value.AsReadOnlySpan().Slice(startIndex)); } /// - public unsafe override int ToInt32(byte[] value, int startIndex) + public override int ToInt32(byte[] value, int startIndex) { - CheckByteArgument(value, startIndex, 4); - return (value[startIndex + 3] << 24) | (value[startIndex + 2] << 16) | (value[startIndex + 1] << 8) | value[startIndex]; + return BinaryPrimitives.ReadInt32LittleEndian(value.AsReadOnlySpan().Slice(startIndex)); } /// - public unsafe override long ToInt64(byte[] value, int startIndex) + public override long ToInt64(byte[] value, int startIndex) { - CheckByteArgument(value, startIndex, 8); - long p1 = (value[startIndex + 7] << 24) | (value[startIndex + 6] << 16) | (value[startIndex + 5] << 8) | value[startIndex + 4]; - long p2 = (value[startIndex + 3] << 24) | (value[startIndex + 2] << 16) | (value[startIndex + 1] << 8) | value[startIndex]; - return (p2 & 0xFFFFFFFF) | (p1 << 32); + return BinaryPrimitives.ReadInt64LittleEndian(value.AsReadOnlySpan().Slice(startIndex)); } } } \ No newline at end of file From db77dc65362d83df2df92d872bca1ea4a56e72ac Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Wed, 21 Mar 2018 09:24:59 -0700 Subject: [PATCH 07/34] Remove BitConverter from EndianBinaryReader Also eliminate unnessary offset arithmetic. --- src/ImageSharp/IO/EndianBinaryReader.cs | 68 ++++++++++++++++--------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/src/ImageSharp/IO/EndianBinaryReader.cs b/src/ImageSharp/IO/EndianBinaryReader.cs index 2b2a79c7e..43bb59682 100644 --- a/src/ImageSharp/IO/EndianBinaryReader.cs +++ b/src/ImageSharp/IO/EndianBinaryReader.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers.Binary; using System.IO; using System.Text; @@ -41,7 +42,7 @@ namespace SixLabors.ImageSharp.IO /// /// The endianness used to read data /// - private Endianness endianness; + private readonly Endianness endianness; /// /// Initializes a new instance of the class. @@ -74,7 +75,6 @@ namespace SixLabors.ImageSharp.IO Guard.IsTrue(stream.CanRead, nameof(stream), "Stream isn't readable"); this.BaseStream = stream; - this.BitConverter = EndianBitConverter.GetConverter(endianness); this.Encoding = encoding; this.decoder = encoding.GetDecoder(); this.endianness = endianness; @@ -96,11 +96,6 @@ namespace SixLabors.ImageSharp.IO /// public Stream BaseStream { get; } - /// - /// Gets the bit converter used to read values from the stream. - /// - internal EndianBitConverter BitConverter { get; } - /// /// Closes the reader, including the underlying stream. /// @@ -149,7 +144,6 @@ namespace SixLabors.ImageSharp.IO this.ReadInternal(this.storageBuffer, 1); return this.storageBuffer[0] != 0; - } /// @@ -160,7 +154,10 @@ namespace SixLabors.ImageSharp.IO public short ReadInt16() { this.ReadInternal(this.storageBuffer, 2); - return this.BitConverter.ToInt16(this.storageBuffer, 0); + + return (this.endianness == Endianness.BigEndian) + ? BinaryPrimitives.ReadInt16BigEndian(this.storageBuffer) + : BinaryPrimitives.ReadInt16LittleEndian(this.storageBuffer); } /// @@ -171,7 +168,10 @@ namespace SixLabors.ImageSharp.IO public int ReadInt32() { this.ReadInternal(this.storageBuffer, 4); - return this.BitConverter.ToInt32(this.storageBuffer, 0); + + return (this.endianness == Endianness.BigEndian) + ? BinaryPrimitives.ReadInt32BigEndian(this.storageBuffer) + : BinaryPrimitives.ReadInt32LittleEndian(this.storageBuffer); } /// @@ -182,7 +182,10 @@ namespace SixLabors.ImageSharp.IO public long ReadInt64() { this.ReadInternal(this.storageBuffer, 8); - return this.BitConverter.ToInt64(this.storageBuffer, 0); + + return (this.endianness == Endianness.BigEndian) + ? BinaryPrimitives.ReadInt64BigEndian(this.storageBuffer) + : BinaryPrimitives.ReadInt64LittleEndian(this.storageBuffer); } /// @@ -193,7 +196,10 @@ namespace SixLabors.ImageSharp.IO public ushort ReadUInt16() { this.ReadInternal(this.storageBuffer, 2); - return this.BitConverter.ToUInt16(this.storageBuffer, 0); + + return (this.endianness == Endianness.BigEndian) + ? BinaryPrimitives.ReadUInt16BigEndian(this.storageBuffer) + : BinaryPrimitives.ReadUInt16LittleEndian(this.storageBuffer); } /// @@ -204,7 +210,10 @@ namespace SixLabors.ImageSharp.IO public uint ReadUInt32() { this.ReadInternal(this.storageBuffer, 4); - return this.BitConverter.ToUInt32(this.storageBuffer, 0); + + return (this.endianness == Endianness.BigEndian) + ? BinaryPrimitives.ReadUInt32BigEndian(this.storageBuffer) + : BinaryPrimitives.ReadUInt32LittleEndian(this.storageBuffer); } /// @@ -215,7 +224,11 @@ namespace SixLabors.ImageSharp.IO public ulong ReadUInt64() { this.ReadInternal(this.storageBuffer, 8); - return this.BitConverter.ToUInt64(this.storageBuffer, 0); + + return (this.endianness == Endianness.BigEndian) + ? BinaryPrimitives.ReadUInt64BigEndian(this.storageBuffer) + : BinaryPrimitives.ReadUInt64LittleEndian(this.storageBuffer); + } /// @@ -223,10 +236,11 @@ namespace SixLabors.ImageSharp.IO /// for this reader. 4 bytes are read. /// /// The floating point value read - public float ReadSingle() + public unsafe float ReadSingle() { - this.ReadInternal(this.storageBuffer, 4); - return this.BitConverter.ToSingle(this.storageBuffer, 0); + int intValue = ReadInt32(); + + return *((float*)&intValue); } /// @@ -234,10 +248,11 @@ namespace SixLabors.ImageSharp.IO /// for this reader. 8 bytes are read. /// /// The floating point value read - public double ReadDouble() + public unsafe double ReadDouble() { - this.ReadInternal(this.storageBuffer, 8); - return this.BitConverter.ToDouble(this.storageBuffer, 0); + long value = this.ReadInt64(); + + return *((double*)&value); } /// @@ -245,10 +260,17 @@ namespace SixLabors.ImageSharp.IO /// for this reader. 16 bytes are read. /// /// The decimal value read - public decimal ReadDecimal() + public unsafe decimal ReadDecimal() { - this.ReadInternal(this.storageBuffer, 16); - return this.BitConverter.ToDecimal(this.storageBuffer, 0); + decimal result = 0m; + int* presult = (int*)&result; + + presult[0] = this.ReadInt32(); + presult[1] = this.ReadInt32(); + presult[2] = this.ReadInt32(); + presult[3] = this.ReadInt32(); + + return result; } /// From 70cdb1984c17ba1a4270e5440d8f01e2477dead8 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Wed, 21 Mar 2018 09:28:29 -0700 Subject: [PATCH 08/34] Update source generators to use ReadOnlySpan --- .../PixelOperations{TPixel}.Generated.cs | 42 +++++++++---------- .../Rgba32.PixelOperations.Generated.tt | 4 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs index 904e27c7f..632455a0e 100644 --- a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs +++ b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs @@ -33,9 +33,9 @@ namespace SixLabors.ImageSharp.PixelFormats dp.PackFromRgba32(rgba); } } - - /// - /// A helper for that expects a byte span. + + /// + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// /// The to the source bytes. @@ -69,14 +69,14 @@ namespace SixLabors.ImageSharp.PixelFormats } } - /// - /// A helper for that expects a byte span as destination. + /// + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// /// The to the source colors. /// The to the destination bytes. /// The number of pixels to convert. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void ToRgba32Bytes(ReadOnlySpan sourceColors, Span destBytes, int count) { this.ToRgba32(sourceColors, destBytes.NonPortableCast(), count); @@ -104,9 +104,9 @@ namespace SixLabors.ImageSharp.PixelFormats dp.PackFromRgba32(rgba); } } - - /// - /// A helper for that expects a byte span. + + /// + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// /// The to the source bytes. @@ -140,14 +140,14 @@ namespace SixLabors.ImageSharp.PixelFormats } } - /// - /// A helper for that expects a byte span as destination. + /// + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// /// The to the source colors. /// The to the destination bytes. /// The number of pixels to convert. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void ToBgra32Bytes(ReadOnlySpan sourceColors, Span destBytes, int count) { this.ToBgra32(sourceColors, destBytes.NonPortableCast(), count); @@ -175,9 +175,9 @@ namespace SixLabors.ImageSharp.PixelFormats dp.PackFromRgba32(rgba); } } - - /// - /// A helper for that expects a byte span. + + /// + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// /// The to the source bytes. @@ -211,14 +211,14 @@ namespace SixLabors.ImageSharp.PixelFormats } } - /// - /// A helper for that expects a byte span as destination. + /// + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// /// The to the source colors. /// The to the destination bytes. /// The number of pixels to convert. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void ToRgb24Bytes(ReadOnlySpan sourceColors, Span destBytes, int count) { this.ToRgb24(sourceColors, destBytes.NonPortableCast(), count); @@ -282,14 +282,14 @@ namespace SixLabors.ImageSharp.PixelFormats } } - /// - /// A helper for that expects a byte span as destination. + /// + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// /// The to the source colors. /// The to the destination bytes. /// The number of pixels to convert. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void ToBgr24Bytes(ReadOnlySpan sourceColors, Span destBytes, int count) { this.ToBgr24(sourceColors, destBytes.NonPortableCast(), count); diff --git a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt index 9dfec2cf9..4a88bbad7 100644 --- a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt @@ -14,7 +14,7 @@ #> /// - internal override void PackFrom<#=pixelType#>(Span<<#=pixelType#>> source, Span destPixels, int count) + internal override void PackFrom<#=pixelType#>(ReadOnlySpan<<#=pixelType#>> source, Span destPixels, int count) { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); @@ -36,7 +36,7 @@ #> /// - internal override void To<#=pixelType#>(Span sourcePixels, Span<<#=pixelType#>> dest, int count) + internal override void To<#=pixelType#>(ReadOnlySpan sourcePixels, Span<<#=pixelType#>> dest, int count) { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); From 4d6afe6d62cc9ccfa35f7660af5cb6bcc6091708 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Wed, 21 Mar 2018 09:44:05 -0700 Subject: [PATCH 09/34] Remove unused ReadDecimal method (unsafe) --- src/ImageSharp/IO/EndianBinaryReader.cs | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/src/ImageSharp/IO/EndianBinaryReader.cs b/src/ImageSharp/IO/EndianBinaryReader.cs index 43bb59682..dfb57924d 100644 --- a/src/ImageSharp/IO/EndianBinaryReader.cs +++ b/src/ImageSharp/IO/EndianBinaryReader.cs @@ -9,7 +9,7 @@ using System.Text; namespace SixLabors.ImageSharp.IO { /// - /// Equivalent of , but with either endianness, depending on the it is constructed with. + /// Equivalent of , but with either endianness. /// No data is buffered in the reader; the client may seek within the stream at will. /// internal class EndianBinaryReader : IDisposable @@ -46,8 +46,7 @@ namespace SixLabors.ImageSharp.IO /// /// Initializes a new instance of the class. - /// Equivalent of , but with either endianness, depending on - /// the EndianBitConverter it is constructed with. + /// Modeled after with endian support. /// /// /// Endianness to use when reading data @@ -238,7 +237,7 @@ namespace SixLabors.ImageSharp.IO /// The floating point value read public unsafe float ReadSingle() { - int intValue = ReadInt32(); + int intValue = this.ReadInt32(); return *((float*)&intValue); } @@ -255,24 +254,6 @@ namespace SixLabors.ImageSharp.IO return *((double*)&value); } - /// - /// Reads a decimal value from the stream, using the bit converter - /// for this reader. 16 bytes are read. - /// - /// The decimal value read - public unsafe decimal ReadDecimal() - { - decimal result = 0m; - int* presult = (int*)&result; - - presult[0] = this.ReadInt32(); - presult[1] = this.ReadInt32(); - presult[2] = this.ReadInt32(); - presult[3] = this.ReadInt32(); - - return result; - } - /// /// Reads a single character from the stream, using the character encoding for /// this reader. If no characters have been fully read by the time the stream ends, From 8fbb326a0f6b9e0c213ae4f78a873fccbab62913 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Wed, 21 Mar 2018 09:55:06 -0700 Subject: [PATCH 10/34] Use Span.CopyTo Fast span has an optimized fast path --- src/ImageSharp/Memory/SpanHelper.cs | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/ImageSharp/Memory/SpanHelper.cs b/src/ImageSharp/Memory/SpanHelper.cs index 3bad54a12..1cfad7222 100644 --- a/src/ImageSharp/Memory/SpanHelper.cs +++ b/src/ImageSharp/Memory/SpanHelper.cs @@ -37,26 +37,7 @@ namespace SixLabors.ImageSharp.Memory public static unsafe void Copy(ReadOnlySpan source, Span destination, int count) where T : struct { - DebugGuard.MustBeLessThanOrEqualTo(count, source.Length, nameof(count)); - DebugGuard.MustBeLessThanOrEqualTo(count, destination.Length, nameof(count)); - - ref byte srcRef = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); - ref byte destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destination)); - - int byteCount = Unsafe.SizeOf() * count; - - // TODO: Use unfixed Unsafe.CopyBlock(ref T, ref T, int) for small blocks, when it gets available! - // This is now available. Check with Anton re intent. Do we replace both ifdefs? - fixed (byte* pSrc = &srcRef) - fixed (byte* pDest = &destRef) - { -#if NETSTANDARD1_1 - Unsafe.CopyBlock(pDest, pSrc, (uint)byteCount); -#else - int destLength = destination.Length * Unsafe.SizeOf(); - Buffer.MemoryCopy(pSrc, pDest, destLength, byteCount); -#endif - } + source.Slice(0, count).CopyTo(destination); } /// From c60f7f2aa33c829427b59db905e37c0ea8c5954b Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Wed, 21 Mar 2018 10:12:02 -0700 Subject: [PATCH 11/34] Revert "Remove unnesssary abstraction and validation for bools." This reverts commit 9b07269085d1ca1da12bc147f24f2f7d3e3bed91. --- src/ImageSharp/IO/EndianBitConverter.ToType.cs | 12 ++++++++++++ .../IO/BigEndianBitConverter.ToTypeTests.cs | 18 ++++++++++++++++++ .../IO/LittleEndianBitConverter.ToTypeTests.cs | 16 ++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/src/ImageSharp/IO/EndianBitConverter.ToType.cs b/src/ImageSharp/IO/EndianBitConverter.ToType.cs index ee14ef33e..0c0e49911 100644 --- a/src/ImageSharp/IO/EndianBitConverter.ToType.cs +++ b/src/ImageSharp/IO/EndianBitConverter.ToType.cs @@ -67,6 +67,18 @@ namespace SixLabors.ImageSharp.IO return unchecked((ulong)this.ToInt64(value, startIndex)); } + /// + /// Returns a Boolean value converted from one byte at a specified position in a byte array. + /// + /// An array of bytes. + /// The starting position within value. + /// true if the byte at startIndex in value is nonzero; otherwise, false. + public bool ToBoolean(byte[] value, int startIndex) + { + CheckByteArgument(value, startIndex, 1); + return value[startIndex] != 0; + } + /// /// Returns a Unicode character converted from two bytes at a specified position in a byte array. /// diff --git a/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs b/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs index 67fb7e2cc..19ef24c79 100644 --- a/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs +++ b/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs @@ -15,6 +15,7 @@ namespace SixLabors.ImageSharp.Tests.IO [Fact] public void CopyToWithNullBufferThrowsException() { + Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToBoolean(null, 0)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt16(null, 0)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt16(null, 0)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt32(null, 0)); @@ -26,6 +27,7 @@ namespace SixLabors.ImageSharp.Tests.IO [Fact] public void CopyToWithIndexTooBigThrowsException() { + Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToBoolean(new byte[1], 1)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt16(new byte[2], 1)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt16(new byte[2], 1)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt32(new byte[4], 1)); @@ -37,6 +39,7 @@ namespace SixLabors.ImageSharp.Tests.IO [Fact] public void CopyToWithBufferTooSmallThrowsException() { + Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToBoolean(new byte[0], 0)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt16(new byte[1], 0)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt16(new byte[1], 0)); Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt32(new byte[3], 0)); @@ -45,6 +48,21 @@ namespace SixLabors.ImageSharp.Tests.IO Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt64(new byte[7], 0)); } + /// + /// Tests that passing a returns the correct bytes. + /// + [Fact] + public void ToBoolean() + { + Assert.False(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0 }, 0)); + Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1 }, 0)); + Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 42 }, 0)); + + Assert.False(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1)); + Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1)); + Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 42 }, 1)); + } + /// /// Tests that passing a returns the correct bytes. /// diff --git a/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs b/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs index 4c890b367..0e09d1d07 100644 --- a/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs +++ b/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs @@ -15,6 +15,7 @@ namespace SixLabors.ImageSharp.Tests.IO [Fact] public void CopyToWithNullBufferThrowsException() { + Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToBoolean(null, 0)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt16(null, 0)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt16(null, 0)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt32(null, 0)); @@ -26,6 +27,7 @@ namespace SixLabors.ImageSharp.Tests.IO [Fact] public void CopyToWithIndexTooBigThrowsException() { + Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[1], 1)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt16(new byte[2], 1)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[2], 1)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt32(new byte[4], 1)); @@ -37,6 +39,7 @@ namespace SixLabors.ImageSharp.Tests.IO [Fact] public void CopyToWithBufferTooSmallThrowsException() { + Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[0], 0)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt16(new byte[1], 0)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[1], 0)); Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt32(new byte[3], 0)); @@ -45,6 +48,19 @@ namespace SixLabors.ImageSharp.Tests.IO Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[7], 0)); } + /// + /// Tests that passing a returns the correct bytes. + /// + [Fact] + public void ToBoolean() + { + Assert.False(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0 }, 0)); + Assert.True(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1 }, 0)); + + Assert.False(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1)); + Assert.True(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1)); + } + /// /// Tests that passing a returns the correct bytes. /// From bb738c359e7338ae37525e8e762232421f6597f0 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Wed, 21 Mar 2018 10:25:17 -0700 Subject: [PATCH 12/34] Fix formatting & docs --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 4 +- src/ImageSharp/IO/EndianBinaryReader.cs | 1 - .../PixelOperations{TPixel}.Generated.cs | 40 +++++++++---------- .../PixelOperations{TPixel}.Generated.tt | 6 +-- 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 349fa7745..af6637fa1 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -1157,7 +1157,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Reads a header chunk from the data. /// - /// The containing data. + /// The containing data. private void ReadHeaderChunk(ReadOnlySpan data) { this.header = new PngHeader @@ -1256,7 +1256,7 @@ namespace SixLabors.ImageSharp.Formats.Png { throw new ImageFormatException("Image stream is not valid!"); } - + chunk.Crc = BinaryPrimitives.ReadUInt32BigEndian(this.crcBuffer); this.crc.Reset(); diff --git a/src/ImageSharp/IO/EndianBinaryReader.cs b/src/ImageSharp/IO/EndianBinaryReader.cs index dfb57924d..25cd0adce 100644 --- a/src/ImageSharp/IO/EndianBinaryReader.cs +++ b/src/ImageSharp/IO/EndianBinaryReader.cs @@ -227,7 +227,6 @@ namespace SixLabors.ImageSharp.IO return (this.endianness == Endianness.BigEndian) ? BinaryPrimitives.ReadUInt64BigEndian(this.storageBuffer) : BinaryPrimitives.ReadUInt64LittleEndian(this.storageBuffer); - } /// diff --git a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs index 632455a0e..c8fe5ab88 100644 --- a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs +++ b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs @@ -33,12 +33,12 @@ namespace SixLabors.ImageSharp.PixelFormats dp.PackFromRgba32(rgba); } } - - /// - /// A helper for that expects a byte span. + + /// + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// - /// The to the source bytes. + /// The to the source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -69,14 +69,14 @@ namespace SixLabors.ImageSharp.PixelFormats } } - /// + /// /// 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)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void ToRgba32Bytes(ReadOnlySpan sourceColors, Span destBytes, int count) { this.ToRgba32(sourceColors, destBytes.NonPortableCast(), count); @@ -104,12 +104,12 @@ namespace SixLabors.ImageSharp.PixelFormats 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 source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -140,14 +140,14 @@ namespace SixLabors.ImageSharp.PixelFormats } } - /// + /// /// 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)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void ToBgra32Bytes(ReadOnlySpan sourceColors, Span destBytes, int count) { this.ToBgra32(sourceColors, destBytes.NonPortableCast(), count); @@ -175,12 +175,12 @@ namespace SixLabors.ImageSharp.PixelFormats 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 source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -211,14 +211,14 @@ namespace SixLabors.ImageSharp.PixelFormats } } - /// + /// /// 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)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void ToRgb24Bytes(ReadOnlySpan sourceColors, Span destBytes, int count) { this.ToRgb24(sourceColors, destBytes.NonPortableCast(), count); @@ -248,10 +248,10 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span. + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// - /// The to the source bytes. + /// The to the source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -282,14 +282,14 @@ namespace SixLabors.ImageSharp.PixelFormats } } - /// + /// /// 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)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void ToBgr24Bytes(ReadOnlySpan sourceColors, Span destBytes, int count) { this.ToBgr24(sourceColors, destBytes.NonPortableCast(), count); diff --git a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt index 999fe6610..d0a05677f 100644 --- a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt +++ b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt @@ -37,7 +37,7 @@ } /// - /// A helper for that expects a byte span as destination. + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// /// The to the source colors. @@ -79,10 +79,10 @@ } /// - /// A helper for that expects a byte span. + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// - /// The to the source bytes. + /// The to the source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] From 849c5961fccc8de3c5cdbfe1c30456d66eef4056 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Wed, 21 Mar 2018 11:01:31 -0700 Subject: [PATCH 13/34] Don't go through SpanHelper to Copy --- src/ImageSharp/Image.LoadPixelData.cs | 19 ++++++------------- src/ImageSharp/ImageFrame.LoadPixelData.cs | 7 ++----- src/ImageSharp/ImageFrame{TPixel}.cs | 2 +- src/ImageSharp/PixelAccessor{TPixel}.cs | 2 +- .../PixelFormats/Rgba32.PixelOperations.cs | 4 ++-- .../RgbaVector.PixelOperations.cs | 2 +- .../Transforms/Processors/CropProcessor.cs | 2 +- 7 files changed, 14 insertions(+), 24 deletions(-) diff --git a/src/ImageSharp/Image.LoadPixelData.cs b/src/ImageSharp/Image.LoadPixelData.cs index 5f1a1617f..9df8b1d99 100644 --- a/src/ImageSharp/Image.LoadPixelData.cs +++ b/src/ImageSharp/Image.LoadPixelData.cs @@ -2,12 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.IO; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp @@ -102,14 +97,11 @@ namespace SixLabors.ImageSharp /// A new . public static Image LoadPixelData(Configuration config, TPixel[] data, int width, int height) where TPixel : struct, IPixel - { - int count = width * height; - Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data)); + { + // There's an implict cast to Span from Array + // Should we remove this overload and expose Span ? - var image = new Image(config, width, height); - SpanHelper.Copy(data, image.GetPixelSpan(), count); - - return image; + return LoadPixelData(config, new Span(data), width, height); } /// @@ -128,7 +120,8 @@ namespace SixLabors.ImageSharp Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data)); var image = new Image(config, width, height); - SpanHelper.Copy(data, image.Frames.RootFrame.GetPixelSpan(), count); + + data.Slice(0, count).CopyTo(image.Frames.RootFrame.GetPixelSpan()); return image; } diff --git a/src/ImageSharp/ImageFrame.LoadPixelData.cs b/src/ImageSharp/ImageFrame.LoadPixelData.cs index b9341a1b2..9a733fb53 100644 --- a/src/ImageSharp/ImageFrame.LoadPixelData.cs +++ b/src/ImageSharp/ImageFrame.LoadPixelData.cs @@ -2,11 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.IO; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -46,7 +42,8 @@ namespace SixLabors.ImageSharp Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data)); var image = new ImageFrame(memoryManager, width, height); - SpanHelper.Copy(data, image.GetPixelSpan(), count); + + data.Slice(0, count).CopyTo(image.GetPixelSpan()); return image; } diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs index 888aff905..338a18a40 100644 --- a/src/ImageSharp/ImageFrame{TPixel}.cs +++ b/src/ImageSharp/ImageFrame{TPixel}.cs @@ -181,7 +181,7 @@ namespace SixLabors.ImageSharp throw new ArgumentException("ImageFrame.CopyTo(): target must be of the same size!", nameof(target)); } - SpanHelper.Copy(this.GetPixelSpan(), target.Span); + this.GetPixelSpan().CopyTo(target.Span); } /// diff --git a/src/ImageSharp/PixelAccessor{TPixel}.cs b/src/ImageSharp/PixelAccessor{TPixel}.cs index 63e4c015c..1e789f0a6 100644 --- a/src/ImageSharp/PixelAccessor{TPixel}.cs +++ b/src/ImageSharp/PixelAccessor{TPixel}.cs @@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp /// The target pixel buffer accessor. internal void CopyTo(PixelAccessor target) { - SpanHelper.Copy(this.PixelBuffer.Span, target.PixelBuffer.Span); + this.PixelBuffer.Span.CopyTo(target.PixelBuffer.Span); } /// diff --git a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs index a7e5736b0..7d5d63241 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs @@ -149,7 +149,7 @@ namespace SixLabors.ImageSharp.PixelFormats { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - SpanHelper.Copy(source, destPixels, count); + source.Slice(0, count).CopyTo(destPixels); } /// @@ -157,7 +157,7 @@ namespace SixLabors.ImageSharp.PixelFormats { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - SpanHelper.Copy(sourcePixels, dest, count); + sourcePixels.Slice(0, count).CopyTo(dest); } /// diff --git a/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs index f038eaa91..0817ef5ad 100644 --- a/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.PixelFormats { GuardSpans(sourceColors, nameof(sourceColors), destVectors, nameof(destVectors), count); - SpanHelper.Copy(sourceColors.NonPortableCast(), destVectors, count); + sourceColors.NonPortableCast().Slice(0, count).CopyTo(destVectors); } } } diff --git a/src/ImageSharp/Processing/Transforms/Processors/CropProcessor.cs b/src/ImageSharp/Processing/Transforms/Processors/CropProcessor.cs index 5462b34dc..bfbf349b5 100644 --- a/src/ImageSharp/Processing/Transforms/Processors/CropProcessor.cs +++ b/src/ImageSharp/Processing/Transforms/Processors/CropProcessor.cs @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Transforms.Processors { Span sourceRow = source.GetPixelRowSpan(y).Slice(minX); Span targetRow = destination.GetPixelRowSpan(y - minY); - SpanHelper.Copy(sourceRow, targetRow, maxX - minX); + sourceRow.Slice(0, maxX - minX).CopyTo(targetRow); }); } } From eb732f9deba6766625c90fc8c1126de1fdb09b30 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Wed, 21 Mar 2018 11:06:09 -0700 Subject: [PATCH 14/34] Avoid slicing spans by constructing directly from array --- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 4 ++-- src/ImageSharp/Memory/BasicArrayBuffer.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 55bf1bbec..26a8b48df 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -525,8 +525,8 @@ namespace SixLabors.ImageSharp.Formats.Png int dpmX = (int)Math.Round(image.MetaData.HorizontalResolution * 39.3700787D); int dpmY = (int)Math.Round(image.MetaData.VerticalResolution * 39.3700787D); - BinaryPrimitives.WriteInt32BigEndian(this.chunkDataBuffer.AsSpan().Slice(0, 4), dpmX); - BinaryPrimitives.WriteInt32BigEndian(this.chunkDataBuffer.AsSpan().Slice(4, 4), dpmY); + BinaryPrimitives.WriteInt32BigEndian(new Span(this.chunkDataBuffer, 0, 4), dpmX); + BinaryPrimitives.WriteInt32BigEndian(new Span(this.chunkDataBuffer, 4, 4), dpmY); this.chunkDataBuffer[8] = 1; diff --git a/src/ImageSharp/Memory/BasicArrayBuffer.cs b/src/ImageSharp/Memory/BasicArrayBuffer.cs index 30ca210ac..a4810d037 100644 --- a/src/ImageSharp/Memory/BasicArrayBuffer.cs +++ b/src/ImageSharp/Memory/BasicArrayBuffer.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Memory public int Length { get; } - public Span Span => this.Array.AsSpan().Slice(0, this.Length); + public Span Span => new Span(this.Array, 0, this.Length); /// /// Returns a reference to specified element of the buffer. From 76504c040aa3c45212c654fb1730715f6e24e522 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Wed, 21 Mar 2018 11:47:10 -0700 Subject: [PATCH 15/34] Remove blank line for STYLECOP! --- src/ImageSharp/Image.LoadPixelData.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ImageSharp/Image.LoadPixelData.cs b/src/ImageSharp/Image.LoadPixelData.cs index 9df8b1d99..3d416b70e 100644 --- a/src/ImageSharp/Image.LoadPixelData.cs +++ b/src/ImageSharp/Image.LoadPixelData.cs @@ -97,10 +97,9 @@ namespace SixLabors.ImageSharp /// A new . public static Image LoadPixelData(Configuration config, TPixel[] data, int width, int height) where TPixel : struct, IPixel - { + { // There's an implict cast to Span from Array // Should we remove this overload and expose Span ? - return LoadPixelData(config, new Span(data), width, height); } From 8fe9620a68a9c993c1c3a33700b637d6d027eeaf Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 07:58:39 -0700 Subject: [PATCH 16/34] Remove unused Write(decimal) method on EndianBinaryWriter --- src/ImageSharp/IO/EndianBinaryWriter.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/ImageSharp/IO/EndianBinaryWriter.cs b/src/ImageSharp/IO/EndianBinaryWriter.cs index dd87faf45..fc6434020 100644 --- a/src/ImageSharp/IO/EndianBinaryWriter.cs +++ b/src/ImageSharp/IO/EndianBinaryWriter.cs @@ -200,17 +200,6 @@ namespace SixLabors.ImageSharp.IO this.WriteInternal(this.buffer, 8); } - /// - /// Writes a decimal value to the stream, using the bit converter for this writer. - /// 16 bytes are written. - /// - /// The value to write - public void Write(decimal value) - { - this.BitConverter.CopyBytes(value, this.buffer, 0); - this.WriteInternal(this.buffer, 16); - } - /// /// Writes a signed byte to the stream. /// From 8ca4ef99373076a644f43bd7104d2b07809b8a6e Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 08:01:16 -0700 Subject: [PATCH 17/34] Add test to ensure that all data written through the EndianBinaryWriter can be read back through EndianBinaryReader --- .../IO/EndianBinaryReaderTests.cs | 8 +-- .../IO/EndianBinaryReaderWriterTests.cs | 58 +++++++++++++++++++ 2 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs diff --git a/tests/ImageSharp.Tests/IO/EndianBinaryReaderTests.cs b/tests/ImageSharp.Tests/IO/EndianBinaryReaderTests.cs index 87adead33..fcf484f49 100644 --- a/tests/ImageSharp.Tests/IO/EndianBinaryReaderTests.cs +++ b/tests/ImageSharp.Tests/IO/EndianBinaryReaderTests.cs @@ -30,8 +30,8 @@ namespace SixLabors.ImageSharp.Tests.IO [Fact] public void ReadCharsBeyondInternalBufferSize() { - MemoryStream stream = new MemoryStream(TestBytes); - using (EndianBinaryReader subject = new EndianBinaryReader(Endianness.LittleEndian, stream)) + var stream = new MemoryStream(TestBytes); + using (var subject = new EndianBinaryReader(Endianness.LittleEndian, stream)) { char[] chars = new char[TestString.Length]; subject.Read(chars, 0, chars.Length); @@ -48,8 +48,8 @@ namespace SixLabors.ImageSharp.Tests.IO Assert.Throws( () => { - MemoryStream stream = new MemoryStream(TestBytes); - using (EndianBinaryReader subject = new EndianBinaryReader(Endianness.LittleEndian, stream)) + var stream = new MemoryStream(TestBytes); + using (var subject = new EndianBinaryReader(Endianness.LittleEndian, stream)) { char[] chars = new char[TestString.Length - 1]; diff --git a/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs b/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs new file mode 100644 index 000000000..6c639693a --- /dev/null +++ b/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs @@ -0,0 +1,58 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.IO; +using SixLabors.ImageSharp.IO; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.IO +{ + public class EndianBinaryReaderWriterTests + { + /// + /// Ensures that the data written through a binary writer can be read back through the reader + /// + [Fact] + public void RoundtripValues() + { + foreach (Endianness endianness in new[] { Endianness.BigEndian, Endianness.LittleEndian }) + { + var stream = new MemoryStream(); + + var writer = new EndianBinaryWriter(endianness, stream); + + writer.Write(true); // Bool + writer.Write((byte)1); // Byte + writer.Write((short)1); // Int16 + writer.Write(1); // Int32 + writer.Write(1L); // Int64 + writer.Write(1f); // Single + writer.Write(1d); // Double + writer.Write((sbyte)1); // SByte + writer.Write((ushort)1); // UInt16 + writer.Write((uint)1); // UInt32 + writer.Write(1UL); // ULong + + Assert.Equal(43, stream.Length); + + stream.Position = 0; + + var reader = new EndianBinaryReader(endianness, stream); + + Assert.True(reader.ReadBoolean()); // Bool + Assert.Equal((byte)1, reader.ReadByte()); // Byte + Assert.Equal((short)1, reader.ReadInt16()); // Int16 + Assert.Equal(1, reader.ReadInt32()); // Int32 + Assert.Equal(1L, reader.ReadInt64()); // Int64 + Assert.Equal(1f, reader.ReadSingle()); // Single + Assert.Equal(1d, reader.ReadDouble()); // Double + Assert.Equal((sbyte)1, reader.ReadSByte()); // SByte + Assert.Equal((ushort)1, reader.ReadUInt16()); // UInt16 + Assert.Equal((uint)1, reader.ReadUInt32()); // UInt32 + Assert.Equal(1UL, reader.ReadUInt64()); // ULong + + stream.Dispose(); + } + } + } +} From 6c1ed4d2c19d1c29d1cfde0e6556732609d35c17 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 08:32:02 -0700 Subject: [PATCH 18/34] Remove BitConverter from EndianBinaryWriter & add Floating point tests --- src/ImageSharp/IO/EndianBinaryWriter.cs | 86 +++++++++++++++---- .../IO/EndianBitConverter.GetBytes.cs | 12 --- .../IO/EndianBinaryReaderWriterTests.cs | 41 ++++++++- 3 files changed, 107 insertions(+), 32 deletions(-) diff --git a/src/ImageSharp/IO/EndianBinaryWriter.cs b/src/ImageSharp/IO/EndianBinaryWriter.cs index fc6434020..10df3f9a6 100644 --- a/src/ImageSharp/IO/EndianBinaryWriter.cs +++ b/src/ImageSharp/IO/EndianBinaryWriter.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers.Binary; using System.IO; using System.Text; @@ -23,6 +24,11 @@ namespace SixLabors.ImageSharp.IO /// private readonly char[] charBuffer = new char[1]; + /// + /// The endianness used to write the data + /// + private readonly Endianness endianness; + /// /// Whether or not this writer has been disposed yet. /// @@ -55,8 +61,8 @@ namespace SixLabors.ImageSharp.IO Guard.IsTrue(stream.CanWrite, nameof(stream), "Stream isn't writable"); this.BaseStream = stream; - this.BitConverter = EndianBitConverter.GetConverter(endianness); this.Encoding = encoding; + this.endianness = endianness; } /// @@ -69,11 +75,6 @@ namespace SixLabors.ImageSharp.IO /// public Stream BaseStream { get; } - /// - /// Gets the bit converter used to write values to the stream - /// - internal EndianBitConverter BitConverter { get; } - /// /// Closes the writer, including the underlying stream. /// @@ -108,7 +109,8 @@ namespace SixLabors.ImageSharp.IO /// The value to write public void Write(bool value) { - this.BitConverter.CopyBytes(value, this.buffer, 0); + this.buffer[0] = value ? (byte)1 : (byte)0; + this.WriteInternal(this.buffer, 1); } @@ -119,7 +121,15 @@ namespace SixLabors.ImageSharp.IO /// The value to write public void Write(short value) { - this.BitConverter.CopyBytes(value, this.buffer, 0); + if (this.endianness == Endianness.BigEndian) + { + BinaryPrimitives.WriteInt16BigEndian(this.buffer, value); + } + else + { + BinaryPrimitives.WriteInt16LittleEndian(this.buffer, value); + } + this.WriteInternal(this.buffer, 2); } @@ -130,7 +140,15 @@ namespace SixLabors.ImageSharp.IO /// The value to write public void Write(int value) { - this.BitConverter.CopyBytes(value, this.buffer, 0); + if (this.endianness == Endianness.BigEndian) + { + BinaryPrimitives.WriteInt32BigEndian(this.buffer, value); + } + else + { + BinaryPrimitives.WriteInt32LittleEndian(this.buffer, value); + } + this.WriteInternal(this.buffer, 4); } @@ -141,7 +159,15 @@ namespace SixLabors.ImageSharp.IO /// The value to write public void Write(long value) { - this.BitConverter.CopyBytes(value, this.buffer, 0); + if (this.endianness == Endianness.BigEndian) + { + BinaryPrimitives.WriteInt64BigEndian(this.buffer, value); + } + else + { + BinaryPrimitives.WriteInt64LittleEndian(this.buffer, value); + } + this.WriteInternal(this.buffer, 8); } @@ -152,7 +178,15 @@ namespace SixLabors.ImageSharp.IO /// The value to write public void Write(ushort value) { - this.BitConverter.CopyBytes(value, this.buffer, 0); + if (this.endianness == Endianness.BigEndian) + { + BinaryPrimitives.WriteUInt16BigEndian(this.buffer, value); + } + else + { + BinaryPrimitives.WriteUInt16LittleEndian(this.buffer, value); + } + this.WriteInternal(this.buffer, 2); } @@ -163,7 +197,15 @@ namespace SixLabors.ImageSharp.IO /// The value to write public void Write(uint value) { - this.BitConverter.CopyBytes(value, this.buffer, 0); + if (this.endianness == Endianness.BigEndian) + { + BinaryPrimitives.WriteUInt32BigEndian(this.buffer, value); + } + else + { + BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, value); + } + this.WriteInternal(this.buffer, 4); } @@ -174,7 +216,15 @@ namespace SixLabors.ImageSharp.IO /// The value to write public void Write(ulong value) { - this.BitConverter.CopyBytes(value, this.buffer, 0); + if (this.endianness == Endianness.BigEndian) + { + BinaryPrimitives.WriteUInt64BigEndian(this.buffer, value); + } + else + { + BinaryPrimitives.WriteUInt64LittleEndian(this.buffer, value); + } + this.WriteInternal(this.buffer, 8); } @@ -183,10 +233,9 @@ namespace SixLabors.ImageSharp.IO /// for this writer. 4 bytes are written. /// /// The value to write - public void Write(float value) + public unsafe void Write(float value) { - this.BitConverter.CopyBytes(value, this.buffer, 0); - this.WriteInternal(this.buffer, 4); + this.Write(*((int*)&value)); } /// @@ -194,10 +243,9 @@ namespace SixLabors.ImageSharp.IO /// for this writer. 8 bytes are written. /// /// The value to write - public void Write(double value) + public unsafe void Write(double value) { - this.BitConverter.CopyBytes(value, this.buffer, 0); - this.WriteInternal(this.buffer, 8); + this.Write(*((long*)&value)); } /// diff --git a/src/ImageSharp/IO/EndianBitConverter.GetBytes.cs b/src/ImageSharp/IO/EndianBitConverter.GetBytes.cs index 5686c829c..e133cf7f4 100644 --- a/src/ImageSharp/IO/EndianBitConverter.GetBytes.cs +++ b/src/ImageSharp/IO/EndianBitConverter.GetBytes.cs @@ -121,17 +121,5 @@ namespace SixLabors.ImageSharp.IO { return this.GetBytes(*((int*)&value)); } - - /// - /// Returns the specified decimal value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 16. - public byte[] GetBytes(decimal value) - { - byte[] result = new byte[16]; - this.CopyBytes(value, result, 0); - return result; - } } } diff --git a/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs b/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs index 6c639693a..6e22b1689 100644 --- a/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs +++ b/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.IO; using SixLabors.ImageSharp.IO; using Xunit; @@ -9,6 +10,44 @@ namespace SixLabors.ImageSharp.Tests.IO { public class EndianBinaryReaderWriterTests { + [Fact] + public void RoundtripSingles() + { + foreach ((Endianness endianness, byte[] bytes) in new[] { + (Endianness.BigEndian, new byte[] { 64, 73, 15, 219 }), + (Endianness.LittleEndian, new byte[] { 219, 15, 73, 64 }) + }) + { + var stream = new MemoryStream(); + + using (var writer = new EndianBinaryWriter(endianness, stream)) + { + writer.Write((float)Math.PI); + + Assert.Equal(bytes, stream.ToArray()); + } + } + } + + [Fact] + public void RoundtripDoubles() + { + foreach ((Endianness endianness, byte[] bytes) in new[] { + (Endianness.BigEndian, new byte[] { 64, 9, 33, 251, 84, 68, 45, 24 }), + (Endianness.LittleEndian, new byte[] { 24, 45, 68, 84, 251, 33, 9, 64 }) + }) + { + var stream = new MemoryStream(); + + using (var writer = new EndianBinaryWriter(endianness, stream)) + { + writer.Write(Math.PI); + + Assert.Equal(bytes, stream.ToArray()); + } + } + } + /// /// Ensures that the data written through a binary writer can be read back through the reader /// @@ -55,4 +94,4 @@ namespace SixLabors.ImageSharp.Tests.IO } } } -} +} \ No newline at end of file From 96e4a7d7d63f3aabe08b2399c2972274096178e5 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 08:44:39 -0700 Subject: [PATCH 19/34] Replace custom BitConverter(s) with BinaryPrimitives --- src/ImageSharp/IO/BigEndianBitConverter.cs | 79 ------ src/ImageSharp/IO/EndianBinaryWriter.cs | 3 +- .../IO/EndianBitConverter.Conversion.cs | 61 ----- .../IO/EndianBitConverter.CopyBytes.cs | 143 ----------- .../IO/EndianBitConverter.GetBytes.cs | 125 ---------- .../IO/EndianBitConverter.ToType.cs | 139 ----------- src/ImageSharp/IO/EndianBitConverter.cs | 127 ---------- src/ImageSharp/IO/LittleEndianBitConverter.cs | 79 ------ .../DataReader/IccDataReader.Primitives.cs | 25 +- .../Profiles/ICC/DataReader/IccDataReader.cs | 6 - .../BigEndianBitConverter.CopyBytesTests.cs | 228 ------------------ .../IO/BigEndianBitConverter.GetBytesTests.cs | 129 ---------- .../IO/BigEndianBitConverter.ToTypeTests.cs | 216 ----------------- ...LittleEndianBitConverter.CopyBytesTests.cs | 228 ------------------ .../LittleEndianBitConverter.GetBytesTests.cs | 129 ---------- .../LittleEndianBitConverter.ToTypeTests.cs | 214 ---------------- 16 files changed, 16 insertions(+), 1915 deletions(-) delete mode 100644 src/ImageSharp/IO/BigEndianBitConverter.cs delete mode 100644 src/ImageSharp/IO/EndianBitConverter.Conversion.cs delete mode 100644 src/ImageSharp/IO/EndianBitConverter.CopyBytes.cs delete mode 100644 src/ImageSharp/IO/EndianBitConverter.GetBytes.cs delete mode 100644 src/ImageSharp/IO/EndianBitConverter.ToType.cs delete mode 100644 src/ImageSharp/IO/EndianBitConverter.cs delete mode 100644 src/ImageSharp/IO/LittleEndianBitConverter.cs delete mode 100644 tests/ImageSharp.Tests/IO/BigEndianBitConverter.CopyBytesTests.cs delete mode 100644 tests/ImageSharp.Tests/IO/BigEndianBitConverter.GetBytesTests.cs delete mode 100644 tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs delete mode 100644 tests/ImageSharp.Tests/IO/LittleEndianBitConverter.CopyBytesTests.cs delete mode 100644 tests/ImageSharp.Tests/IO/LittleEndianBitConverter.GetBytesTests.cs delete mode 100644 tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs diff --git a/src/ImageSharp/IO/BigEndianBitConverter.cs b/src/ImageSharp/IO/BigEndianBitConverter.cs deleted file mode 100644 index a9a713e1a..000000000 --- a/src/ImageSharp/IO/BigEndianBitConverter.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers.Binary; - -namespace SixLabors.ImageSharp.IO -{ - /// - /// Implementation of EndianBitConverter which converts to/from big-endian byte arrays. - /// - internal sealed class BigEndianBitConverter : EndianBitConverter - { - /// - public override Endianness Endianness - { - get { return Endianness.BigEndian; } - } - - /// - public override bool IsLittleEndian - { - get { return false; } - } - - /// - public override void CopyBytes(short value, byte[] buffer, int index) - { - CheckByteArgument(buffer, index, 2); - - buffer[index] = (byte)(value >> 8); - buffer[index + 1] = (byte)value; - } - - /// - public override void CopyBytes(int value, byte[] buffer, int index) - { - CheckByteArgument(buffer, index, 4); - - buffer[index] = (byte)(value >> 24); - buffer[index + 1] = (byte)(value >> 16); - buffer[index + 2] = (byte)(value >> 8); - buffer[index + 3] = (byte)value; - } - - /// - public override void CopyBytes(long value, byte[] buffer, int index) - { - CheckByteArgument(buffer, index, 8); - - buffer[index] = (byte)(value >> 56); - buffer[index + 1] = (byte)(value >> 48); - buffer[index + 2] = (byte)(value >> 40); - buffer[index + 3] = (byte)(value >> 32); - buffer[index + 4] = (byte)(value >> 24); - buffer[index + 5] = (byte)(value >> 16); - buffer[index + 6] = (byte)(value >> 8); - buffer[index + 7] = (byte)value; - } - - /// - public override short ToInt16(byte[] value, int startIndex) - { - return BinaryPrimitives.ReadInt16BigEndian(value.AsReadOnlySpan().Slice(startIndex)); - } - - /// - public override int ToInt32(byte[] value, int startIndex) - { - return BinaryPrimitives.ReadInt32BigEndian(value.AsReadOnlySpan().Slice(startIndex)); - } - - /// - public override long ToInt64(byte[] value, int startIndex) - { - return BinaryPrimitives.ReadInt64BigEndian(value.AsReadOnlySpan().Slice(startIndex)); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/IO/EndianBinaryWriter.cs b/src/ImageSharp/IO/EndianBinaryWriter.cs index 10df3f9a6..b8cd2cad5 100644 --- a/src/ImageSharp/IO/EndianBinaryWriter.cs +++ b/src/ImageSharp/IO/EndianBinaryWriter.cs @@ -9,8 +9,7 @@ using System.Text; namespace SixLabors.ImageSharp.IO { /// - /// Equivalent of , but with either endianness, depending on - /// the it is constructed with. + /// Equivalent of , but with either endianness /// internal class EndianBinaryWriter : IDisposable { diff --git a/src/ImageSharp/IO/EndianBitConverter.Conversion.cs b/src/ImageSharp/IO/EndianBitConverter.Conversion.cs deleted file mode 100644 index 844c81cc9..000000000 --- a/src/ImageSharp/IO/EndianBitConverter.Conversion.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -namespace SixLabors.ImageSharp.IO -{ - /// - /// Equivalent of , but with either endianness. - /// - internal abstract partial class EndianBitConverter - { - /// - /// Converts the specified double-precision floating point number to a - /// 64-bit signed integer. Note: the endianness of this converter does not - /// affect the returned value. - /// - /// The number to convert. - /// A 64-bit signed integer whose value is equivalent to value. - public unsafe long DoubleToInt64Bits(double value) - { - return *((long*)&value); - } - - /// - /// Converts the specified 64-bit signed integer to a double-precision - /// floating point number. Note: the endianness of this converter does not - /// affect the returned value. - /// - /// The number to convert. - /// A double-precision floating point number whose value is equivalent to value. - public unsafe double Int64BitsToDouble(long value) - { - return *((double*)&value); - } - - /// - /// Converts the specified single-precision floating point number to a - /// 32-bit signed integer. Note: the endianness of this converter does not - /// affect the returned value. - /// - /// The number to convert. - /// A 32-bit signed integer whose value is equivalent to value. - public unsafe int SingleToInt32Bits(float value) - { - return *((int*)&value); - } - - /// - /// Converts the specified 32-bit signed integer to a single-precision floating point - /// number. Note: the endianness of this converter does not - /// affect the returned value. - /// - /// The number to convert. - /// A single-precision floating point number whose value is equivalent to value. - public unsafe float Int32BitsToSingle(int value) - { - return *((float*)&value); - } - } -} diff --git a/src/ImageSharp/IO/EndianBitConverter.CopyBytes.cs b/src/ImageSharp/IO/EndianBitConverter.CopyBytes.cs deleted file mode 100644 index ea1d7aa5a..000000000 --- a/src/ImageSharp/IO/EndianBitConverter.CopyBytes.cs +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -namespace SixLabors.ImageSharp.IO -{ - /// - /// Equivalent of , but with either endianness. - /// - internal abstract partial class EndianBitConverter - { - /// - /// Copies the specified 16-bit signed integer value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public abstract void CopyBytes(short value, byte[] buffer, int index); - - /// - /// Copies the specified 32-bit signed integer value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public abstract void CopyBytes(int value, byte[] buffer, int index); - - /// - /// Copies the specified 64-bit signed integer value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public abstract void CopyBytes(long value, byte[] buffer, int index); - - /// - /// Copies the specified 16-bit unsigned integer value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(ushort value, byte[] buffer, int index) - { - this.CopyBytes(unchecked((short)value), buffer, index); - } - - /// - /// Copies the specified 32-bit unsigned integer value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(uint value, byte[] buffer, int index) - { - this.CopyBytes(unchecked((int)value), buffer, index); - } - - /// - /// Copies the specified 64-bit unsigned integer value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(ulong value, byte[] buffer, int index) - { - this.CopyBytes(unchecked((long)value), buffer, index); - } - - /// - /// Copies the specified Boolean value into the specified byte array, - /// beginning at the specified index. - /// - /// A Boolean value. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(bool value, byte[] buffer, int index) - { - CheckByteArgument(buffer, index, 1); - buffer[index] = value ? (byte)1 : (byte)0; - } - - /// - /// Copies the specified Unicode character value into the specified byte array, - /// beginning at the specified index. - /// - /// A character to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public void CopyBytes(char value, byte[] buffer, int index) - { - this.CopyBytes(unchecked((short)value), buffer, index); - } - - /// - /// Copies the specified double-precision floating point value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public unsafe void CopyBytes(double value, byte[] buffer, int index) - { - this.CopyBytes(*((long*)&value), buffer, index); - } - - /// - /// Copies the specified single-precision floating point value into the specified byte array, - /// beginning at the specified index. - /// - /// The number to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public unsafe void CopyBytes(float value, byte[] buffer, int index) - { - this.CopyBytes(*((int*)&value), buffer, index); - } - - /// - /// Copies the specified decimal value into the specified byte array, - /// beginning at the specified index. - /// - /// A character to convert. - /// The byte array to copy the bytes into - /// The first index into the array to copy the bytes into - public unsafe void CopyBytes(decimal value, byte[] buffer, int index) - { - CheckByteArgument(buffer, index, 16); - - int* pvalue = (int*)&value; - this.CopyBytes(pvalue[0], buffer, index); - this.CopyBytes(pvalue[1], buffer, index + 4); - this.CopyBytes(pvalue[2], buffer, index + 8); - this.CopyBytes(pvalue[3], buffer, index + 12); - } - } -} diff --git a/src/ImageSharp/IO/EndianBitConverter.GetBytes.cs b/src/ImageSharp/IO/EndianBitConverter.GetBytes.cs deleted file mode 100644 index e133cf7f4..000000000 --- a/src/ImageSharp/IO/EndianBitConverter.GetBytes.cs +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -namespace SixLabors.ImageSharp.IO -{ - /// - /// Equivalent of , but with either endianness. - /// - internal abstract partial class EndianBitConverter - { - /// - /// Returns the specified 16-bit signed integer value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 2. - public byte[] GetBytes(short value) - { - byte[] result = new byte[2]; - this.CopyBytes(value, result, 0); - return result; - } - - /// - /// Returns the specified 32-bit signed integer value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 4. - public byte[] GetBytes(int value) - { - byte[] result = new byte[4]; - this.CopyBytes(value, result, 0); - return result; - } - - /// - /// Returns the specified 64-bit signed integer value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 8. - public byte[] GetBytes(long value) - { - byte[] result = new byte[8]; - this.CopyBytes(value, result, 0); - return result; - } - - /// - /// Returns the specified 16-bit unsigned integer value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 2. - public byte[] GetBytes(ushort value) - { - return this.GetBytes(unchecked((short)value)); - } - - /// - /// Returns the specified 32-bit unsigned integer value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 4. - public byte[] GetBytes(uint value) - { - return this.GetBytes(unchecked((int)value)); - } - - /// - /// Returns the specified 64-bit unsigned integer value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 8. - public byte[] GetBytes(ulong value) - { - return this.GetBytes(unchecked((long)value)); - } - - /// - /// Returns the specified Boolean value as an array of bytes. - /// - /// A Boolean value. - /// An array of bytes with length 1. - /// - /// The . - /// - public byte[] GetBytes(bool value) - { - return new byte[1] { value ? (byte)1 : (byte)0 }; - } - - /// - /// Returns the specified Unicode character value as an array of bytes. - /// - /// A character to convert. - /// An array of bytes with length 2. - /// - /// The . - /// - public byte[] GetBytes(char value) - { - return this.GetBytes((short)value); - } - - /// - /// Returns the specified double-precision floating point value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 8. - public unsafe byte[] GetBytes(double value) - { - return this.GetBytes(*((long*)&value)); - } - - /// - /// Returns the specified single-precision floating point value as an array of bytes. - /// - /// The number to convert. - /// An array of bytes with length 4. - public unsafe byte[] GetBytes(float value) - { - return this.GetBytes(*((int*)&value)); - } - } -} diff --git a/src/ImageSharp/IO/EndianBitConverter.ToType.cs b/src/ImageSharp/IO/EndianBitConverter.ToType.cs deleted file mode 100644 index 0c0e49911..000000000 --- a/src/ImageSharp/IO/EndianBitConverter.ToType.cs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -namespace SixLabors.ImageSharp.IO -{ - /// - /// Equivalent of , but with either endianness. - /// - internal abstract partial class EndianBitConverter - { - /// - /// Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A 16-bit signed integer formed by two bytes beginning at startIndex. - public abstract short ToInt16(byte[] value, int startIndex); - - /// - /// Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A 32-bit signed integer formed by four bytes beginning at startIndex. - public abstract int ToInt32(byte[] value, int startIndex); - - /// - /// Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A 64-bit signed integer formed by eight bytes beginning at startIndex. - public abstract long ToInt64(byte[] value, int startIndex); - - /// - /// Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A 16-bit unsigned integer formed by two bytes beginning at startIndex. - public ushort ToUInt16(byte[] value, int startIndex) - { - return unchecked((ushort)this.ToInt16(value, startIndex)); - } - - /// - /// Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A 32-bit unsigned integer formed by four bytes beginning at startIndex. - public uint ToUInt32(byte[] value, int startIndex) - { - return unchecked((uint)this.ToInt32(value, startIndex)); - } - - /// - /// Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A 64-bit unsigned integer formed by eight bytes beginning at startIndex. - public ulong ToUInt64(byte[] value, int startIndex) - { - return unchecked((ulong)this.ToInt64(value, startIndex)); - } - - /// - /// Returns a Boolean value converted from one byte at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// true if the byte at startIndex in value is nonzero; otherwise, false. - public bool ToBoolean(byte[] value, int startIndex) - { - CheckByteArgument(value, startIndex, 1); - return value[startIndex] != 0; - } - - /// - /// Returns a Unicode character converted from two bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A character formed by two bytes beginning at startIndex. - public char ToChar(byte[] value, int startIndex) - { - return unchecked((char)this.ToInt16(value, startIndex)); - } - - /// - /// Returns a double-precision floating point number converted from eight bytes - /// at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A double precision floating point number formed by eight bytes beginning at startIndex. - public unsafe double ToDouble(byte[] value, int startIndex) - { - long intValue = this.ToInt64(value, startIndex); - return *((double*)&intValue); - } - - /// - /// Returns a single-precision floating point number converted from four bytes - /// at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A single precision floating point number formed by four bytes beginning at startIndex. - public unsafe float ToSingle(byte[] value, int startIndex) - { - int intValue = this.ToInt32(value, startIndex); - return *((float*)&intValue); - } - - /// - /// Returns a decimal value converted from sixteen bytes - /// at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// A decimal formed by sixteen bytes beginning at startIndex. - public unsafe decimal ToDecimal(byte[] value, int startIndex) - { - CheckByteArgument(value, startIndex, 16); - - decimal result = 0m; - int* presult = (int*)&result; - presult[0] = this.ToInt32(value, startIndex); - presult[1] = this.ToInt32(value, startIndex + 4); - presult[2] = this.ToInt32(value, startIndex + 8); - presult[3] = this.ToInt32(value, startIndex + 12); - return result; - } - } -} diff --git a/src/ImageSharp/IO/EndianBitConverter.cs b/src/ImageSharp/IO/EndianBitConverter.cs deleted file mode 100644 index b563a09cb..000000000 --- a/src/ImageSharp/IO/EndianBitConverter.cs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.IO -{ - /// - /// Equivalent of , but with either endianness. - /// - internal abstract partial class EndianBitConverter - { - /// - /// The little-endian bit converter. - /// - public static readonly LittleEndianBitConverter LittleEndianConverter = new LittleEndianBitConverter(); - - /// - /// The big-endian bit converter. - /// - public static readonly BigEndianBitConverter BigEndianConverter = new BigEndianBitConverter(); - - /// - /// Gets the byte order ("endianness") in which data is converted using this class. - /// - public abstract Endianness Endianness { get; } - - /// - /// Gets a value indicating whether the byte order ("endianness") in which data is converted is little endian. - /// - /// - /// Different computer architectures store data using different byte orders. "Big-endian" - /// means the most significant byte is on the left end of a word. "Little-endian" means the - /// most significant byte is on the right end of a word. - /// - public abstract bool IsLittleEndian { get; } - - /// - /// Gets the converter. - /// - /// The endianness. - /// an - /// Not a valid form of Endianness - endianness - public static EndianBitConverter GetConverter(Endianness endianness) - { - switch (endianness) - { - case Endianness.LittleEndian: - return LittleEndianConverter; - case Endianness.BigEndian: - return BigEndianConverter; - default: - throw new ArgumentException("Not a valid form of Endianness", nameof(endianness)); - } - } - - /// - /// Returns a String converted from the elements of a byte array. - /// - /// An array of bytes. - /// All the elements of value are converted. - /// - /// A String of hexadecimal pairs separated by hyphens, where each pair - /// represents the corresponding element in value; for example, "7F-2C-4A". - /// - public static string ToString(byte[] value) - { - return BitConverter.ToString(value); - } - - /// - /// Returns a String converted from the elements of a byte array starting at a specified array position. - /// - /// An array of bytes. - /// The starting position within value. - /// The elements from array position startIndex to the end of the array are converted. - /// - /// A String of hexadecimal pairs separated by hyphens, where each pair - /// represents the corresponding element in value; for example, "7F-2C-4A". - /// - public static string ToString(byte[] value, int startIndex) - { - return BitConverter.ToString(value, startIndex); - } - - /// - /// Returns a String converted from a specified number of bytes at a specified position in a byte array. - /// - /// An array of bytes. - /// The starting position within value. - /// The number of bytes to convert. - /// The length elements from array position startIndex are converted. - /// - /// A String of hexadecimal pairs separated by hyphens, where each pair - /// represents the corresponding element in value; for example, "7F-2C-4A". - /// - public static string ToString(byte[] value, int startIndex, int length) - { - return BitConverter.ToString(value, startIndex, length); - } - - /// - /// Checks the given argument for validity. - /// - /// The byte array passed in - /// The start index passed in - /// The number of bytes required - /// value is a null reference - /// - /// startIndex is less than zero or greater than the length of value minus bytesRequired. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected static void CheckByteArgument(byte[] value, int startIndex, int bytesRequired) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (startIndex < 0 || startIndex > value.Length - bytesRequired) - { - throw new ArgumentOutOfRangeException(nameof(startIndex)); - } - } - } -} diff --git a/src/ImageSharp/IO/LittleEndianBitConverter.cs b/src/ImageSharp/IO/LittleEndianBitConverter.cs deleted file mode 100644 index b9db34f90..000000000 --- a/src/ImageSharp/IO/LittleEndianBitConverter.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers.Binary; - -namespace SixLabors.ImageSharp.IO -{ - /// - /// Implementation of EndianBitConverter which converts to/from little-endian byte arrays. - /// - internal sealed class LittleEndianBitConverter : EndianBitConverter - { - /// - public override Endianness Endianness - { - get { return Endianness.LittleEndian; } - } - - /// - public override bool IsLittleEndian - { - get { return true; } - } - - /// - public override void CopyBytes(short value, byte[] buffer, int index) - { - CheckByteArgument(buffer, index, 2); - - buffer[index + 1] = (byte)(value >> 8); - buffer[index] = (byte)value; - } - - /// - public override void CopyBytes(int value, byte[] buffer, int index) - { - CheckByteArgument(buffer, index, 4); - - buffer[index + 3] = (byte)(value >> 24); - buffer[index + 2] = (byte)(value >> 16); - buffer[index + 1] = (byte)(value >> 8); - buffer[index] = (byte)value; - } - - /// - public override void CopyBytes(long value, byte[] buffer, int index) - { - CheckByteArgument(buffer, index, 8); - - buffer[index + 7] = (byte)(value >> 56); - buffer[index + 6] = (byte)(value >> 48); - buffer[index + 5] = (byte)(value >> 40); - buffer[index + 4] = (byte)(value >> 32); - buffer[index + 3] = (byte)(value >> 24); - buffer[index + 2] = (byte)(value >> 16); - buffer[index + 1] = (byte)(value >> 8); - buffer[index] = (byte)value; - } - - /// - public override short ToInt16(byte[] value, int startIndex) - { - return BinaryPrimitives.ReadInt16LittleEndian(value.AsReadOnlySpan().Slice(startIndex)); - } - - /// - public override int ToInt32(byte[] value, int startIndex) - { - return BinaryPrimitives.ReadInt32LittleEndian(value.AsReadOnlySpan().Slice(startIndex)); - } - - /// - public override long ToInt64(byte[] value, int startIndex) - { - return BinaryPrimitives.ReadInt64LittleEndian(value.AsReadOnlySpan().Slice(startIndex)); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs index 14f7f9570..794d77ba1 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers.Binary; using System.Text; namespace SixLabors.ImageSharp.MetaData.Profiles.Icc @@ -17,7 +18,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// the value public ushort ReadUInt16() { - return this.converter.ToUInt16(this.data, this.AddIndex(2)); + return BinaryPrimitives.ReadUInt16BigEndian(new Span(this.data, this.AddIndex(2), 2)); } /// @@ -26,7 +27,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// the value public short ReadInt16() { - return this.converter.ToInt16(this.data, this.AddIndex(2)); + return BinaryPrimitives.ReadInt16BigEndian(new Span(this.data, this.AddIndex(2), 2)); } /// @@ -35,7 +36,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// the value public uint ReadUInt32() { - return this.converter.ToUInt32(this.data, this.AddIndex(4)); + return BinaryPrimitives.ReadUInt32BigEndian(new Span(this.data, this.AddIndex(4), 4)); } /// @@ -44,7 +45,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// the value public int ReadInt32() { - return this.converter.ToInt32(this.data, this.AddIndex(4)); + return BinaryPrimitives.ReadInt32BigEndian(new Span(this.data, this.AddIndex(4), 4)); } /// @@ -53,7 +54,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// the value public ulong ReadUInt64() { - return this.converter.ToUInt64(this.data, this.AddIndex(8)); + return BinaryPrimitives.ReadUInt64BigEndian(new Span(this.data, this.AddIndex(8), 8)); } /// @@ -62,25 +63,29 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// the value public long ReadInt64() { - return this.converter.ToInt64(this.data, this.AddIndex(8)); + return BinaryPrimitives.ReadInt64BigEndian(new Span(this.data, this.AddIndex(8), 8)); } /// /// Reads a float /// /// the value - public float ReadSingle() + public unsafe float ReadSingle() { - return this.converter.ToSingle(this.data, this.AddIndex(4)); + int intValue = this.ReadInt32(); + + return *((float*)&intValue); } /// /// Reads a double /// /// the value - public double ReadDouble() + public unsafe double ReadDouble() { - return this.converter.ToDouble(this.data, this.AddIndex(8)); + long intValue = this.ReadInt64(); + + return *((double*)&intValue); } /// diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs index 1fecd761a..c4a6a9039 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs @@ -3,7 +3,6 @@ using System; using System.Text; -using SixLabors.ImageSharp.IO; namespace SixLabors.ImageSharp.MetaData.Profiles.Icc { @@ -20,11 +19,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// private readonly byte[] data; - /// - /// The bit converter - /// - private readonly EndianBitConverter converter = new BigEndianBitConverter(); - /// /// The current reading position /// diff --git a/tests/ImageSharp.Tests/IO/BigEndianBitConverter.CopyBytesTests.cs b/tests/ImageSharp.Tests/IO/BigEndianBitConverter.CopyBytesTests.cs deleted file mode 100644 index 254cfa2dc..000000000 --- a/tests/ImageSharp.Tests/IO/BigEndianBitConverter.CopyBytesTests.cs +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using SixLabors.ImageSharp.IO; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.IO -{ - /// - /// The tests. - /// - public class BigEndianBitConverterCopyBytesTests - { - [Fact] - public void CopyToWithNullBufferThrowsException() - { - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes(false, null, 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes((short)42, null, 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes((ushort)42, null, 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes(42, null, 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes(42u, null, 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes(42L, null, 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes((ulong)42L, null, 0)); - } - - [Fact] - public void CopyToWithIndexTooBigThrowsException() - { - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes(false, new byte[1], 1)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes((short)42, new byte[2], 1)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes((ushort)42, new byte[2], 1)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes(42, new byte[4], 1)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes(42u, new byte[4], 1)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes(42L, new byte[8], 1)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes((ulong)42L, new byte[8], 1)); - } - - [Fact] - public void CopyToWithBufferTooSmallThrowsException() - { - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes(false, new byte[0], 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes((short)42, new byte[1], 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes((ushort)42, new byte[1], 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes(42, new byte[3], 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes(42u, new byte[3], 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes(42L, new byte[7], 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.CopyBytes((ulong)42L, new byte[7], 0)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesBoolean() - { - byte[] buffer = new byte[1]; - - EndianBitConverter.BigEndianConverter.CopyBytes(false, buffer, 0); - this.CheckBytes(new byte[] { 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(true, buffer, 0); - this.CheckBytes(new byte[] { 1 }, buffer); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesShort() - { - byte[] buffer = new byte[2]; - - EndianBitConverter.BigEndianConverter.CopyBytes((short)0, buffer, 0); - this.CheckBytes(new byte[] { 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes((short)1, buffer, 0); - this.CheckBytes(new byte[] { 0, 1 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes((short)256, buffer, 0); - this.CheckBytes(new byte[] { 1, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes((short)-1, buffer, 0); - this.CheckBytes(new byte[] { 255, 255 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes((short)257, buffer, 0); - this.CheckBytes(new byte[] { 1, 1 }, buffer); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesUShort() - { - byte[] buffer = new byte[2]; - - EndianBitConverter.BigEndianConverter.CopyBytes((ushort)0, buffer, 0); - this.CheckBytes(new byte[] { 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes((ushort)1, buffer, 0); - this.CheckBytes(new byte[] { 0, 1 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes((ushort)256, buffer, 0); - this.CheckBytes(new byte[] { 1, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(ushort.MaxValue, buffer, 0); - this.CheckBytes(new byte[] { 255, 255 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes((ushort)257, buffer, 0); - this.CheckBytes(new byte[] { 1, 1 }, buffer); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesInt() - { - byte[] buffer = new byte[4]; - - EndianBitConverter.BigEndianConverter.CopyBytes(0, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(1, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 1 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(256, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 1, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(65536, buffer, 0); - this.CheckBytes(new byte[] { 0, 1, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(16777216, buffer, 0); - this.CheckBytes(new byte[] { 1, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(-1, buffer, 0); - this.CheckBytes(new byte[] { 255, 255, 255, 255 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(257, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 1, 1 }, buffer); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesUInt() - { - byte[] buffer = new byte[4]; - - EndianBitConverter.BigEndianConverter.CopyBytes((uint)0, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes((uint)1, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 1 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes((uint)256, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 1, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes((uint)65536, buffer, 0); - this.CheckBytes(new byte[] { 0, 1, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes((uint)16777216, buffer, 0); - this.CheckBytes(new byte[] { 1, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(uint.MaxValue, buffer, 0); - this.CheckBytes(new byte[] { 255, 255, 255, 255 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes((uint)257, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 1, 1 }, buffer); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesLong() - { - byte[] buffer = new byte[8]; - - EndianBitConverter.BigEndianConverter.CopyBytes(0L, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(1L, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(256L, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(65536L, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(16777216L, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(4294967296L, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(1099511627776L, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(1099511627776L * 256, buffer, 0); - this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(1099511627776L * 256 * 256, buffer, 0); - this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(-1L, buffer, 0); - this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(257L, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, buffer); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesULong() - { - byte[] buffer = new byte[8]; - - EndianBitConverter.BigEndianConverter.CopyBytes(0UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(1UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(256UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(65536UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(16777216UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(4294967296UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(1099511627776UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(1099511627776UL * 256, buffer, 0); - this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(1099511627776UL * 256 * 256, buffer, 0); - this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(ulong.MaxValue, buffer, 0); - this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, buffer); - EndianBitConverter.BigEndianConverter.CopyBytes(257UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, buffer); - } - - /// - /// Tests the two byte arrays for equality. - /// - /// The expected bytes. - /// The actual bytes. - private void CheckBytes(byte[] expected, byte[] actual) - { - Assert.Equal(expected.Length, actual.Length); - Assert.Equal(expected, actual); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/IO/BigEndianBitConverter.GetBytesTests.cs b/tests/ImageSharp.Tests/IO/BigEndianBitConverter.GetBytesTests.cs deleted file mode 100644 index d8408523b..000000000 --- a/tests/ImageSharp.Tests/IO/BigEndianBitConverter.GetBytesTests.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.IO; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.IO -{ - /// - /// The tests. - /// - public class BigEndianBitConverterGetBytesTests - { - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesBoolean() - { - this.CheckBytes(new byte[] { 0 }, EndianBitConverter.BigEndianConverter.GetBytes(false)); - this.CheckBytes(new byte[] { 1 }, EndianBitConverter.BigEndianConverter.GetBytes(true)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesShort() - { - this.CheckBytes(new byte[] { 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((short)0)); - this.CheckBytes(new byte[] { 0, 1 }, EndianBitConverter.BigEndianConverter.GetBytes((short)1)); - this.CheckBytes(new byte[] { 1, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((short)256)); - this.CheckBytes(new byte[] { 255, 255 }, EndianBitConverter.BigEndianConverter.GetBytes((short)-1)); - this.CheckBytes(new byte[] { 1, 1 }, EndianBitConverter.BigEndianConverter.GetBytes((short)257)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesUShort() - { - this.CheckBytes(new byte[] { 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((ushort)0)); - this.CheckBytes(new byte[] { 0, 1 }, EndianBitConverter.BigEndianConverter.GetBytes((ushort)1)); - this.CheckBytes(new byte[] { 1, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((ushort)256)); - this.CheckBytes(new byte[] { 255, 255 }, EndianBitConverter.BigEndianConverter.GetBytes(ushort.MaxValue)); - this.CheckBytes(new byte[] { 1, 1 }, EndianBitConverter.BigEndianConverter.GetBytes((ushort)257)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesInt() - { - this.CheckBytes(new byte[] { 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(0)); - this.CheckBytes(new byte[] { 0, 0, 0, 1 }, EndianBitConverter.BigEndianConverter.GetBytes(1)); - this.CheckBytes(new byte[] { 0, 0, 1, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(256)); - this.CheckBytes(new byte[] { 0, 1, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(65536)); - this.CheckBytes(new byte[] { 1, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(16777216)); - this.CheckBytes(new byte[] { 255, 255, 255, 255 }, EndianBitConverter.BigEndianConverter.GetBytes(-1)); - this.CheckBytes(new byte[] { 0, 0, 1, 1 }, EndianBitConverter.BigEndianConverter.GetBytes(257)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesUInt() - { - this.CheckBytes(new byte[] { 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((uint)0)); - this.CheckBytes(new byte[] { 0, 0, 0, 1 }, EndianBitConverter.BigEndianConverter.GetBytes((uint)1)); - this.CheckBytes(new byte[] { 0, 0, 1, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((uint)256)); - this.CheckBytes(new byte[] { 0, 1, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((uint)65536)); - this.CheckBytes(new byte[] { 1, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes((uint)16777216)); - this.CheckBytes(new byte[] { 255, 255, 255, 255 }, EndianBitConverter.BigEndianConverter.GetBytes(uint.MaxValue)); - this.CheckBytes(new byte[] { 0, 0, 1, 1 }, EndianBitConverter.BigEndianConverter.GetBytes((uint)257)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesLong() - { - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(0L)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, EndianBitConverter.BigEndianConverter.GetBytes(1L)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(256L)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(65536L)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(16777216L)); - this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(4294967296L)); - this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(1099511627776L)); - this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(1099511627776L * 256)); - this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(1099511627776L * 256 * 256)); - this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, EndianBitConverter.BigEndianConverter.GetBytes(-1L)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, EndianBitConverter.BigEndianConverter.GetBytes(257L)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesULong() - { - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(0UL)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, EndianBitConverter.BigEndianConverter.GetBytes(1UL)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(256UL)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(65536UL)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(16777216UL)); - this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(4294967296UL)); - this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(1099511627776UL)); - this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(1099511627776UL * 256)); - this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.BigEndianConverter.GetBytes(1099511627776UL * 256 * 256)); - this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, EndianBitConverter.BigEndianConverter.GetBytes(ulong.MaxValue)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, EndianBitConverter.BigEndianConverter.GetBytes(257UL)); - } - - /// - /// Tests the two byte arrays for equality. - /// - /// The expected bytes. - /// The actual bytes. - private void CheckBytes(byte[] expected, byte[] actual) - { - Assert.Equal(expected.Length, actual.Length); - Assert.Equal(expected, actual); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs b/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs deleted file mode 100644 index 19ef24c79..000000000 --- a/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using SixLabors.ImageSharp.IO; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.IO -{ - /// - /// The tests. - /// - public class BigEndianBitConverterTests - { - [Fact] - public void CopyToWithNullBufferThrowsException() - { - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToBoolean(null, 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt16(null, 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt16(null, 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt32(null, 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt32(null, 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt64(null, 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt64(null, 0)); - } - - [Fact] - public void CopyToWithIndexTooBigThrowsException() - { - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToBoolean(new byte[1], 1)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt16(new byte[2], 1)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt16(new byte[2], 1)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt32(new byte[4], 1)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt32(new byte[4], 1)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt64(new byte[8], 1)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt64(new byte[8], 1)); - } - - [Fact] - public void CopyToWithBufferTooSmallThrowsException() - { - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToBoolean(new byte[0], 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt16(new byte[1], 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt16(new byte[1], 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt32(new byte[3], 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt32(new byte[3], 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToInt64(new byte[7], 0)); - Assert.Throws(() => EndianBitConverter.BigEndianConverter.ToUInt64(new byte[7], 0)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToBoolean() - { - Assert.False(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0 }, 0)); - Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1 }, 0)); - Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 42 }, 0)); - - Assert.False(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1)); - Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1)); - Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 42 }, 1)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToInt16() - { - Assert.Equal((short)0, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 0, 0 }, 0)); - Assert.Equal((short)1, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 0, 1 }, 0)); - Assert.Equal((short)256, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 1, 0 }, 0)); - Assert.Equal((short)-1, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 255, 255 }, 0)); - Assert.Equal((short)257, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 1, 1 }, 0)); - - Assert.Equal((short)0, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 1, 0, 0 }, 1)); - Assert.Equal((short)1, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 1, 0, 1 }, 1)); - Assert.Equal((short)256, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 0, 1, 0 }, 1)); - Assert.Equal((short)-1, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 0, 255, 255 }, 1)); - Assert.Equal((short)257, EndianBitConverter.BigEndianConverter.ToInt16(new byte[] { 0, 1, 1 }, 1)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToUInt16() - { - Assert.Equal((ushort)0, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 0, 0 }, 0)); - Assert.Equal((ushort)1, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 0, 1 }, 0)); - Assert.Equal((ushort)256, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 1, 0 }, 0)); - Assert.Equal(ushort.MaxValue, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 255, 255 }, 0)); - Assert.Equal((ushort)257, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 1, 1 }, 0)); - - Assert.Equal((ushort)0, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 1, 0, 0 }, 1)); - Assert.Equal((ushort)1, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 1, 0, 1 }, 1)); - Assert.Equal((ushort)256, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 0, 1, 0 }, 1)); - Assert.Equal(ushort.MaxValue, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 0, 255, 255 }, 1)); - Assert.Equal((ushort)257, EndianBitConverter.BigEndianConverter.ToUInt16(new byte[] { 0, 1, 1 }, 1)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToInt32() - { - Assert.Equal(0, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 0, 0, 0, 0 }, 0)); - Assert.Equal(1, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 0, 0, 0, 1 }, 0)); - Assert.Equal(256, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 0, 0, 1, 0 }, 0)); - Assert.Equal(65536, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 0, 1, 0, 0 }, 0)); - Assert.Equal(16777216, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 1, 0, 0, 0 }, 0)); - Assert.Equal(-1, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 255, 255, 255, 255 }, 0)); - Assert.Equal(257, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 0, 0, 1, 1 }, 0)); - - Assert.Equal(0, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 1, 0, 0, 0, 0 }, 1)); - Assert.Equal(1, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 1, 0, 0, 0, 1 }, 1)); - Assert.Equal(256, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 1, 0, 0, 1, 0 }, 1)); - Assert.Equal(65536, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 1, 0, 1, 0, 0 }, 1)); - Assert.Equal(16777216, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 0, 1, 0, 0, 0 }, 1)); - Assert.Equal(-1, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 0, 255, 255, 255, 255 }, 1)); - Assert.Equal(257, EndianBitConverter.BigEndianConverter.ToInt32(new byte[] { 1, 0, 0, 1, 1 }, 1)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToUInt32() - { - Assert.Equal((uint)0, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 0, 0, 0, 0 }, 0)); - Assert.Equal((uint)1, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 0, 0, 0, 1 }, 0)); - Assert.Equal((uint)256, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 0, 0, 1, 0 }, 0)); - Assert.Equal((uint)65536, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 0, 1, 0, 0 }, 0)); - Assert.Equal((uint)16777216, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 1, 0, 0, 0 }, 0)); - Assert.Equal(uint.MaxValue, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 255, 255, 255, 255 }, 0)); - Assert.Equal((uint)257, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 0, 0, 1, 1 }, 0)); - - Assert.Equal((uint)0, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 1, 0, 0, 0, 0 }, 1)); - Assert.Equal((uint)1, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 1, 0, 0, 0, 1 }, 1)); - Assert.Equal((uint)256, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 1, 0, 0, 1, 0 }, 1)); - Assert.Equal((uint)65536, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 1, 0, 1, 0, 0 }, 1)); - Assert.Equal((uint)16777216, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 0, 1, 0, 0, 0 }, 1)); - Assert.Equal(uint.MaxValue, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 0, 255, 255, 255, 255 }, 1)); - Assert.Equal((uint)257, EndianBitConverter.BigEndianConverter.ToUInt32(new byte[] { 1, 0, 0, 1, 1 }, 1)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToInt64() - { - Assert.Equal(0L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(1L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, 0)); - Assert.Equal(256L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, 0)); - Assert.Equal(65536L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, 0)); - Assert.Equal(16777216L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, 0)); - Assert.Equal(4294967296L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, 0)); - Assert.Equal(1099511627776L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(1099511627776L * 256, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(1099511627776L * 256 * 256, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(-1L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, 0)); - Assert.Equal(257L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, 0)); - Assert.Equal(4294967295L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 255, 255, 255, 255 }, 0)); - Assert.Equal(-4294967296L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 255, 255, 255, 255, 0, 0, 0, 0 }, 0)); - - Assert.Equal(0L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(1L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 1 }, 1)); - Assert.Equal(256L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 1, 0 }, 1)); - Assert.Equal(65536L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 0, 1, 0, 0 }, 1)); - Assert.Equal(16777216L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 1, 0, 0, 0 }, 1)); - Assert.Equal(4294967296L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0, 0 }, 1)); - Assert.Equal(1099511627776L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(1099511627776L * 256, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 1, 0, 1, 0, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(1099511627776L * 256 * 256, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(-1L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 0, 255, 255, 255, 255, 255, 255, 255, 255 }, 1)); - Assert.Equal(257L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 1, 1 }, 1)); - Assert.Equal(4294967295L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 255, 255, 255, 255 }, 1)); - Assert.Equal(-4294967296L, EndianBitConverter.BigEndianConverter.ToInt64(new byte[] { 1, 255, 255, 255, 255, 0, 0, 0, 0 }, 1)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToUInt64() - { - Assert.Equal(0UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(1UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, 0)); - Assert.Equal(256UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, 0)); - Assert.Equal(65536UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, 0)); - Assert.Equal(16777216UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, 0)); - Assert.Equal(4294967296UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, 0)); - Assert.Equal(1099511627776UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(1099511627776UL * 256, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(1099511627776UL * 256 * 256, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(ulong.MaxValue, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, 0)); - Assert.Equal(257UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 1 }, 0)); - - Assert.Equal(0UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(1UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 1 }, 1)); - Assert.Equal(256UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 1, 0 }, 1)); - Assert.Equal(65536UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 1, 0, 0 }, 1)); - Assert.Equal(16777216UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 1, 0, 0, 0 }, 1)); - Assert.Equal(4294967296UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0, 0 }, 1)); - Assert.Equal(1099511627776UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(1099511627776UL * 256, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 1, 0, 1, 0, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(1099511627776UL * 256 * 256, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(ulong.MaxValue, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 0, 255, 255, 255, 255, 255, 255, 255, 255 }, 1)); - Assert.Equal(257UL, EndianBitConverter.BigEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 1, 1 }, 1)); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.CopyBytesTests.cs b/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.CopyBytesTests.cs deleted file mode 100644 index 97d9275ad..000000000 --- a/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.CopyBytesTests.cs +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using SixLabors.ImageSharp.IO; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.IO -{ - /// - /// The tests. - /// - public class LittleEndianBitConverterCopyBytesTests - { - [Fact] - public void CopyToWithNullBufferThrowsException() - { - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes(false, null, 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes((short)42, null, 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)42, null, 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42, null, 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42u, null, 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42L, null, 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes((ulong)42L, null, 0)); - } - - [Fact] - public void CopyToWithIndexTooBigThrowsException() - { - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes(false, new byte[1], 1)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes((short)42, new byte[2], 1)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)42, new byte[2], 1)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42, new byte[4], 1)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42u, new byte[4], 1)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42L, new byte[8], 1)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes((ulong)42L, new byte[8], 1)); - } - - [Fact] - public void CopyToWithBufferTooSmallThrowsException() - { - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes(false, new byte[0], 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes((short)42, new byte[1], 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)42, new byte[1], 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42, new byte[3], 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42u, new byte[3], 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes(42L, new byte[7], 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.CopyBytes((ulong)42L, new byte[7], 0)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesBoolean() - { - byte[] buffer = new byte[1]; - - EndianBitConverter.LittleEndianConverter.CopyBytes(false, buffer, 0); - this.CheckBytes(new byte[] { 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(true, buffer, 0); - this.CheckBytes(new byte[] { 1 }, buffer); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesShort() - { - byte[] buffer = new byte[2]; - - EndianBitConverter.LittleEndianConverter.CopyBytes((short)0, buffer, 0); - this.CheckBytes(new byte[] { 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes((short)1, buffer, 0); - this.CheckBytes(new byte[] { 1, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes((short)256, buffer, 0); - this.CheckBytes(new byte[] { 0, 1 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes((short)-1, buffer, 0); - this.CheckBytes(new byte[] { 255, 255 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes((short)257, buffer, 0); - this.CheckBytes(new byte[] { 1, 1 }, buffer); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesUShort() - { - byte[] buffer = new byte[2]; - - EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)0, buffer, 0); - this.CheckBytes(new byte[] { 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)1, buffer, 0); - this.CheckBytes(new byte[] { 1, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)256, buffer, 0); - this.CheckBytes(new byte[] { 0, 1 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(ushort.MaxValue, buffer, 0); - this.CheckBytes(new byte[] { 255, 255 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes((ushort)257, buffer, 0); - this.CheckBytes(new byte[] { 1, 1 }, buffer); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesInt() - { - byte[] buffer = new byte[4]; - - EndianBitConverter.LittleEndianConverter.CopyBytes(0, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(1, buffer, 0); - this.CheckBytes(new byte[] { 1, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(256, buffer, 0); - this.CheckBytes(new byte[] { 0, 1, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(65536, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 1, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(16777216, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 1 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(-1, buffer, 0); - this.CheckBytes(new byte[] { 255, 255, 255, 255 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(257, buffer, 0); - this.CheckBytes(new byte[] { 1, 1, 0, 0 }, buffer); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesUInt() - { - byte[] buffer = new byte[4]; - - EndianBitConverter.LittleEndianConverter.CopyBytes((uint)0, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes((uint)1, buffer, 0); - this.CheckBytes(new byte[] { 1, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes((uint)256, buffer, 0); - this.CheckBytes(new byte[] { 0, 1, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes((uint)65536, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 1, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes((uint)16777216, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 1 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(uint.MaxValue, buffer, 0); - this.CheckBytes(new byte[] { 255, 255, 255, 255 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes((uint)257, buffer, 0); - this.CheckBytes(new byte[] { 1, 1, 0, 0 }, buffer); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesLong() - { - byte[] buffer = new byte[8]; - - EndianBitConverter.LittleEndianConverter.CopyBytes(0L, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(1L, buffer, 0); - this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(256L, buffer, 0); - this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(65536L, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(16777216L, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(4294967296L, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(1099511627776L, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(1099511627776L * 256, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(1099511627776L * 256 * 256, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(-1L, buffer, 0); - this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(257L, buffer, 0); - this.CheckBytes(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, buffer); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void CopyBytesULong() - { - byte[] buffer = new byte[8]; - - EndianBitConverter.LittleEndianConverter.CopyBytes(0UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(1UL, buffer, 0); - this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(256UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(65536UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(16777216UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(4294967296UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(1099511627776UL, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(1099511627776UL * 256, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(1099511627776UL * 256 * 256, buffer, 0); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(ulong.MaxValue, buffer, 0); - this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, buffer); - EndianBitConverter.LittleEndianConverter.CopyBytes(257UL, buffer, 0); - this.CheckBytes(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, buffer); - } - - /// - /// Tests the two byte arrays for equality. - /// - /// The expected bytes. - /// The actual bytes. - private void CheckBytes(byte[] expected, byte[] actual) - { - Assert.Equal(expected.Length, actual.Length); - Assert.Equal(expected, actual); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.GetBytesTests.cs b/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.GetBytesTests.cs deleted file mode 100644 index eae8ca291..000000000 --- a/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.GetBytesTests.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.IO; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.IO -{ - /// - /// The tests. - /// - public class LittleEndianBitConverterGetBytesTests - { - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesBoolean() - { - this.CheckBytes(new byte[] { 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(false)); - this.CheckBytes(new byte[] { 1 }, EndianBitConverter.LittleEndianConverter.GetBytes(true)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesShort() - { - this.CheckBytes(new byte[] { 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((short)0)); - this.CheckBytes(new byte[] { 1, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((short)1)); - this.CheckBytes(new byte[] { 0, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes((short)256)); - this.CheckBytes(new byte[] { 255, 255 }, EndianBitConverter.LittleEndianConverter.GetBytes((short)-1)); - this.CheckBytes(new byte[] { 1, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes((short)257)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesUShort() - { - this.CheckBytes(new byte[] { 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((ushort)0)); - this.CheckBytes(new byte[] { 1, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((ushort)1)); - this.CheckBytes(new byte[] { 0, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes((ushort)256)); - this.CheckBytes(new byte[] { 255, 255 }, EndianBitConverter.LittleEndianConverter.GetBytes(ushort.MaxValue)); - this.CheckBytes(new byte[] { 1, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes((ushort)257)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesInt() - { - this.CheckBytes(new byte[] { 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(0)); - this.CheckBytes(new byte[] { 1, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1)); - this.CheckBytes(new byte[] { 0, 1, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(256)); - this.CheckBytes(new byte[] { 0, 0, 1, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(65536)); - this.CheckBytes(new byte[] { 0, 0, 0, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes(16777216)); - this.CheckBytes(new byte[] { 255, 255, 255, 255 }, EndianBitConverter.LittleEndianConverter.GetBytes(-1)); - this.CheckBytes(new byte[] { 1, 1, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(257)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesUInt() - { - this.CheckBytes(new byte[] { 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((uint)0)); - this.CheckBytes(new byte[] { 1, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((uint)1)); - this.CheckBytes(new byte[] { 0, 1, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((uint)256)); - this.CheckBytes(new byte[] { 0, 0, 1, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((uint)65536)); - this.CheckBytes(new byte[] { 0, 0, 0, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes((uint)16777216)); - this.CheckBytes(new byte[] { 255, 255, 255, 255 }, EndianBitConverter.LittleEndianConverter.GetBytes(uint.MaxValue)); - this.CheckBytes(new byte[] { 1, 1, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes((uint)257)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesLong() - { - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(0L)); - this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1L)); - this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(256L)); - this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(65536L)); - this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(16777216L)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(4294967296L)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1099511627776L)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1099511627776L * 256)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes(1099511627776L * 256 * 256)); - this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, EndianBitConverter.LittleEndianConverter.GetBytes(-1L)); - this.CheckBytes(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(257L)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void GetBytesULong() - { - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(0UL)); - this.CheckBytes(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1UL)); - this.CheckBytes(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(256UL)); - this.CheckBytes(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(65536UL)); - this.CheckBytes(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(16777216UL)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(4294967296UL)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1099511627776UL)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(1099511627776UL * 256)); - this.CheckBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, EndianBitConverter.LittleEndianConverter.GetBytes(1099511627776UL * 256 * 256)); - this.CheckBytes(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, EndianBitConverter.LittleEndianConverter.GetBytes(ulong.MaxValue)); - this.CheckBytes(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, EndianBitConverter.LittleEndianConverter.GetBytes(257UL)); - } - - /// - /// Tests the two byte arrays for equality. - /// - /// The expected bytes. - /// The actual bytes. - private void CheckBytes(byte[] expected, byte[] actual) - { - Assert.Equal(expected.Length, actual.Length); - Assert.Equal(expected, actual); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs b/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs deleted file mode 100644 index 0e09d1d07..000000000 --- a/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using SixLabors.ImageSharp.IO; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.IO -{ - /// - /// The tests. - /// - public class LittleEndianBitConverterToTypeTests - { - [Fact] - public void CopyToWithNullBufferThrowsException() - { - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToBoolean(null, 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt16(null, 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt16(null, 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt32(null, 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt32(null, 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt64(null, 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt64(null, 0)); - } - - [Fact] - public void CopyToWithIndexTooBigThrowsException() - { - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[1], 1)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt16(new byte[2], 1)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[2], 1)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt32(new byte[4], 1)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[4], 1)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt64(new byte[8], 1)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[8], 1)); - } - - [Fact] - public void CopyToWithBufferTooSmallThrowsException() - { - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[0], 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt16(new byte[1], 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[1], 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt32(new byte[3], 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[3], 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToInt64(new byte[7], 0)); - Assert.Throws(() => EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[7], 0)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToBoolean() - { - Assert.False(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0 }, 0)); - Assert.True(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1 }, 0)); - - Assert.False(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1)); - Assert.True(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToInt16() - { - Assert.Equal((short)0, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 0, 0 }, 0)); - Assert.Equal((short)1, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 1, 0 }, 0)); - Assert.Equal((short)256, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 0, 1 }, 0)); - Assert.Equal((short)-1, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 255, 255 }, 0)); - Assert.Equal((short)257, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 1, 1 }, 0)); - - Assert.Equal((short)0, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 1, 0, 0 }, 1)); - Assert.Equal((short)1, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 0, 1, 0 }, 1)); - Assert.Equal((short)256, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 1, 0, 1 }, 1)); - Assert.Equal((short)-1, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 0, 255, 255 }, 1)); - Assert.Equal((short)257, EndianBitConverter.LittleEndianConverter.ToInt16(new byte[] { 0, 1, 1 }, 1)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToUInt16() - { - Assert.Equal((ushort)0, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 0, 0 }, 0)); - Assert.Equal((ushort)1, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 1, 0 }, 0)); - Assert.Equal((ushort)256, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 0, 1 }, 0)); - Assert.Equal(ushort.MaxValue, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 255, 255 }, 0)); - Assert.Equal((ushort)257, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 1, 1 }, 0)); - - Assert.Equal((ushort)0, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 1, 0, 0 }, 1)); - Assert.Equal((ushort)1, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 0, 1, 0 }, 1)); - Assert.Equal((ushort)256, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 1, 0, 1 }, 1)); - Assert.Equal(ushort.MaxValue, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 0, 255, 255 }, 1)); - Assert.Equal((ushort)257, EndianBitConverter.LittleEndianConverter.ToUInt16(new byte[] { 0, 1, 1 }, 1)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToInt32() - { - Assert.Equal(0, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 0, 0, 0, 0 }, 0)); - Assert.Equal(1, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 1, 0, 0, 0 }, 0)); - Assert.Equal(256, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 0, 1, 0, 0 }, 0)); - Assert.Equal(65536, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 0, 0, 1, 0 }, 0)); - Assert.Equal(16777216, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 0, 0, 0, 1 }, 0)); - Assert.Equal(-1, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 255, 255, 255, 255 }, 0)); - Assert.Equal(257, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 1, 1, 0, 0 }, 0)); - - Assert.Equal(0, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 1, 0, 0, 0, 0 }, 1)); - Assert.Equal(1, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 0, 1, 0, 0, 0 }, 1)); - Assert.Equal(256, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 1, 0, 1, 0, 0 }, 1)); - Assert.Equal(65536, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 1, 0, 0, 1, 0 }, 1)); - Assert.Equal(16777216, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 1, 0, 0, 0, 1 }, 1)); - Assert.Equal(-1, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 0, 255, 255, 255, 255 }, 1)); - Assert.Equal(257, EndianBitConverter.LittleEndianConverter.ToInt32(new byte[] { 0, 1, 1, 0, 0 }, 1)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToUInt32() - { - Assert.Equal((uint)0, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 0, 0, 0, 0 }, 0)); - Assert.Equal((uint)1, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 1, 0, 0, 0 }, 0)); - Assert.Equal((uint)256, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 0, 1, 0, 0 }, 0)); - Assert.Equal((uint)65536, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 0, 0, 1, 0 }, 0)); - Assert.Equal((uint)16777216, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 0, 0, 0, 1 }, 0)); - Assert.Equal(uint.MaxValue, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 255, 255, 255, 255 }, 0)); - Assert.Equal((uint)257, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 1, 1, 0, 0 }, 0)); - - Assert.Equal((uint)0, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 1, 0, 0, 0, 0 }, 1)); - Assert.Equal((uint)1, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 0, 1, 0, 0, 0 }, 1)); - Assert.Equal((uint)256, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 1, 0, 1, 0, 0 }, 1)); - Assert.Equal((uint)65536, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 1, 0, 0, 1, 0 }, 1)); - Assert.Equal((uint)16777216, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 1, 0, 0, 0, 1 }, 1)); - Assert.Equal(uint.MaxValue, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 0, 255, 255, 255, 255 }, 1)); - Assert.Equal((uint)257, EndianBitConverter.LittleEndianConverter.ToUInt32(new byte[] { 0, 1, 1, 0, 0 }, 1)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToInt64() - { - Assert.Equal(0L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(1L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(256L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(65536L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(16777216L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, 0)); - Assert.Equal(4294967296L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, 0)); - Assert.Equal(1099511627776L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, 0)); - Assert.Equal(1099511627776L * 256, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, 0)); - Assert.Equal(1099511627776L * 256 * 256, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, 0)); - Assert.Equal(-1L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, 0)); - Assert.Equal(257L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(4294967295L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 255, 255, 255, 255, 0, 0, 0, 0 }, 0)); - Assert.Equal(-4294967296L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 255, 255, 255, 255 }, 0)); - - Assert.Equal(0L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(1L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(256L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 1, 0, 1, 0, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(65536L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(16777216L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0, 0 }, 1)); - Assert.Equal(4294967296L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 1, 0, 0, 0 }, 1)); - Assert.Equal(1099511627776L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 0, 1, 0, 0 }, 1)); - Assert.Equal(1099511627776L * 256, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 1, 0 }, 1)); - Assert.Equal(1099511627776L * 256 * 256, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 1 }, 1)); - Assert.Equal(-1L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 255, 255, 255, 255, 255, 255, 255, 255 }, 1)); - Assert.Equal(257L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 1, 1, 0, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(4294967295L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 255, 255, 255, 255, 0, 0, 0, 0 }, 1)); - Assert.Equal(-4294967296L, EndianBitConverter.LittleEndianConverter.ToInt64(new byte[] { 0, 0, 0, 0, 0, 255, 255, 255, 255 }, 1)); - } - - /// - /// Tests that passing a returns the correct bytes. - /// - [Fact] - public void ToUInt64() - { - Assert.Equal(0UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(1UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(256UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(65536UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 1, 0, 0, 0, 0, 0 }, 0)); - Assert.Equal(16777216UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 }, 0)); - Assert.Equal(4294967296UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, 0)); - Assert.Equal(1099511627776UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, 0)); - Assert.Equal(1099511627776UL * 256, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 1, 0 }, 0)); - Assert.Equal(1099511627776UL * 256 * 256, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, 0)); - Assert.Equal(ulong.MaxValue, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, 0)); - Assert.Equal(257UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 1, 1, 0, 0, 0, 0, 0, 0 }, 0)); - - Assert.Equal(0UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(1UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 1, 0, 0, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(256UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 1, 0, 1, 0, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(65536UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0 }, 1)); - Assert.Equal(16777216UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0, 0 }, 1)); - Assert.Equal(4294967296UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 1, 0, 0, 0 }, 1)); - Assert.Equal(1099511627776UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 1, 0, 0 }, 1)); - Assert.Equal(1099511627776UL * 256, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 1, 0 }, 1)); - Assert.Equal(1099511627776UL * 256 * 256, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 1 }, 1)); - Assert.Equal(ulong.MaxValue, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 255, 255, 255, 255, 255, 255, 255, 255 }, 1)); - Assert.Equal(257UL, EndianBitConverter.LittleEndianConverter.ToUInt64(new byte[] { 0, 1, 1, 0, 0, 0, 0, 0, 0 }, 1)); - } - } -} \ No newline at end of file From 32bd209cfc9342b042569d54d72895d7960f3539 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 12:23:05 -0700 Subject: [PATCH 20/34] Remove string encoding concerns from BinaryReader&Writer --- src/ImageSharp/Formats/Gif/GifConstants.cs | 10 + src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 4 +- src/ImageSharp/IO/EndianBinaryReader.cs | 211 +----------------- src/ImageSharp/IO/EndianBinaryWriter.cs | 94 +------- .../IO/EndianBinaryReaderTests.cs | 61 ----- 5 files changed, 14 insertions(+), 366 deletions(-) delete mode 100644 tests/ImageSharp.Tests/IO/EndianBinaryReaderTests.cs diff --git a/src/ImageSharp/Formats/Gif/GifConstants.cs b/src/ImageSharp/Formats/Gif/GifConstants.cs index d448cf783..dba26bd80 100644 --- a/src/ImageSharp/Formats/Gif/GifConstants.cs +++ b/src/ImageSharp/Formats/Gif/GifConstants.cs @@ -21,6 +21,11 @@ namespace SixLabors.ImageSharp.Formats.Gif /// public const string FileVersion = "89a"; + /// + /// The ASCII encoded bytes used to identify the GIF file. + /// + internal static readonly byte[] MagicNumber = { 71, 73, 70, 56, 57, 97 }; // GIF89a + /// /// The extension block introducer !. /// @@ -41,6 +46,11 @@ namespace SixLabors.ImageSharp.Formats.Gif /// public const string ApplicationIdentification = "NETSCAPE2.0"; + /// + /// The ASCII encoded application identification bytes. + /// + internal static readonly byte[] ApplicationIdentificationBytes = Encoding.UTF8.GetBytes(ApplicationIdentification); + /// /// The application block size. /// diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 57bb3d09a..7550d0669 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -157,7 +157,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The writer to write to the stream with. private void WriteHeader(EndianBinaryWriter writer) { - writer.Write((GifConstants.FileType + GifConstants.FileVersion).ToCharArray()); + writer.Write(GifConstants.MagicNumber, 0, GifConstants.MagicNumber.Length); } /// @@ -213,7 +213,7 @@ namespace SixLabors.ImageSharp.Formats.Gif writer.Write(this.buffer, 0, 3); - writer.Write(GifConstants.ApplicationIdentification.ToCharArray()); // NETSCAPE2.0 + writer.Write(GifConstants.ApplicationIdentificationBytes, 0, GifConstants.ApplicationIdentificationBytes.Length); // NETSCAPE2.0 writer.Write((byte)3); // Application block length writer.Write((byte)1); // Data sub-block index (always 1) diff --git a/src/ImageSharp/IO/EndianBinaryReader.cs b/src/ImageSharp/IO/EndianBinaryReader.cs index 25cd0adce..6454ff250 100644 --- a/src/ImageSharp/IO/EndianBinaryReader.cs +++ b/src/ImageSharp/IO/EndianBinaryReader.cs @@ -14,26 +14,11 @@ namespace SixLabors.ImageSharp.IO /// internal class EndianBinaryReader : IDisposable { - /// - /// Decoder to use for string conversions. - /// - private readonly Decoder decoder; - /// /// Buffer used for temporary storage before conversion into primitives /// private readonly byte[] storageBuffer = new byte[16]; - /// - /// Buffer used for temporary storage when reading a single character - /// - private readonly char[] charBuffer = new char[1]; - - /// - /// Minimum number of bytes used to encode a character - /// - private readonly int minBytesPerChar; - /// /// Whether or not this reader has been disposed yet. /// @@ -44,21 +29,6 @@ namespace SixLabors.ImageSharp.IO /// private readonly Endianness endianness; - /// - /// Initializes a new instance of the class. - /// Modeled after with endian support. - /// - /// - /// Endianness to use when reading data - /// - /// - /// Stream to read data from - /// - public EndianBinaryReader(Endianness endianness, Stream stream) - : this(endianness, stream, Encoding.UTF8) - { - } - /// /// Initializes a new instance of the class. /// Constructs a new binary reader with the given bit converter, reading @@ -66,30 +36,15 @@ namespace SixLabors.ImageSharp.IO /// /// Endianness to use when reading data /// Stream to read data from - /// Encoding to use when reading character data - public EndianBinaryReader(Endianness endianness, Stream stream, Encoding encoding) + public EndianBinaryReader(Endianness endianness, Stream stream) { Guard.NotNull(stream, nameof(stream)); - Guard.NotNull(encoding, nameof(encoding)); Guard.IsTrue(stream.CanRead, nameof(stream), "Stream isn't readable"); this.BaseStream = stream; - this.Encoding = encoding; - this.decoder = encoding.GetDecoder(); this.endianness = endianness; - this.minBytesPerChar = 1; - - if (encoding is UnicodeEncoding) - { - this.minBytesPerChar = 2; - } } - /// - /// Gets the encoding used to read strings - /// - public Encoding Encoding { get; } - /// /// Gets the underlying stream of the EndianBinaryReader. /// @@ -253,92 +208,6 @@ namespace SixLabors.ImageSharp.IO return *((double*)&value); } - /// - /// Reads a single character from the stream, using the character encoding for - /// this reader. If no characters have been fully read by the time the stream ends, - /// -1 is returned. - /// - /// The character read, or -1 for end of stream. - public int Read() - { - int charsRead = this.Read(this.charBuffer, 0, 1); - if (charsRead == 0) - { - return -1; - } - else - { - return this.charBuffer[0]; - } - } - - /// - /// Reads the specified number of characters into the given buffer, starting at - /// the given index. - /// - /// The buffer to copy data into - /// The first index to copy data into - /// The number of characters to read - /// The number of characters actually read. This will only be less than - /// the requested number of characters if the end of the stream is reached. - /// - public int Read(char[] data, int index, int count) - { - this.CheckDisposed(); - - Guard.NotNull(this.storageBuffer, nameof(this.storageBuffer)); - Guard.MustBeGreaterThanOrEqualTo(index, 0, nameof(index)); - Guard.MustBeGreaterThanOrEqualTo(count, 0, nameof(count)); - Guard.IsFalse(count + index > data.Length, nameof(data.Length), "Not enough space in buffer for specified number of characters starting at specified index."); - - int read = 0; - bool firstTime = true; - - // Use the normal buffer if we're only reading a small amount, otherwise - // use at most 4K at a time. - byte[] byteBuffer = this.storageBuffer; - - if (byteBuffer.Length < count * this.minBytesPerChar) - { - byteBuffer = new byte[4096]; - } - - while (read < count) - { - int amountToRead; - - // First time through we know we haven't previously read any data - if (firstTime) - { - amountToRead = count * this.minBytesPerChar; - firstTime = false; - } - else - { - // After that we can only assume we need to fully read 'chars left -1' characters - // and a single byte of the character we may be in the middle of - amountToRead = ((count - read - 1) * this.minBytesPerChar) + 1; - } - - if (amountToRead > byteBuffer.Length) - { - amountToRead = byteBuffer.Length; - } - - int bytesRead = this.TryReadInternal(byteBuffer, amountToRead); - if (bytesRead == 0) - { - return read; - } - - int decoded = this.decoder.GetChars(byteBuffer, 0, bytesRead, data, index); - read += decoded; - index += decoded; - } - - return read; - } - /// /// Reads the specified number of bytes into the given buffer, starting at /// the given index. @@ -421,84 +290,6 @@ namespace SixLabors.ImageSharp.IO return ret; } - /// - /// Reads a 7-bit encoded integer from the stream. This is stored with the least significant - /// information first, with 7 bits of information per byte of value, and the top - /// bit as a continuation flag. This method is not affected by the endianness - /// of the bit converter. - /// - /// The 7-bit encoded integer read from the stream. - public int Read7BitEncodedInt() - { - this.CheckDisposed(); - - int ret = 0; - for (int shift = 0; shift < 35; shift += 7) - { - int b = this.BaseStream.ReadByte(); - if (b == -1) - { - throw new EndOfStreamException(); - } - - ret = ret | ((b & 0x7f) << shift); - if ((b & 0x80) == 0) - { - return ret; - } - } - - // Still haven't seen a byte with the high bit unset? Dodgy data. - throw new IOException("Invalid 7-bit encoded integer in stream."); - } - - /// - /// Reads a 7-bit encoded integer from the stream. This is stored with the most significant - /// information first, with 7 bits of information per byte of value, and the top - /// bit as a continuation flag. This method is not affected by the endianness - /// of the bit converter. - /// - /// The 7-bit encoded integer read from the stream. - public int ReadBigEndian7BitEncodedInt() - { - this.CheckDisposed(); - - int ret = 0; - for (int i = 0; i < 5; i++) - { - int b = this.BaseStream.ReadByte(); - if (b == -1) - { - throw new EndOfStreamException(); - } - - ret = (ret << 7) | (b & 0x7f); - if ((b & 0x80) == 0) - { - return ret; - } - } - - // Still haven't seen a byte with the high bit unset? Dodgy data. - throw new IOException("Invalid 7-bit encoded integer in stream."); - } - - /// - /// Reads a length-prefixed string from the stream, using the encoding for this reader. - /// A 7-bit encoded integer is first read, which specifies the number of bytes - /// to read from the stream. These bytes are then converted into a string with - /// the encoding for this reader. - /// - /// The string read from the stream. - public string ReadString() - { - int bytesToRead = this.Read7BitEncodedInt(); - - byte[] data = new byte[bytesToRead]; - this.ReadInternal(data, bytesToRead); - return this.Encoding.GetString(data, 0, data.Length); - } - /// /// Disposes of the underlying stream. /// diff --git a/src/ImageSharp/IO/EndianBinaryWriter.cs b/src/ImageSharp/IO/EndianBinaryWriter.cs index b8cd2cad5..9c42f0b69 100644 --- a/src/ImageSharp/IO/EndianBinaryWriter.cs +++ b/src/ImageSharp/IO/EndianBinaryWriter.cs @@ -4,7 +4,6 @@ using System; using System.Buffers.Binary; using System.IO; -using System.Text; namespace SixLabors.ImageSharp.IO { @@ -18,11 +17,6 @@ namespace SixLabors.ImageSharp.IO /// private readonly byte[] buffer = new byte[16]; - /// - /// Buffer used for Write(char) - /// - private readonly char[] charBuffer = new char[1]; - /// /// The endianness used to write the data /// @@ -33,42 +27,21 @@ namespace SixLabors.ImageSharp.IO /// private bool disposed; - /// - /// Initializes a new instance of the class - /// with the given bit converter, writing to the given stream, using UTF-8 encoding. - /// - /// Endianness to use when writing data - /// Stream to write data to - public EndianBinaryWriter(Endianness endianness, Stream stream) - : this(endianness, stream, Encoding.UTF8) - { - } - /// /// Initializes a new instance of the class /// with the given bit converter, writing to the given stream, using the given encoding. /// /// Endianness to use when writing data /// Stream to write data to - /// - /// Encoding to use when writing character data - /// - public EndianBinaryWriter(Endianness endianness, Stream stream, Encoding encoding) + public EndianBinaryWriter(Endianness endianness, Stream stream) { Guard.NotNull(stream, nameof(stream)); - Guard.NotNull(stream, nameof(encoding)); Guard.IsTrue(stream.CanWrite, nameof(stream), "Stream isn't writable"); this.BaseStream = stream; - this.Encoding = encoding; this.endianness = endianness; } - /// - /// Gets the encoding used to write strings - /// - public Encoding Encoding { get; } - /// /// Gets the underlying stream of the EndianBinaryWriter. /// @@ -291,71 +264,6 @@ namespace SixLabors.ImageSharp.IO this.BaseStream.Write(value, offset, count); } - /// - /// Writes a single character to the stream, using the encoding for this writer. - /// - /// The value to write - public void Write(char value) - { - this.charBuffer[0] = value; - this.Write(this.charBuffer); - } - - /// - /// Writes an array of characters to the stream, using the encoding for this writer. - /// - /// An array containing the characters to write - /// value is null - public void Write(char[] value) - { - Guard.NotNull(value, nameof(value)); - - this.CheckDisposed(); - byte[] data = this.Encoding.GetBytes(value, 0, value.Length); - this.WriteInternal(data, data.Length); - } - - /// - /// Writes a length-prefixed string to the stream, using the encoding for this writer. - /// - /// The value to write. Must not be null. - /// value is null - public void Write(string value) - { - Guard.NotNull(value, nameof(value)); - - this.CheckDisposed(); - byte[] data = this.Encoding.GetBytes(value); - this.Write7BitEncodedInt(data.Length); - this.WriteInternal(data, data.Length); - } - - /// - /// Writes a 7-bit encoded integer from the stream. This is stored with the least significant - /// information first, with 7 bits of information per byte of value, and the top - /// bit as a continuation flag. - /// - /// The 7-bit encoded integer to write to the stream - public void Write7BitEncodedInt(int value) - { - this.CheckDisposed(); - if (value < 0) - { - throw new ArgumentOutOfRangeException(nameof(value), "Value must be greater than or equal to 0."); - } - - int index = 0; - while (value >= 128) - { - this.buffer[index++] = (byte)((value & 0x7f) | 0x80); - value = value >> 7; - index++; - } - - this.buffer[index++] = (byte)value; - this.BaseStream.Write(this.buffer, 0, index); - } - /// /// Disposes of the underlying stream. /// diff --git a/tests/ImageSharp.Tests/IO/EndianBinaryReaderTests.cs b/tests/ImageSharp.Tests/IO/EndianBinaryReaderTests.cs deleted file mode 100644 index fcf484f49..000000000 --- a/tests/ImageSharp.Tests/IO/EndianBinaryReaderTests.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.IO; -using System.Text; -using SixLabors.ImageSharp.IO; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.IO -{ - /// - /// The endian binary reader tests. - /// - public class EndianBinaryReaderTests - { - /// - /// The test string. - /// - private const string TestString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmopqrstuvwxyz"; - - /// - /// The test bytes. - /// - private static readonly byte[] TestBytes = Encoding.ASCII.GetBytes(TestString); - - /// - /// Tests to ensure that the reader can read beyond internal buffer size. - /// - [Fact] - public void ReadCharsBeyondInternalBufferSize() - { - var stream = new MemoryStream(TestBytes); - using (var subject = new EndianBinaryReader(Endianness.LittleEndian, stream)) - { - char[] chars = new char[TestString.Length]; - subject.Read(chars, 0, chars.Length); - Assert.Equal(TestString, new string(chars)); - } - } - - /// - /// Tests to ensure that the reader cannot read beyond the provided buffer size. - /// - [Fact] - public void ReadCharsBeyondProvidedBufferSize() - { - Assert.Throws( - () => - { - var stream = new MemoryStream(TestBytes); - using (var subject = new EndianBinaryReader(Endianness.LittleEndian, stream)) - { - char[] chars = new char[TestString.Length - 1]; - - subject.Read(chars, 0, TestString.Length); - } - }); - } - } -} From 5dacf84c5b9ccbca29463d8bc8dae544bc535dd3 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 13:01:47 -0700 Subject: [PATCH 21/34] Create specialized BigEndianBinaryWriter & LittleEndianBinaryWriter classes --- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 26 ++-- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 18 +-- src/ImageSharp/IO/BigEndianBinaryWriter.cs | 87 ++++++++++++ src/ImageSharp/IO/EndianBinaryWriter.cs | 130 ++++-------------- src/ImageSharp/IO/LittleEndianBinaryWriter.cs | 87 ++++++++++++ .../IO/EndianBinaryReaderWriterTests.cs | 6 +- 6 files changed, 229 insertions(+), 125 deletions(-) create mode 100644 src/ImageSharp/IO/BigEndianBinaryWriter.cs create mode 100644 src/ImageSharp/IO/LittleEndianBinaryWriter.cs diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 66c8b6c08..42a350c15 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -55,9 +55,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.padding = bytesPerLine - (image.Width * (int)this.bitsPerPixel); // Do not use IDisposable pattern here as we want to preserve the stream. - EndianBinaryWriter writer = new EndianBinaryWriter(Endianness.LittleEndian, stream); + var writer = new LittleEndianBinaryWriter(stream); - BmpInfoHeader infoHeader = new BmpInfoHeader + var infoHeader = new BmpInfoHeader { HeaderSize = BmpInfoHeader.BitmapInfoHeaderSize, Height = image.Height, @@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp ClrImportant = 0 }; - BmpFileHeader fileHeader = new BmpFileHeader + var fileHeader = new BmpFileHeader { Type = 19778, // BM Offset = 54, @@ -87,12 +87,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Writes the bitmap header data to the binary stream. /// /// - /// The containing the stream to write to. + /// The containing the stream to write to. /// /// /// The containing the header data. /// - private static void WriteHeader(EndianBinaryWriter writer, BmpFileHeader fileHeader) + private static void WriteHeader(LittleEndianBinaryWriter writer, BmpFileHeader fileHeader) { writer.Write(fileHeader.Type); writer.Write(fileHeader.FileSize); @@ -104,12 +104,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Writes the bitmap information to the binary stream. /// /// - /// The containing the stream to write to. + /// The containing the stream to write to. /// /// /// The containing the detailed information about the image. /// - private void WriteInfo(EndianBinaryWriter writer, BmpInfoHeader infoHeader) + private void WriteInfo(LittleEndianBinaryWriter writer, BmpInfoHeader infoHeader) { writer.Write(infoHeader.HeaderSize); writer.Write(infoHeader.Width); @@ -128,11 +128,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Writes the pixel data to the binary stream. /// /// The pixel format. - /// The containing the stream to write to. + /// The containing the stream to write to. /// /// The containing pixel data. /// - private void WriteImage(EndianBinaryWriter writer, ImageFrame image) + private void WriteImage(LittleEndianBinaryWriter writer, ImageFrame image) where TPixel : struct, IPixel { using (PixelAccessor pixels = image.Lock()) @@ -159,9 +159,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Writes the 32bit color palette to the stream. /// /// The pixel format. - /// The containing the stream to write to. + /// The containing the stream to write to. /// The containing pixel data. - private void Write32Bit(EndianBinaryWriter writer, PixelAccessor pixels) + private void Write32Bit(LittleEndianBinaryWriter writer, PixelAccessor pixels) where TPixel : struct, IPixel { using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 4)) @@ -179,9 +179,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Writes the 24bit color palette to the stream. /// /// The pixel format. - /// The containing the stream to write to. + /// The containing the stream to write to. /// The containing pixel data. - private void Write24Bit(EndianBinaryWriter writer, PixelAccessor pixels) + private void Write24Bit(LittleEndianBinaryWriter writer, PixelAccessor pixels) where TPixel : struct, IPixel { using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 3)) diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 7550d0669..5472b3fd4 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Formats.Gif Guard.NotNull(stream, nameof(stream)); // Do not use IDisposable pattern here as we want to preserve the stream. - var writer = new EndianBinaryWriter(Endianness.LittleEndian, stream); + var writer = new LittleEndianBinaryWriter(stream); this.hasFrames = image.Frames.Count > 1; @@ -155,7 +155,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// Writes the file header signature and version to the stream. /// /// The writer to write to the stream with. - private void WriteHeader(EndianBinaryWriter writer) + private void WriteHeader(LittleEndianBinaryWriter writer) { writer.Write(GifConstants.MagicNumber, 0, GifConstants.MagicNumber.Length); } @@ -167,7 +167,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The image to encode. /// The writer to write to the stream with. /// The transparency index to set the default background index to. - private void WriteLogicalScreenDescriptor(Image image, EndianBinaryWriter writer, int transparencyIndex) + private void WriteLogicalScreenDescriptor(Image image, LittleEndianBinaryWriter writer, int transparencyIndex) where TPixel : struct, IPixel { var descriptor = new GifLogicalScreenDescriptor @@ -202,7 +202,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The writer to write to the stream with. /// The animated image repeat count. /// The number of image frames. - private void WriteApplicationExtension(EndianBinaryWriter writer, ushort repeatCount, int frames) + private void WriteApplicationExtension(LittleEndianBinaryWriter writer, ushort repeatCount, int frames) { // Application Extension Header if (repeatCount != 1 && frames > 0) @@ -231,7 +231,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The pixel format. /// The to be encoded. /// The stream to write to. - private void WriteComments(Image image, EndianBinaryWriter writer) + private void WriteComments(Image image, LittleEndianBinaryWriter writer) where TPixel : struct, IPixel { if (this.ignoreMetadata) @@ -264,7 +264,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The metadata of the image or frame. /// The stream to write to. /// The index of the color in the color palette to make transparent. - private void WriteGraphicalControlExtension(ImageFrameMetaData metaData, EndianBinaryWriter writer, int transparencyIndex) + private void WriteGraphicalControlExtension(ImageFrameMetaData metaData, LittleEndianBinaryWriter writer, int transparencyIndex) { var extension = new GifGraphicsControlExtension { @@ -299,7 +299,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The pixel format. /// The to be encoded. /// The stream to write to. - private void WriteImageDescriptor(ImageFrame image, EndianBinaryWriter writer) + private void WriteImageDescriptor(ImageFrame image, LittleEndianBinaryWriter writer) where TPixel : struct, IPixel { writer.Write(GifConstants.ImageDescriptorLabel); // 2c @@ -325,7 +325,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The pixel format. /// The to encode. /// The writer to write to the stream with. - private void WriteColorTable(QuantizedFrame image, EndianBinaryWriter writer) + private void WriteColorTable(QuantizedFrame image, LittleEndianBinaryWriter writer) where TPixel : struct, IPixel { // Grab the palette and write it to the stream. @@ -357,7 +357,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The pixel format. /// The containing indexed pixels. /// The stream to write to. - private void WriteImageData(QuantizedFrame image, EndianBinaryWriter writer) + private void WriteImageData(QuantizedFrame image, LittleEndianBinaryWriter writer) where TPixel : struct, IPixel { using (var encoder = new LzwEncoder(this.memoryManager, image.Pixels, (byte)this.bitDepth)) diff --git a/src/ImageSharp/IO/BigEndianBinaryWriter.cs b/src/ImageSharp/IO/BigEndianBinaryWriter.cs new file mode 100644 index 000000000..a3de65557 --- /dev/null +++ b/src/ImageSharp/IO/BigEndianBinaryWriter.cs @@ -0,0 +1,87 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers.Binary; +using System.IO; + +namespace SixLabors.ImageSharp.IO +{ + /// + /// A BigEndian variant of + /// + internal sealed class BigEndianBinaryWriter : EndianBinaryWriter + { + /// + /// Initializes a new instance of the class + /// + /// Stream to write data to + public BigEndianBinaryWriter(Stream stream) + : base(stream) + { + } + + /// + public override Endianness Endianness => Endianness.BigEndian; + + /// + public override void Write(short value) + { + BinaryPrimitives.WriteInt16BigEndian(this.buffer, value); + + this.WriteInternal(this.buffer, 2); + } + + /// + public override void Write(int value) + { + BinaryPrimitives.WriteInt32BigEndian(this.buffer, value); + + this.WriteInternal(this.buffer, 4); + } + + /// + public override void Write(long value) + { + BinaryPrimitives.WriteInt64BigEndian(this.buffer, value); + + this.WriteInternal(this.buffer, 8); + } + + /// + public override void Write(ushort value) + { + BinaryPrimitives.WriteUInt16BigEndian(this.buffer, value); + + this.WriteInternal(this.buffer, 2); + } + + /// + public override void Write(uint value) + { + BinaryPrimitives.WriteUInt32BigEndian(this.buffer, value); + + this.WriteInternal(this.buffer, 4); + } + + /// + public override void Write(ulong value) + { + BinaryPrimitives.WriteUInt64BigEndian(this.buffer, value); + + this.WriteInternal(this.buffer, 8); + } + + /// + public override unsafe void Write(float value) + { + this.Write(*((int*)&value)); + } + + /// + public override unsafe void Write(double value) + { + this.Write(*((long*)&value)); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/IO/EndianBinaryWriter.cs b/src/ImageSharp/IO/EndianBinaryWriter.cs index 9c42f0b69..1366764de 100644 --- a/src/ImageSharp/IO/EndianBinaryWriter.cs +++ b/src/ImageSharp/IO/EndianBinaryWriter.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Buffers.Binary; using System.IO; namespace SixLabors.ImageSharp.IO @@ -10,17 +9,12 @@ namespace SixLabors.ImageSharp.IO /// /// Equivalent of , but with either endianness /// - internal class EndianBinaryWriter : IDisposable + internal abstract class EndianBinaryWriter : IDisposable { /// /// Buffer used for temporary storage during conversion from primitives /// - private readonly byte[] buffer = new byte[16]; - - /// - /// The endianness used to write the data - /// - private readonly Endianness endianness; + protected readonly byte[] buffer = new byte[16]; /// /// Whether or not this writer has been disposed yet. @@ -29,17 +23,14 @@ namespace SixLabors.ImageSharp.IO /// /// Initializes a new instance of the class - /// with the given bit converter, writing to the given stream, using the given encoding. /// - /// Endianness to use when writing data /// Stream to write data to - public EndianBinaryWriter(Endianness endianness, Stream stream) + public EndianBinaryWriter(Stream stream) { Guard.NotNull(stream, nameof(stream)); Guard.IsTrue(stream.CanWrite, nameof(stream), "Stream isn't writable"); this.BaseStream = stream; - this.endianness = endianness; } /// @@ -47,6 +38,11 @@ namespace SixLabors.ImageSharp.IO /// public Stream BaseStream { get; } + /// + /// Gets the endianness of the BinaryWriter + /// + public abstract Endianness Endianness { get; } + /// /// Closes the writer, including the underlying stream. /// @@ -91,134 +87,56 @@ namespace SixLabors.ImageSharp.IO /// for this writer. 2 bytes are written. /// /// The value to write - public void Write(short value) - { - if (this.endianness == Endianness.BigEndian) - { - BinaryPrimitives.WriteInt16BigEndian(this.buffer, value); - } - else - { - BinaryPrimitives.WriteInt16LittleEndian(this.buffer, value); - } - - this.WriteInternal(this.buffer, 2); - } + public abstract void Write(short value); /// /// Writes a 32-bit signed integer to the stream, using the bit converter /// for this writer. 4 bytes are written. /// /// The value to write - public void Write(int value) - { - if (this.endianness == Endianness.BigEndian) - { - BinaryPrimitives.WriteInt32BigEndian(this.buffer, value); - } - else - { - BinaryPrimitives.WriteInt32LittleEndian(this.buffer, value); - } - - this.WriteInternal(this.buffer, 4); - } + public abstract void Write(int value); /// /// Writes a 64-bit signed integer to the stream, using the bit converter /// for this writer. 8 bytes are written. /// /// The value to write - public void Write(long value) - { - if (this.endianness == Endianness.BigEndian) - { - BinaryPrimitives.WriteInt64BigEndian(this.buffer, value); - } - else - { - BinaryPrimitives.WriteInt64LittleEndian(this.buffer, value); - } - - this.WriteInternal(this.buffer, 8); - } + public abstract void Write(long value); /// /// Writes a 16-bit unsigned integer to the stream, using the bit converter /// for this writer. 2 bytes are written. /// /// The value to write - public void Write(ushort value) - { - if (this.endianness == Endianness.BigEndian) - { - BinaryPrimitives.WriteUInt16BigEndian(this.buffer, value); - } - else - { - BinaryPrimitives.WriteUInt16LittleEndian(this.buffer, value); - } - - this.WriteInternal(this.buffer, 2); - } + public abstract void Write(ushort value); /// /// Writes a 32-bit unsigned integer to the stream, using the bit converter /// for this writer. 4 bytes are written. /// /// The value to write - public void Write(uint value) - { - if (this.endianness == Endianness.BigEndian) - { - BinaryPrimitives.WriteUInt32BigEndian(this.buffer, value); - } - else - { - BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, value); - } - - this.WriteInternal(this.buffer, 4); - } + public abstract void Write(uint value); /// /// Writes a 64-bit unsigned integer to the stream, using the bit converter /// for this writer. 8 bytes are written. /// /// The value to write - public void Write(ulong value) - { - if (this.endianness == Endianness.BigEndian) - { - BinaryPrimitives.WriteUInt64BigEndian(this.buffer, value); - } - else - { - BinaryPrimitives.WriteUInt64LittleEndian(this.buffer, value); - } - - this.WriteInternal(this.buffer, 8); - } + public abstract void Write(ulong value); /// /// Writes a single-precision floating-point value to the stream, using the bit converter /// for this writer. 4 bytes are written. /// /// The value to write - public unsafe void Write(float value) - { - this.Write(*((int*)&value)); - } + public abstract void Write(float value); /// /// Writes a double-precision floating-point value to the stream, using the bit converter /// for this writer. 8 bytes are written. /// /// The value to write - public unsafe void Write(double value) - { - this.Write(*((long*)&value)); - } + public abstract void Write(double value); /// /// Writes a signed byte to the stream. @@ -284,7 +202,7 @@ namespace SixLabors.ImageSharp.IO { if (this.disposed) { - throw new ObjectDisposedException(nameof(EndianBinaryWriter)); + throw new ObjectDisposedException(nameof(BigEndianBinaryWriter)); } } @@ -294,10 +212,22 @@ namespace SixLabors.ImageSharp.IO /// /// The array of bytes to write from /// The number of bytes to write - private void WriteInternal(byte[] bytes, int length) + protected void WriteInternal(byte[] bytes, int length) { this.CheckDisposed(); this.BaseStream.Write(bytes, 0, length); } + + public static EndianBinaryWriter Create(Endianness endianness, Stream stream) + { + if (endianness == Endianness.BigEndian) + { + return new BigEndianBinaryWriter(stream); + } + else + { + return new LittleEndianBinaryWriter(stream); + } + } } } \ No newline at end of file diff --git a/src/ImageSharp/IO/LittleEndianBinaryWriter.cs b/src/ImageSharp/IO/LittleEndianBinaryWriter.cs new file mode 100644 index 000000000..7be137fb0 --- /dev/null +++ b/src/ImageSharp/IO/LittleEndianBinaryWriter.cs @@ -0,0 +1,87 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers.Binary; +using System.IO; + +namespace SixLabors.ImageSharp.IO +{ + /// + /// A Little Endian variant of + /// + internal sealed class LittleEndianBinaryWriter : EndianBinaryWriter + { + /// + /// Initializes a new instance of the class + /// + /// Stream to write data to + public LittleEndianBinaryWriter(Stream stream) + : base(stream) + { + } + + /// + public override Endianness Endianness => Endianness.LittleEndian; + + /// + public override void Write(short value) + { + BinaryPrimitives.WriteInt16LittleEndian(this.buffer, value); + + this.WriteInternal(this.buffer, 2); + } + + /// + public override void Write(int value) + { + BinaryPrimitives.WriteInt32LittleEndian(this.buffer, value); + + this.WriteInternal(this.buffer, 4); + } + + /// + public override void Write(long value) + { + BinaryPrimitives.WriteInt64LittleEndian(this.buffer, value); + + this.WriteInternal(this.buffer, 8); + } + + /// + public override void Write(ushort value) + { + BinaryPrimitives.WriteUInt16LittleEndian(this.buffer, value); + + this.WriteInternal(this.buffer, 2); + } + + /// + public override void Write(uint value) + { + BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, value); + + this.WriteInternal(this.buffer, 4); + } + + /// + public override void Write(ulong value) + { + BinaryPrimitives.WriteUInt64LittleEndian(this.buffer, value); + + this.WriteInternal(this.buffer, 8); + } + + /// + public override unsafe void Write(float value) + { + this.Write(*((int*)&value)); + } + + /// + public override unsafe void Write(double value) + { + this.Write(*((long*)&value)); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs b/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs index 6e22b1689..2712baafa 100644 --- a/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs +++ b/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests.IO { var stream = new MemoryStream(); - using (var writer = new EndianBinaryWriter(endianness, stream)) + using (var writer = EndianBinaryWriter.Create(endianness, stream)) { writer.Write((float)Math.PI); @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests.IO { var stream = new MemoryStream(); - using (var writer = new EndianBinaryWriter(endianness, stream)) + using (var writer = EndianBinaryWriter.Create(endianness, stream)) { writer.Write(Math.PI); @@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Tests.IO { var stream = new MemoryStream(); - var writer = new EndianBinaryWriter(endianness, stream); + var writer = EndianBinaryWriter.Create(endianness, stream); writer.Write(true); // Bool writer.Write((byte)1); // Byte From b1228659c08089c46946adb3c3e0d9a524aae149 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 13:07:45 -0700 Subject: [PATCH 22/34] Revert "Create specialized BigEndianBinaryWriter & LittleEndianBinaryWriter classes" This reverts commit 0a88cde8e6b542ef9289567019070f18ed8037d3. --- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 26 ++-- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 18 +-- src/ImageSharp/IO/BigEndianBinaryWriter.cs | 87 ------------ src/ImageSharp/IO/EndianBinaryWriter.cs | 130 ++++++++++++++---- src/ImageSharp/IO/LittleEndianBinaryWriter.cs | 87 ------------ .../IO/EndianBinaryReaderWriterTests.cs | 6 +- 6 files changed, 125 insertions(+), 229 deletions(-) delete mode 100644 src/ImageSharp/IO/BigEndianBinaryWriter.cs delete mode 100644 src/ImageSharp/IO/LittleEndianBinaryWriter.cs diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 42a350c15..66c8b6c08 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -55,9 +55,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.padding = bytesPerLine - (image.Width * (int)this.bitsPerPixel); // Do not use IDisposable pattern here as we want to preserve the stream. - var writer = new LittleEndianBinaryWriter(stream); + EndianBinaryWriter writer = new EndianBinaryWriter(Endianness.LittleEndian, stream); - var infoHeader = new BmpInfoHeader + BmpInfoHeader infoHeader = new BmpInfoHeader { HeaderSize = BmpInfoHeader.BitmapInfoHeaderSize, Height = image.Height, @@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp ClrImportant = 0 }; - var fileHeader = new BmpFileHeader + BmpFileHeader fileHeader = new BmpFileHeader { Type = 19778, // BM Offset = 54, @@ -87,12 +87,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Writes the bitmap header data to the binary stream. /// /// - /// The containing the stream to write to. + /// The containing the stream to write to. /// /// /// The containing the header data. /// - private static void WriteHeader(LittleEndianBinaryWriter writer, BmpFileHeader fileHeader) + private static void WriteHeader(EndianBinaryWriter writer, BmpFileHeader fileHeader) { writer.Write(fileHeader.Type); writer.Write(fileHeader.FileSize); @@ -104,12 +104,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Writes the bitmap information to the binary stream. /// /// - /// The containing the stream to write to. + /// The containing the stream to write to. /// /// /// The containing the detailed information about the image. /// - private void WriteInfo(LittleEndianBinaryWriter writer, BmpInfoHeader infoHeader) + private void WriteInfo(EndianBinaryWriter writer, BmpInfoHeader infoHeader) { writer.Write(infoHeader.HeaderSize); writer.Write(infoHeader.Width); @@ -128,11 +128,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Writes the pixel data to the binary stream. /// /// The pixel format. - /// The containing the stream to write to. + /// The containing the stream to write to. /// /// The containing pixel data. /// - private void WriteImage(LittleEndianBinaryWriter writer, ImageFrame image) + private void WriteImage(EndianBinaryWriter writer, ImageFrame image) where TPixel : struct, IPixel { using (PixelAccessor pixels = image.Lock()) @@ -159,9 +159,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Writes the 32bit color palette to the stream. /// /// The pixel format. - /// The containing the stream to write to. + /// The containing the stream to write to. /// The containing pixel data. - private void Write32Bit(LittleEndianBinaryWriter writer, PixelAccessor pixels) + private void Write32Bit(EndianBinaryWriter writer, PixelAccessor pixels) where TPixel : struct, IPixel { using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 4)) @@ -179,9 +179,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Writes the 24bit color palette to the stream. /// /// The pixel format. - /// The containing the stream to write to. + /// The containing the stream to write to. /// The containing pixel data. - private void Write24Bit(LittleEndianBinaryWriter writer, PixelAccessor pixels) + private void Write24Bit(EndianBinaryWriter writer, PixelAccessor pixels) where TPixel : struct, IPixel { using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 3)) diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 5472b3fd4..7550d0669 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Formats.Gif Guard.NotNull(stream, nameof(stream)); // Do not use IDisposable pattern here as we want to preserve the stream. - var writer = new LittleEndianBinaryWriter(stream); + var writer = new EndianBinaryWriter(Endianness.LittleEndian, stream); this.hasFrames = image.Frames.Count > 1; @@ -155,7 +155,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// Writes the file header signature and version to the stream. /// /// The writer to write to the stream with. - private void WriteHeader(LittleEndianBinaryWriter writer) + private void WriteHeader(EndianBinaryWriter writer) { writer.Write(GifConstants.MagicNumber, 0, GifConstants.MagicNumber.Length); } @@ -167,7 +167,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The image to encode. /// The writer to write to the stream with. /// The transparency index to set the default background index to. - private void WriteLogicalScreenDescriptor(Image image, LittleEndianBinaryWriter writer, int transparencyIndex) + private void WriteLogicalScreenDescriptor(Image image, EndianBinaryWriter writer, int transparencyIndex) where TPixel : struct, IPixel { var descriptor = new GifLogicalScreenDescriptor @@ -202,7 +202,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The writer to write to the stream with. /// The animated image repeat count. /// The number of image frames. - private void WriteApplicationExtension(LittleEndianBinaryWriter writer, ushort repeatCount, int frames) + private void WriteApplicationExtension(EndianBinaryWriter writer, ushort repeatCount, int frames) { // Application Extension Header if (repeatCount != 1 && frames > 0) @@ -231,7 +231,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The pixel format. /// The to be encoded. /// The stream to write to. - private void WriteComments(Image image, LittleEndianBinaryWriter writer) + private void WriteComments(Image image, EndianBinaryWriter writer) where TPixel : struct, IPixel { if (this.ignoreMetadata) @@ -264,7 +264,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The metadata of the image or frame. /// The stream to write to. /// The index of the color in the color palette to make transparent. - private void WriteGraphicalControlExtension(ImageFrameMetaData metaData, LittleEndianBinaryWriter writer, int transparencyIndex) + private void WriteGraphicalControlExtension(ImageFrameMetaData metaData, EndianBinaryWriter writer, int transparencyIndex) { var extension = new GifGraphicsControlExtension { @@ -299,7 +299,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The pixel format. /// The to be encoded. /// The stream to write to. - private void WriteImageDescriptor(ImageFrame image, LittleEndianBinaryWriter writer) + private void WriteImageDescriptor(ImageFrame image, EndianBinaryWriter writer) where TPixel : struct, IPixel { writer.Write(GifConstants.ImageDescriptorLabel); // 2c @@ -325,7 +325,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The pixel format. /// The to encode. /// The writer to write to the stream with. - private void WriteColorTable(QuantizedFrame image, LittleEndianBinaryWriter writer) + private void WriteColorTable(QuantizedFrame image, EndianBinaryWriter writer) where TPixel : struct, IPixel { // Grab the palette and write it to the stream. @@ -357,7 +357,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The pixel format. /// The containing indexed pixels. /// The stream to write to. - private void WriteImageData(QuantizedFrame image, LittleEndianBinaryWriter writer) + private void WriteImageData(QuantizedFrame image, EndianBinaryWriter writer) where TPixel : struct, IPixel { using (var encoder = new LzwEncoder(this.memoryManager, image.Pixels, (byte)this.bitDepth)) diff --git a/src/ImageSharp/IO/BigEndianBinaryWriter.cs b/src/ImageSharp/IO/BigEndianBinaryWriter.cs deleted file mode 100644 index a3de65557..000000000 --- a/src/ImageSharp/IO/BigEndianBinaryWriter.cs +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers.Binary; -using System.IO; - -namespace SixLabors.ImageSharp.IO -{ - /// - /// A BigEndian variant of - /// - internal sealed class BigEndianBinaryWriter : EndianBinaryWriter - { - /// - /// Initializes a new instance of the class - /// - /// Stream to write data to - public BigEndianBinaryWriter(Stream stream) - : base(stream) - { - } - - /// - public override Endianness Endianness => Endianness.BigEndian; - - /// - public override void Write(short value) - { - BinaryPrimitives.WriteInt16BigEndian(this.buffer, value); - - this.WriteInternal(this.buffer, 2); - } - - /// - public override void Write(int value) - { - BinaryPrimitives.WriteInt32BigEndian(this.buffer, value); - - this.WriteInternal(this.buffer, 4); - } - - /// - public override void Write(long value) - { - BinaryPrimitives.WriteInt64BigEndian(this.buffer, value); - - this.WriteInternal(this.buffer, 8); - } - - /// - public override void Write(ushort value) - { - BinaryPrimitives.WriteUInt16BigEndian(this.buffer, value); - - this.WriteInternal(this.buffer, 2); - } - - /// - public override void Write(uint value) - { - BinaryPrimitives.WriteUInt32BigEndian(this.buffer, value); - - this.WriteInternal(this.buffer, 4); - } - - /// - public override void Write(ulong value) - { - BinaryPrimitives.WriteUInt64BigEndian(this.buffer, value); - - this.WriteInternal(this.buffer, 8); - } - - /// - public override unsafe void Write(float value) - { - this.Write(*((int*)&value)); - } - - /// - public override unsafe void Write(double value) - { - this.Write(*((long*)&value)); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/IO/EndianBinaryWriter.cs b/src/ImageSharp/IO/EndianBinaryWriter.cs index 1366764de..9c42f0b69 100644 --- a/src/ImageSharp/IO/EndianBinaryWriter.cs +++ b/src/ImageSharp/IO/EndianBinaryWriter.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers.Binary; using System.IO; namespace SixLabors.ImageSharp.IO @@ -9,12 +10,17 @@ namespace SixLabors.ImageSharp.IO /// /// Equivalent of , but with either endianness /// - internal abstract class EndianBinaryWriter : IDisposable + internal class EndianBinaryWriter : IDisposable { /// /// Buffer used for temporary storage during conversion from primitives /// - protected readonly byte[] buffer = new byte[16]; + private readonly byte[] buffer = new byte[16]; + + /// + /// The endianness used to write the data + /// + private readonly Endianness endianness; /// /// Whether or not this writer has been disposed yet. @@ -23,14 +29,17 @@ namespace SixLabors.ImageSharp.IO /// /// Initializes a new instance of the class + /// with the given bit converter, writing to the given stream, using the given encoding. /// + /// Endianness to use when writing data /// Stream to write data to - public EndianBinaryWriter(Stream stream) + public EndianBinaryWriter(Endianness endianness, Stream stream) { Guard.NotNull(stream, nameof(stream)); Guard.IsTrue(stream.CanWrite, nameof(stream), "Stream isn't writable"); this.BaseStream = stream; + this.endianness = endianness; } /// @@ -38,11 +47,6 @@ namespace SixLabors.ImageSharp.IO /// public Stream BaseStream { get; } - /// - /// Gets the endianness of the BinaryWriter - /// - public abstract Endianness Endianness { get; } - /// /// Closes the writer, including the underlying stream. /// @@ -87,56 +91,134 @@ namespace SixLabors.ImageSharp.IO /// for this writer. 2 bytes are written. /// /// The value to write - public abstract void Write(short value); + public void Write(short value) + { + if (this.endianness == Endianness.BigEndian) + { + BinaryPrimitives.WriteInt16BigEndian(this.buffer, value); + } + else + { + BinaryPrimitives.WriteInt16LittleEndian(this.buffer, value); + } + + this.WriteInternal(this.buffer, 2); + } /// /// Writes a 32-bit signed integer to the stream, using the bit converter /// for this writer. 4 bytes are written. /// /// The value to write - public abstract void Write(int value); + public void Write(int value) + { + if (this.endianness == Endianness.BigEndian) + { + BinaryPrimitives.WriteInt32BigEndian(this.buffer, value); + } + else + { + BinaryPrimitives.WriteInt32LittleEndian(this.buffer, value); + } + + this.WriteInternal(this.buffer, 4); + } /// /// Writes a 64-bit signed integer to the stream, using the bit converter /// for this writer. 8 bytes are written. /// /// The value to write - public abstract void Write(long value); + public void Write(long value) + { + if (this.endianness == Endianness.BigEndian) + { + BinaryPrimitives.WriteInt64BigEndian(this.buffer, value); + } + else + { + BinaryPrimitives.WriteInt64LittleEndian(this.buffer, value); + } + + this.WriteInternal(this.buffer, 8); + } /// /// Writes a 16-bit unsigned integer to the stream, using the bit converter /// for this writer. 2 bytes are written. /// /// The value to write - public abstract void Write(ushort value); + public void Write(ushort value) + { + if (this.endianness == Endianness.BigEndian) + { + BinaryPrimitives.WriteUInt16BigEndian(this.buffer, value); + } + else + { + BinaryPrimitives.WriteUInt16LittleEndian(this.buffer, value); + } + + this.WriteInternal(this.buffer, 2); + } /// /// Writes a 32-bit unsigned integer to the stream, using the bit converter /// for this writer. 4 bytes are written. /// /// The value to write - public abstract void Write(uint value); + public void Write(uint value) + { + if (this.endianness == Endianness.BigEndian) + { + BinaryPrimitives.WriteUInt32BigEndian(this.buffer, value); + } + else + { + BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, value); + } + + this.WriteInternal(this.buffer, 4); + } /// /// Writes a 64-bit unsigned integer to the stream, using the bit converter /// for this writer. 8 bytes are written. /// /// The value to write - public abstract void Write(ulong value); + public void Write(ulong value) + { + if (this.endianness == Endianness.BigEndian) + { + BinaryPrimitives.WriteUInt64BigEndian(this.buffer, value); + } + else + { + BinaryPrimitives.WriteUInt64LittleEndian(this.buffer, value); + } + + this.WriteInternal(this.buffer, 8); + } /// /// Writes a single-precision floating-point value to the stream, using the bit converter /// for this writer. 4 bytes are written. /// /// The value to write - public abstract void Write(float value); + public unsafe void Write(float value) + { + this.Write(*((int*)&value)); + } /// /// Writes a double-precision floating-point value to the stream, using the bit converter /// for this writer. 8 bytes are written. /// /// The value to write - public abstract void Write(double value); + public unsafe void Write(double value) + { + this.Write(*((long*)&value)); + } /// /// Writes a signed byte to the stream. @@ -202,7 +284,7 @@ namespace SixLabors.ImageSharp.IO { if (this.disposed) { - throw new ObjectDisposedException(nameof(BigEndianBinaryWriter)); + throw new ObjectDisposedException(nameof(EndianBinaryWriter)); } } @@ -212,22 +294,10 @@ namespace SixLabors.ImageSharp.IO /// /// The array of bytes to write from /// The number of bytes to write - protected void WriteInternal(byte[] bytes, int length) + private void WriteInternal(byte[] bytes, int length) { this.CheckDisposed(); this.BaseStream.Write(bytes, 0, length); } - - public static EndianBinaryWriter Create(Endianness endianness, Stream stream) - { - if (endianness == Endianness.BigEndian) - { - return new BigEndianBinaryWriter(stream); - } - else - { - return new LittleEndianBinaryWriter(stream); - } - } } } \ No newline at end of file diff --git a/src/ImageSharp/IO/LittleEndianBinaryWriter.cs b/src/ImageSharp/IO/LittleEndianBinaryWriter.cs deleted file mode 100644 index 7be137fb0..000000000 --- a/src/ImageSharp/IO/LittleEndianBinaryWriter.cs +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers.Binary; -using System.IO; - -namespace SixLabors.ImageSharp.IO -{ - /// - /// A Little Endian variant of - /// - internal sealed class LittleEndianBinaryWriter : EndianBinaryWriter - { - /// - /// Initializes a new instance of the class - /// - /// Stream to write data to - public LittleEndianBinaryWriter(Stream stream) - : base(stream) - { - } - - /// - public override Endianness Endianness => Endianness.LittleEndian; - - /// - public override void Write(short value) - { - BinaryPrimitives.WriteInt16LittleEndian(this.buffer, value); - - this.WriteInternal(this.buffer, 2); - } - - /// - public override void Write(int value) - { - BinaryPrimitives.WriteInt32LittleEndian(this.buffer, value); - - this.WriteInternal(this.buffer, 4); - } - - /// - public override void Write(long value) - { - BinaryPrimitives.WriteInt64LittleEndian(this.buffer, value); - - this.WriteInternal(this.buffer, 8); - } - - /// - public override void Write(ushort value) - { - BinaryPrimitives.WriteUInt16LittleEndian(this.buffer, value); - - this.WriteInternal(this.buffer, 2); - } - - /// - public override void Write(uint value) - { - BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, value); - - this.WriteInternal(this.buffer, 4); - } - - /// - public override void Write(ulong value) - { - BinaryPrimitives.WriteUInt64LittleEndian(this.buffer, value); - - this.WriteInternal(this.buffer, 8); - } - - /// - public override unsafe void Write(float value) - { - this.Write(*((int*)&value)); - } - - /// - public override unsafe void Write(double value) - { - this.Write(*((long*)&value)); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs b/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs index 2712baafa..6e22b1689 100644 --- a/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs +++ b/tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests.IO { var stream = new MemoryStream(); - using (var writer = EndianBinaryWriter.Create(endianness, stream)) + using (var writer = new EndianBinaryWriter(endianness, stream)) { writer.Write((float)Math.PI); @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests.IO { var stream = new MemoryStream(); - using (var writer = EndianBinaryWriter.Create(endianness, stream)) + using (var writer = new EndianBinaryWriter(endianness, stream)) { writer.Write(Math.PI); @@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Tests.IO { var stream = new MemoryStream(); - var writer = EndianBinaryWriter.Create(endianness, stream); + var writer = new EndianBinaryWriter(endianness, stream); writer.Write(true); // Bool writer.Write((byte)1); // Byte From 8770cc71e9882414046f5f11b4e57a303381327f Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 17:52:46 -0700 Subject: [PATCH 23/34] Update Checksum algorithms to use Spans --- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 2 +- src/ImageSharp/Formats/Png/Zlib/Adler32.cs | 25 ++++--------------- src/ImageSharp/Formats/Png/Zlib/Crc32.cs | 23 +++-------------- src/ImageSharp/Formats/Png/Zlib/IChecksum.cs | 22 ++++------------ .../Formats/Png/Zlib/ZlibDeflateStream.cs | 2 +- 5 files changed, 15 insertions(+), 59 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 26a8b48df..c3750eb09 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -677,7 +677,7 @@ namespace SixLabors.ImageSharp.Formats.Png if (data != null && length > 0) { - this.crc.Update(data, offset, length); + this.crc.Update(new ReadOnlySpan(data, offset, length)); } WriteInteger(stream, (uint)this.crc.Value); diff --git a/src/ImageSharp/Formats/Png/Zlib/Adler32.cs b/src/ImageSharp/Formats/Png/Zlib/Adler32.cs index 1cce90c0b..9c4e9e4b9 100644 --- a/src/ImageSharp/Formats/Png/Zlib/Adler32.cs +++ b/src/ImageSharp/Formats/Png/Zlib/Adler32.cs @@ -113,30 +113,15 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Update(byte[] buffer) + public void Update(ReadOnlySpan data) { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - this.Update(buffer, 0, buffer.Length); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Update(byte[] buffer, int offset, int count) - { - DebugGuard.NotNull(buffer, nameof(buffer)); - DebugGuard.MustBeGreaterThanOrEqualTo(offset, 0, nameof(offset)); - DebugGuard.MustBeGreaterThanOrEqualTo(count, 0, nameof(count)); - DebugGuard.MustBeLessThan(offset, buffer.Length, nameof(offset)); - DebugGuard.MustBeLessThanOrEqualTo(offset + count, buffer.Length, nameof(count)); - // (By Per Bothner) uint s1 = this.checksum & 0xFFFF; uint s2 = this.checksum >> 16; + int count = data.Length; + int offset = 0; + while (count > 0) { // We can defer the modulo operation: @@ -151,7 +136,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib count -= n; while (--n >= 0) { - s1 = s1 + (uint)(buffer[offset++] & 0xff); + s1 = s1 + (uint)(data[offset++] & 0xff); s2 = s2 + s1; } diff --git a/src/ImageSharp/Formats/Png/Zlib/Crc32.cs b/src/ImageSharp/Formats/Png/Zlib/Crc32.cs index bd686f2b9..d1588c384 100644 --- a/src/ImageSharp/Formats/Png/Zlib/Crc32.cs +++ b/src/ImageSharp/Formats/Png/Zlib/Crc32.cs @@ -137,30 +137,13 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Update(byte[] buffer) + public void Update(ReadOnlySpan data) { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - this.Update(buffer, 0, buffer.Length); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Update(byte[] buffer, int offset, int count) - { - DebugGuard.NotNull(buffer, nameof(buffer)); - DebugGuard.MustBeGreaterThanOrEqualTo(count, 0, nameof(count)); - DebugGuard.MustBeGreaterThanOrEqualTo(offset, 0, nameof(offset)); - DebugGuard.MustBeLessThanOrEqualTo(offset + count, buffer.Length, nameof(count)); - this.crc ^= CrcSeed; - while (--count >= 0) + for (int i = 0; i < data.Length; i++) { - this.crc = CrcTable[(this.crc ^ buffer[offset++]) & 0xFF] ^ (this.crc >> 8); + this.crc = CrcTable[(this.crc ^ data[i]) & 0xFF] ^ (this.crc >> 8); } this.crc ^= CrcSeed; diff --git a/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs b/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs index 9d84258ca..a2a57332b 100644 --- a/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs +++ b/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; + namespace SixLabors.ImageSharp.Formats.Png.Zlib { /// @@ -34,25 +36,11 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib void Update(int value); /// - /// Updates the data checksum with the bytes taken from the array. + /// Updates the data checksum with the bytes taken from the span. /// - /// + /// /// buffer an array of bytes /// - void Update(byte[] buffer); - - /// - /// Adds the byte array to the data checksum. - /// - /// - /// The buffer which contains the data - /// - /// - /// The offset in the buffer where the data starts - /// - /// - /// the number of data bytes to add. - /// - void Update(byte[] buffer, int offset, int count); + void Update(ReadOnlySpan data); } } diff --git a/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs b/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs index dd20886ff..51e6b4859 100644 --- a/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs +++ b/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs @@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib public override void Write(byte[] buffer, int offset, int count) { this.deflateStream.Write(buffer, offset, count); - this.adler32.Update(buffer, offset, count); + this.adler32.Update(new ReadOnlySpan(buffer, offset, count)); } /// From 3fb692127a9c48b65c44d2c3e9c0c355c2a1d907 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 17:59:38 -0700 Subject: [PATCH 24/34] Eliminate buffer allocations for integers in PngEncoderCore.WriteChunk --- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 49 ++++++-------------- 1 file changed, 14 insertions(+), 35 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index c3750eb09..333ed44e3 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -37,6 +37,11 @@ namespace SixLabors.ImageSharp.Formats.Png /// private readonly byte[] chunkDataBuffer = new byte[16]; + /// + /// Reusable buffer for writing int data. + /// + private readonly byte[] intBuffer = new byte[4]; + /// /// Reusable crc for validating chunks. /// @@ -245,34 +250,6 @@ namespace SixLabors.ImageSharp.Formats.Png this.paeth?.Dispose(); } - /// - /// Writes an integer to the stream. - /// - /// The containing image data. - /// The value to write. - private static void WriteInteger(Stream stream, int value) - { - byte[] buffer = new byte[4]; - - BinaryPrimitives.WriteInt32BigEndian(buffer, value); - - stream.Write(buffer, 0, 4); - } - - /// - /// Writes an unsigned integer to the stream. - /// - /// The containing image data. - /// The value to write. - private static void WriteInteger(Stream stream, uint value) - { - byte[] buffer = new byte[4]; - - BinaryPrimitives.WriteUInt32BigEndian(buffer, value); - - stream.Write(buffer, 0, 4); - } - /// /// Collects a row of grayscale pixels. /// @@ -658,7 +635,9 @@ namespace SixLabors.ImageSharp.Formats.Png /// The of the data to write. private void WriteChunk(Stream stream, string type, byte[] data, int offset, int length) { - WriteInteger(stream, length); + BinaryPrimitives.WriteInt32BigEndian(this.intBuffer, length); + + stream.Write(this.intBuffer, 0, 4); // write the length this.chunkTypeBuffer[0] = (byte)type[0]; this.chunkTypeBuffer[1] = (byte)type[1]; @@ -667,20 +646,20 @@ namespace SixLabors.ImageSharp.Formats.Png stream.Write(this.chunkTypeBuffer, 0, 4); - if (data != null) - { - stream.Write(data, offset, length); - } - this.crc.Reset(); + this.crc.Update(this.chunkTypeBuffer); if (data != null && length > 0) { + stream.Write(data, offset, length); + this.crc.Update(new ReadOnlySpan(data, offset, length)); } - WriteInteger(stream, (uint)this.crc.Value); + BinaryPrimitives.WriteUInt32BigEndian(this.intBuffer, (uint)this.crc.Value); + + stream.Write(intBuffer, 0, 4); // write the crc } } } \ No newline at end of file From f8f809981c064d1381a7a1194f2872f5b6d9a853 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 18:01:51 -0700 Subject: [PATCH 25/34] Reduce magic --- src/ImageSharp/Formats/Gif/GifConstants.cs | 2 +- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp/Formats/Gif/GifConstants.cs b/src/ImageSharp/Formats/Gif/GifConstants.cs index dba26bd80..ffab45a56 100644 --- a/src/ImageSharp/Formats/Gif/GifConstants.cs +++ b/src/ImageSharp/Formats/Gif/GifConstants.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// The ASCII encoded bytes used to identify the GIF file. /// - internal static readonly byte[] MagicNumber = { 71, 73, 70, 56, 57, 97 }; // GIF89a + internal static readonly byte[] MagicNumber = Encoding.UTF8.GetBytes(FileType + FileVersion); /// /// The extension block introducer !. diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 7550d0669..436db636d 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -157,7 +157,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The writer to write to the stream with. private void WriteHeader(EndianBinaryWriter writer) { - writer.Write(GifConstants.MagicNumber, 0, GifConstants.MagicNumber.Length); + writer.Write(GifConstants.MagicNumber); } /// @@ -213,7 +213,7 @@ namespace SixLabors.ImageSharp.Formats.Gif writer.Write(this.buffer, 0, 3); - writer.Write(GifConstants.ApplicationIdentificationBytes, 0, GifConstants.ApplicationIdentificationBytes.Length); // NETSCAPE2.0 + writer.Write(GifConstants.ApplicationIdentificationBytes); // NETSCAPE2.0 writer.Write((byte)3); // Application block length writer.Write((byte)1); // Data sub-block index (always 1) From 8642a9cd73248d22d8af892107cae4efe617e865 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 18:30:31 -0700 Subject: [PATCH 26/34] Fix build --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 2 +- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index af6637fa1..0cfada661 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -1261,7 +1261,7 @@ namespace SixLabors.ImageSharp.Formats.Png this.crc.Reset(); this.crc.Update(this.chunkTypeBuffer); - this.crc.Update(chunk.Data.Array, 0, chunk.Length); + this.crc.Update(new ReadOnlySpan(chunk.Data.Array, 0, chunk.Length)); if (this.crc.Value != chunk.Crc && IsCriticalChunk(chunk)) { diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 333ed44e3..e438975a4 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -659,7 +659,7 @@ namespace SixLabors.ImageSharp.Formats.Png BinaryPrimitives.WriteUInt32BigEndian(this.intBuffer, (uint)this.crc.Value); - stream.Write(intBuffer, 0, 4); // write the crc + stream.Write(this.intBuffer, 0, 4); // write the crc } } } \ No newline at end of file From 4a5589ef5ed3147f31e26be72aeb6d58279113d9 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 18:33:01 -0700 Subject: [PATCH 27/34] Fix documentation --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 0cfada661..2c7396f3e 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -1157,7 +1157,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Reads a header chunk from the data. /// - /// The containing data. + /// The containing data. private void ReadHeaderChunk(ReadOnlySpan data) { this.header = new PngHeader From b0f5c6048ad20a5e9706c956018bed97c8ad8678 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 18:55:08 -0700 Subject: [PATCH 28/34] Pass ColorSpace types by readonly ref --- src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs | 6 ++++-- .../Implementation/CieLab/CieLabToCieXyzConverter.cs | 2 +- .../Implementation/CieLab/CieXyzToCieLabConverter.cs | 4 ++-- .../Implementation/CieLch/CIeLchToCieLabConverter.cs | 2 +- .../Implementation/CieLch/CieLabToCieLchConverter.cs | 2 +- .../Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs | 3 +-- .../Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs | 2 +- .../Implementation/CieLuv/CieLuvToCieXyzConverter.cs | 3 +-- .../Implementation/CieLuv/CieXyzToCieLuvConverter.cs | 4 ++-- .../Implementation/CieXyy/CieXyzAndCieXyyConverter.cs | 4 ++-- .../Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs | 4 ++-- .../Conversion/Implementation/Hsl/HslAndRgbConverter.cs | 4 ++-- .../Conversion/Implementation/Hsv/HsvAndRgbConverter.cs | 5 ++--- .../Implementation/HunterLab/CieXyzToHunterLabConverter.cs | 4 ++-- .../Implementation/HunterLab/HunterLabToCieXyzConverter.cs | 2 +- .../Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs | 5 ++--- .../Implementation/Rgb/CieXyzToLinearRgbConverter.cs | 2 +- .../Implementation/Rgb/LinearRgbToCieXyzConverter.cs | 2 +- .../Implementation/Rgb/LinearRgbToRgbConverter.cs | 2 +- .../Implementation/Rgb/RgbToLinearRgbConverter.cs | 2 +- .../Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs | 5 ++--- 21 files changed, 33 insertions(+), 36 deletions(-) diff --git a/src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs b/src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs index 9ef24b38a..19feeaa5d 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs @@ -8,13 +8,15 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The input color type. /// The result color type. - internal interface IColorConversion + internal interface IColorConversion + where T: struct + where TResult: struct { /// /// Performs the conversion from the input to an instance of the output type. /// /// The input color instance. /// The converted result - TResult Convert(T input); + TResult Convert(in T input); } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs index 0a5ae3627..15f50971a 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLabColor { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyz Convert(CieLab input) + public CieXyz Convert(in CieLab input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs index 22308260c..cdeda7f78 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLabColor /// /// The target reference lab white point [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyzToCieLabConverter(CieXyz labWhitePoint) + public CieXyzToCieLabConverter(in CieXyz labWhitePoint) { this.LabWhitePoint = labWhitePoint; } @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLabColor /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieLab Convert(CieXyz input) + public CieLab Convert(in CieXyz input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs index 35fae30e8..fcc8687fb 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchColor { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieLab Convert(CieLch input) + public CieLab Convert(in CieLch input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs index aa4614f9c..134cc1a08 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchColor { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieLch Convert(CieLab input) + public CieLch Convert(in CieLab input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs index fc6554a90..2cbb953b8 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs @@ -3,7 +3,6 @@ using System; using System.Runtime.CompilerServices; -using SixLabors.ImageSharp.ColorSpaces; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvColorSapce { @@ -14,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvCol { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieLuv Convert(CieLchuv input) + public CieLuv Convert(in CieLchuv input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs index f0d7a80a2..427fb8f83 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvCol { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieLchuv Convert(CieLuv input) + public CieLchuv Convert(in CieLuv input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs index 50e8335ed..03eddab44 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs @@ -3,7 +3,6 @@ using System; using System.Runtime.CompilerServices; -using SixLabors.ImageSharp.ColorSpaces; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColorSapce { @@ -14,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColor { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyz Convert(CieLuv input) + public CieXyz Convert(in CieLuv input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs index 709d8d426..162f5b9c2 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColor /// /// The target reference luv white point [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyzToCieLuvConverter(CieXyz luvWhitePoint) + public CieXyzToCieLuvConverter(in CieXyz luvWhitePoint) { this.LuvWhitePoint = luvWhitePoint; } @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColor /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieLuv Convert(CieXyz input) + public CieLuv Convert(in CieXyz input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs index 64fc84b1d..ef9672d6c 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs @@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieXyyColor { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyy Convert(CieXyz input) + public CieXyy Convert(in CieXyz input) { DebugGuard.NotNull(input, nameof(input)); @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieXyyColor /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyz Convert(CieXyy input) + public CieXyz Convert(in CieXyy input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs index 404bc811f..be4be5e65 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CmykColorSa { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rgb Convert(Cmyk input) + public Rgb Convert(in Cmyk input) { float r = (1F - input.C) * (1F - input.K); float g = (1F - input.M) * (1F - input.K); @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CmykColorSa /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cmyk Convert(Rgb input) + public Cmyk Convert(in Rgb input) { // To CMYK float c = 1F - input.R; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs index 3de3baddd..597e571a8 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs @@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HslColorSap { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rgb Convert(Hsl input) + public Rgb Convert(in Hsl input) { DebugGuard.NotNull(input, nameof(input)); @@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HslColorSap /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Hsl Convert(Rgb input) + public Hsl Convert(in Rgb input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsv/HsvAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsv/HsvAndRgbConverter.cs index 6219533ca..443252a63 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsv/HsvAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsv/HsvAndRgbConverter.cs @@ -3,7 +3,6 @@ using System; using System.Runtime.CompilerServices; -using SixLabors.ImageSharp.ColorSpaces; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HsvColorSapce { @@ -15,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HsvColorSap { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rgb Convert(Hsv input) + public Rgb Convert(in Hsv input) { DebugGuard.NotNull(input, nameof(input)); @@ -80,7 +79,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HsvColorSap /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Hsv Convert(Rgb input) + public Hsv Convert(in Rgb input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs index 7faf03c9a..f13155120 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HunterLabCo /// /// The hunter Lab white point. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyzToHunterLabConverter(CieXyz labWhitePoint) + public CieXyzToHunterLabConverter(in CieXyz labWhitePoint) { this.HunterLabWhitePoint = labWhitePoint; } @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HunterLabCo /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public HunterLab Convert(CieXyz input) + public HunterLab Convert(in CieXyz input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs index 7e7c536e3..d62eba30b 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HunterLabCo { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyz Convert(HunterLab input) + public CieXyz Convert(in HunterLab input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs index 780c9e5a6..83a64d3d0 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs @@ -3,7 +3,6 @@ using System.Numerics; using System.Runtime.CompilerServices; -using SixLabors.ImageSharp.ColorSpaces; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.LmsColorSapce { @@ -61,7 +60,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.LmsColorSap /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Lms Convert(CieXyz input) + public Lms Convert(in CieXyz input) { DebugGuard.NotNull(input, nameof(input)); @@ -71,7 +70,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.LmsColorSap /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyz Convert(Lms input) + public CieXyz Convert(in Lms input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/CieXyzToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/CieXyzToLinearRgbConverter.cs index fd76a30fb..9c02aacaa 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/CieXyzToLinearRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/CieXyzToLinearRgbConverter.cs @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap public IRgbWorkingSpace TargetWorkingSpace { get; } /// - public LinearRgb Convert(CieXyz input) + public LinearRgb Convert(in CieXyz input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs index bf36e252a..23625fc02 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap public IRgbWorkingSpace SourceWorkingSpace { get; } /// - public CieXyz Convert(LinearRgb input) + public CieXyz Convert(in LinearRgb input) { DebugGuard.NotNull(input, nameof(input)); DebugGuard.IsTrue(input.WorkingSpace.Equals(this.SourceWorkingSpace), nameof(input.WorkingSpace), "Input and source working spaces must be equal."); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs index 29ea0f314..e746b40c5 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap internal class LinearRgbToRgbConverter : IColorConversion { /// - public Rgb Convert(LinearRgb input) + public Rgb Convert(in LinearRgb input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs index e40ecc192..af2c39f0f 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap internal class RgbToLinearRgbConverter : IColorConversion { /// - public LinearRgb Convert(Rgb input) + public LinearRgb Convert(in Rgb input) { Guard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs index f552acbb4..548fe6128 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs @@ -4,7 +4,6 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; -using SixLabors.ImageSharp.ColorSpaces; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.YCbCrColorSapce { @@ -18,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.YCbCrColorS /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rgb Convert(YCbCr input) + public Rgb Convert(in YCbCr input) { DebugGuard.NotNull(input, nameof(input)); @@ -35,7 +34,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.YCbCrColorS /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public YCbCr Convert(Rgb input) + public YCbCr Convert(in Rgb input) { DebugGuard.NotNull(input, nameof(input)); From 9b06f9f477ca2bb58a42115f8b9e922c0f8a05aa Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Thu, 22 Mar 2018 19:00:25 -0700 Subject: [PATCH 29/34] Revert "Pass ColorSpace types by readonly ref" This reverts commit f7d8e706f135d79dda94cc8fdf5a0c1f3c1b1a28. --- src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs | 6 ++---- .../Implementation/CieLab/CieLabToCieXyzConverter.cs | 2 +- .../Implementation/CieLab/CieXyzToCieLabConverter.cs | 4 ++-- .../Implementation/CieLch/CIeLchToCieLabConverter.cs | 2 +- .../Implementation/CieLch/CieLabToCieLchConverter.cs | 2 +- .../Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs | 3 ++- .../Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs | 2 +- .../Implementation/CieLuv/CieLuvToCieXyzConverter.cs | 3 ++- .../Implementation/CieLuv/CieXyzToCieLuvConverter.cs | 4 ++-- .../Implementation/CieXyy/CieXyzAndCieXyyConverter.cs | 4 ++-- .../Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs | 4 ++-- .../Conversion/Implementation/Hsl/HslAndRgbConverter.cs | 4 ++-- .../Conversion/Implementation/Hsv/HsvAndRgbConverter.cs | 5 +++-- .../Implementation/HunterLab/CieXyzToHunterLabConverter.cs | 4 ++-- .../Implementation/HunterLab/HunterLabToCieXyzConverter.cs | 2 +- .../Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs | 5 +++-- .../Implementation/Rgb/CieXyzToLinearRgbConverter.cs | 2 +- .../Implementation/Rgb/LinearRgbToCieXyzConverter.cs | 2 +- .../Implementation/Rgb/LinearRgbToRgbConverter.cs | 2 +- .../Implementation/Rgb/RgbToLinearRgbConverter.cs | 2 +- .../Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs | 5 +++-- 21 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs b/src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs index 19feeaa5d..9ef24b38a 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs @@ -8,15 +8,13 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The input color type. /// The result color type. - internal interface IColorConversion - where T: struct - where TResult: struct + internal interface IColorConversion { /// /// Performs the conversion from the input to an instance of the output type. /// /// The input color instance. /// The converted result - TResult Convert(in T input); + TResult Convert(T input); } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs index 15f50971a..0a5ae3627 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLabColor { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyz Convert(in CieLab input) + public CieXyz Convert(CieLab input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs index cdeda7f78..22308260c 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLabColor /// /// The target reference lab white point [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyzToCieLabConverter(in CieXyz labWhitePoint) + public CieXyzToCieLabConverter(CieXyz labWhitePoint) { this.LabWhitePoint = labWhitePoint; } @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLabColor /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieLab Convert(in CieXyz input) + public CieLab Convert(CieXyz input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs index fcc8687fb..35fae30e8 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchColor { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieLab Convert(in CieLch input) + public CieLab Convert(CieLch input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs index 134cc1a08..aa4614f9c 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchColor { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieLch Convert(in CieLab input) + public CieLch Convert(CieLab input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs index 2cbb953b8..fc6554a90 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.CompilerServices; +using SixLabors.ImageSharp.ColorSpaces; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvColorSapce { @@ -13,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvCol { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieLuv Convert(in CieLchuv input) + public CieLuv Convert(CieLchuv input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs index 427fb8f83..f0d7a80a2 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvCol { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieLchuv Convert(in CieLuv input) + public CieLchuv Convert(CieLuv input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs index 03eddab44..50e8335ed 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.CompilerServices; +using SixLabors.ImageSharp.ColorSpaces; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColorSapce { @@ -13,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColor { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyz Convert(in CieLuv input) + public CieXyz Convert(CieLuv input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs index 162f5b9c2..709d8d426 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColor /// /// The target reference luv white point [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyzToCieLuvConverter(in CieXyz luvWhitePoint) + public CieXyzToCieLuvConverter(CieXyz luvWhitePoint) { this.LuvWhitePoint = luvWhitePoint; } @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColor /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieLuv Convert(in CieXyz input) + public CieLuv Convert(CieXyz input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs index ef9672d6c..64fc84b1d 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs @@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieXyyColor { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyy Convert(in CieXyz input) + public CieXyy Convert(CieXyz input) { DebugGuard.NotNull(input, nameof(input)); @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieXyyColor /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyz Convert(in CieXyy input) + public CieXyz Convert(CieXyy input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs index be4be5e65..404bc811f 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CmykColorSa { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rgb Convert(in Cmyk input) + public Rgb Convert(Cmyk input) { float r = (1F - input.C) * (1F - input.K); float g = (1F - input.M) * (1F - input.K); @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CmykColorSa /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Cmyk Convert(in Rgb input) + public Cmyk Convert(Rgb input) { // To CMYK float c = 1F - input.R; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs index 597e571a8..3de3baddd 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs @@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HslColorSap { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rgb Convert(in Hsl input) + public Rgb Convert(Hsl input) { DebugGuard.NotNull(input, nameof(input)); @@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HslColorSap /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Hsl Convert(in Rgb input) + public Hsl Convert(Rgb input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsv/HsvAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsv/HsvAndRgbConverter.cs index 443252a63..6219533ca 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsv/HsvAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsv/HsvAndRgbConverter.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.CompilerServices; +using SixLabors.ImageSharp.ColorSpaces; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HsvColorSapce { @@ -14,7 +15,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HsvColorSap { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rgb Convert(in Hsv input) + public Rgb Convert(Hsv input) { DebugGuard.NotNull(input, nameof(input)); @@ -79,7 +80,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HsvColorSap /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Hsv Convert(in Rgb input) + public Hsv Convert(Rgb input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs index f13155120..7faf03c9a 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HunterLabCo /// /// The hunter Lab white point. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyzToHunterLabConverter(in CieXyz labWhitePoint) + public CieXyzToHunterLabConverter(CieXyz labWhitePoint) { this.HunterLabWhitePoint = labWhitePoint; } @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HunterLabCo /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public HunterLab Convert(in CieXyz input) + public HunterLab Convert(CieXyz input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs index d62eba30b..7e7c536e3 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HunterLabCo { /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyz Convert(in HunterLab input) + public CieXyz Convert(HunterLab input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs index 83a64d3d0..780c9e5a6 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs @@ -3,6 +3,7 @@ using System.Numerics; using System.Runtime.CompilerServices; +using SixLabors.ImageSharp.ColorSpaces; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.LmsColorSapce { @@ -60,7 +61,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.LmsColorSap /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Lms Convert(in CieXyz input) + public Lms Convert(CieXyz input) { DebugGuard.NotNull(input, nameof(input)); @@ -70,7 +71,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.LmsColorSap /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CieXyz Convert(in Lms input) + public CieXyz Convert(Lms input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/CieXyzToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/CieXyzToLinearRgbConverter.cs index 9c02aacaa..fd76a30fb 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/CieXyzToLinearRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/CieXyzToLinearRgbConverter.cs @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap public IRgbWorkingSpace TargetWorkingSpace { get; } /// - public LinearRgb Convert(in CieXyz input) + public LinearRgb Convert(CieXyz input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs index 23625fc02..bf36e252a 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap public IRgbWorkingSpace SourceWorkingSpace { get; } /// - public CieXyz Convert(in LinearRgb input) + public CieXyz Convert(LinearRgb input) { DebugGuard.NotNull(input, nameof(input)); DebugGuard.IsTrue(input.WorkingSpace.Equals(this.SourceWorkingSpace), nameof(input.WorkingSpace), "Input and source working spaces must be equal."); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs index e746b40c5..29ea0f314 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap internal class LinearRgbToRgbConverter : IColorConversion { /// - public Rgb Convert(in LinearRgb input) + public Rgb Convert(LinearRgb input) { DebugGuard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs index af2c39f0f..e40ecc192 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap internal class RgbToLinearRgbConverter : IColorConversion { /// - public LinearRgb Convert(in Rgb input) + public LinearRgb Convert(Rgb input) { Guard.NotNull(input, nameof(input)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs index 548fe6128..f552acbb4 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs @@ -4,6 +4,7 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; +using SixLabors.ImageSharp.ColorSpaces; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.YCbCrColorSapce { @@ -17,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.YCbCrColorS /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rgb Convert(in YCbCr input) + public Rgb Convert(YCbCr input) { DebugGuard.NotNull(input, nameof(input)); @@ -34,7 +35,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.YCbCrColorS /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public YCbCr Convert(in Rgb input) + public YCbCr Convert(Rgb input) { DebugGuard.NotNull(input, nameof(input)); From 2b4d2a735d8e5998dc34ff43b73ce9df9e1afb09 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 23 Mar 2018 09:49:59 -0700 Subject: [PATCH 30/34] Eliminate allocation in WriteGammaChunk --- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index e438975a4..a0e09e911 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -519,14 +519,10 @@ namespace SixLabors.ImageSharp.Formats.Png { if (this.writeGamma) { - int gammaValue = (int)(this.gamma * 100000F); + // 4-byte unsigned integer of gamma * 100,000. + uint gammaValue = (uint)(this.gamma * 100_000F); - byte[] size = BitConverter.GetBytes(gammaValue); - - this.chunkDataBuffer[0] = size[3]; - this.chunkDataBuffer[1] = size[2]; - this.chunkDataBuffer[2] = size[1]; - this.chunkDataBuffer[3] = size[0]; + BinaryPrimitives.WriteUInt32BigEndian(new Span(this.chunkDataBuffer, 0, 4), gammaValue); this.WriteChunk(stream, PngChunkTypes.Gamma, this.chunkDataBuffer, 0, 4); } From 997ca496790a93e5fe429895375446a9e6f4351b Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 23 Mar 2018 10:03:45 -0700 Subject: [PATCH 31/34] Remove unused FetchVector helper This doesn't account for alignment and we're getting a native constructor soon. https://github.com/dotnet/corefx/issues/24343 --- src/ImageSharp/Memory/SpanHelper.cs | 15 --------------- tests/ImageSharp.Tests/Memory/SpanUtilityTests.cs | 15 --------------- 2 files changed, 30 deletions(-) diff --git a/src/ImageSharp/Memory/SpanHelper.cs b/src/ImageSharp/Memory/SpanHelper.cs index 1cfad7222..4a6b7b7ce 100644 --- a/src/ImageSharp/Memory/SpanHelper.cs +++ b/src/ImageSharp/Memory/SpanHelper.cs @@ -2,9 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Numerics; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.Memory { @@ -13,19 +11,6 @@ namespace SixLabors.ImageSharp.Memory /// internal static class SpanHelper { - /// - /// Fetches a from the beginning of the span. - /// - /// The value type - /// The span to fetch the vector from - /// A reference to the beginning of the span - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ref Vector FetchVector(this Span span) - where T : struct - { - return ref Unsafe.As>(ref MemoryMarshal.GetReference(span)); - } - /// /// Copy 'count' number of elements of the same type from 'source' to 'dest' /// diff --git a/tests/ImageSharp.Tests/Memory/SpanUtilityTests.cs b/tests/ImageSharp.Tests/Memory/SpanUtilityTests.cs index 23bc29743..a813e0c1d 100644 --- a/tests/ImageSharp.Tests/Memory/SpanUtilityTests.cs +++ b/tests/ImageSharp.Tests/Memory/SpanUtilityTests.cs @@ -26,21 +26,6 @@ namespace SixLabors.ImageSharp.Tests.Memory Assert.True(Unsafe.AreSame(ref a, ref bb), "References are not same!"); } } - - [Fact] - public void FetchVector() - { - float[] stuff = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; - - var span = new Span(stuff); - - ref Vector v = ref span.FetchVector(); - - Assert.Equal(0, v[0]); - Assert.Equal(1, v[1]); - Assert.Equal(2, v[2]); - Assert.Equal(3, v[3]); - } public class SpanHelper_Copy { From 915b707fa4fe980cbb8160eb37f41f4102b0b19b Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 23 Mar 2018 10:23:08 -0700 Subject: [PATCH 32/34] Express readonly intent in Span parameters --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 33 ++++++++++---------- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 17 ++++------ 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 2c7396f3e..ffa387505 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -349,13 +349,12 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Converts a byte array to a new array where each value in the original array is represented by the specified number of bits. /// - /// The bytes to convert from. Cannot be null. + /// The bytes to convert from. Cannot be empty. /// The number of bytes per scanline /// The number of bits per value. - /// The resulting array. Is never null. - /// is null. + /// The resulting array. /// is less than or equals than zero. - private static Span ToArrayByBitsLength(Span source, int bytesPerScanline, int bits) + private static ReadOnlySpan ToArrayByBitsLength(ReadOnlySpan source, int bytesPerScanline, int bits) { Guard.MustBeGreaterThan(source.Length, 0, nameof(source)); Guard.MustBeGreaterThan(bits, 0, nameof(bits)); @@ -669,7 +668,7 @@ namespace SixLabors.ImageSharp.Formats.Png } Span rowSpan = image.GetPixelRowSpan(this.currentRow); - this.ProcessInterlacedDefilteredScanline(this.scanline.Array, rowSpan, Adam7FirstColumn[this.pass], Adam7ColumnIncrement[this.pass]); + this.ProcessInterlacedDefilteredScanline(this.scanline.Span, rowSpan, Adam7FirstColumn[this.pass], Adam7ColumnIncrement[this.pass]); this.SwapBuffers(); @@ -697,20 +696,20 @@ namespace SixLabors.ImageSharp.Formats.Png /// The pixel format. /// The de-filtered scanline /// The image - private void ProcessDefilteredScanline(Span defilteredScanline, ImageFrame pixels) + private void ProcessDefilteredScanline(ReadOnlySpan defilteredScanline, ImageFrame pixels) where TPixel : struct, IPixel { var color = default(TPixel); Span rowSpan = pixels.GetPixelRowSpan(this.currentRow); // Trim the first marker byte from the buffer - Span scanlineBuffer = defilteredScanline.Slice(1, defilteredScanline.Length - 1); + ReadOnlySpan scanlineBuffer = defilteredScanline.Slice(1, defilteredScanline.Length - 1); switch (this.pngColorType) { case PngColorType.Grayscale: int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1); - Span newScanline1 = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth); + ReadOnlySpan newScanline1 = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth); for (int x = 0; x < this.header.Width; x++) { @@ -794,10 +793,10 @@ namespace SixLabors.ImageSharp.Formats.Png } else { - Span rgb24Span = scanlineBuffer.NonPortableCast(); + ReadOnlySpan rgb24Span = scanlineBuffer.NonPortableCast(); for (int x = 0; x < this.header.Width; x++) { - ref Rgb24 rgb24 = ref rgb24Span[x]; + ref readonly Rgb24 rgb24 = ref rgb24Span[x]; var rgba32 = default(Rgba32); rgba32.Rgb = rgb24; rgba32.A = (byte)(rgb24.Equals(this.rgb24Trans) ? 0 : 255); @@ -838,7 +837,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The target buffer /// The target length [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void From16BitTo8Bit(Span source, Span target, int length) + private void From16BitTo8Bit(ReadOnlySpan source, Span target, int length) { for (int i = 0, j = 0; i < length; i++, j += 2) { @@ -879,10 +878,10 @@ namespace SixLabors.ImageSharp.Formats.Png /// The type of pixel we are expanding to /// The scanline /// Thecurrent output image row - private void ProcessScanlineFromPalette(Span defilteredScanline, Span row) + private void ProcessScanlineFromPalette(ReadOnlySpan defilteredScanline, Span row) where TPixel : struct, IPixel { - Span newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth); + ReadOnlySpan newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth); byte[] pal = this.palette; var color = default(TPixel); @@ -929,19 +928,19 @@ namespace SixLabors.ImageSharp.Formats.Png /// The current image row. /// The column start index. Always 0 for none interlaced images. /// The column increment. Always 1 for none interlaced images. - private void ProcessInterlacedDefilteredScanline(byte[] defilteredScanline, Span rowSpan, int pixelOffset = 0, int increment = 1) + private void ProcessInterlacedDefilteredScanline(ReadOnlySpan defilteredScanline, Span rowSpan, int pixelOffset = 0, int increment = 1) where TPixel : struct, IPixel { var color = default(TPixel); // Trim the first marker byte from the buffer - var scanlineBuffer = new Span(defilteredScanline, 1, defilteredScanline.Length - 1); + ReadOnlySpan scanlineBuffer = defilteredScanline.Slice(1, defilteredScanline.Length - 1); switch (this.pngColorType) { case PngColorType.Grayscale: int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1); - Span newScanline1 = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth); + ReadOnlySpan newScanline1 = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth); for (int x = pixelOffset, o = 0; x < this.header.Width; x += increment, o++) { @@ -974,7 +973,7 @@ namespace SixLabors.ImageSharp.Formats.Png case PngColorType.Palette: - Span newScanline = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth); + ReadOnlySpan newScanline = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth); var rgba = default(Rgba32); if (this.paletteAlpha != null && this.paletteAlpha.Length > 0) diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index a0e09e911..0cded1d80 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -255,7 +255,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// The pixel format. /// The image row span. - private void CollectGrayscaleBytes(Span rowSpan) + private void CollectGrayscaleBytes(ReadOnlySpan rowSpan) where TPixel : struct, IPixel { byte[] rawScanlineArray = this.rawScanline.Array; @@ -290,7 +290,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// The pixel format. /// The row span. - private void CollecTPixelBytes(Span rowSpan) + private void CollecTPixelBytes(ReadOnlySpan rowSpan) where TPixel : struct, IPixel { if (this.bytesPerPixel == 4) @@ -311,7 +311,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The row span. /// The row. /// The - private IManagedByteBuffer EncodePixelRow(Span rowSpan, int row) + private IManagedByteBuffer EncodePixelRow(ReadOnlySpan rowSpan, int row) where TPixel : struct, IPixel { switch (this.pngColorType) @@ -554,15 +554,14 @@ namespace SixLabors.ImageSharp.Formats.Png byte[] buffer; int bufferLength; - MemoryStream memoryStream = null; - try + + using (var memoryStream = new MemoryStream()) { - memoryStream = new MemoryStream(); using (var deflateStream = new ZlibDeflateStream(memoryStream, this.compressionLevel)) { for (int y = 0; y < this.height; y++) { - IManagedByteBuffer r = this.EncodePixelRow(pixels.GetPixelRowSpan(y), y); + IManagedByteBuffer r = this.EncodePixelRow(pixels.GetPixelRowSpan(y).AsReadOnlySpan(), y); deflateStream.Write(r.Array, 0, resultLength); IManagedByteBuffer temp = this.rawScanline; @@ -574,10 +573,6 @@ namespace SixLabors.ImageSharp.Formats.Png buffer = memoryStream.ToArray(); bufferLength = buffer.Length; } - finally - { - memoryStream?.Dispose(); - } // Store the chunks in repeated 64k blocks. // This reduces the memory load for decoding the image for many decoders. From 01448179ebb967429f46a6974e9678b85bb3ca96 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 23 Mar 2018 10:33:06 -0700 Subject: [PATCH 33/34] Benchmark removed SpanUtility logic inplace --- .../General/Vectorization/VectorFetching.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/VectorFetching.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/VectorFetching.cs index 147f66f8f..aa7d926a4 100644 --- a/tests/ImageSharp.Benchmarks/General/Vectorization/VectorFetching.cs +++ b/tests/ImageSharp.Benchmarks/General/Vectorization/VectorFetching.cs @@ -3,7 +3,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization using System; using System.Numerics; using System.Runtime.CompilerServices; - + using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.Memory; @@ -90,13 +90,13 @@ namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization } [Benchmark] - public void FetchWithSpanUtility() + public void FetchWithUnsafeCastFromReference() { - Vector v = new Vector(this.testValue); + var v = new Vector(this.testValue); - Span span = new Span(this.data); + var span = new Span(this.data); - ref Vector start = ref span.FetchVector(); + ref Vector start = ref Unsafe.As>(ref MemoryMarshal.GetReference(span)); int n = this.InputSize / Vector.Count; From c512b9d4bc0bf3d36f1e72cc3110390590e8530b Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 23 Mar 2018 10:36:33 -0700 Subject: [PATCH 34/34] Remove note The explict cast doesn't work as expected --- src/ImageSharp/Image.LoadPixelData.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ImageSharp/Image.LoadPixelData.cs b/src/ImageSharp/Image.LoadPixelData.cs index 3d416b70e..f90f4c895 100644 --- a/src/ImageSharp/Image.LoadPixelData.cs +++ b/src/ImageSharp/Image.LoadPixelData.cs @@ -98,8 +98,6 @@ namespace SixLabors.ImageSharp public static Image LoadPixelData(Configuration config, TPixel[] data, int width, int height) where TPixel : struct, IPixel { - // There's an implict cast to Span from Array - // Should we remove this overload and expose Span ? return LoadPixelData(config, new Span(data), width, height); }