diff --git a/src/ImageSharp/Common/Helpers/UnitConverter.cs b/src/ImageSharp/Common/Helpers/UnitConverter.cs index 983d86a711..45dbe41cb9 100644 --- a/src/ImageSharp/Common/Helpers/UnitConverter.cs +++ b/src/ImageSharp/Common/Helpers/UnitConverter.cs @@ -91,10 +91,13 @@ internal static class UnitConverter [MethodImpl(InliningOptions.ShortMethod)] public static PixelResolutionUnit ExifProfileToResolutionUnit(ExifProfile profile) { - IExifValue? resolution = profile.GetValue(ExifTag.ResolutionUnit); + if (profile.TryGetValue(ExifTag.ResolutionUnit, out IExifValue? resolution)) + { + // EXIF is 1, 2, 3 so we minus "1" off the result. + return (PixelResolutionUnit)(byte)(resolution.Value - 1); + } - // EXIF is 1, 2, 3 so we minus "1" off the result. - return resolution is null ? DefaultResolutionUnit : (PixelResolutionUnit)(byte)(resolution.Value - 1); + return DefaultResolutionUnit; } /// diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 511ec1ba1d..77ea4e86fc 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -705,9 +705,12 @@ internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals private double GetExifResolutionValue(ExifTag tag) { - IExifValue resolution = this.Metadata.ExifProfile.GetValue(tag); + if (this.Metadata.ExifProfile.TryGetValue(tag, out IExifValue resolution)) + { + return resolution.Value.ToDouble(); + } - return resolution is null ? 0 : resolution.Value.ToDouble(); + return 0; } /// diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs index fb35ef2de3..382faa3874 100644 --- a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs +++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs @@ -82,7 +82,7 @@ public readonly struct TiffBitsPerSample : IEquatable /// The value to parse. /// The tiff bits per sample. /// True, if the value could be parsed. - public static bool TryParse(ushort[] value, out TiffBitsPerSample sample) + public static bool TryParse(ushort[]? value, out TiffBitsPerSample sample) { if (value is null || value.Length == 0) { diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index e74c53e22d..87784d1cb4 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -276,9 +276,15 @@ internal class TiffDecoderCore : IImageDecoderInternals private void DecodeImageWithStrips(ExifProfile tags, ImageFrame frame, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { - int rowsPerStrip = tags.GetValue(ExifTag.RowsPerStrip) != null - ? (int)tags.GetValue(ExifTag.RowsPerStrip).Value - : TiffConstants.RowsPerStripInfinity; + int rowsPerStrip; + if (tags.TryGetValue(ExifTag.RowsPerStrip, out IExifValue value)) + { + rowsPerStrip = (int)value.Value; + } + else + { + rowsPerStrip = TiffConstants.RowsPerStripInfinity; + } Array stripOffsetsArray = (Array)tags.GetValueInternal(ExifTag.StripOffsets).GetValue(); Array stripByteCountsArray = (Array)tags.GetValueInternal(ExifTag.StripByteCounts).GetValue(); @@ -320,8 +326,18 @@ internal class TiffDecoderCore : IImageDecoderInternals int width = pixels.Width; int height = pixels.Height; - int tileWidth = (int)tags.GetValue(ExifTag.TileWidth).Value; - int tileLength = (int)tags.GetValue(ExifTag.TileLength).Value; + if (!tags.TryGetValue(ExifTag.TileWidth, out IExifValue valueWidth)) + { + ArgumentNullException.ThrowIfNull(valueWidth); + } + + if (!tags.TryGetValue(ExifTag.TileWidth, out IExifValue valueLength)) + { + ArgumentNullException.ThrowIfNull(valueLength); + } + + int tileWidth = (int)valueWidth.Value; + int tileLength = (int)valueLength.Value; int tilesAcross = (width + tileWidth - 1) / tileWidth; int tilesDown = (height + tileLength - 1) / tileLength; @@ -775,8 +791,7 @@ internal class TiffDecoderCore : IImageDecoderInternals /// The image width. private static int GetImageWidth(ExifProfile exifProfile) { - IExifValue width = exifProfile.GetValue(ExifTag.ImageWidth); - if (width == null) + if (!exifProfile.TryGetValue(ExifTag.ImageWidth, out IExifValue width)) { TiffThrowHelper.ThrowImageFormatException("The TIFF image frame is missing the ImageWidth"); } @@ -793,8 +808,7 @@ internal class TiffDecoderCore : IImageDecoderInternals /// The image height. private static int GetImageHeight(ExifProfile exifProfile) { - IExifValue height = exifProfile.GetValue(ExifTag.ImageLength); - if (height == null) + if (!exifProfile.TryGetValue(ExifTag.ImageLength, out IExifValue height)) { TiffThrowHelper.ThrowImageFormatException("The TIFF image frame is missing the ImageLength"); } diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs index b6ce718f38..1a6c9dd7de 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs @@ -38,14 +38,12 @@ internal static class TiffDecoderMetadataCreator frameMetaData.IptcProfile = new IptcProfile(iptcBytes); } - IExifValue xmpProfileBytes = frameMetaData.ExifProfile.GetValue(ExifTag.XMP); - if (xmpProfileBytes != null) + if (frameMetaData.ExifProfile.TryGetValue(ExifTag.XMP, out IExifValue xmpProfileBytes)) { frameMetaData.XmpProfile = new XmpProfile(xmpProfileBytes.Value); } - IExifValue iccProfileBytes = frameMetaData.ExifProfile.GetValue(ExifTag.IccProfile); - if (iccProfileBytes != null) + if (frameMetaData.ExifProfile.TryGetValue(ExifTag.IccProfile, out IExifValue iccProfileBytes)) { frameMetaData.IccProfile = new IccProfile(iccProfileBytes.Value); } @@ -70,16 +68,20 @@ internal static class TiffDecoderMetadataCreator private static void SetResolution(ImageMetadata imageMetaData, ExifProfile exifProfile) { imageMetaData.ResolutionUnits = exifProfile != null ? UnitConverter.ExifProfileToResolutionUnit(exifProfile) : PixelResolutionUnit.PixelsPerInch; - double? horizontalResolution = exifProfile?.GetValue(ExifTag.XResolution)?.Value.ToDouble(); - if (horizontalResolution != null) + + if (exifProfile is null) + { + return; + } + + if (exifProfile.TryGetValue(ExifTag.XResolution, out IExifValue horizontalResolution)) { - imageMetaData.HorizontalResolution = horizontalResolution.Value; + imageMetaData.HorizontalResolution = horizontalResolution.Value.ToDouble(); } - double? verticalResolution = exifProfile?.GetValue(ExifTag.YResolution)?.Value.ToDouble(); - if (verticalResolution != null) + if (exifProfile.TryGetValue(ExifTag.YResolution, out IExifValue verticalResolution)) { - imageMetaData.VerticalResolution = verticalResolution.Value; + imageMetaData.VerticalResolution = verticalResolution.Value.ToDouble(); } } diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs index f20263602d..a13fb58de7 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs @@ -42,7 +42,16 @@ internal static class TiffDecoderOptionsParser } } - TiffFillOrder fillOrder = (TiffFillOrder?)exifProfile.GetValue(ExifTag.FillOrder)?.Value ?? TiffFillOrder.MostSignificantBitFirst; + TiffFillOrder fillOrder; + if (exifProfile.TryGetValue(ExifTag.FillOrder, out IExifValue value)) + { + fillOrder = (TiffFillOrder)value.Value; + } + else + { + fillOrder = TiffFillOrder.MostSignificantBitFirst; + } + if (fillOrder == TiffFillOrder.LeastSignificantBitFirst && frameMetadata.BitsPerPixel != TiffBitsPerPixel.Bit1) { TiffThrowHelper.ThrowNotSupported("The lower-order bits of the byte FillOrder is only supported in combination with 1bit per pixel bicolor tiff's."); @@ -53,10 +62,10 @@ internal static class TiffDecoderOptionsParser TiffThrowHelper.ThrowNotSupported("TIFF images with FloatingPoint horizontal predictor are not supported."); } - TiffSampleFormat[] sampleFormats = exifProfile.GetValue(ExifTag.SampleFormat)?.Value?.Select(a => (TiffSampleFormat)a).ToArray(); TiffSampleFormat? sampleFormat = null; - if (sampleFormats != null) + if (exifProfile.TryGetValue(ExifTag.SampleFormat, out var formatValue)) { + TiffSampleFormat[] sampleFormats = formatValue.Value.Select(a => (TiffSampleFormat)a).ToArray(); sampleFormat = sampleFormats[0]; foreach (TiffSampleFormat format in sampleFormats) { @@ -67,7 +76,12 @@ internal static class TiffDecoderOptionsParser } } - ushort[] ycbcrSubSampling = exifProfile.GetValue(ExifTag.YCbCrSubsampling)?.Value; + ushort[] ycbcrSubSampling = null; + if (exifProfile.TryGetValue(ExifTag.YCbCrSubsampling, out IExifValue subSamplingValue)) + { + ycbcrSubSampling = subSamplingValue.Value; + } + if (ycbcrSubSampling != null && ycbcrSubSampling.Length != 2) { TiffThrowHelper.ThrowImageFormatException("Invalid YCbCrSubsampling, expected 2 values."); @@ -78,23 +92,52 @@ internal static class TiffDecoderOptionsParser TiffThrowHelper.ThrowImageFormatException("ChromaSubsampleVert shall always be less than or equal to ChromaSubsampleHoriz."); } - if (exifProfile.GetValue(ExifTag.StripRowCounts)?.Value != null) + if (exifProfile.TryGetValue(ExifTag.StripRowCounts, out _)) { TiffThrowHelper.ThrowNotSupported("Variable-sized strips are not supported."); } - options.PlanarConfiguration = (TiffPlanarConfiguration?)exifProfile.GetValue(ExifTag.PlanarConfiguration)?.Value ?? DefaultPlanarConfiguration; + if (exifProfile.TryGetValue(ExifTag.PlanarConfiguration, out IExifValue planarValue)) + { + options.PlanarConfiguration = (TiffPlanarConfiguration)planarValue.Value; + } + else + { + options.PlanarConfiguration = DefaultPlanarConfiguration; + } + options.Predictor = frameMetadata.Predictor ?? TiffPredictor.None; options.PhotometricInterpretation = frameMetadata.PhotometricInterpretation ?? TiffPhotometricInterpretation.Rgb; options.SampleFormat = sampleFormat ?? TiffSampleFormat.UnsignedInteger; options.BitsPerPixel = frameMetadata.BitsPerPixel != null ? (int)frameMetadata.BitsPerPixel.Value : (int)TiffBitsPerPixel.Bit24; options.BitsPerSample = frameMetadata.BitsPerSample ?? new TiffBitsPerSample(0, 0, 0); - options.ReferenceBlackAndWhite = exifProfile.GetValue(ExifTag.ReferenceBlackWhite)?.Value; - options.YcbcrCoefficients = exifProfile.GetValue(ExifTag.YCbCrCoefficients)?.Value; - options.YcbcrSubSampling = exifProfile.GetValue(ExifTag.YCbCrSubsampling)?.Value; + + if (exifProfile.TryGetValue(ExifTag.ReferenceBlackWhite, out IExifValue blackWhiteValue)) + { + options.ReferenceBlackAndWhite = blackWhiteValue.Value; + } + + if (exifProfile.TryGetValue(ExifTag.YCbCrCoefficients, out IExifValue coefficientsValue)) + { + options.YcbcrCoefficients = coefficientsValue.Value; + } + + if (exifProfile.TryGetValue(ExifTag.YCbCrSubsampling, out IExifValue ycbrSubSamplingValue)) + { + options.YcbcrSubSampling = ycbrSubSamplingValue.Value; + } + options.FillOrder = fillOrder; - options.JpegTables = exifProfile.GetValue(ExifTag.JPEGTables)?.Value; - options.OldJpegCompressionStartOfImageMarker = exifProfile.GetValue(ExifTag.JPEGInterchangeFormat)?.Value; + + if (exifProfile.TryGetValue(ExifTag.JPEGTables, out IExifValue jpegTablesValue)) + { + options.JpegTables = jpegTablesValue.Value; + } + + if (exifProfile.TryGetValue(ExifTag.JPEGInterchangeFormat, out IExifValue jpegInterchangeFormatValue)) + { + options.OldJpegCompressionStartOfImageMarker = jpegInterchangeFormatValue.Value; + } options.ParseColorType(exifProfile); options.ParseCompression(frameMetadata.Compression, exifProfile); @@ -394,9 +437,9 @@ internal static class TiffDecoderOptionsParser case TiffPhotometricInterpretation.PaletteColor: { - options.ColorMap = exifProfile.GetValue(ExifTag.ColorMap)?.Value; - if (options.ColorMap != null) + if (exifProfile.TryGetValue(ExifTag.ColorMap, out IExifValue value)) { + options.ColorMap = value.Value; if (options.BitsPerSample.Channels != 1) { TiffThrowHelper.ThrowNotSupported("The number of samples in the TIFF BitsPerSample entry is not supported."); @@ -414,7 +457,11 @@ internal static class TiffDecoderOptionsParser case TiffPhotometricInterpretation.YCbCr: { - options.ColorMap = exifProfile.GetValue(ExifTag.ColorMap)?.Value; + if (exifProfile.TryGetValue(ExifTag.ColorMap, out IExifValue value)) + { + options.ColorMap = value.Value; + } + if (options.BitsPerSample.Channels != 3) { TiffThrowHelper.ThrowNotSupported("The number of samples in the TIFF BitsPerSample entry is not supported for YCbCr images."); @@ -508,7 +555,15 @@ internal static class TiffDecoderOptionsParser case TiffCompression.CcittGroup3Fax: { options.CompressionType = TiffDecoderCompressionType.T4; - options.FaxCompressionOptions = exifProfile.GetValue(ExifTag.T4Options) != null ? (FaxCompressionOptions)exifProfile.GetValue(ExifTag.T4Options).Value : FaxCompressionOptions.None; + + if (exifProfile.TryGetValue(ExifTag.T4Options, out IExifValue t4OptionsValue)) + { + options.FaxCompressionOptions = (FaxCompressionOptions)t4OptionsValue.Value; + } + else + { + options.FaxCompressionOptions = FaxCompressionOptions.None; + } break; } @@ -516,7 +571,14 @@ internal static class TiffDecoderOptionsParser case TiffCompression.CcittGroup4Fax: { options.CompressionType = TiffDecoderCompressionType.T6; - options.FaxCompressionOptions = exifProfile.GetValue(ExifTag.T4Options) != null ? (FaxCompressionOptions)exifProfile.GetValue(ExifTag.T4Options).Value : FaxCompressionOptions.None; + if (exifProfile.TryGetValue(ExifTag.T4Options, out IExifValue t4OptionsValue)) + { + options.FaxCompressionOptions = (FaxCompressionOptions)t4OptionsValue.Value; + } + else + { + options.FaxCompressionOptions = FaxCompressionOptions.None; + } break; } diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs index 8da2c26dee..3a4e71d3e8 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs @@ -164,8 +164,6 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals { cancellationToken.ThrowIfCancellationRequested(); - TiffNewSubfileType subfileType = (TiffNewSubfileType)(frame.Metadata.ExifProfile?.GetValue(ExifTag.SubfileType)?.Value ?? (int)TiffNewSubfileType.FullImage); - ifdMarker = this.WriteFrame(writer, frame, image.Metadata, metadataImage, ifdMarker); metadataImage = null; } diff --git a/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs b/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs index 956213c231..5d0b85bf22 100644 --- a/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs +++ b/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using SixLabors.ImageSharp.Formats.Tiff.Constants; using SixLabors.ImageSharp.Metadata.Profiles.Exif; @@ -78,15 +77,30 @@ public class TiffFrameMetadata : IDeepCloneable { if (profile != null) { - if (TiffBitsPerSample.TryParse(profile.GetValue(ExifTag.BitsPerSample)?.Value, out TiffBitsPerSample bitsPerSample)) + if (profile.TryGetValue(ExifTag.BitsPerSample, out IExifValue? bitsPerSampleValue)) { - meta.BitsPerSample = bitsPerSample; + if (TiffBitsPerSample.TryParse(bitsPerSampleValue.Value, out TiffBitsPerSample bitsPerSample)) + { + meta.BitsPerSample = bitsPerSample; + } } meta.BitsPerPixel = meta.BitsPerSample?.BitsPerPixel(); - meta.Compression = (TiffCompression?)profile.GetValue(ExifTag.Compression)?.Value; - meta.PhotometricInterpretation = (TiffPhotometricInterpretation?)profile.GetValue(ExifTag.PhotometricInterpretation)?.Value; - meta.Predictor = (TiffPredictor?)profile.GetValue(ExifTag.Predictor)?.Value; + + if (profile.TryGetValue(ExifTag.Compression, out IExifValue? compressionValue)) + { + meta.Compression = (TiffCompression)compressionValue.Value; + } + + if (profile.TryGetValue(ExifTag.PhotometricInterpretation, out IExifValue? photometricInterpretationValue)) + { + meta.PhotometricInterpretation = (TiffPhotometricInterpretation)photometricInterpretationValue.Value; + } + + if (profile.TryGetValue(ExifTag.Predictor, out IExifValue? predictorValue)) + { + meta.Predictor = (TiffPredictor)predictorValue.Value; + } profile.RemoveValue(ExifTag.BitsPerSample); profile.RemoveValue(ExifTag.Compression); diff --git a/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs b/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs index b2cc638ba0..3957ccb02f 100644 --- a/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs +++ b/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs @@ -1,21 +1,30 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; + namespace SixLabors.ImageSharp.Formats.Tiff; internal static class TiffThrowHelper { + [DoesNotReturn] public static Exception ThrowImageFormatException(string errorMessage) => throw new ImageFormatException(errorMessage); + [DoesNotReturn] public static Exception NotSupportedDecompressor(string compressionType) => throw new NotSupportedException($"Not supported decoder compression method: {compressionType}"); + [DoesNotReturn] public static Exception NotSupportedCompressor(string compressionType) => throw new NotSupportedException($"Not supported encoder compression method: {compressionType}"); + [DoesNotReturn] public static Exception InvalidColorType(string colorType) => throw new NotSupportedException($"Invalid color type: {colorType}"); + [DoesNotReturn] public static Exception ThrowInvalidHeader() => throw new ImageFormatException("Invalid TIFF file header."); + [DoesNotReturn] public static void ThrowNotSupported(string message) => throw new NotSupportedException(message); + [DoesNotReturn] public static void ThrowArgumentException(string message) => throw new ArgumentException(message); } diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs index ebe20cff6b..e14c88229d 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs @@ -172,12 +172,21 @@ public sealed class ExifProfile : IDeepCloneable /// Returns the value with the specified tag. /// /// The tag of the exif value. - /// The value with the specified tag. + /// The value with the specified tag. + /// True when found, otherwise false /// The data type of the tag. - public IExifValue? GetValue(ExifTag tag) + public bool TryGetValue(ExifTag tag, [NotNullWhen(true)] out IExifValue? exifValue) { IExifValue? value = this.GetValueInternal(tag); - return value is null ? null : (IExifValue)value; + + if (value is null) + { + exifValue = null; + return false; + } + + exifValue = (IExifValue)value; + return true; } /// @@ -291,9 +300,7 @@ public sealed class ExifProfile : IDeepCloneable private void SyncResolution(ExifTag tag, double resolution) { - IExifValue? value = this.GetValue(tag); - - if (value is null) + if (!this.TryGetValue(tag, out IExifValue? value)) { return; } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs index 6d70bd3797..0ad6842128 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs @@ -88,8 +88,7 @@ internal class AutoOrientProcessor : ImageProcessor return ExifOrientationMode.Unknown; } - IExifValue? value = source.Metadata.ExifProfile.GetValue(ExifTag.Orientation); - if (value is null) + if (!source.Metadata.ExifProfile.TryGetValue(ExifTag.Orientation, out IExifValue? value)) { return ExifOrientationMode.Unknown; } diff --git a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs index 172d7d677f..0bb4920f0f 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs @@ -26,12 +26,12 @@ internal static class TransformProcessorHelpers } // Only set the value if it already exists. - if (profile.GetValue(ExifTag.PixelXDimension) != null) + if (profile.TryGetValue(ExifTag.PixelXDimension, out _)) { profile.SetValue(ExifTag.PixelXDimension, image.Width); } - if (profile.GetValue(ExifTag.PixelYDimension) != null) + if (profile.TryGetValue(ExifTag.PixelYDimension, out _)) { profile.SetValue(ExifTag.PixelYDimension, image.Height); } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs index 7e0b1de82b..9bff30b6f4 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs @@ -8,6 +8,7 @@ using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Jpg; diff --git a/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs index 9653a06564..d7a353665a 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs @@ -6,6 +6,7 @@ using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; namespace SixLabors.ImageSharp.Tests.Formats.Png; diff --git a/tests/ImageSharp.Tests/Formats/Tiff/BigTiffDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/BigTiffDecoderTests.cs index 5c110844c3..8e90b1dd57 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/BigTiffDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/BigTiffDecoderTests.cs @@ -6,6 +6,7 @@ using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using static SixLabors.ImageSharp.Tests.TestImages.BigTiff; diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderBaseTester.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderBaseTester.cs index 6da0d4fd89..2a822e7054 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderBaseTester.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderBaseTester.cs @@ -6,6 +6,7 @@ using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Tiff.Constants; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs index 2a809e895a..51c0b6ef7e 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs @@ -10,6 +10,7 @@ using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Iptc; using SixLabors.ImageSharp.Metadata.Profiles.Xmp; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; using static SixLabors.ImageSharp.Tests.TestImages.Tiff; namespace SixLabors.ImageSharp.Tests.Formats.Tiff; @@ -167,9 +168,9 @@ public class TiffMetadataTests Assert.Equal("Make", exifProfile.GetValue(ExifTag.Make).Value); Assert.Equal("Model", exifProfile.GetValue(ExifTag.Model).Value); Assert.Equal("ImageSharp", exifProfile.GetValue(ExifTag.Software).Value); - Assert.Null(exifProfile.GetValue(ExifTag.DateTime)?.Value); + Assert.Null(exifProfile.GetValue(ExifTag.DateTime, false)?.Value); Assert.Equal("Artist", exifProfile.GetValue(ExifTag.Artist).Value); - Assert.Null(exifProfile.GetValue(ExifTag.HostComputer)?.Value); + Assert.Null(exifProfile.GetValue(ExifTag.HostComputer, false)?.Value); Assert.Equal("Copyright", exifProfile.GetValue(ExifTag.Copyright).Value); Assert.Equal(4, exifProfile.GetValue(ExifTag.Rating).Value); Assert.Equal(75, exifProfile.GetValue(ExifTag.RatingPercent).Value); @@ -178,9 +179,9 @@ public class TiffMetadataTests Assert.Equal(expectedResolution, exifProfile.GetValue(ExifTag.YResolution).Value); Assert.Equal(new Number[] { 8u }, exifProfile.GetValue(ExifTag.StripOffsets)?.Value, new NumberComparer()); Assert.Equal(new Number[] { 285u }, exifProfile.GetValue(ExifTag.StripByteCounts)?.Value, new NumberComparer()); - Assert.Null(exifProfile.GetValue(ExifTag.ExtraSamples)?.Value); + Assert.Null(exifProfile.GetValue(ExifTag.ExtraSamples, false)?.Value); Assert.Equal(32u, exifProfile.GetValue(ExifTag.RowsPerStrip).Value); - Assert.Null(exifProfile.GetValue(ExifTag.SampleFormat)); + Assert.Null(exifProfile.GetValue(ExifTag.SampleFormat, false)); Assert.Equal(PixelResolutionUnit.PixelsPerInch, UnitConverter.ExifProfileToResolutionUnit(exifProfile)); ushort[] colorMap = exifProfile.GetValue(ExifTag.ColorMap)?.Value; Assert.NotNull(colorMap); diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs index c0c2e375f4..ab8fef60f7 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs @@ -5,6 +5,7 @@ using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Webp; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Webp; diff --git a/tests/ImageSharp.Tests/Metadata/ImageMetadataTests.cs b/tests/ImageSharp.Tests/Metadata/ImageMetadataTests.cs index 9b1e42d016..330b701474 100644 --- a/tests/ImageSharp.Tests/Metadata/ImageMetadataTests.cs +++ b/tests/ImageSharp.Tests/Metadata/ImageMetadataTests.cs @@ -4,6 +4,7 @@ using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; namespace SixLabors.ImageSharp.Tests.Metadata; diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs index 873bc9ca2c..8072bebd77 100644 --- a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs +++ b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs @@ -7,6 +7,7 @@ using SixLabors.ImageSharp.Formats.Webp; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif; @@ -255,7 +256,7 @@ public class ExifProfileTests xResolution = image.Metadata.ExifProfile.GetValue(ExifTag.XResolution); Assert.Equal(new Rational(150.0), xResolution.Value); - referenceBlackWhite = image.Metadata.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite); + referenceBlackWhite = image.Metadata.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite, false); Assert.Null(referenceBlackWhite); latitude = image.Metadata.ExifProfile.GetValue(ExifTag.GPSLatitude); @@ -300,7 +301,7 @@ public class ExifProfileTests Assert.NotNull(image.Metadata.ExifProfile.GetValue(ExifTag.ColorSpace)); Assert.True(image.Metadata.ExifProfile.RemoveValue(ExifTag.ColorSpace)); Assert.False(image.Metadata.ExifProfile.RemoveValue(ExifTag.ColorSpace)); - Assert.Null(image.Metadata.ExifProfile.GetValue(ExifTag.ColorSpace)); + Assert.Null(image.Metadata.ExifProfile.GetValue(ExifTag.ColorSpace, false)); Assert.Equal(profileCount - 1, image.Metadata.ExifProfile.Values.Count); } diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifTagDescriptionAttributeTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifTagDescriptionAttributeTests.cs index d2198f9cae..1154b3439c 100644 --- a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifTagDescriptionAttributeTests.cs +++ b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifTagDescriptionAttributeTests.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Metadata.Profiles.Exif; +using SixLabors.ImageSharp.Tests.TestUtilities; namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif; diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifValueTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifValueTests.cs index 548329250e..d04aa5e765 100644 --- a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifValueTests.cs +++ b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifValueTests.cs @@ -23,7 +23,9 @@ public class ExifValueTests { Assert.NotNull(this.profile); - return this.profile.GetValue(ExifTag.Software); + this.profile.TryGetValue(ExifTag.Software, out IExifValue value); + + return value; } [Fact] diff --git a/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs index 594eb7e7c8..21b92a01e8 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs @@ -4,6 +4,7 @@ using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Transforms; +using SixLabors.ImageSharp.Tests.TestUtilities; namespace SixLabors.ImageSharp.Tests.Processing.Transforms; diff --git a/tests/ImageSharp.Tests/TestUtilities/ExifProfileExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/ExifProfileExtensions.cs new file mode 100644 index 0000000000..259b6a9335 --- /dev/null +++ b/tests/ImageSharp.Tests/TestUtilities/ExifProfileExtensions.cs @@ -0,0 +1,18 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using SixLabors.ImageSharp.Metadata.Profiles.Exif; + +namespace SixLabors.ImageSharp.Tests.TestUtilities; + +public static class ExifProfileExtensions +{ + public static IExifValue GetValue(this ExifProfile exifProfileInput, ExifTag tag, bool assertTrue = true) + { + bool boolValue = exifProfileInput.TryGetValue(tag, out IExifValue value); + + Assert.Equal(assertTrue, boolValue); + + return value; + } +}