From a8bd6580a24df1432366ebdb23e1bb4f98ecf462 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 19 Jun 2018 23:40:51 +1000 Subject: [PATCH] Use SD, Better conversion and cleanup SD Bridge. --- src/ImageSharp/PixelFormats/Rgb48.cs | 8 +++- src/ImageSharp/PixelFormats/Rgba64.cs | 8 +++- .../Formats/Png/PngDecoderTests.cs | 8 ++-- .../ImageSharp.Tests/ImageSharp.Tests.csproj | 8 ++-- .../ReferenceCodecs/SystemDrawingBridge.cs | 41 +++++++++++-------- .../SystemDrawingReferenceDecoder.cs | 5 ++- .../SystemDrawingReferenceEncoder.cs | 2 +- .../TestUtilities/TestEnvironment.Formats.cs | 8 +++- .../TestUtilities/TestImageExtensions.cs | 6 +-- .../Tests/ReferenceCodecTests.cs | 28 +++++++------ .../Tests/TestEnvironmentTests.cs | 8 ++-- 11 files changed, 78 insertions(+), 52 deletions(-) diff --git a/src/ImageSharp/PixelFormats/Rgb48.cs b/src/ImageSharp/PixelFormats/Rgb48.cs index e4c1345d2..834006011 100644 --- a/src/ImageSharp/PixelFormats/Rgb48.cs +++ b/src/ImageSharp/PixelFormats/Rgb48.cs @@ -160,7 +160,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + public void PackFromRgba64(Rgba64 source) => this = source.Rgb; /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -225,7 +225,11 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + public void ToRgba64(ref Rgba64 dest) + { + dest.Rgb = this; + dest.A = ushort.MaxValue; + } /// public override bool Equals(object obj) diff --git a/src/ImageSharp/PixelFormats/Rgba64.cs b/src/ImageSharp/PixelFormats/Rgba64.cs index cdc3f38b2..ad7d2dc9d 100644 --- a/src/ImageSharp/PixelFormats/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/Rgba64.cs @@ -232,11 +232,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4()); + public void PackFromRgb48(Rgb48 source) + { + this.Rgb = source; + this.A = ushort.MaxValue; + } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4()); + public void ToRgb48(ref Rgb48 dest) => dest = this.Rgb; /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index 6b24e127c..c3c2cf23e 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -20,8 +20,8 @@ namespace SixLabors.ImageSharp.Tests { private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32 | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32; - // This should be exact but for some reason it fails in some build environments. - private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.0001F, 26); + // TODO: Cannot use exact comparer since System.Drawing doesn't preserve more than 32bits. + private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.1302F, 2134); // Contains the png marker, IHDR and pHYs chunks of a 1x1 pixel 32bit png 1 a single black pixel. private static readonly byte[] raw1x1PngIHDRAndpHYs = @@ -173,7 +173,7 @@ namespace SixLabors.ImageSharp.Tests if (!SkipVerification(provider)) { - image.VerifyEncoder(provider, "png", null, encoder, customComparer: ImageComparer.Exact); + image.VerifyEncoder(provider, "png", null, encoder, customComparer: ValidatorComparer); } } } @@ -189,7 +189,7 @@ namespace SixLabors.ImageSharp.Tests if (!SkipVerification(provider)) { - image.VerifyEncoder(provider, "png", null, encoder, customComparer: ImageComparer.Exact); + image.VerifyEncoder(provider, "png", null, encoder, customComparer: ValidatorComparer); } } } diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 139df3972..18db6db9c 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -22,6 +22,11 @@ true + + + + + @@ -49,7 +54,4 @@ PreserveNewest - - - diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs index 1dfb3ba46..c281b50c3 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Drawing; using System.Drawing.Imaging; using SixLabors.ImageSharp.Advanced; @@ -10,26 +11,34 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs { + /// + /// Provides methods to convert to/from System.Drawing bitmaps. + /// public static class SystemDrawingBridge { - internal static unsafe Image FromFromArgb32SystemDrawingBitmap(System.Drawing.Bitmap bmp) + /// + /// Returns an image from the given System.Drawing bitmap. + /// + /// The input bitmap. + /// Thrown if the image pixel format is not of type + internal static unsafe Image From32bppArgbSystemDrawingBitmap(Bitmap bmp) where TPixel : struct, IPixel { int w = bmp.Width; int h = bmp.Height; - var fullRect = new System.Drawing.Rectangle(0, 0, w, h); + var fullRect = new Rectangle(0, 0, w, h); if (bmp.PixelFormat != PixelFormat.Format32bppArgb) { - throw new ArgumentException($"FromFromArgb32SystemDrawingBitmap(): pixel format should be Argb32!", nameof(bmp)); + throw new ArgumentException($"{nameof(From32bppArgbSystemDrawingBitmap)} : pixel format should be {PixelFormat.Format32bppArgb}!", nameof(bmp)); } BitmapData data = bmp.LockBits(fullRect, ImageLockMode.ReadWrite, bmp.PixelFormat); byte* sourcePtrBase = (byte*)data.Scan0; long sourceRowByteCount = data.Stride; - long destRowByteCount = w * sizeof(Argb32); + long destRowByteCount = w * sizeof(Bgra32); var image = new Image(w, h); @@ -41,7 +50,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs { Span row = image.Frames.RootFrame.GetPixelRowSpan(y); - byte* sourcePtr = sourcePtrBase + data.Stride * y; + byte* sourcePtr = sourcePtrBase + (data.Stride * y); Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); PixelOperations.Instance.PackFromBgra32(workBuffer.GetSpan(), row, row.Length); @@ -53,19 +62,21 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs } /// - /// TODO: Doesn not work yet! + /// Returns an image from the given System.Drawing bitmap. /// - internal static unsafe Image FromFromRgb24SystemDrawingBitmap(System.Drawing.Bitmap bmp) + /// The input bitmap. + /// Thrown if the image pixel format is not of type + internal static unsafe Image From24bppRgbSystemDrawingBitmap(Bitmap bmp) where TPixel : struct, IPixel { int w = bmp.Width; int h = bmp.Height; - var fullRect = new System.Drawing.Rectangle(0, 0, w, h); + var fullRect = new Rectangle(0, 0, w, h); if (bmp.PixelFormat != PixelFormat.Format24bppRgb) { - throw new ArgumentException($"FromFromArgb32SystemDrawingBitmap(): pixel format should be Rgb24!", nameof(bmp)); + throw new ArgumentException($"{nameof(From24bppRgbSystemDrawingBitmap)}: pixel format should be {PixelFormat.Format24bppRgb}!", nameof(bmp)); } BitmapData data = bmp.LockBits(fullRect, ImageLockMode.ReadWrite, bmp.PixelFormat); @@ -84,12 +95,10 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs { Span row = image.Frames.RootFrame.GetPixelRowSpan(y); - byte* sourcePtr = sourcePtrBase + data.Stride * y; + byte* sourcePtr = sourcePtrBase + (data.Stride * y); Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); PixelOperations.Instance.PackFromBgr24(workBuffer.GetSpan(), row, row.Length); - - // FromRgb24(workBuffer.GetSpan(), row); } } } @@ -97,14 +106,14 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs return image; } - internal static unsafe System.Drawing.Bitmap ToSystemDrawingBitmap(Image image) + internal static unsafe Bitmap To32bppArgbSystemDrawingBitmap(Image image) where TPixel : struct, IPixel { int w = image.Width; int h = image.Height; - var resultBitmap = new System.Drawing.Bitmap(w, h, PixelFormat.Format32bppArgb); - var fullRect = new System.Drawing.Rectangle(0, 0, w, h); + var resultBitmap = new Bitmap(w, h, PixelFormat.Format32bppArgb); + var fullRect = new Rectangle(0, 0, w, h); BitmapData data = resultBitmap.LockBits(fullRect, ImageLockMode.ReadWrite, resultBitmap.PixelFormat); byte* destPtrBase = (byte*)data.Scan0; @@ -120,7 +129,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs { Span row = image.Frames.RootFrame.GetPixelRowSpan(y); PixelOperations.Instance.ToBgra32(row, workBuffer.GetSpan(), row.Length); - byte* destPtr = destPtrBase + data.Stride * y; + byte* destPtr = destPtrBase + (data.Stride * y); Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); } diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs index b1e53cb6a..427a56542 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs { if (sourceBitmap.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb) { - return SystemDrawingBridge.FromFromArgb32SystemDrawingBitmap(sourceBitmap); + return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap(sourceBitmap); } using (var convertedBitmap = new System.Drawing.Bitmap( @@ -37,7 +37,8 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs g.DrawImage(sourceBitmap, 0, 0, sourceBitmap.Width, sourceBitmap.Height); } - return SystemDrawingBridge.FromFromArgb32SystemDrawingBitmap(convertedBitmap); + + return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap(convertedBitmap); } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceEncoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceEncoder.cs index ca6f32f5b..912333695 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceEncoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceEncoder.cs @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs public void Encode(Image image, Stream stream) where TPixel : struct, IPixel { - using (System.Drawing.Bitmap sdBitmap = SystemDrawingBridge.ToSystemDrawingBitmap(image)) + using (System.Drawing.Bitmap sdBitmap = SystemDrawingBridge.To32bppArgbSystemDrawingBitmap(image)) { sdBitmap.Save(stream, this.imageFormat); } diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs index f62237936..566c22342 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs @@ -60,10 +60,14 @@ namespace SixLabors.ImageSharp.Tests if (!IsLinux) { - // System.Drawing on Windows can decode 48bit and 64bit pngs but + // TODO: System.Drawing on Windows can decode 48bit and 64bit pngs but // it doesn't preserve the accuracy we require for comparison. // This makes CompareToOriginal method non-useful. - configuration.Configure(new PngConfigurationModule()); + configuration.ConfigureCodecs( + ImageFormats.Png, + SystemDrawingReferenceDecoder.Instance, + SystemDrawingReferenceEncoder.Png, + new PngImageFormatDetector()); configuration.ConfigureCodecs( ImageFormats.Bmp, diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index e135c5d31..016ae7ad2 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -38,15 +38,15 @@ namespace SixLabors.ImageSharp.Tests { Span pixelSpan = frame.GetPixelSpan(); - PixelOperations.Instance.ToVector4(pixelSpan, tempSpan, pixelSpan.Length); + PixelOperations.Instance.ToScaledVector4(pixelSpan, tempSpan, pixelSpan.Length); for (int i = 0; i < tempSpan.Length; i++) { ref Vector4 v = ref tempSpan[i]; - v.W = 1.0f; + v.W = 1F; } - PixelOperations.Instance.PackFromVector4(tempSpan, pixelSpan, pixelSpan.Length); + PixelOperations.Instance.PackFromScaledVector4(tempSpan, pixelSpan, pixelSpan.Length); } } }); diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceCodecTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceCodecTests.cs index 520b8d93f..3ad595b7e 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceCodecTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceCodecTests.cs @@ -1,3 +1,4 @@ +using System.IO; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; @@ -20,12 +21,12 @@ namespace SixLabors.ImageSharp.Tests [Theory] [WithTestPatternImages(20, 20, PixelTypes.Rgba32 | PixelTypes.Bgra32)] - public void ToSystemDrawingBitmap(TestImageProvider provider) + public void To32bppArgbSystemDrawingBitmap(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { - using (System.Drawing.Bitmap sdBitmap = SystemDrawingBridge.ToSystemDrawingBitmap(image)) + using (System.Drawing.Bitmap sdBitmap = SystemDrawingBridge.To32bppArgbSystemDrawingBitmap(image)) { string fileName = provider.Utility.GetTestOutputFileName("png"); sdBitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Png); @@ -35,14 +36,14 @@ namespace SixLabors.ImageSharp.Tests [Theory] [WithBlankImages(1, 1, PixelTypes.Rgba32 | PixelTypes.Bgra32)] - public void FromFromArgb32SystemDrawingBitmap(TestImageProvider dummyProvider) + public void From32bppArgbSystemDrawingBitmap(TestImageProvider dummyProvider) where TPixel : struct, IPixel { string path = TestFile.GetInputFileFullPath(TestImages.Png.Splash); using (var sdBitmap = new System.Drawing.Bitmap(path)) { - using (Image image = SystemDrawingBridge.FromFromArgb32SystemDrawingBitmap(sdBitmap)) + using (Image image = SystemDrawingBridge.From32bppArgbSystemDrawingBitmap(sdBitmap)) { image.DebugSave(dummyProvider); } @@ -66,17 +67,20 @@ namespace SixLabors.ImageSharp.Tests [Theory] [WithTestPatternImages(100, 100, PixelTypes.Rgba32)] - public void FromFromArgb32SystemDrawingBitmap2(TestImageProvider provider) + public void From32bppArgbSystemDrawingBitmap2(TestImageProvider provider) where TPixel : struct, IPixel { - if (TestEnvironment.IsLinux) return; + if (TestEnvironment.IsLinux) + { + return; + } string path = SavePng(provider, PngColorType.RgbWithAlpha); using (var sdBitmap = new System.Drawing.Bitmap(path)) { using (Image original = provider.GetImage()) - using (Image resaved = SystemDrawingBridge.FromFromArgb32SystemDrawingBitmap(sdBitmap)) + using (Image resaved = SystemDrawingBridge.From32bppArgbSystemDrawingBitmap(sdBitmap)) { ImageComparer comparer = ImageComparer.Exact; comparer.VerifySimilarity(original, resaved); @@ -85,20 +89,18 @@ namespace SixLabors.ImageSharp.Tests } [Theory] - [WithTestPatternImages(100, 100, PixelTypes.Rgba32)] - public void FromFromRgb24SystemDrawingBitmap2(TestImageProvider provider) + [WithTestPatternImages(100, 100, PixelTypes.Rgb24)] + public void From24bppRgbSystemDrawingBitmap(TestImageProvider provider) where TPixel : struct, IPixel { string path = SavePng(provider, PngColorType.Rgb); using (Image original = provider.GetImage()) { - original.Mutate(c => c.MakeOpaque()); using (var sdBitmap = new System.Drawing.Bitmap(path)) { - using (Image resaved = SystemDrawingBridge.FromFromRgb24SystemDrawingBitmap(sdBitmap)) + using (Image resaved = SystemDrawingBridge.From24bppRgbSystemDrawingBitmap(sdBitmap)) { - resaved.Mutate(c => c.MakeOpaque()); ImageComparer comparer = ImageComparer.Exact; comparer.VerifySimilarity(original, resaved); } @@ -112,7 +114,7 @@ namespace SixLabors.ImageSharp.Tests where TPixel : struct, IPixel { string path = TestFile.GetInputFileFullPath(TestImages.Png.Splash); - using (Image image = Image.Load(path, SystemDrawingReferenceDecoder.Instance)) + using (var image = Image.Load(path, SystemDrawingReferenceDecoder.Instance)) { image.DebugSave(dummyProvider); } diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs index 40338e859..d2ef63a11 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs @@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.Tests } [Theory] - [InlineData("lol/foo.png", typeof(PngEncoder))] + [InlineData("lol/foo.png", typeof(SystemDrawingReferenceEncoder))] [InlineData("lol/Rofl.bmp", typeof(SystemDrawingReferenceEncoder))] [InlineData("lol/Baz.JPG", typeof(JpegEncoder))] [InlineData("lol/Baz.gif", typeof(GifEncoder))] @@ -73,11 +73,11 @@ namespace SixLabors.ImageSharp.Tests } [Theory] - [InlineData("lol/foo.png", typeof(PngDecoder))] + [InlineData("lol/foo.png", typeof(SystemDrawingReferenceDecoder))] [InlineData("lol/Rofl.bmp", typeof(SystemDrawingReferenceDecoder))] [InlineData("lol/Baz.JPG", typeof(JpegDecoder))] [InlineData("lol/Baz.gif", typeof(GifDecoder))] - public void GetReferenceDecoder_ReturnsCorrectEncoders_Windows(string fileName, Type expectedDecoderType) + public void GetReferenceDecoder_ReturnsCorrectDecoders_Windows(string fileName, Type expectedDecoderType) { if (TestEnvironment.IsLinux) return; @@ -103,7 +103,7 @@ namespace SixLabors.ImageSharp.Tests [InlineData("lol/Rofl.bmp", typeof(BmpDecoder))] [InlineData("lol/Baz.JPG", typeof(JpegDecoder))] [InlineData("lol/Baz.gif", typeof(GifDecoder))] - public void GetReferenceDecoder_ReturnsCorrectEncoders_Linux(string fileName, Type expectedDecoderType) + public void GetReferenceDecoder_ReturnsCorrectDecoders_Linux(string fileName, Type expectedDecoderType) { if (!TestEnvironment.IsLinux) return;