Skip to content

Commit 22840b3

Browse files
Merge pull request #2320 from stefannikolei/stefannikolei/nullable/exifprofile
Remove #nullable disable from ExifProfile
2 parents 84dcd18 + 54df7ab commit 22840b3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+356
-196
lines changed

src/ImageSharp/Common/Helpers/UnitConverter.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,13 @@ internal static class UnitConverter
9191
[MethodImpl(InliningOptions.ShortMethod)]
9292
public static PixelResolutionUnit ExifProfileToResolutionUnit(ExifProfile profile)
9393
{
94-
IExifValue<ushort> resolution = profile.GetValue(ExifTag.ResolutionUnit);
94+
if (profile.TryGetValue(ExifTag.ResolutionUnit, out IExifValue<ushort>? resolution))
95+
{
96+
// EXIF is 1, 2, 3 so we minus "1" off the result.
97+
return (PixelResolutionUnit)(byte)(resolution.Value - 1);
98+
}
9599

96-
// EXIF is 1, 2, 3 so we minus "1" off the result.
97-
return resolution is null ? DefaultResolutionUnit : (PixelResolutionUnit)(byte)(resolution.Value - 1);
100+
return DefaultResolutionUnit;
98101
}
99102

100103
/// <summary>

src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -717,9 +717,12 @@ private void InitDerivedMetadataProperties()
717717

718718
private double GetExifResolutionValue(ExifTag<Rational> tag)
719719
{
720-
IExifValue<Rational> resolution = this.Metadata.ExifProfile.GetValue(tag);
720+
if (this.Metadata.ExifProfile.TryGetValue(tag, out IExifValue<Rational> resolution))
721+
{
722+
return resolution.Value.ToDouble();
723+
}
721724

722-
return resolution is null ? 0 : resolution.Value.ToDouble();
725+
return 0;
723726
}
724727

725728
/// <summary>

