From d7f6badc19010ce02c6312a74453480f6a2ae362 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sat, 4 Aug 2018 09:56:39 +0100 Subject: [PATCH] Align ICC and EXIF API. --- .../Formats/Jpeg/JpegDecoderCore.cs | 80 ++++++++++++------- .../MetaData/Profiles/ICC/IccProfile.cs | 11 --- 2 files changed, 53 insertions(+), 38 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 4eb770994..4f71d15b0 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg private ushort resetInterval; /// - /// Whether the image has a EXIF header + /// Whether the image has an EXIF marker /// private bool isExif; @@ -79,6 +79,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// private byte[] exifData; + /// + /// Whether the image has an ICC marker + /// + private bool isIcc; + + /// + /// Contains ICC data + /// + private byte[] iccData; + /// /// Contains information about the JFIF marker /// @@ -208,6 +218,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { this.ParseStream(stream); this.InitExifProfile(); + this.InitIccProfile(); this.InitDerivedMetaDataProperties(); return this.PostProcessIntoImage(); } @@ -220,6 +231,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { this.ParseStream(stream, true); this.InitExifProfile(); + this.InitIccProfile(); this.InitDerivedMetaDataProperties(); return new ImageInfo(new PixelTypeInfo(this.BitsPerPixel), this.ImageWidth, this.ImageHeight, this.MetaData); } @@ -412,7 +424,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } /// - /// Initializes the exif profile. + /// Initializes the EXIF profile. /// private void InitExifProfile() { @@ -422,6 +434,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } } + /// + /// Initializes the ICC profile. + /// + private void InitIccProfile() + { + if (this.isIcc) + { + var profile = new IccProfile(this.iccData); + if (profile.CheckIsValid()) + { + this.MetaData.IccProfile = profile; + } + } + } + /// /// Assigns derived metadata properties to , eg. horizontal and vertical resolution if it has a JFIF header. /// @@ -450,11 +477,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.MetaData.ResolutionUnits = UnitConverter.ExifProfileToResolutionUnit(this.MetaData.ExifProfile); } } + } - if (this.MetaData.IccProfile?.CheckIsValid() == false) - { - this.MetaData.IccProfile = null; - } + /// + /// Extends the profile with additional data. + /// + /// The profile data array. + /// The array containing addition profile data. + private void ExtendProfile(ref byte[] profile, byte[] extension) + { + int currentLength = profile.Length; + + Array.Resize(ref profile, currentLength + extension.Length); + Buffer.BlockCopy(extension, 0, profile, currentLength, extension.Length); } /// @@ -488,7 +523,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The remaining bytes in the segment block. private void ProcessApp1Marker(int remaining) { - if (remaining < 6 || this.IgnoreMetadata) + const int Exif00 = 6; + if (remaining < Exif00 || this.IgnoreMetadata) { // Skip the application header length this.InputStream.Skip(remaining); @@ -503,29 +539,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.isExif = true; if (this.exifData == null) { - // the first 6 bytes (Exif00) will be skipped, because this is Jpeg specific - this.exifData = profile.Skip(6).ToArray(); + // The first 6 bytes (Exif00) will be skipped, because this is Jpeg specific + this.exifData = profile.Skip(Exif00).ToArray(); } else { - // if the exif information exceeds 64K, it will be split over multiple APP1 markers - this.ExtendExif(profile.Skip(6).ToArray()); + // If the EXIF information exceeds 64K, it will be split over multiple APP1 markers + this.ExtendProfile(ref this.exifData, profile.Skip(Exif00).ToArray()); } } } - /// - /// Extends the exif profile with additional data. - /// - /// The array containing addition profile data. - private void ExtendExif(byte[] bytes) - { - int currentLength = this.exifData.Length; - - Array.Resize(ref this.exifData, currentLength + bytes.Length); - Buffer.BlockCopy(bytes, 0, this.exifData, currentLength, bytes.Length); - } - /// /// Processes the App2 marker retrieving any stored ICC profile information /// @@ -546,16 +570,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg if (ProfileResolver.IsProfile(identifier, ProfileResolver.IccMarker)) { + this.isIcc = true; byte[] profile = new byte[remaining]; this.InputStream.Read(profile, 0, remaining); - if (this.MetaData.IccProfile == null) + if (this.iccData == null) { - this.MetaData.IccProfile = new IccProfile(profile); + this.iccData = profile; } else { - this.MetaData.IccProfile.Extend(profile); + // If the ICC information exceeds 64K, it will be split over multiple APP2 markers + this.ExtendProfile(ref this.iccData, profile); } } else @@ -670,7 +696,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The remaining bytes in the segment block. /// The current frame marker. /// Whether to parse metadata only - private void ProcessStartOfFrameMarker(int remaining, JpegFileMarker frameMarker, bool metadataOnly) + private void ProcessStartOfFrameMarker(int remaining, in JpegFileMarker frameMarker, bool metadataOnly) { if (this.Frame != null) { diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs index db1d96d7e..2b2fe1e4e 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs @@ -149,17 +149,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc #endif - /// - /// Extends the profile with additional data. - /// - /// The array containing addition profile data. - public void Extend(byte[] bytes) - { - int currentLength = this.data.Length; - Array.Resize(ref this.data, currentLength + bytes.Length); - Buffer.BlockCopy(bytes, 0, this.data, currentLength, bytes.Length); - } - /// /// Checks for signs of a corrupt profile. ///