From c3872f9ff9d8e86759932473016de28ebe142a11 Mon Sep 17 00:00:00 2001 From: Frederik Carlier Date: Wed, 14 Aug 2019 20:11:21 +0200 Subject: [PATCH] Consolidate the Image class, fix bug (dotnet/corefx#40181) * Add new values for Encoder, EncoderParameterValueType * Support encoder parameters of type ValueTypePointer * Fix an overflow error when reading EncoderParameters * Add unit tests * Consolidate the Image class Share the following methods across Windows & Unix: - FromFile - GetEncoderParameterList - GetPixelFormatSize - IsAlphaPixelFormat * Fix P/Invoke declaration * Fix compliation on NetFX * Skip test on NetFX * Fix typo * Always skip GetEncoderParameterList_ReturnsExpected on netFX * Remove new API * Revert changes which require an API change * Suppress failing test * Image: Consolidate CreateImageObject Metafile: Consolidate initialization from native handle * Throw SkipTestException instead of silently skipping the test * Enable some on Unix which rely on consolidated code * Add missing using statement * Get SkipTestException right Commit migrated from https://github.com/dotnet/corefx/commit/31a04af352c0046b21b2ccdf5b409203a43fae1f --- .../ref/System.Drawing.Common.cs | 2 +- .../src/System/Drawing/GdiplusNative.Unix.cs | 12 -- .../src/System/Drawing/GdiplusNative.Windows.cs | 12 -- .../src/System/Drawing/GdiplusNative.cs | 12 ++ .../src/System/Drawing/Image.Unix.cs | 129 +-------------------- .../src/System/Drawing/Image.Windows.cs | 96 --------------- .../src/System/Drawing/Image.cs | 96 +++++++++++++++ .../System/Drawing/Imaging/EncoderParameters.cs | 2 +- .../src/System/Drawing/Imaging/Metafile.Unix.cs | 5 - .../src/System/Drawing/Imaging/Metafile.Windows.cs | 14 --- .../src/System/Drawing/Imaging/Metafile.cs | 5 + .../System.Drawing.Common/tests/ImageTests.cs | 84 +++++++++++++- 12 files changed, 197 insertions(+), 272 deletions(-) diff --git a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.cs b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.cs index 1d20e74..2cf7f5d 100644 --- a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.cs +++ b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.cs @@ -2151,7 +2151,7 @@ namespace System.Drawing.Imaging ValueTypeRational = 5, ValueTypeLongRange = 6, ValueTypeUndefined = 7, - ValueTypeRationalRange = 8, + ValueTypeRationalRange = 8 } public enum EncoderValue { diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Unix.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Unix.cs index da37356..c3d9de2 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Unix.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Unix.cs @@ -140,15 +140,9 @@ namespace System.Drawing [DllImport(LibraryName, ExactSpelling = true)] internal static extern int GdipCreateFromHWND(IntPtr hwnd, out IntPtr graphics); - [DllImport(LibraryName, ExactSpelling = true, CharSet = CharSet.Unicode)] - internal static extern int GdipLoadImageFromFile(string filename, out IntPtr image); - [DllImport(LibraryName, ExactSpelling = true)] internal static extern int GdipCloneImage(IntPtr image, out IntPtr imageclone); - [DllImport(LibraryName, ExactSpelling = true, CharSet = CharSet.Unicode)] - internal static extern int GdipLoadImageFromFileICM(string filename, out IntPtr image); - [DllImport(LibraryName, ExactSpelling = true)] internal static extern int GdipGetImagePaletteSize(IntPtr image, out int size); @@ -174,12 +168,6 @@ namespace System.Drawing internal static extern int GdipGetImageBounds(IntPtr image, out RectangleF source, ref GraphicsUnit unit); [DllImport(LibraryName, ExactSpelling = true)] - internal static extern int GdipGetEncoderParameterListSize(IntPtr image, ref Guid encoder, out uint size); - - [DllImport(LibraryName, ExactSpelling = true)] - internal static extern int GdipGetEncoderParameterList(IntPtr image, ref Guid encoder, uint size, IntPtr buffer); - - [DllImport(LibraryName, ExactSpelling = true)] internal static extern int GdipGetPropertyItemSize(IntPtr image, int propertyID, out int propertySize); [DllImport(LibraryName, ExactSpelling = true)] diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Windows.cs index 545759d..db9ef1a 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Windows.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Windows.cs @@ -215,15 +215,9 @@ namespace System.Drawing [DllImport(LibraryName, ExactSpelling = true)] internal static extern int GdipLoadImageFromStream(Interop.Ole32.IStream stream, out IntPtr image); - [DllImport(LibraryName, ExactSpelling = true, CharSet = CharSet.Unicode)] - internal static extern int GdipLoadImageFromFile(string filename, out IntPtr image); - [DllImport(LibraryName, ExactSpelling = true)] internal static extern int GdipLoadImageFromStreamICM(Interop.Ole32.IStream stream, out IntPtr image); - [DllImport(LibraryName, ExactSpelling = true, CharSet = CharSet.Unicode)] - internal static extern int GdipLoadImageFromFileICM(string filename, out IntPtr image); - [DllImport(LibraryName, ExactSpelling = true)] internal static extern int GdipCloneImage(HandleRef image, out IntPtr cloneimage); @@ -249,12 +243,6 @@ namespace System.Drawing internal static extern int GdipGetImageThumbnail(HandleRef image, int thumbWidth, int thumbHeight, out IntPtr thumbImage, Image.GetThumbnailImageAbort callback, IntPtr callbackdata); [DllImport(LibraryName, ExactSpelling = true)] - internal static extern int GdipGetEncoderParameterListSize(HandleRef image, ref Guid clsid, out int size); - - [DllImport(LibraryName, ExactSpelling = true)] - internal static extern int GdipGetEncoderParameterList(HandleRef image, ref Guid clsid, int size, IntPtr buffer); - - [DllImport(LibraryName, ExactSpelling = true)] internal static extern int GdipGetImagePalette(HandleRef image, IntPtr palette, int size); [DllImport(LibraryName, ExactSpelling = true)] diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs index 53b762c..281d1f0 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs @@ -1344,6 +1344,18 @@ namespace System.Drawing [DllImport(LibraryName, ExactSpelling = true)] internal static extern int GdipTransformPointsI(HandleRef graphics, int destSpace, int srcSpace, Point* points, int count); + + [DllImport(LibraryName, ExactSpelling = true, CharSet = CharSet.Unicode)] + internal static extern int GdipLoadImageFromFileICM(string filename, out IntPtr image); + + [DllImport(LibraryName, ExactSpelling = true, CharSet = CharSet.Unicode)] + internal static extern int GdipLoadImageFromFile(string filename, out IntPtr image); + + [DllImport(LibraryName, ExactSpelling = true)] + internal static extern int GdipGetEncoderParameterListSize(HandleRef image, ref Guid encoder, out int size); + + [DllImport(LibraryName, ExactSpelling = true)] + internal static extern int GdipGetEncoderParameterList(HandleRef image, ref Guid encoder, int size, IntPtr buffer); } [StructLayout(LayoutKind.Sequential)] diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Unix.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Unix.cs index 021ec33..1604a34 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Unix.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Unix.cs @@ -54,23 +54,6 @@ namespace System.Drawing // public methods // static - public static Image FromFile(string filename, bool useEmbeddedColorManagement) - { - IntPtr imagePtr; - int st; - - if (!File.Exists(filename)) - throw new FileNotFoundException(filename); - - if (useEmbeddedColorManagement) - st = Gdip.GdipLoadImageFromFileICM(filename, out imagePtr); - else - st = Gdip.GdipLoadImageFromFile(filename, out imagePtr); - Gdip.CheckStatus(st); - - return CreateFromHandle(imagePtr); - } - // See http://support.microsoft.com/default.aspx?scid=kb;en-us;831419 for performance discussion public static Image FromStream(Stream stream, bool useEmbeddedColorManagement, bool validateImageData) { @@ -82,95 +65,10 @@ namespace System.Drawing if (stream == null) throw new ArgumentNullException(nameof(stream)); - Image img = CreateFromHandle(InitializeFromStream(stream)); + Image img = CreateImageObject(InitializeFromStream(stream)); return img; } - internal static Image CreateImageObject(IntPtr nativeImage) - { - return CreateFromHandle(nativeImage); - } - - internal static Image CreateFromHandle(IntPtr handle) - { - Gdip.CheckStatus(Gdip.GdipGetImageType(handle, out int type)); - switch ((ImageType)type) - { - case ImageType.Bitmap: - return new Bitmap(handle); - case ImageType.Metafile: - return new Metafile(handle); - default: - throw new NotSupportedException("Unknown image type."); - } - } - - public static int GetPixelFormatSize(PixelFormat pixfmt) - { - int result = 0; - switch (pixfmt) - { - case PixelFormat.Format16bppArgb1555: - case PixelFormat.Format16bppGrayScale: - case PixelFormat.Format16bppRgb555: - case PixelFormat.Format16bppRgb565: - result = 16; - break; - case PixelFormat.Format1bppIndexed: - result = 1; - break; - case PixelFormat.Format24bppRgb: - result = 24; - break; - case PixelFormat.Format32bppArgb: - case PixelFormat.Format32bppPArgb: - case PixelFormat.Format32bppRgb: - result = 32; - break; - case PixelFormat.Format48bppRgb: - result = 48; - break; - case PixelFormat.Format4bppIndexed: - result = 4; - break; - case PixelFormat.Format64bppArgb: - case PixelFormat.Format64bppPArgb: - result = 64; - break; - case PixelFormat.Format8bppIndexed: - result = 8; - break; - } - return result; - } - - public static bool IsAlphaPixelFormat(PixelFormat pixfmt) - { - bool result = false; - switch (pixfmt) - { - case PixelFormat.Format16bppArgb1555: - case PixelFormat.Format32bppArgb: - case PixelFormat.Format32bppPArgb: - case PixelFormat.Format64bppArgb: - case PixelFormat.Format64bppPArgb: - result = true; - break; - case PixelFormat.Format16bppGrayScale: - case PixelFormat.Format16bppRgb555: - case PixelFormat.Format16bppRgb565: - case PixelFormat.Format1bppIndexed: - case PixelFormat.Format24bppRgb: - case PixelFormat.Format32bppRgb: - case PixelFormat.Format48bppRgb: - case PixelFormat.Format4bppIndexed: - case PixelFormat.Format8bppIndexed: - result = false; - break; - } - return result; - } - private protected static IntPtr InitializeFromStream(Stream stream) { if (stream == null) @@ -203,31 +101,6 @@ namespace System.Drawing return source; } - public EncoderParameters GetEncoderParameterList(Guid encoder) - { - int status; - uint sz; - - status = Gdip.GdipGetEncoderParameterListSize(nativeImage, ref encoder, out sz); - Gdip.CheckStatus(status); - - IntPtr rawEPList = Marshal.AllocHGlobal((int)sz); - EncoderParameters eps; - - try - { - status = Gdip.GdipGetEncoderParameterList(nativeImage, ref encoder, sz, rawEPList); - eps = EncoderParameters.ConvertFromMemory(rawEPList); - Gdip.CheckStatus(status); - } - finally - { - Marshal.FreeHGlobal(rawEPList); - } - - return eps; - } - public PropertyItem GetPropertyItem(int propid) { int propSize; diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Windows.cs index 4780b00..b504a7d 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Windows.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Windows.cs @@ -19,38 +19,6 @@ namespace System.Drawing private string allocationSite = Graphics.GetAllocationStack(); #endif - public static Image FromFile(string filename, bool useEmbeddedColorManagement) - { - if (!File.Exists(filename)) - { - // Throw a more specific exception for invalid paths that are null or empty, - // contain invalid characters or are too long. - filename = Path.GetFullPath(filename); - throw new FileNotFoundException(filename); - } - - // GDI+ will read this file multiple times. Get the fully qualified path - // so if our app changes default directory we won't get an error - filename = Path.GetFullPath(filename); - - IntPtr image = IntPtr.Zero; - - if (useEmbeddedColorManagement) - { - Gdip.CheckStatus(Gdip.GdipLoadImageFromFileICM(filename, out image)); - } - else - { - Gdip.CheckStatus(Gdip.GdipLoadImageFromFile(filename, out image)); - } - - ValidateImage(image); - - Image img = CreateImageObject(image); - EnsureSave(img, filename, null); - return img; - } - public static Image FromStream(Stream stream, bool useEmbeddedColorManagement, bool validateImageData) { if (stream == null) @@ -141,54 +109,6 @@ namespace System.Drawing } } - internal static Image CreateImageObject(IntPtr nativeImage) - { - Gdip.CheckStatus(Gdip.GdipGetImageType(nativeImage, out int type)); - switch ((ImageType)type) - { - case ImageType.Bitmap: - return new Bitmap(nativeImage); - case ImageType.Metafile: - return Metafile.FromGDIplus(nativeImage); - default: - throw new ArgumentException(SR.InvalidImage); - } - } - - /// - /// Returns information about the codecs used for this . - /// - public EncoderParameters GetEncoderParameterList(Guid encoder) - { - EncoderParameters p; - - Gdip.CheckStatus(Gdip.GdipGetEncoderParameterListSize( - new HandleRef(this, nativeImage), - ref encoder, - out int size)); - - if (size <= 0) - return null; - - IntPtr buffer = Marshal.AllocHGlobal(size); - try - { - Gdip.CheckStatus(Gdip.GdipGetEncoderParameterList( - new HandleRef(this, nativeImage), - ref encoder, - size, - buffer)); - - p = EncoderParameters.ConvertFromMemory(buffer); - } - finally - { - Marshal.FreeHGlobal(buffer); - } - - return p; - } - /// /// Saves this to the specified file in the specified format. /// @@ -557,22 +477,6 @@ namespace System.Drawing } } - /// - /// Returns the size of the specified pixel format. - /// - public static int GetPixelFormatSize(PixelFormat pixfmt) - { - return (unchecked((int)pixfmt) >> 8) & 0xFF; - } - - /// - /// Returns a value indicating whether the pixel format contains alpha information. - /// - public static bool IsAlphaPixelFormat(PixelFormat pixfmt) - { - return (pixfmt & PixelFormat.Alpha) != 0; - } - internal static void ValidateImage(IntPtr image) { try diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs index 0cc4251..012f7d7 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.cs @@ -99,6 +99,38 @@ namespace System.Drawing /// public static Image FromFile(string filename) => FromFile(filename, false); + public static Image FromFile(string filename, bool useEmbeddedColorManagement) + { + if (!File.Exists(filename)) + { + // Throw a more specific exception for invalid paths that are null or empty, + // contain invalid characters or are too long. + filename = Path.GetFullPath(filename); + throw new FileNotFoundException(filename); + } + + // GDI+ will read this file multiple times. Get the fully qualified path + // so if our app changes default directory we won't get an error + filename = Path.GetFullPath(filename); + + IntPtr image = IntPtr.Zero; + + if (useEmbeddedColorManagement) + { + Gdip.CheckStatus(Gdip.GdipLoadImageFromFileICM(filename, out image)); + } + else + { + Gdip.CheckStatus(Gdip.GdipLoadImageFromFile(filename, out image)); + } + + ValidateImage(image); + + Image img = CreateImageObject(image); + EnsureSave(img, filename, null); + return img; + } + /// /// Creates an from the specified data stream. /// @@ -298,6 +330,40 @@ namespace System.Drawing } /// + /// Returns information about the codecs used for this . + /// + public EncoderParameters GetEncoderParameterList(Guid encoder) + { + EncoderParameters p; + + Gdip.CheckStatus(Gdip.GdipGetEncoderParameterListSize( + new HandleRef(this, nativeImage), + ref encoder, + out int size)); + + if (size <= 0) + return null; + + IntPtr buffer = Marshal.AllocHGlobal(size); + try + { + Gdip.CheckStatus(Gdip.GdipGetEncoderParameterList( + new HandleRef(this, nativeImage), + ref encoder, + size, + buffer)); + + p = EncoderParameters.ConvertFromMemory(buffer); + } + finally + { + Marshal.FreeHGlobal(buffer); + } + + return p; + } + + /// /// Creates a from a Windows handle. /// public static Bitmap FromHbitmap(IntPtr hbitmap) => FromHbitmap(hbitmap, IntPtr.Zero); @@ -368,6 +434,36 @@ namespace System.Drawing } } + /// + /// Returns the size of the specified pixel format. + /// + public static int GetPixelFormatSize(PixelFormat pixfmt) + { + return (unchecked((int)pixfmt) >> 8) & 0xFF; + } + + /// + /// Returns a value indicating whether the pixel format contains alpha information. + /// + public static bool IsAlphaPixelFormat(PixelFormat pixfmt) + { + return (pixfmt & PixelFormat.Alpha) != 0; + } + + internal static Image CreateImageObject(IntPtr nativeImage) + { + Gdip.CheckStatus(Gdip.GdipGetImageType(nativeImage, out int type)); + switch ((ImageType)type) + { + case ImageType.Bitmap: + return new Bitmap(nativeImage); + case ImageType.Metafile: + return new Metafile(nativeImage); + default: + throw new ArgumentException(SR.InvalidImage); + } + } + internal static unsafe void EnsureSave(Image image, string filename, Stream dataStream) { if (image.RawFormat.Equals(ImageFormat.Gif)) diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/EncoderParameters.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/EncoderParameters.cs index 9bbdd61..a61c918 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/EncoderParameters.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/EncoderParameters.cs @@ -87,7 +87,7 @@ namespace System.Drawing.Imaging throw Gdip.StatusException(Gdip.InvalidParameter); } - int count = Marshal.ReadIntPtr(memory).ToInt32(); + int count = Marshal.ReadInt32(memory); EncoderParameters p = new EncoderParameters(count); int size = Marshal.SizeOf(typeof(EncoderParameter)); diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Unix.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Unix.cs index 55bc065..3ef5808 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Unix.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Unix.cs @@ -45,11 +45,6 @@ namespace System.Drawing.Imaging #endif public sealed partial class Metafile : Image { - - // constructors - - internal Metafile(IntPtr ptr) => SetNativeImage(ptr); - // Usually called when cloning images that need to have // not only the handle saved, but also the underlying stream // (when using MS GDI+ and IStream we must ensure the stream stays alive for all the life of the Image) diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Windows.cs index 7a187d6..9cb891d 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Windows.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Windows.cs @@ -376,19 +376,5 @@ namespace System.Drawing.Imaging Gdip.CheckStatus(Gdip.GdipGetHemfFromMetafile(new HandleRef(this, nativeImage), out IntPtr hEmf)); return hEmf; } - - /// - /// Create a new metafile object from a native metafile handle. - /// - internal static Metafile FromGDIplus(IntPtr nativeImage) - { - Metafile metafile = new Metafile(); - metafile.SetNativeImage(nativeImage); - return metafile; - } - - private Metafile() - { - } } } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.cs index 5cd557b..db91a2a 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.cs @@ -304,6 +304,11 @@ namespace System.Drawing.Imaging } /// + /// Initializes a new instance of the class from a native metafile handle. + /// + internal Metafile(IntPtr ptr) => SetNativeImage(ptr); + + /// /// Plays an EMF+ file. /// public void PlayRecord(EmfPlusRecordType recordType, int flags, int dataSize, byte[] data) diff --git a/src/libraries/System.Drawing.Common/tests/ImageTests.cs b/src/libraries/System.Drawing.Common/tests/ImageTests.cs index c80d903..5e176f9 100644 --- a/src/libraries/System.Drawing.Common/tests/ImageTests.cs +++ b/src/libraries/System.Drawing.Common/tests/ImageTests.cs @@ -2,7 +2,10 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Drawing.Imaging; using System.IO; +using System.Linq; +using Microsoft.DotNet.XUnitExtensions; using Xunit; namespace System.Drawing.Tests @@ -31,7 +34,6 @@ namespace System.Drawing.Tests } } - [ActiveIssue(20884, TestPlatforms.AnyUnix)] [Fact] public void FromFile_NullFileName_ThrowsArgumentNullException() { @@ -39,7 +41,6 @@ namespace System.Drawing.Tests AssertExtensions.Throws("path", () => Image.FromFile(null, useEmbeddedColorManagement: true)); } - [ActiveIssue(20884, TestPlatforms.AnyUnix)] [Fact] public void FromFile_EmptyFileName_ThrowsArgumentNullException() { @@ -47,7 +48,6 @@ namespace System.Drawing.Tests AssertExtensions.Throws("path", null, () => Image.FromFile(string.Empty, useEmbeddedColorManagement: true)); } - [ActiveIssue(20884, TestPlatforms.AnyUnix)] [Fact] public void FromFile_LongSegment_ThrowsException() { @@ -103,5 +103,83 @@ namespace System.Drawing.Tests AssertExtensions.Throws("stream", null, () => Image.FromStream(null, useEmbeddedColorManagement: true)); AssertExtensions.Throws("stream", null, () => Image.FromStream(null, useEmbeddedColorManagement: true, validateImageData: true)); } + + [Theory] + [InlineData(PixelFormat.Format1bppIndexed, 1)] + [InlineData(PixelFormat.Format4bppIndexed, 4)] + [InlineData(PixelFormat.Format8bppIndexed, 8)] + [InlineData(PixelFormat.Format16bppArgb1555, 16)] + [InlineData(PixelFormat.Format16bppGrayScale, 16)] + [InlineData(PixelFormat.Format16bppRgb555, 16)] + [InlineData(PixelFormat.Format16bppRgb565, 16)] + [InlineData(PixelFormat.Format24bppRgb, 24)] + [InlineData(PixelFormat.Format32bppArgb, 32)] + [InlineData(PixelFormat.Format32bppPArgb, 32)] + [InlineData(PixelFormat.Format32bppRgb, 32)] + [InlineData(PixelFormat.Format48bppRgb, 48)] + [InlineData(PixelFormat.Format64bppArgb, 64)] + [InlineData(PixelFormat.Format64bppPArgb, 64)] + public void GetPixelFormatSize_ReturnsExpected(PixelFormat format, int expectedSize) + { + Assert.Equal(expectedSize, Image.GetPixelFormatSize(format)); + } + + [Theory] + [InlineData(PixelFormat.Format16bppArgb1555, true)] + [InlineData(PixelFormat.Format32bppArgb, true)] + [InlineData(PixelFormat.Format32bppPArgb, true)] + [InlineData(PixelFormat.Format64bppArgb, true)] + [InlineData(PixelFormat.Format64bppPArgb, true)] + [InlineData(PixelFormat.Format16bppGrayScale, false)] + [InlineData(PixelFormat.Format16bppRgb555, false)] + [InlineData(PixelFormat.Format16bppRgb565, false)] + [InlineData(PixelFormat.Format1bppIndexed, false)] + [InlineData(PixelFormat.Format24bppRgb, false)] + [InlineData(PixelFormat.Format32bppRgb, false)] + [InlineData(PixelFormat.Format48bppRgb, false)] + [InlineData(PixelFormat.Format4bppIndexed, false)] + [InlineData(PixelFormat.Format8bppIndexed, false)] + public void IsAlphaPixelFormat_ReturnsExpected(PixelFormat format, bool expected) + { + Assert.Equal(expected, Image.IsAlphaPixelFormat(format)); + } + + public static IEnumerable GetEncoderParameterList_ReturnsExpected_TestData() + { + yield return new object[] + { + ImageFormat.Tiff, + new Guid[] + { + Encoder.Compression.Guid, + Encoder.ColorDepth.Guid, + Encoder.SaveFlag.Guid, + new Guid(unchecked((int)0xa219bbc9), unchecked((short)0x0a9d), unchecked((short)0x4005), new byte[] { 0xa3, 0xee, 0x3a, 0x42, 0x1b, 0x8b, 0xb0, 0x6c }) /* Encoder.SaveAsCmyk.Guid */ + } + }; + } + + [ActiveIssue(20884, TestPlatforms.AnyUnix)] + [ConditionalTheory(Helpers.IsDrawingSupported)] + [MemberData(nameof(GetEncoderParameterList_ReturnsExpected_TestData))] + public void GetEncoderParameterList_ReturnsExpected(ImageFormat format, Guid[] expectedParameters) + { + if (PlatformDetection.IsFullFramework) + { + throw new SkipTestException("This is a known bug for .NET Framework"); + } + + ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); + ImageCodecInfo codec = codecs.Single(c => c.FormatID == format.Guid); + + using (var bitmap = new Bitmap(1, 1)) + { + EncoderParameters paramList = bitmap.GetEncoderParameterList(codec.Clsid); + + Assert.Equal( + expectedParameters, + paramList.Param.Select(p => p.Encoder.Guid)); + } + } } } -- 2.7.4