src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public TiffBitsPerSample(ushort channel0, ushort channel1, ushort channel2, usho
8282
/// <param name="value">The value to parse.</param>
8383
/// <param name="sample">The tiff bits per sample.</param>
8484
/// <returns>True, if the value could be parsed.</returns>
85-
public static bool TryParse(ushort[] value, out TiffBitsPerSample sample)
85+
public static bool TryParse(ushort[]? value, out TiffBitsPerSample sample)
8686
{
8787
if (value is null || value.Length == 0)
8888
{

src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,15 @@ private ImageFrame<TPixel> DecodeFrame<TPixel>(ExifProfile tags, CancellationTok
276276
private void DecodeImageWithStrips<TPixel>(ExifProfile tags, ImageFrame<TPixel> frame, CancellationToken cancellationToken)
277277
where TPixel : unmanaged, IPixel<TPixel>
278278
{
279-
int rowsPerStrip = tags.GetValue(ExifTag.RowsPerStrip) != null
280-
? (int)tags.GetValue(ExifTag.RowsPerStrip).Value
281-
: TiffConstants.RowsPerStripInfinity;
279+
int rowsPerStrip;
280+
if (tags.TryGetValue(ExifTag.RowsPerStrip, out IExifValue<Number> value))
281+
{
282+
rowsPerStrip = (int)value.Value;
283+
}
284+
else
285+
{
286+
rowsPerStrip = TiffConstants.RowsPerStripInfinity;
287+
}
282288

283289
Array stripOffsetsArray = (Array)tags.GetValueInternal(ExifTag.StripOffsets).GetValue();
284290
Array stripByteCountsArray = (Array)tags.GetValueInternal(ExifTag.StripByteCounts).GetValue();
@@ -320,8 +326,18 @@ private void DecodeImageWithTiles<TPixel>(ExifProfile tags, ImageFrame<TPixel> f
320326
int width = pixels.Width;
321327
int height = pixels.Height;
322328

323-
int tileWidth = (int)tags.GetValue(ExifTag.TileWidth).Value;
324-
int tileLength = (int)tags.GetValue(ExifTag.TileLength).Value;
329+
if (!tags.TryGetValue(ExifTag.TileWidth, out IExifValue<Number> valueWidth))
330+
{
331+
ArgumentNullException.ThrowIfNull(valueWidth);
332+
}
333+
334+
if (!tags.TryGetValue(ExifTag.TileWidth, out IExifValue<Number> valueLength))
335+
{
336+
ArgumentNullException.ThrowIfNull(valueLength);
337+
}
338+
339+
int tileWidth = (int)valueWidth.Value;
340+
int tileLength = (int)valueLength.Value;
325341
int tilesAcross = (width + tileWidth - 1) / tileWidth;
326342
int tilesDown = (height + tileLength - 1) / tileLength;
327343

@@ -775,10 +791,9 @@ private int CalculateStripBufferSize(int width, int height, int plane = -1)
775791
/// <returns>The image width.</returns>
776792
private static int GetImageWidth(ExifProfile exifProfile)
777793
{
778-
IExifValue<Number> width = exifProfile.GetValue(ExifTag.ImageWidth);
779-
if (width == null)
794+
if (!exifProfile.TryGetValue(ExifTag.ImageWidth, out IExifValue<Number> width))
780795
{
781-
TiffThrowHelper.ThrowImageFormatException("The TIFF image frame is missing the ImageWidth");
796+
TiffThrowHelper.ThrowInvalidImageContentException("The TIFF image frame is missing the ImageWidth");
782797
}
783798

784799
DebugGuard.MustBeLessThanOrEqualTo((ulong)width.Value, (ulong)int.MaxValue, nameof(ExifTag.ImageWidth));
@@ -793,8 +808,7 @@ private static int GetImageWidth(ExifProfile exifProfile)
793808
/// <returns>The image height.</returns>
794809
private static int GetImageHeight(ExifProfile exifProfile)
795810
{
796-
IExifValue<Number> height = exifProfile.GetValue(ExifTag.ImageLength);
797-
if (height == null)
811+
if (!exifProfile.TryGetValue(ExifTag.ImageLength, out IExifValue<Number> height))
798812
{
799813
TiffThrowHelper.ThrowImageFormatException("The TIFF image frame is missing the ImageLength");
800814
}

src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,12 @@ public static ImageMetadata Create<TPixel>(List<ImageFrame<TPixel>> frames, bool
3838
frameMetaData.IptcProfile = new IptcProfile(iptcBytes);
3939
}
4040

41-
IExifValue<byte[]> xmpProfileBytes = frameMetaData.ExifProfile.GetValue(ExifTag.XMP);
42-
if (xmpProfileBytes != null)
41+
if (frameMetaData.ExifProfile.TryGetValue(ExifTag.XMP, out IExifValue<byte[]> xmpProfileBytes))
4342
{
4443
frameMetaData.XmpProfile = new XmpProfile(xmpProfileBytes.Value);
4544
}
4645

47-
IExifValue<byte[]> iccProfileBytes = frameMetaData.ExifProfile.GetValue(ExifTag.IccProfile);
48-
if (iccProfileBytes != null)
46+
if (frameMetaData.ExifProfile.TryGetValue(ExifTag.IccProfile, out IExifValue<byte[]> iccProfileBytes))
4947
{
5048
frameMetaData.IccProfile = new IccProfile(iccProfileBytes.Value);
5149
}
@@ -70,16 +68,20 @@ public static ImageMetadata Create(ByteOrder byteOrder, bool isBigTiff, ExifProf
7068
private static void SetResolution(ImageMetadata imageMetaData, ExifProfile exifProfile)
7169
{
7270
imageMetaData.ResolutionUnits = exifProfile != null ? UnitConverter.ExifProfileToResolutionUnit(exifProfile) : PixelResolutionUnit.PixelsPerInch;
73-
double? horizontalResolution = exifProfile?.GetValue(ExifTag.XResolution)?.Value.ToDouble();
74-
if (horizontalResolution != null)
71+
72+
if (exifProfile is null)
73+
{
74+
return;
75+
}
76+
77+
if (exifProfile.TryGetValue(ExifTag.XResolution, out IExifValue<Rational> horizontalResolution))
7578
{
76-
imageMetaData.HorizontalResolution = horizontalResolution.Value;
79+
imageMetaData.HorizontalResolution = horizontalResolution.Value.ToDouble();
7780
}
7881

79-
double? verticalResolution = exifProfile?.GetValue(ExifTag.YResolution)?.Value.ToDouble();
80-
if (verticalResolution != null)
82+
if (exifProfile.TryGetValue(ExifTag.YResolution, out IExifValue<Rational> verticalResolution))
8183
{
82-
imageMetaData.VerticalResolution = verticalResolution.Value;
84+
imageMetaData.VerticalResolution = verticalResolution.Value.ToDouble();
8385
}
8486
}
8587

src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,16 @@ public static bool VerifyAndParse(this TiffDecoderCore options, ExifProfile exif
4242
}
4343
}
4444

45-
TiffFillOrder fillOrder = (TiffFillOrder?)exifProfile.GetValue(ExifTag.FillOrder)?.Value ?? TiffFillOrder.MostSignificantBitFirst;
45+
TiffFillOrder fillOrder;
46+
if (exifProfile.TryGetValue(ExifTag.FillOrder, out IExifValue<ushort> value))
47+
{
48+
fillOrder = (TiffFillOrder)value.Value;
49+
}
50+
else
51+
{
52+
fillOrder = TiffFillOrder.MostSignificantBitFirst;
53+
}
54+
4655
if (fillOrder == TiffFillOrder.LeastSignificantBitFirst && frameMetadata.BitsPerPixel != TiffBitsPerPixel.Bit1)
4756
{
4857
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 @@ public static bool VerifyAndParse(this TiffDecoderCore options, ExifProfile exif
5362
TiffThrowHelper.ThrowNotSupported("TIFF images with FloatingPoint horizontal predictor are not supported.");
5463
}
5564

56-
TiffSampleFormat[] sampleFormats = exifProfile.GetValue(ExifTag.SampleFormat)?.Value?.Select(a => (TiffSampleFormat)a).ToArray();
5765
TiffSampleFormat? sampleFormat = null;
58-
if (sampleFormats != null)
66+
if (exifProfile.TryGetValue(ExifTag.SampleFormat, out var formatValue))
5967
{
68+
TiffSampleFormat[] sampleFormats = formatValue.Value.Select(a => (TiffSampleFormat)a).ToArray();
6069
sampleFormat = sampleFormats[0];
6170
foreach (TiffSampleFormat format in sampleFormats)
6271
{
@@ -67,7 +76,12 @@ public static bool VerifyAndParse(this TiffDecoderCore options, ExifProfile exif
6776
}
6877
}
6978

70-
ushort[] ycbcrSubSampling = exifProfile.GetValue(ExifTag.YCbCrSubsampling)?.Value;
79+
ushort[] ycbcrSubSampling = null;
80+
if (exifProfile.TryGetValue(ExifTag.YCbCrSubsampling, out IExifValue<ushort[]> subSamplingValue))
81+
{
82+
ycbcrSubSampling = subSamplingValue.Value;
83+
}
84+
7185
if (ycbcrSubSampling != null && ycbcrSubSampling.Length != 2)
7286
{
7387
TiffThrowHelper.ThrowImageFormatException("Invalid YCbCrSubsampling, expected 2 values.");
@@ -78,23 +92,52 @@ public static bool VerifyAndParse(this TiffDecoderCore options, ExifProfile exif
7892
TiffThrowHelper.ThrowImageFormatException("ChromaSubsampleVert shall always be less than or equal to ChromaSubsampleHoriz.");
7993
}
8094

81-
if (exifProfile.GetValue(ExifTag.StripRowCounts)?.Value != null)
95+
if (exifProfile.TryGetValue(ExifTag.StripRowCounts, out _))
8296
{
8397
TiffThrowHelper.ThrowNotSupported("Variable-sized strips are not supported.");
8498
}
8599

86-
options.PlanarConfiguration = (TiffPlanarConfiguration?)exifProfile.GetValue(ExifTag.PlanarConfiguration)?.Value ?? DefaultPlanarConfiguration;
100+
if (exifProfile.TryGetValue(ExifTag.PlanarConfiguration, out IExifValue<ushort> planarValue))
101+
{
102+
options.PlanarConfiguration = (TiffPlanarConfiguration)planarValue.Value;
103+
}
104+
else
105+
{
106+
options.PlanarConfiguration = DefaultPlanarConfiguration;
107+
}
108+
87109
options.Predictor = frameMetadata.Predictor ?? TiffPredictor.None;
88110
options.PhotometricInterpretation = frameMetadata.PhotometricInterpretation ?? TiffPhotometricInterpretation.Rgb;
89111
options.SampleFormat = sampleFormat ?? TiffSampleFormat.UnsignedInteger;
90112
options.BitsPerPixel = frameMetadata.BitsPerPixel != null ? (int)frameMetadata.BitsPerPixel.Value : (int)TiffBitsPerPixel.Bit24;
91113
options.BitsPerSample = frameMetadata.BitsPerSample ?? new TiffBitsPerSample(0, 0, 0);
92-
options.ReferenceBlackAndWhite = exifProfile.GetValue(ExifTag.ReferenceBlackWhite)?.Value;
93-
options.YcbcrCoefficients = exifProfile.GetValue(ExifTag.YCbCrCoefficients)?.Value;
94-
options.YcbcrSubSampling = exifProfile.GetValue(ExifTag.YCbCrSubsampling)?.Value;
114+
115+
if (exifProfile.TryGetValue(ExifTag.ReferenceBlackWhite, out IExifValue<Rational[]> blackWhiteValue))
116+
{
117+
options.ReferenceBlackAndWhite = blackWhiteValue.Value;
118+
}
119+
120+
if (exifProfile.TryGetValue(ExifTag.YCbCrCoefficients, out IExifValue<Rational[]> coefficientsValue))
121+
{
122+
options.YcbcrCoefficients = coefficientsValue.Value;
123+
}
124+
125+
if (exifProfile.TryGetValue(ExifTag.YCbCrSubsampling, out IExifValue<ushort[]> ycbrSubSamplingValue))
126+
{
127+
options.YcbcrSubSampling = ycbrSubSamplingValue.Value;
128+
}
129+
95130
options.FillOrder = fillOrder;
96-
options.JpegTables = exifProfile.GetValue(ExifTag.JPEGTables)?.Value;
97-
options.OldJpegCompressionStartOfImageMarker = exifProfile.GetValue(ExifTag.JPEGInterchangeFormat)?.Value;
131+
132+
if (exifProfile.TryGetValue(ExifTag.JPEGTables, out IExifValue<byte[]> jpegTablesValue))
133+
{
134+
options.JpegTables = jpegTablesValue.Value;
135+
}
136+
137+
if (exifProfile.TryGetValue(ExifTag.JPEGInterchangeFormat, out IExifValue<uint> jpegInterchangeFormatValue))
138+
{
139+
options.OldJpegCompressionStartOfImageMarker = jpegInterchangeFormatValue.Value;
140+
}
98141

99142
options.ParseColorType(exifProfile);
100143
options.ParseCompression(frameMetadata.Compression, exifProfile);
@@ -394,9 +437,9 @@ private static void ParseColorType(this TiffDecoderCore options, ExifProfile exi
394437

395438
case TiffPhotometricInterpretation.PaletteColor:
396439
{
397-
options.ColorMap = exifProfile.GetValue(ExifTag.ColorMap)?.Value;
398-
if (options.ColorMap != null)
440+
if (exifProfile.TryGetValue(ExifTag.ColorMap, out IExifValue<ushort[]> value))
399441
{
442+
options.ColorMap = value.Value;
400443
if (options.BitsPerSample.Channels != 1)
401444
{
402445
TiffThrowHelper.ThrowNotSupported("The number of samples in the TIFF BitsPerSample entry is not supported.");
@@ -414,7 +457,11 @@ private static void ParseColorType(this TiffDecoderCore options, ExifProfile exi
414457

415458
case TiffPhotometricInterpretation.YCbCr:
416459
{
417-
options.ColorMap = exifProfile.GetValue(ExifTag.ColorMap)?.Value;
460+
if (exifProfile.TryGetValue(ExifTag.ColorMap, out IExifValue<ushort[]> value))
461+
{
462+
options.ColorMap = value.Value;
463+
}
464+
418465
if (options.BitsPerSample.Channels != 3)
419466
{
420467
TiffThrowHelper.ThrowNotSupported("The number of samples in the TIFF BitsPerSample entry is not supported for YCbCr images.");
@@ -508,15 +555,30 @@ private static void ParseCompression(this TiffDecoderCore options, TiffCompressi
508555
case TiffCompression.CcittGroup3Fax:
509556
{
510557
options.CompressionType = TiffDecoderCompressionType.T4;
511-
options.FaxCompressionOptions = exifProfile.GetValue(ExifTag.T4Options) != null ? (FaxCompressionOptions)exifProfile.GetValue(ExifTag.T4Options).Value : FaxCompressionOptions.None;
558+
559+
if (exifProfile.TryGetValue(ExifTag.T4Options, out IExifValue<uint> t4OptionsValue))
560+
{
561+
options.FaxCompressionOptions = (FaxCompressionOptions)t4OptionsValue.Value;
562+
}
563+
else
564+
{
565+
options.FaxCompressionOptions = FaxCompressionOptions.None;
566+
}
512567

513568
break;
514569
}
515570

516571
case TiffCompression.CcittGroup4Fax:
517572
{
518573
options.CompressionType = TiffDecoderCompressionType.T6;
519-
options.FaxCompressionOptions = exifProfile.GetValue(ExifTag.T4Options) != null ? (FaxCompressionOptions)exifProfile.GetValue(ExifTag.T4Options).Value : FaxCompressionOptions.None;
574+
if (exifProfile.TryGetValue(ExifTag.T4Options, out IExifValue<uint> t4OptionsValue))
575+
{
576+
options.FaxCompressionOptions = (FaxCompressionOptions)t4OptionsValue.Value;
577+
}
578+
else
579+
{
580+
options.FaxCompressionOptions = FaxCompressionOptions.None;
581+
}
520582

521583
break;
522584
}

src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,6 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
164164
{
165165
cancellationToken.ThrowIfCancellationRequested();
166166

167-
TiffNewSubfileType subfileType = (TiffNewSubfileType)(frame.Metadata.ExifProfile?.GetValue(ExifTag.SubfileType)?.Value ?? (int)TiffNewSubfileType.FullImage);
168-
169167
ifdMarker = this.WriteFrame(writer, frame, image.Metadata, metadataImage, ifdMarker);
170168
metadataImage = null;
171169
}

src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
3-
#nullable disable
43

54
using SixLabors.ImageSharp.Formats.Tiff.Constants;
65
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
@@ -78,15 +77,30 @@ internal static void Parse(TiffFrameMetadata meta, ExifProfile profile)
7877
{
7978
if (profile != null)
8079
{
81-
if (TiffBitsPerSample.TryParse(profile.GetValue(ExifTag.BitsPerSample)?.Value, out TiffBitsPerSample bitsPerSample))
80+
if (profile.TryGetValue(ExifTag.BitsPerSample, out IExifValue<ushort[]>? bitsPerSampleValue))
8281
{
83-
meta.BitsPerSample = bitsPerSample;
82+
if (TiffBitsPerSample.TryParse(bitsPerSampleValue.Value, out TiffBitsPerSample bitsPerSample))
83+
{
84+
meta.BitsPerSample = bitsPerSample;
85+
}
8486
}
8587

8688
meta.BitsPerPixel = meta.BitsPerSample?.BitsPerPixel();
87-
meta.Compression = (TiffCompression?)profile.GetValue(ExifTag.Compression)?.Value;
88-
meta.PhotometricInterpretation = (TiffPhotometricInterpretation?)profile.GetValue(ExifTag.PhotometricInterpretation)?.Value;
89-
meta.Predictor = (TiffPredictor?)profile.GetValue(ExifTag.Predictor)?.Value;
89+
90+
if (profile.TryGetValue(ExifTag.Compression, out IExifValue<ushort>? compressionValue))
91+
{
92+
meta.Compression = (TiffCompression)compressionValue.Value;
93+
}
94+
95+
if (profile.TryGetValue(ExifTag.PhotometricInterpretation, out IExifValue<ushort>? photometricInterpretationValue))
96+
{
97+
meta.PhotometricInterpretation = (TiffPhotometricInterpretation)photometricInterpretationValue.Value;
98+
}
99+
100+
if (profile.TryGetValue(ExifTag.Predictor, out IExifValue<ushort>? predictorValue))
101+
{
102+
meta.Predictor = (TiffPredictor)predictorValue.Value;
103+
}
90104

91105
profile.RemoveValue(ExifTag.BitsPerSample);
92106
profile.RemoveValue(ExifTag.Compression);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,33 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
33

4+
using System.Diagnostics.CodeAnalysis;
5+
46
namespace SixLabors.ImageSharp.Formats.Tiff;
57

68
internal static class TiffThrowHelper
79
{
10+
[DoesNotReturn]
811
public static Exception ThrowImageFormatException(string errorMessage) => throw new ImageFormatException(errorMessage);
912

13+
[DoesNotReturn]
14+
public static Exception ThrowInvalidImageContentException(string errorMessage) => throw new InvalidImageContentException(errorMessage);
15+
16+
[DoesNotReturn]
1017
public static Exception NotSupportedDecompressor(string compressionType) => throw new NotSupportedException($"Not supported decoder compression method: {compressionType}");
1118

19+
[DoesNotReturn]
1220
public static Exception NotSupportedCompressor(string compressionType) => throw new NotSupportedException($"Not supported encoder compression method: {compressionType}");
1321

22+
[DoesNotReturn]
1423
public static Exception InvalidColorType(string colorType) => throw new NotSupportedException($"Invalid color type: {colorType}");
1524

25+
[DoesNotReturn]
1626
public static Exception ThrowInvalidHeader() => throw new ImageFormatException("Invalid TIFF file header.");
1727

28+
[DoesNotReturn]
1829
public static void ThrowNotSupported(string message) => throw new NotSupportedException(message);
1930

31+
[DoesNotReturn]
2032
public static void ThrowArgumentException(string message) => throw new ArgumentException(message);
2133
}

0 commit comments

Comments
 (0)