From 37d4ed23b57ddd80e673e52080f02fdc87a356b0 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 16 Oct 2022 21:46:23 +1000 Subject: [PATCH] Allow skipping Tiff metadata --- .../Formats/Tiff/TiffEncoderCore.cs | 8 +- .../Tiff/TiffEncoderEntriesCollector.cs | 153 +++++++++--------- 2 files changed, 79 insertions(+), 82 deletions(-) diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs index 849eb69ae..2013377ed 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs @@ -73,6 +73,11 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals /// private const TiffPhotometricInterpretation DefaultPhotometricInterpretation = TiffPhotometricInterpretation.Rgb; + /// + /// Whether to skip metadata during encoding. + /// + private readonly bool skipMetadata; + private readonly List<(long, uint)> frameMarkers = new(); /// @@ -90,6 +95,7 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals this.HorizontalPredictor = options.HorizontalPredictor; this.CompressionType = options.Compression; this.compressionLevel = options.CompressionLevel ?? DeflateCompressionLevel.DefaultCompression; + this.skipMetadata = options.SkipMetadata; } /// @@ -232,7 +238,7 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals if (image != null) { - entriesCollector.ProcessMetadata(image); + entriesCollector.ProcessMetadata(image, this.skipMetadata); } entriesCollector.ProcessFrameInfo(frame, imageMetadata); diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs index e158900cd..64b300cd6 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs @@ -15,8 +15,8 @@ internal class TiffEncoderEntriesCollector public List Entries { get; } = new List(); - public void ProcessMetadata(Image image) - => new MetadataProcessor(this).Process(image); + public void ProcessMetadata(Image image, bool skipMetadata) + => new MetadataProcessor(this).Process(image, skipMetadata); public void ProcessFrameInfo(ImageFrame frame, ImageMetadata imageMetadata) => new FrameInfoProcessor(this).Process(frame, imageMetadata); @@ -41,7 +41,7 @@ internal class TiffEncoderEntriesCollector private abstract class BaseProcessor { - public BaseProcessor(TiffEncoderEntriesCollector collector) => this.Collector = collector; + protected BaseProcessor(TiffEncoderEntriesCollector collector) => this.Collector = collector; protected TiffEncoderEntriesCollector Collector { get; } } @@ -53,14 +53,18 @@ internal class TiffEncoderEntriesCollector { } - public void Process(Image image) + public void Process(Image image, bool skipMetadata) { ImageFrame rootFrame = image.Frames.RootFrame; - ExifProfile rootFrameExifProfile = rootFrame.Metadata.ExifProfile ?? new ExifProfile(); + ExifProfile rootFrameExifProfile = rootFrame.Metadata.ExifProfile; XmpProfile rootFrameXmpProfile = rootFrame.Metadata.XmpProfile; - this.ProcessProfiles(image.Metadata, rootFrameExifProfile, rootFrameXmpProfile); - this.ProcessMetadata(rootFrameExifProfile); + this.ProcessProfiles(image.Metadata, skipMetadata, rootFrameExifProfile, rootFrameXmpProfile); + + if (!skipMetadata) + { + this.ProcessMetadata(rootFrameExifProfile ?? new ExifProfile()); + } if (!this.Collector.Entries.Exists(t => t.Tag == ExifTag.Software)) { @@ -72,39 +76,35 @@ internal class TiffEncoderEntriesCollector } private static bool IsPureMetadata(ExifTag tag) - { - switch ((ExifTagValue)(ushort)tag) + => (ExifTagValue)(ushort)tag switch { - case ExifTagValue.DocumentName: - case ExifTagValue.ImageDescription: - case ExifTagValue.Make: - case ExifTagValue.Model: - case ExifTagValue.Software: - case ExifTagValue.DateTime: - case ExifTagValue.Artist: - case ExifTagValue.HostComputer: - case ExifTagValue.TargetPrinter: - case ExifTagValue.XMP: - case ExifTagValue.Rating: - case ExifTagValue.RatingPercent: - case ExifTagValue.ImageID: - case ExifTagValue.Copyright: - case ExifTagValue.MDLabName: - case ExifTagValue.MDSampleInfo: - case ExifTagValue.MDPrepDate: - case ExifTagValue.MDPrepTime: - case ExifTagValue.MDFileUnits: - case ExifTagValue.SEMInfo: - case ExifTagValue.XPTitle: - case ExifTagValue.XPComment: - case ExifTagValue.XPAuthor: - case ExifTagValue.XPKeywords: - case ExifTagValue.XPSubject: - return true; - default: - return false; - } - } + ExifTagValue.DocumentName or + ExifTagValue.ImageDescription or + ExifTagValue.Make or + ExifTagValue.Model or + ExifTagValue.Software or + ExifTagValue.DateTime or + ExifTagValue.Artist or + ExifTagValue.HostComputer or + ExifTagValue.TargetPrinter or + ExifTagValue.XMP or + ExifTagValue.Rating or + ExifTagValue.RatingPercent or + ExifTagValue.ImageID or + ExifTagValue.Copyright or + ExifTagValue.MDLabName or + ExifTagValue.MDSampleInfo or + ExifTagValue.MDPrepDate or + ExifTagValue.MDPrepTime or + ExifTagValue.MDFileUnits or + ExifTagValue.SEMInfo or + ExifTagValue.XPTitle or + ExifTagValue.XPComment or + ExifTagValue.XPAuthor or + ExifTagValue.XPKeywords or + ExifTagValue.XPSubject => true, + _ => false, + }; private void ProcessMetadata(ExifProfile exifProfile) { @@ -149,9 +149,9 @@ internal class TiffEncoderEntriesCollector } } - private void ProcessProfiles(ImageMetadata imageMetadata, ExifProfile exifProfile, XmpProfile xmpProfile) + private void ProcessProfiles(ImageMetadata imageMetadata, bool skipMetadata, ExifProfile exifProfile, XmpProfile xmpProfile) { - if (exifProfile != null && exifProfile.Parts != ExifParts.None) + if (!skipMetadata && (exifProfile != null && exifProfile.Parts != ExifParts.None)) { foreach (IExifValue entry in exifProfile.Values) { @@ -167,13 +167,13 @@ internal class TiffEncoderEntriesCollector } else { - exifProfile.RemoveValue(ExifTag.SubIFDOffset); + exifProfile?.RemoveValue(ExifTag.SubIFDOffset); } - if (imageMetadata.IptcProfile != null) + if (!skipMetadata && imageMetadata.IptcProfile != null) { imageMetadata.IptcProfile.UpdateData(); - var iptc = new ExifByteArray(ExifTagValue.IPTC, ExifDataType.Byte) + ExifByteArray iptc = new(ExifTagValue.IPTC, ExifDataType.Byte) { Value = imageMetadata.IptcProfile.Data }; @@ -182,12 +182,12 @@ internal class TiffEncoderEntriesCollector } else { - exifProfile.RemoveValue(ExifTag.IPTC); + exifProfile?.RemoveValue(ExifTag.IPTC); } if (imageMetadata.IccProfile != null) { - var icc = new ExifByteArray(ExifTagValue.IccProfile, ExifDataType.Undefined) + ExifByteArray icc = new(ExifTagValue.IccProfile, ExifDataType.Undefined) { Value = imageMetadata.IccProfile.ToByteArray() }; @@ -196,12 +196,12 @@ internal class TiffEncoderEntriesCollector } else { - exifProfile.RemoveValue(ExifTag.IccProfile); + exifProfile?.RemoveValue(ExifTag.IccProfile); } - if (xmpProfile != null) + if (!skipMetadata && xmpProfile != null) { - var xmp = new ExifByteArray(ExifTagValue.XMP, ExifDataType.Byte) + ExifByteArray xmp = new(ExifTagValue.XMP, ExifDataType.Byte) { Value = xmpProfile.Data }; @@ -210,7 +210,7 @@ internal class TiffEncoderEntriesCollector } else { - exifProfile.RemoveValue(ExifTag.XMP); + exifProfile?.RemoveValue(ExifTag.XMP); } } } @@ -273,29 +273,29 @@ internal class TiffEncoderEntriesCollector public void Process(TiffEncoderCore encoder) { - var planarConfig = new ExifShort(ExifTagValue.PlanarConfiguration) + ExifShort planarConfig = new(ExifTagValue.PlanarConfiguration) { Value = (ushort)TiffPlanarConfiguration.Chunky }; - var samplesPerPixel = new ExifLong(ExifTagValue.SamplesPerPixel) + ExifLong samplesPerPixel = new(ExifTagValue.SamplesPerPixel) { Value = GetSamplesPerPixel(encoder) }; ushort[] bitsPerSampleValue = GetBitsPerSampleValue(encoder); - var bitPerSample = new ExifShortArray(ExifTagValue.BitsPerSample) + ExifShortArray bitPerSample = new(ExifTagValue.BitsPerSample) { Value = bitsPerSampleValue }; ushort compressionType = GetCompressionType(encoder); - var compression = new ExifShort(ExifTagValue.Compression) + ExifShort compression = new(ExifTagValue.Compression) { Value = compressionType }; - var photometricInterpretation = new ExifShort(ExifTagValue.PhotometricInterpretation) + ExifShort photometricInterpretation = new(ExifTagValue.PhotometricInterpretation) { Value = (ushort)encoder.PhotometricInterpretation }; @@ -306,32 +306,25 @@ internal class TiffEncoderEntriesCollector this.Collector.AddOrReplace(compression); this.Collector.AddOrReplace(photometricInterpretation); - if (encoder.HorizontalPredictor == TiffPredictor.Horizontal) + if (encoder.HorizontalPredictor == TiffPredictor.Horizontal && + (encoder.PhotometricInterpretation is TiffPhotometricInterpretation.Rgb or + TiffPhotometricInterpretation.PaletteColor or + TiffPhotometricInterpretation.BlackIsZero)) { - if (encoder.PhotometricInterpretation == TiffPhotometricInterpretation.Rgb || - encoder.PhotometricInterpretation == TiffPhotometricInterpretation.PaletteColor || - encoder.PhotometricInterpretation == TiffPhotometricInterpretation.BlackIsZero) - { - var predictor = new ExifShort(ExifTagValue.Predictor) { Value = (ushort)TiffPredictor.Horizontal }; + ExifShort predictor = new(ExifTagValue.Predictor) { Value = (ushort)TiffPredictor.Horizontal }; - this.Collector.AddOrReplace(predictor); - } + this.Collector.AddOrReplace(predictor); } } private static uint GetSamplesPerPixel(TiffEncoderCore encoder) - { - switch (encoder.PhotometricInterpretation) + => encoder.PhotometricInterpretation switch { - case TiffPhotometricInterpretation.PaletteColor: - case TiffPhotometricInterpretation.BlackIsZero: - case TiffPhotometricInterpretation.WhiteIsZero: - return 1; - case TiffPhotometricInterpretation.Rgb: - default: - return 3; - } - } + TiffPhotometricInterpretation.PaletteColor or + TiffPhotometricInterpretation.BlackIsZero or + TiffPhotometricInterpretation.WhiteIsZero => 1, + _ => 3, + }; private static ushort[] GetBitsPerSampleValue(TiffEncoderCore encoder) { @@ -342,10 +335,8 @@ internal class TiffEncoderEntriesCollector { return TiffConstants.BitsPerSample4Bit.ToArray(); } - else - { - return TiffConstants.BitsPerSample8Bit.ToArray(); - } + + return TiffConstants.BitsPerSample8Bit.ToArray(); case TiffPhotometricInterpretation.Rgb: return TiffConstants.BitsPerSampleRgb8Bit.ToArray(); @@ -382,9 +373,9 @@ internal class TiffEncoderEntriesCollector // PackBits is allowed for all modes. return (ushort)TiffCompression.PackBits; case TiffCompression.Lzw: - if (encoder.PhotometricInterpretation == TiffPhotometricInterpretation.Rgb || - encoder.PhotometricInterpretation == TiffPhotometricInterpretation.PaletteColor || - encoder.PhotometricInterpretation == TiffPhotometricInterpretation.BlackIsZero) + if (encoder.PhotometricInterpretation is TiffPhotometricInterpretation.Rgb or + TiffPhotometricInterpretation.PaletteColor or + TiffPhotometricInterpretation.BlackIsZero) { return (ushort)TiffCompression.Lzw; }