From 6991fd13bd64becce280b63ab99bcf9a01de61ee Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Fri, 6 May 2022 17:50:37 +0200 Subject: [PATCH] Read ICC profile from v5 header --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 41 ++++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index ab0f1bd03..f88e5762d 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -11,6 +11,7 @@ using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Bmp @@ -185,7 +186,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp break; default: - BmpThrowHelper.ThrowNotSupportedException("Does not support this kind of bitmap files."); + BmpThrowHelper.ThrowNotSupportedException("ImageSharp does not support this kind of bitmap files."); break; } @@ -1199,6 +1200,13 @@ namespace SixLabors.ImageSharp.Formats.Bmp private void ReadInfoHeader() { Span buffer = stackalloc byte[BmpInfoHeader.MaxHeaderSize]; + var infoHeaderStart = this.stream.Position; + + // Resolution is stored in PPM. + this.metadata = new ImageMetadata + { + ResolutionUnits = PixelResolutionUnit.PixelsPerMeter + }; // Read the header size. this.stream.Read(buffer, 0, BmpInfoHeader.HeaderSizeSize); @@ -1282,31 +1290,34 @@ namespace SixLabors.ImageSharp.Formats.Bmp // > 108 bytes infoHeaderType = BmpInfoHeaderType.WinVersion5; this.infoHeader = BmpInfoHeader.ParseV5(buffer); + if (this.infoHeader.ProfileData != 0 && this.infoHeader.ProfileSize != 0) + { + // Read color profile. + long streamPosition = this.stream.Position; + byte[] iccProfileData = new byte[this.infoHeader.ProfileSize]; + this.stream.Position = infoHeaderStart + this.infoHeader.ProfileData; + this.stream.Read(iccProfileData); + this.metadata.IccProfile = new IccProfile(iccProfileData); + this.stream.Position = streamPosition; + } } else { BmpThrowHelper.ThrowNotSupportedException($"ImageSharp does not support this BMP file. HeaderSize '{headerSize}'."); } - // Resolution is stored in PPM. - var meta = new ImageMetadata - { - ResolutionUnits = PixelResolutionUnit.PixelsPerMeter - }; if (this.infoHeader.XPelsPerMeter > 0 && this.infoHeader.YPelsPerMeter > 0) { - meta.HorizontalResolution = this.infoHeader.XPelsPerMeter; - meta.VerticalResolution = this.infoHeader.YPelsPerMeter; + this.metadata.HorizontalResolution = this.infoHeader.XPelsPerMeter; + this.metadata.VerticalResolution = this.infoHeader.YPelsPerMeter; } else { // Convert default metadata values to PPM. - meta.HorizontalResolution = Math.Round(UnitConverter.InchToMeter(ImageMetadata.DefaultHorizontalResolution)); - meta.VerticalResolution = Math.Round(UnitConverter.InchToMeter(ImageMetadata.DefaultVerticalResolution)); + this.metadata.HorizontalResolution = Math.Round(UnitConverter.InchToMeter(ImageMetadata.DefaultHorizontalResolution)); + this.metadata.VerticalResolution = Math.Round(UnitConverter.InchToMeter(ImageMetadata.DefaultVerticalResolution)); } - this.metadata = meta; - short bitsPerPixel = this.infoHeader.BitsPerPixel; this.bmpMetadata = this.metadata.GetBmpMetadata(); this.bmpMetadata.InfoHeaderType = infoHeaderType; @@ -1376,9 +1387,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp int colorMapSizeBytes = -1; if (this.infoHeader.ClrUsed == 0) { - if (this.infoHeader.BitsPerPixel == 1 - || this.infoHeader.BitsPerPixel == 4 - || this.infoHeader.BitsPerPixel == 8) + if (this.infoHeader.BitsPerPixel is 1 or 4 or 8) { switch (this.fileMarkerType) { @@ -1430,7 +1439,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp int skipAmount = this.fileHeader.Offset - (int)this.stream.Position; if ((skipAmount + (int)this.stream.Position) > this.stream.Length) { - BmpThrowHelper.ThrowInvalidImageContentException("Invalid fileheader offset found. Offset is greater than the stream length."); + BmpThrowHelper.ThrowInvalidImageContentException("Invalid file header offset found. Offset is greater than the stream length."); } if (skipAmount > 0)