From 551dd9ba794fdc162371209f623ab025117f527e Mon Sep 17 00:00:00 2001 From: first-ironsoftware Date: Wed, 23 Apr 2025 15:52:32 +0700 Subject: [PATCH 01/12] Update dependencies and nuspec file --- .../IronSoftware.Drawing.Common.csproj | 4 ++-- NuGet/IronSoftware.Drawing.nuspec | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/IronSoftware.Drawing/IronSoftware.Drawing.Common/IronSoftware.Drawing.Common.csproj b/IronSoftware.Drawing/IronSoftware.Drawing.Common/IronSoftware.Drawing.Common.csproj index af58cb4..ec774df 100644 --- a/IronSoftware.Drawing/IronSoftware.Drawing.Common/IronSoftware.Drawing.Common.csproj +++ b/IronSoftware.Drawing/IronSoftware.Drawing.Common/IronSoftware.Drawing.Common.csproj @@ -1,4 +1,4 @@ - + IronSoftware.Drawing.Common.snk @@ -25,7 +25,7 @@ - + diff --git a/NuGet/IronSoftware.Drawing.nuspec b/NuGet/IronSoftware.Drawing.nuspec index 730882b..aa7f61e 100644 --- a/NuGet/IronSoftware.Drawing.nuspec +++ b/NuGet/IronSoftware.Drawing.nuspec @@ -46,14 +46,14 @@ For general support and technical inquiries, please email us at: support@ironsof - + - + From 1ade516bf7284a6cbf8777bca43052878ec162b0 Mon Sep 17 00:00:00 2001 From: Meee <104610177+mee-ironsoftware@users.noreply.github.com> Date: Thu, 24 Apr 2025 12:09:23 +0700 Subject: [PATCH 02/12] PR: Install GDI+ dependencies on Ubuntu agent before execute tests --- CI/job_templates/test_drawing_libraries.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CI/job_templates/test_drawing_libraries.yml b/CI/job_templates/test_drawing_libraries.yml index ac8c71e..b8c1fa7 100644 --- a/CI/job_templates/test_drawing_libraries.yml +++ b/CI/job_templates/test_drawing_libraries.yml @@ -20,6 +20,14 @@ jobs: buildType: 'current' artifactName: 'IronDrawingDataTests' targetPath: '$(Agent.BuildDirectory)/Data' + - ${{ if eq(parameters.OSPlatform, 'Ubuntu') }}: + - task: Bash@3 + displayName: 'Install GDI+ dependencies' + inputs: + targetType: 'inline' + script: | + sudo apt-get update + sudo apt-get install -y libgdiplus libc6-dev - ${{ if eq(parameters.framework, 'netcoreapp3.1') }}: - task: UseDotNet@2 displayName: 'Install .Netcoreapp3.1 Core sdk' From 59b7d7a53f1aa0d38d221b200ba7d8d9059f9f20 Mon Sep 17 00:00:00 2001 From: first-ironsoftware Date: Fri, 25 Apr 2025 12:45:41 +0700 Subject: [PATCH 03/12] Attempted to fix deployment issue in unit test for Linux --- CI/job_templates/test_drawing_libraries.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/job_templates/test_drawing_libraries.yml b/CI/job_templates/test_drawing_libraries.yml index b8c1fa7..46c9b26 100644 --- a/CI/job_templates/test_drawing_libraries.yml +++ b/CI/job_templates/test_drawing_libraries.yml @@ -20,7 +20,7 @@ jobs: buildType: 'current' artifactName: 'IronDrawingDataTests' targetPath: '$(Agent.BuildDirectory)/Data' - - ${{ if eq(parameters.OSPlatform, 'Ubuntu') }}: + - ${{ if eq(parameters.OSPlatform, 'Ubuntu') || eq(parameters.OSPlatform, 'Linux') }}: - task: Bash@3 displayName: 'Install GDI+ dependencies' inputs: From f91e9488481b0db98ee4f36c4005e453831f5cf4 Mon Sep 17 00:00:00 2001 From: first-ironsoftware Date: Fri, 25 Apr 2025 12:52:32 +0700 Subject: [PATCH 04/12] Second attempted to fix the unit test issue --- CI/job_templates/test_drawing_libraries.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/job_templates/test_drawing_libraries.yml b/CI/job_templates/test_drawing_libraries.yml index 46c9b26..d6a6b42 100644 --- a/CI/job_templates/test_drawing_libraries.yml +++ b/CI/job_templates/test_drawing_libraries.yml @@ -20,7 +20,7 @@ jobs: buildType: 'current' artifactName: 'IronDrawingDataTests' targetPath: '$(Agent.BuildDirectory)/Data' - - ${{ if eq(parameters.OSPlatform, 'Ubuntu') || eq(parameters.OSPlatform, 'Linux') }}: + - ${{ if or(eq(parameters.OSPlatform, 'Ubuntu'), eq(parameters.OSPlatform, 'Linux')) }}: - task: Bash@3 displayName: 'Install GDI+ dependencies' inputs: From 3779a0d8d53aaa54a9839e699a6a205b583e1954 Mon Sep 17 00:00:00 2001 From: first-ironsoftware Date: Fri, 25 Apr 2025 13:51:36 +0700 Subject: [PATCH 05/12] Update release notes --- NuGet/IronSoftware.Drawing.nuspec | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/NuGet/IronSoftware.Drawing.nuspec b/NuGet/IronSoftware.Drawing.nuspec index aa7f61e..45234c3 100644 --- a/NuGet/IronSoftware.Drawing.nuspec +++ b/NuGet/IronSoftware.Drawing.nuspec @@ -39,8 +39,7 @@ Supports: For general support and technical inquiries, please email us at: support@ironsoftware.com IronSoftware.System.Drawing is an open-source solution for .NET developers to replace System.Drawing.Common with a universal and flexible library. - - Fixes incorrect HorizontalResolution and VerticalResolution of AnyBitmap images. - - Improves library's internal functionality and performance. + - Updates internal dependencies. Copyright © Iron Software 2022-2025 Images, Bitmap, SkiaSharp, SixLabors, BitMiracle, Maui, SVG, TIFF, TIF, GIF, JPEG, PNG, Color, Rectangle, Drawing, C#, VB.NET, ASPX, create, render, generate, standard, netstandard2.0, core, netcore From ace14e797fc3d36298f3de16ca805c61424f9019 Mon Sep 17 00:00:00 2001 From: kannapat-ironsoftware Date: Wed, 7 May 2025 13:17:40 +0700 Subject: [PATCH 06/12] Disable warning messages from BitMiracle.LibTiff.NET --- .../IronSoftware.Drawing.Common/AnyBitmap.cs | 18 ++++++++++++++++++ NuGet/IronSoftware.Drawing.nuspec | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs index 94503d4..bb8e1fe 100644 --- a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs +++ b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs @@ -2233,6 +2233,21 @@ private static SKBitmap OpenTiffToSKBitmap(AnyBitmap anyBitmap) } } + /// + /// Disable warning message written to console by BitMiracle.LibTiff.NET. + /// + private class DisableErrorHandler : TiffErrorHandler + { + public override void WarningHandler(Tiff tif, string method, string format, params object[] args) + { + // do nothing, ie, do not write warnings to console + } + public override void WarningHandlerExt(Tiff tif, object clientData, string method, string format, params object[] args) + { + // do nothing ie, do not write warnings to console + } + } + private void OpenTiffToImageSharp(ReadOnlySpan bytes) { try @@ -2246,6 +2261,9 @@ private void OpenTiffToImageSharp(ReadOnlySpan bytes) // create a memory stream out of them using MemoryStream tiffStream = new(bytes.ToArray()); + // Disable warning messages + Tiff.SetErrorHandler(new DisableErrorHandler()); + // open a TIFF stored in the stream using (Tiff tiff = Tiff.ClientOpen("in-memory", "r", tiffStream, new TiffStream())) { diff --git a/NuGet/IronSoftware.Drawing.nuspec b/NuGet/IronSoftware.Drawing.nuspec index 45234c3..2a28cbb 100644 --- a/NuGet/IronSoftware.Drawing.nuspec +++ b/NuGet/IronSoftware.Drawing.nuspec @@ -39,7 +39,8 @@ Supports: For general support and technical inquiries, please email us at: support@ironsoftware.com IronSoftware.System.Drawing is an open-source solution for .NET developers to replace System.Drawing.Common with a universal and flexible library. - - Updates internal dependencies. + - Updates internal dependencies. + - Disable warning messages from BitMiracle.LibTiff.NET. Copyright © Iron Software 2022-2025 Images, Bitmap, SkiaSharp, SixLabors, BitMiracle, Maui, SVG, TIFF, TIF, GIF, JPEG, PNG, Color, Rectangle, Drawing, C#, VB.NET, ASPX, create, render, generate, standard, netstandard2.0, core, netcore From e3221e9aba2e4bfdebcf0a559feafb4f92fcd580 Mon Sep 17 00:00:00 2001 From: kannapat-ironsoftware Date: Tue, 13 May 2025 15:13:26 +0700 Subject: [PATCH 07/12] Add preserveOriginalFormat bool while loading image --- .../UnitTests/AnyBitmapFunctionality.cs | 20 +++ .../IronSoftware.Drawing.Common/AnyBitmap.cs | 121 +++++++++++------- 2 files changed, 96 insertions(+), 45 deletions(-) diff --git a/IronSoftware.Drawing/IronSoftware.Drawing.Common.Tests/UnitTests/AnyBitmapFunctionality.cs b/IronSoftware.Drawing/IronSoftware.Drawing.Common.Tests/UnitTests/AnyBitmapFunctionality.cs index b563d9b..83f30a5 100644 --- a/IronSoftware.Drawing/IronSoftware.Drawing.Common.Tests/UnitTests/AnyBitmapFunctionality.cs +++ b/IronSoftware.Drawing/IronSoftware.Drawing.Common.Tests/UnitTests/AnyBitmapFunctionality.cs @@ -942,6 +942,26 @@ public void LoadImage_TiffImage_ShouldLoadWithoutThumbnail() bitmap.FrameCount.Should().Be(1); } + [TheoryWithAutomaticDisplayName] + [InlineData("24_bit.png")] + [InlineData("checkmark.jpg")] + [InlineData("DW-26 Jpg72Input.jpg")] + [InlineData("DW-26 Jpg300Input.jpg")] + [InlineData("mountainclimbers.jpg")] + public void LoadImage_SetPreserveOriginalFormat_ShouldReturnCorrectBitPerPixel(string imageFileName) + { + // Arrange + string imagePath = GetRelativeFilePath(imageFileName); + + // Act + var preserve = new AnyBitmap(imagePath, true); + var notPreserve = new AnyBitmap(imagePath, false); + + // Assert + Assert.Equal(24, preserve.BitsPerPixel); + Assert.Equal(32, notPreserve.BitsPerPixel); + } + #if !NET7_0 [FactWithAutomaticDisplayName] public void CastAnyBitmap_from_SixLabors() diff --git a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs index bb8e1fe..b9c8c31 100644 --- a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs +++ b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs @@ -462,87 +462,99 @@ public T ToBitmap() /// Create a new Bitmap from a a Byte Span. /// /// A Byte Span of image data in any common format. - public static AnyBitmap FromSpan(ReadOnlySpan span) + /// Determine wheter load as its original pixel format or Rgba32. + /// Default is true. Set to false to load as Rgba32. + public static AnyBitmap FromSpan(ReadOnlySpan span, bool preserveOriginalFormat = true) { - return new AnyBitmap(span); + return new AnyBitmap(span, preserveOriginalFormat); } /// /// Create a new Bitmap from a a Byte Array. /// /// A ByteArray of image data in any common format. - public static AnyBitmap FromBytes(byte[] bytes) + /// Determine wheter load as its original pixel format or Rgba32. + /// Default is true. Set to false to load as Rgba32. + public static AnyBitmap FromBytes(byte[] bytes, bool preserveOriginalFormat = true) { - return new AnyBitmap(bytes); + return new AnyBitmap(bytes, preserveOriginalFormat); } /// /// Create a new Bitmap from a (bytes). /// - /// A of image data in any - /// common format. - /// + /// A of image data in any common format. + /// Determine wheter load as its original pixel format or Rgba32. + /// Default is true. Set to false to load as Rgba32. + /// /// - public static AnyBitmap FromStream(MemoryStream stream) + public static AnyBitmap FromStream(MemoryStream stream, bool preserveOriginalFormat = true) { - return new AnyBitmap(stream); + return new AnyBitmap(stream, preserveOriginalFormat); } /// /// Create a new Bitmap from a (bytes). /// - /// A of image data in any - /// common format. - /// + /// A of image data in any common format. + /// Determine wheter load as its original pixel format or Rgba32. + /// Default is true. Set to false to load as Rgba32. + /// /// - public static AnyBitmap FromStream(Stream stream) + public static AnyBitmap FromStream(Stream stream, bool preserveOriginalFormat = true) { - return new AnyBitmap(stream); + return new AnyBitmap(stream, preserveOriginalFormat); } /// /// Construct a new Bitmap from binary data (byte span). /// /// A byte span of image data in any common format. + /// Determine wheter load as its original pixel format or Rgba32. + /// Default is true. Set to false to load as Rgba32. /// - public AnyBitmap(ReadOnlySpan span) + public AnyBitmap(ReadOnlySpan span, bool preserveOriginalFormat = true) { - LoadImage(span); + LoadImage(span, preserveOriginalFormat); } /// /// Construct a new Bitmap from binary data (bytes). /// /// A ByteArray of image data in any common format. + /// Determine wheter load as its original pixel format or Rgba32. + /// Default is true. Set to false to load as Rgba32. /// /// - public AnyBitmap(byte[] bytes) + public AnyBitmap(byte[] bytes, bool preserveOriginalFormat = true) { - LoadImage(bytes); + LoadImage(bytes, preserveOriginalFormat); } /// /// Construct a new Bitmap from a (bytes). /// - /// A of image data in any - /// common format. - /// + /// A of image data in any common format. + /// Determine wheter load as its original pixel format or Rgba32. + /// Default is true. Set to false to load as Rgba32. + /// /// - public AnyBitmap(MemoryStream stream) + public AnyBitmap(MemoryStream stream, bool preserveOriginalFormat = true) { - LoadImage(stream.ToArray()); + LoadImage(stream.ToArray(), preserveOriginalFormat); } /// /// Construct a new Bitmap from a (bytes). /// - /// A of image data in any - /// common format. - /// + /// A of image data in any common format. + /// Determine wheter load as its original pixel format or Rgba32. + /// Default is true. Set to false to load as Rgba32. + /// /// - public AnyBitmap(Stream stream) + public AnyBitmap(Stream stream, bool preserveOriginalFormat = true) { - LoadImage(stream); + LoadImage(stream, preserveOriginalFormat); } /// @@ -561,25 +573,29 @@ public AnyBitmap(AnyBitmap original, int width, int height) /// Construct a new Bitmap from a file. /// /// A fully qualified file path./ + /// Determine wheter load as its original pixel format or Rgba32. + /// Default is true. Set to false to load as Rgba32. /// /// - public AnyBitmap(string file) + public AnyBitmap(string file, bool preserveOriginalFormat = true) { - LoadImage(File.ReadAllBytes(file)); + LoadImage(File.ReadAllBytes(file), preserveOriginalFormat); } /// /// Construct a new Bitmap from a Uri /// /// The uri of the image. + /// Determine wheter load as its original pixel format or Rgba32. + /// Default is true. Set to false to load as Rgba32. /// /// - public AnyBitmap(Uri uri) + public AnyBitmap(Uri uri, bool preserveOriginalFormat = true) { try { using Stream stream = LoadUriAsync(uri).GetAwaiter().GetResult(); - LoadImage(stream); + LoadImage(stream, preserveOriginalFormat); } catch (Exception e) { @@ -602,17 +618,19 @@ public AnyBitmap(int width, int height, Color backgroundColor = null) /// Create a new Bitmap from a file. /// /// A fully qualified file path. + /// Determine wheter load as its original pixel format or Rgba32. + /// Default is true. Set to false to load as Rgba32. /// /// - public static AnyBitmap FromFile(string file) + public static AnyBitmap FromFile(string file, bool preserveOriginalFormat = true) { if (file.ToLower().EndsWith(".svg")) { - return LoadSVGImage(file); + return LoadSVGImage(file, preserveOriginalFormat); } else { - return new AnyBitmap(file); + return new AnyBitmap(file, preserveOriginalFormat); } } @@ -620,16 +638,18 @@ public static AnyBitmap FromFile(string file) /// Construct a new Bitmap from a Uri /// /// The uri of the image. + /// Determine wheter load as its original pixel format or Rgba32. + /// Default is true. Set to false to load as Rgba32. /// /// /// /// - public static async Task FromUriAsync(Uri uri) + public static async Task FromUriAsync(Uri uri, bool preserveOriginalFormat = true) { try { using Stream stream = await LoadUriAsync(uri); - return new AnyBitmap(stream); + return new AnyBitmap(stream, preserveOriginalFormat); } catch (Exception e) { @@ -641,13 +661,15 @@ public static async Task FromUriAsync(Uri uri) /// Construct a new Bitmap from a Uri /// /// The uri of the image. + /// Determine wheter load as its original pixel format or Rgba32. + /// Default is true. Set to false to load as Rgba32. /// /// /// #if NET6_0_OR_GREATER [Obsolete("FromUri(Uri) is obsolete for net60 or greater because it uses WebClient which is obsolete. Consider using FromUriAsync(Uri) method.")] #endif - public static AnyBitmap FromUri(Uri uri) + public static AnyBitmap FromUri(Uri uri, bool preserveOriginalFormat = true) { try { @@ -2017,19 +2039,28 @@ private void CreateNewImageInstance(int width, int height, Color backgroundColor Binary = stream.ToArray(); } - private void LoadImage(ReadOnlySpan bytes) + private void LoadImage(ReadOnlySpan bytes, bool preserveOriginalFormat) { Format = Image.DetectFormat(bytes); try { if (Format is TiffFormat) OpenTiffToImageSharp(bytes); - else { Binary = bytes.ToArray(); Image = Image.Load(bytes); - + + if (!preserveOriginalFormat) + { + if (Image is not Image) + Image = Image.CloneAs(); + + // .png image pre-processing + if (Format.Name == "PNG") + Image.Mutate(img => img.BackgroundColor(SixLabors.ImageSharp.Color.White)); + } + var resolutionUnit = this.Image.Metadata.ResolutionUnits; var horizontal = this.Image.Metadata.HorizontalResolution; var vertical = this.Image.Metadata.VerticalResolution; @@ -2067,7 +2098,7 @@ private void LoadImage(ReadOnlySpan bytes) } } - private void LoadImage(Stream stream) + private void LoadImage(Stream stream, bool preserveOriginalFormat) { byte[] buffer = new byte[16 * 1024]; using MemoryStream ms = new(); @@ -2077,17 +2108,17 @@ private void LoadImage(Stream stream) ms.Write(buffer, 0, read); } - LoadImage(ms.ToArray()); + LoadImage(ms.ToArray(), preserveOriginalFormat); } - private static AnyBitmap LoadSVGImage(string file) + private static AnyBitmap LoadSVGImage(string file, bool preserveOriginalFormat) { try { return new AnyBitmap( DecodeSVG(file).Encode(SKEncodedImageFormat.Png, 100) - .ToArray()); + .ToArray(), preserveOriginalFormat); } catch (DllNotFoundException e) { From 56cd3eb170bbc55b4ba51df43e10aa6218f46cf4 Mon Sep 17 00:00:00 2001 From: kannapat-ironsoftware Date: Wed, 14 May 2025 09:15:06 +0700 Subject: [PATCH 08/12] Load directly and fix typos regarding PR suggestion. --- .../IronSoftware.Drawing.Common/AnyBitmap.cs | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs index b9c8c31..bdf9f79 100644 --- a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs +++ b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs @@ -462,7 +462,7 @@ public T ToBitmap() /// Create a new Bitmap from a a Byte Span. /// /// A Byte Span of image data in any common format. - /// Determine wheter load as its original pixel format or Rgba32. + /// Determine whether load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. public static AnyBitmap FromSpan(ReadOnlySpan span, bool preserveOriginalFormat = true) { @@ -473,7 +473,7 @@ public static AnyBitmap FromSpan(ReadOnlySpan span, bool preserveOriginalF /// Create a new Bitmap from a a Byte Array. /// /// A ByteArray of image data in any common format. - /// Determine wheter load as its original pixel format or Rgba32. + /// Determine whether load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. public static AnyBitmap FromBytes(byte[] bytes, bool preserveOriginalFormat = true) { @@ -484,7 +484,7 @@ public static AnyBitmap FromBytes(byte[] bytes, bool preserveOriginalFormat = tr /// Create a new Bitmap from a (bytes). /// /// A of image data in any common format. - /// Determine wheter load as its original pixel format or Rgba32. + /// Determine whether load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -497,7 +497,7 @@ public static AnyBitmap FromStream(MemoryStream stream, bool preserveOriginalFor /// Create a new Bitmap from a (bytes). /// /// A of image data in any common format. - /// Determine wheter load as its original pixel format or Rgba32. + /// Determine whether load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -510,7 +510,7 @@ public static AnyBitmap FromStream(Stream stream, bool preserveOriginalFormat = /// Construct a new Bitmap from binary data (byte span). /// /// A byte span of image data in any common format. - /// Determine wheter load as its original pixel format or Rgba32. + /// Determine whether load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// public AnyBitmap(ReadOnlySpan span, bool preserveOriginalFormat = true) @@ -522,7 +522,7 @@ public AnyBitmap(ReadOnlySpan span, bool preserveOriginalFormat = true) /// Construct a new Bitmap from binary data (bytes). /// /// A ByteArray of image data in any common format. - /// Determine wheter load as its original pixel format or Rgba32. + /// Determine whether load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -535,7 +535,7 @@ public AnyBitmap(byte[] bytes, bool preserveOriginalFormat = true) /// Construct a new Bitmap from a (bytes). /// /// A of image data in any common format. - /// Determine wheter load as its original pixel format or Rgba32. + /// Determine whether load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -548,7 +548,7 @@ public AnyBitmap(MemoryStream stream, bool preserveOriginalFormat = true) /// Construct a new Bitmap from a (bytes). /// /// A of image data in any common format. - /// Determine wheter load as its original pixel format or Rgba32. + /// Determine whether load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -573,7 +573,7 @@ public AnyBitmap(AnyBitmap original, int width, int height) /// Construct a new Bitmap from a file. /// /// A fully qualified file path./ - /// Determine wheter load as its original pixel format or Rgba32. + /// Determine whether load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -586,7 +586,7 @@ public AnyBitmap(string file, bool preserveOriginalFormat = true) /// Construct a new Bitmap from a Uri /// /// The uri of the image. - /// Determine wheter load as its original pixel format or Rgba32. + /// Determine whether load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -618,7 +618,7 @@ public AnyBitmap(int width, int height, Color backgroundColor = null) /// Create a new Bitmap from a file. /// /// A fully qualified file path. - /// Determine wheter load as its original pixel format or Rgba32. + /// Determine whether load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -638,7 +638,7 @@ public static AnyBitmap FromFile(string file, bool preserveOriginalFormat = true /// Construct a new Bitmap from a Uri /// /// The uri of the image. - /// Determine wheter load as its original pixel format or Rgba32. + /// Determine whether load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -661,7 +661,7 @@ public static async Task FromUriAsync(Uri uri, bool preserveOriginalF /// Construct a new Bitmap from a Uri /// /// The uri of the image. - /// Determine wheter load as its original pixel format or Rgba32. + /// Determine whether load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -2049,12 +2049,12 @@ private void LoadImage(ReadOnlySpan bytes, bool preserveOriginalFormat) else { Binary = bytes.ToArray(); - Image = Image.Load(bytes); - if (!preserveOriginalFormat) + if (preserveOriginalFormat) + Image = Image.Load(bytes); + else { - if (Image is not Image) - Image = Image.CloneAs(); + Image = Image.Load(bytes); // .png image pre-processing if (Format.Name == "PNG") From ed4ea029dafbdf69aa9721b23b40914eabaa750b Mon Sep 17 00:00:00 2001 From: kannapat-ironsoftware Date: Thu, 15 May 2025 12:38:55 +0700 Subject: [PATCH 09/12] add private global bool called PreserveOriginalFormat to keep the same PixelFormat when Clone() in GetAllFrames --- IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs index bdf9f79..43bb3d4 100644 --- a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs +++ b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs @@ -52,6 +52,7 @@ public partial class AnyBitmap : IDisposable, IAnyImage private byte[] Binary { get; set; } private IImageFormat Format { get; set; } private TiffCompression TiffCompression { get; set; } = TiffCompression.Lzw; + private bool PreserveOriginalFormat { get; set; } = true; /// /// Width of the image. @@ -138,7 +139,7 @@ public MemoryStream GetStream() /// public AnyBitmap Clone() { - return new AnyBitmap(Binary); + return new AnyBitmap(Binary, PreserveOriginalFormat); } /// @@ -2054,6 +2055,7 @@ private void LoadImage(ReadOnlySpan bytes, bool preserveOriginalFormat) Image = Image.Load(bytes); else { + PreserveOriginalFormat = preserveOriginalFormat; Image = Image.Load(bytes); // .png image pre-processing From ce2a3f5c32326153ed6f0b69d16ad717a72b7976 Mon Sep 17 00:00:00 2001 From: kannapat-ironsoftware Date: Fri, 16 May 2025 10:31:59 +0700 Subject: [PATCH 10/12] Fix if the input image is auto-rotated from SixLabor.ImageSharp.Load() please see https://ironsoftware.atlassian.net/browse/DW-32 --- IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs index 43bb3d4..52cce01 100644 --- a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs +++ b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs @@ -2063,6 +2063,10 @@ private void LoadImage(ReadOnlySpan bytes, bool preserveOriginalFormat) Image.Mutate(img => img.BackgroundColor(SixLabors.ImageSharp.Color.White)); } + // Fix if the input image is auto-rotated; this issue is acknowledged by SixLabors.ImageSharp community + // ref: https://github.com/SixLabors/ImageSharp/discussions/2685 + Image.Mutate(x => x.AutoOrient()); + var resolutionUnit = this.Image.Metadata.ResolutionUnits; var horizontal = this.Image.Metadata.HorizontalResolution; var vertical = this.Image.Metadata.VerticalResolution; From 53c76414313768329a359d3b376b9e81593b39c6 Mon Sep 17 00:00:00 2001 From: kannapat-ironsoftware Date: Fri, 16 May 2025 13:13:09 +0700 Subject: [PATCH 11/12] Intellisense grammar correction --- .../IronSoftware.Drawing.Common/AnyBitmap.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs index 52cce01..5f3a22d 100644 --- a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs +++ b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs @@ -463,7 +463,7 @@ public T ToBitmap() /// Create a new Bitmap from a a Byte Span. /// /// A Byte Span of image data in any common format. - /// Determine whether load as its original pixel format or Rgba32. + /// Determine whether to load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. public static AnyBitmap FromSpan(ReadOnlySpan span, bool preserveOriginalFormat = true) { @@ -474,7 +474,7 @@ public static AnyBitmap FromSpan(ReadOnlySpan span, bool preserveOriginalF /// Create a new Bitmap from a a Byte Array. /// /// A ByteArray of image data in any common format. - /// Determine whether load as its original pixel format or Rgba32. + /// Determine whether to load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. public static AnyBitmap FromBytes(byte[] bytes, bool preserveOriginalFormat = true) { @@ -485,7 +485,7 @@ public static AnyBitmap FromBytes(byte[] bytes, bool preserveOriginalFormat = tr /// Create a new Bitmap from a (bytes). /// /// A of image data in any common format. - /// Determine whether load as its original pixel format or Rgba32. + /// Determine whether to load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -498,7 +498,7 @@ public static AnyBitmap FromStream(MemoryStream stream, bool preserveOriginalFor /// Create a new Bitmap from a (bytes). /// /// A of image data in any common format. - /// Determine whether load as its original pixel format or Rgba32. + /// Determine whether to load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -511,7 +511,7 @@ public static AnyBitmap FromStream(Stream stream, bool preserveOriginalFormat = /// Construct a new Bitmap from binary data (byte span). /// /// A byte span of image data in any common format. - /// Determine whether load as its original pixel format or Rgba32. + /// Determine whether to load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// public AnyBitmap(ReadOnlySpan span, bool preserveOriginalFormat = true) @@ -523,7 +523,7 @@ public AnyBitmap(ReadOnlySpan span, bool preserveOriginalFormat = true) /// Construct a new Bitmap from binary data (bytes). /// /// A ByteArray of image data in any common format. - /// Determine whether load as its original pixel format or Rgba32. + /// Determine whether to load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -536,7 +536,7 @@ public AnyBitmap(byte[] bytes, bool preserveOriginalFormat = true) /// Construct a new Bitmap from a (bytes). /// /// A of image data in any common format. - /// Determine whether load as its original pixel format or Rgba32. + /// Determine whether to load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -549,7 +549,7 @@ public AnyBitmap(MemoryStream stream, bool preserveOriginalFormat = true) /// Construct a new Bitmap from a (bytes). /// /// A of image data in any common format. - /// Determine whether load as its original pixel format or Rgba32. + /// Determine whether to load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -574,7 +574,7 @@ public AnyBitmap(AnyBitmap original, int width, int height) /// Construct a new Bitmap from a file. /// /// A fully qualified file path./ - /// Determine whether load as its original pixel format or Rgba32. + /// Determine whether to load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -587,7 +587,7 @@ public AnyBitmap(string file, bool preserveOriginalFormat = true) /// Construct a new Bitmap from a Uri /// /// The uri of the image. - /// Determine whether load as its original pixel format or Rgba32. + /// Determine whether to load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -619,7 +619,7 @@ public AnyBitmap(int width, int height, Color backgroundColor = null) /// Create a new Bitmap from a file. /// /// A fully qualified file path. - /// Determine whether load as its original pixel format or Rgba32. + /// Determine whether to load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -639,7 +639,7 @@ public static AnyBitmap FromFile(string file, bool preserveOriginalFormat = true /// Construct a new Bitmap from a Uri /// /// The uri of the image. - /// Determine whether load as its original pixel format or Rgba32. + /// Determine whether to load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// @@ -662,7 +662,7 @@ public static async Task FromUriAsync(Uri uri, bool preserveOriginalF /// Construct a new Bitmap from a Uri /// /// The uri of the image. - /// Determine whether load as its original pixel format or Rgba32. + /// Determine whether to load as its original pixel format or Rgba32. /// Default is true. Set to false to load as Rgba32. /// /// From 2f3184eb5a2e148eeda15dddd956755d1290f3cd Mon Sep 17 00:00:00 2001 From: kannapat-ironsoftware Date: Fri, 16 May 2025 14:16:06 +0700 Subject: [PATCH 12/12] Update SixLabors.ImageSharp packages for net60 target --- NuGet/IronSoftware.Drawing.nuspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NuGet/IronSoftware.Drawing.nuspec b/NuGet/IronSoftware.Drawing.nuspec index 2a28cbb..0946583 100644 --- a/NuGet/IronSoftware.Drawing.nuspec +++ b/NuGet/IronSoftware.Drawing.nuspec @@ -54,8 +54,8 @@ For general support and technical inquiries, please email us at: support@ironsof - - + +