Browse Source

Remove properties from TiffFrameMetadata, which can be accessed by the exifProfile directly

pull/1553/head
Brian Popow 5 years ago
parent
commit
8461c72ed9
  1. 11
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
  2. 25
      src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs
  3. 67
      src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
  4. 223
      src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs
  5. 17
      tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
  6. 96
      tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs

11
src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

@ -150,10 +150,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff
framesMetadata.Add(meta); framesMetadata.Add(meta);
} }
ImageMetadata metadata = TiffDecoderMetadataCreator.Create(framesMetadata, reader.ByteOrder);
TiffFrameMetadata root = framesMetadata[0]; TiffFrameMetadata root = framesMetadata[0];
ExifProfile rootFrameExifProfile = directories.First(); ExifProfile rootFrameExifProfile = directories.First();
ImageMetadata metadata = TiffDecoderMetadataCreator.Create(framesMetadata, reader.ByteOrder, rootFrameExifProfile);
int width = GetImageWidth(rootFrameExifProfile); int width = GetImageWidth(rootFrameExifProfile);
int height = GetImageHeight(rootFrameExifProfile); int height = GetImageHeight(rootFrameExifProfile);
@ -177,15 +176,15 @@ namespace SixLabors.ImageSharp.Formats.Tiff
new ImageFrameMetadata { ExifProfile = tags, XmpProfile = tags.GetValue(ExifTag.XMP)?.Value }; new ImageFrameMetadata { ExifProfile = tags, XmpProfile = tags.GetValue(ExifTag.XMP)?.Value };
tiffFrameMetaData = new TiffFrameMetadata(tags); tiffFrameMetaData = new TiffFrameMetadata(tags);
this.VerifyAndParse(tiffFrameMetaData); this.VerifyAndParse(tags, tiffFrameMetaData);
int width = GetImageWidth(tags); int width = GetImageWidth(tags);
int height = GetImageHeight(tags); int height = GetImageHeight(tags);
var frame = new ImageFrame<TPixel>(this.Configuration, width, height, imageFrameMetaData); var frame = new ImageFrame<TPixel>(this.Configuration, width, height, imageFrameMetaData);
int rowsPerStrip = (int)tiffFrameMetaData.RowsPerStrip; int rowsPerStrip = tags.GetValue(ExifTag.RowsPerStrip) != null ? (int)tags.GetValue(ExifTag.RowsPerStrip).Value : TiffConstants.RowsPerStripInfinity;
Number[] stripOffsets = tiffFrameMetaData.StripOffsets; Number[] stripOffsets = tags.GetValue(ExifTag.StripOffsets)?.Value;
Number[] stripByteCounts = tiffFrameMetaData.StripByteCounts; Number[] stripByteCounts = tags.GetValue(ExifTag.StripByteCounts)?.Value;
if (this.PlanarConfiguration == TiffPlanarConfiguration.Planar) if (this.PlanarConfiguration == TiffPlanarConfiguration.Planar)
{ {

25
src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Icc;
@ -28,8 +29,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff
} }
var imageMetaData = new ImageMetadata(); var imageMetaData = new ImageMetadata();
TiffFrameMetadata rootFrameMetadata = framesMetaData[0]; ExifProfile exifProfileRootFrame = frames[0].Metadata.ExifProfile;
SetResolution(imageMetaData, rootFrameMetadata);
SetResolution(imageMetaData, exifProfileRootFrame);
TiffMetadata tiffMetadata = imageMetaData.GetTiffMetadata(); TiffMetadata tiffMetadata = imageMetaData.GetTiffMetadata();
tiffMetadata.ByteOrder = byteOrder; tiffMetadata.ByteOrder = byteOrder;
@ -56,7 +58,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
return imageMetaData; return imageMetaData;
} }
public static ImageMetadata Create(List<TiffFrameMetadata> framesMetaData, ByteOrder byteOrder) public static ImageMetadata Create(List<TiffFrameMetadata> framesMetaData, ByteOrder byteOrder, ExifProfile exifProfile)
{ {
if (framesMetaData.Count < 1) if (framesMetaData.Count < 1)
{ {
@ -64,8 +66,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
} }
var imageMetaData = new ImageMetadata(); var imageMetaData = new ImageMetadata();
TiffFrameMetadata rootFrameMetadata = framesMetaData[0]; SetResolution(imageMetaData, exifProfile);
SetResolution(imageMetaData, rootFrameMetadata);
TiffMetadata tiffMetadata = imageMetaData.GetTiffMetadata(); TiffMetadata tiffMetadata = imageMetaData.GetTiffMetadata();
tiffMetadata.ByteOrder = byteOrder; tiffMetadata.ByteOrder = byteOrder;
@ -73,17 +74,19 @@ namespace SixLabors.ImageSharp.Formats.Tiff
return imageMetaData; return imageMetaData;
} }
private static void SetResolution(ImageMetadata imageMetaData, TiffFrameMetadata rootFrameMetadata) private static void SetResolution(ImageMetadata imageMetaData, ExifProfile exifProfile)
{ {
imageMetaData.ResolutionUnits = rootFrameMetadata.ResolutionUnit; imageMetaData.ResolutionUnits = exifProfile != null ? UnitConverter.ExifProfileToResolutionUnit(exifProfile) : PixelResolutionUnit.PixelsPerInch;
if (rootFrameMetadata.HorizontalResolution != null) double? horizontalResolution = exifProfile?.GetValue(ExifTag.XResolution)?.Value.ToDouble();
if (horizontalResolution != null)
{ {
imageMetaData.HorizontalResolution = rootFrameMetadata.HorizontalResolution.Value; imageMetaData.HorizontalResolution = horizontalResolution.Value;
} }
if (rootFrameMetadata.VerticalResolution != null) double? verticalResolution = exifProfile?.GetValue(ExifTag.YResolution)?.Value.ToDouble();
if (verticalResolution != null)
{ {
imageMetaData.VerticalResolution = rootFrameMetadata.VerticalResolution.Value; imageMetaData.VerticalResolution = verticalResolution.Value;
} }
} }

67
src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs

@ -1,9 +1,11 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System.Linq;
using SixLabors.ImageSharp.Formats.Tiff.Compression; using SixLabors.ImageSharp.Formats.Tiff.Compression;
using SixLabors.ImageSharp.Formats.Tiff.Constants; using SixLabors.ImageSharp.Formats.Tiff.Constants;
using SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation; using SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff
{ {
@ -12,36 +14,44 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// </summary> /// </summary>
internal static class TiffDecoderOptionsParser internal static class TiffDecoderOptionsParser
{ {
private const TiffPredictor DefaultPredictor = TiffPredictor.None;
private const TiffPlanarConfiguration DefaultPlanarConfiguration = TiffPlanarConfiguration.Chunky;
/// <summary> /// <summary>
/// Determines the TIFF compression and color types, and reads any associated parameters. /// Determines the TIFF compression and color types, and reads any associated parameters.
/// </summary> /// </summary>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
/// <param name="exifProfile">The exif profile of the frame to decode.</param>
/// <param name="entries">The IFD entries container to read the image format information for.</param> /// <param name="entries">The IFD entries container to read the image format information for.</param>
public static void VerifyAndParse(this TiffDecoderCore options, TiffFrameMetadata entries) public static void VerifyAndParse(this TiffDecoderCore options, ExifProfile exifProfile, TiffFrameMetadata entries)
{ {
if (entries.TileOffsets != null) if (exifProfile.GetValue(ExifTag.TileOffsets)?.Value != null)
{ {
TiffThrowHelper.ThrowNotSupported("Tiled images are not supported."); TiffThrowHelper.ThrowNotSupported("Tiled images are not supported.");
} }
if (entries.ExtraSamples != null) if (exifProfile.GetValue(ExifTag.ExtraSamples)?.Value != null)
{ {
TiffThrowHelper.ThrowNotSupported("ExtraSamples is not supported."); TiffThrowHelper.ThrowNotSupported("ExtraSamples is not supported.");
} }
if (entries.FillOrder != TiffFillOrder.MostSignificantBitFirst) TiffFillOrder fillOrder = (TiffFillOrder?)exifProfile.GetValue(ExifTag.FillOrder)?.Value ?? TiffFillOrder.MostSignificantBitFirst;
if (fillOrder != TiffFillOrder.MostSignificantBitFirst)
{ {
TiffThrowHelper.ThrowNotSupported("The lower-order bits of the byte FillOrder is not supported."); TiffThrowHelper.ThrowNotSupported("The lower-order bits of the byte FillOrder is not supported.");
} }
if (entries.Predictor == TiffPredictor.FloatingPoint) TiffPredictor predictor = (TiffPredictor?)exifProfile.GetValue(ExifTag.Predictor)?.Value ?? DefaultPredictor;
if (predictor == TiffPredictor.FloatingPoint)
{ {
TiffThrowHelper.ThrowNotSupported("TIFF images with FloatingPoint horizontal predictor are not supported."); TiffThrowHelper.ThrowNotSupported("TIFF images with FloatingPoint horizontal predictor are not supported.");
} }
if (entries.SampleFormat != null) TiffSampleFormat[] sampleFormat = exifProfile.GetValue(ExifTag.SampleFormat)?.Value?.Select(a => (TiffSampleFormat)a).ToArray();
if (sampleFormat != null)
{ {
foreach (TiffSampleFormat format in entries.SampleFormat) foreach (TiffSampleFormat format in sampleFormat)
{ {
if (format != TiffSampleFormat.UnsignedInteger) if (format != TiffSampleFormat.UnsignedInteger)
{ {
@ -50,24 +60,43 @@ namespace SixLabors.ImageSharp.Formats.Tiff
} }
} }
if (entries.StripRowCounts != null) if (exifProfile.GetValue(ExifTag.StripRowCounts)?.Value != null)
{ {
TiffThrowHelper.ThrowNotSupported("Variable-sized strips are not supported."); TiffThrowHelper.ThrowNotSupported("Variable-sized strips are not supported.");
} }
entries.VerifyRequiredFieldsArePresent(); VerifyRequiredFieldsArePresent(exifProfile);
options.PlanarConfiguration = entries.PlanarConfiguration; options.PlanarConfiguration = (TiffPlanarConfiguration?)exifProfile.GetValue(ExifTag.PlanarConfiguration)?.Value ?? DefaultPlanarConfiguration;
options.Predictor = entries.Predictor; options.Predictor = predictor;
options.PhotometricInterpretation = entries.PhotometricInterpretation; options.PhotometricInterpretation = exifProfile.GetValue(ExifTag.PhotometricInterpretation) != null ?
(TiffPhotometricInterpretation)exifProfile.GetValue(ExifTag.PhotometricInterpretation).Value : TiffPhotometricInterpretation.WhiteIsZero;
options.BitsPerSample = entries.BitsPerSample.GetValueOrDefault(); options.BitsPerSample = entries.BitsPerSample.GetValueOrDefault();
options.BitsPerPixel = entries.BitsPerSample.GetValueOrDefault().BitsPerPixel(); options.BitsPerPixel = entries.BitsPerSample.GetValueOrDefault().BitsPerPixel();
ParseColorType(options, entries); ParseColorType(options, exifProfile);
ParseCompression(options, entries); ParseCompression(options, exifProfile);
}
private static void VerifyRequiredFieldsArePresent(ExifProfile exifProfile)
{
if (exifProfile.GetValue(ExifTag.StripOffsets) == null)
{
TiffThrowHelper.ThrowImageFormatException("StripOffsets are missing and are required for decoding the TIFF image!");
}
if (exifProfile.GetValue(ExifTag.StripByteCounts) == null)
{
TiffThrowHelper.ThrowImageFormatException("StripByteCounts are missing and are required for decoding the TIFF image!");
}
if (exifProfile.GetValue(ExifTag.BitsPerSample) == null)
{
TiffThrowHelper.ThrowNotSupported("The TIFF BitsPerSample entry is missing which is required to decode the image!");
}
} }
private static void ParseColorType(this TiffDecoderCore options, TiffFrameMetadata entries) private static void ParseColorType(this TiffDecoderCore options, ExifProfile exifProfile)
{ {
switch (options.PhotometricInterpretation) switch (options.PhotometricInterpretation)
{ {
@ -166,7 +195,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
case TiffPhotometricInterpretation.PaletteColor: case TiffPhotometricInterpretation.PaletteColor:
{ {
options.ColorMap = entries.ColorMap; options.ColorMap = exifProfile.GetValue(ExifTag.ColorMap)?.Value;
if (options.ColorMap != null) if (options.ColorMap != null)
{ {
if (options.BitsPerSample.Bits().Length != 1) if (options.BitsPerSample.Bits().Length != 1)
@ -193,9 +222,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff
} }
} }
private static void ParseCompression(this TiffDecoderCore options, TiffFrameMetadata tiffFrameMetaData) private static void ParseCompression(this TiffDecoderCore options, ExifProfile exifProfile)
{ {
TiffCompression compression = tiffFrameMetaData.Compression; TiffCompression compression = exifProfile.GetValue(ExifTag.Compression) != null ? (TiffCompression)exifProfile.GetValue(ExifTag.Compression).Value : TiffCompression.None;
switch (compression) switch (compression)
{ {
case TiffCompression.None: case TiffCompression.None:
@ -226,7 +255,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
case TiffCompression.CcittGroup3Fax: case TiffCompression.CcittGroup3Fax:
{ {
options.CompressionType = TiffDecoderCompressionType.T4; options.CompressionType = TiffDecoderCompressionType.T4;
options.FaxCompressionOptions = tiffFrameMetaData.FaxCompressionOptions; options.FaxCompressionOptions = exifProfile.GetValue(ExifTag.T4Options) != null ? (FaxCompressionOptions)exifProfile.GetValue(ExifTag.T4Options).Value : FaxCompressionOptions.None;
break; break;
} }

223
src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs

@ -1,12 +1,7 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System;
using System.Linq;
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats.Tiff.Compression;
using SixLabors.ImageSharp.Formats.Tiff.Constants; using SixLabors.ImageSharp.Formats.Tiff.Constants;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Exif;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff
@ -16,10 +11,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// </summary> /// </summary>
internal class TiffFrameMetadata : IDeepCloneable internal class TiffFrameMetadata : IDeepCloneable
{ {
private const TiffPlanarConfiguration DefaultPlanarConfiguration = TiffPlanarConfiguration.Chunky;
private const TiffPredictor DefaultPredictor = TiffPredictor.None;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TiffFrameMetadata"/> class. /// Initializes a new instance of the <see cref="TiffFrameMetadata"/> class.
/// </summary> /// </summary>
@ -34,17 +25,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
public TiffFrameMetadata(ExifProfile frameTags) => this.Initialize(frameTags ?? new ExifProfile()); public TiffFrameMetadata(ExifProfile frameTags) => this.Initialize(frameTags ?? new ExifProfile());
/// <summary> /// <summary>
/// Gets or sets a general indication of the kind of data contained in this subfile. /// Gets or sets the number of bits per component.
/// </summary>
public TiffNewSubfileType? SubfileType { get; set; }
/// <summary>
/// Gets or sets a general indication of the kind of data contained in this subfile.
/// </summary>
public TiffSubfileType? OldSubfileType { get; set; }
/// <summary>
/// Gets or sets the number of bits per component.
/// </summary> /// </summary>
public TiffBitsPerSample? BitsPerSample { get; set; } public TiffBitsPerSample? BitsPerSample { get; set; }
@ -53,131 +34,19 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// </summary> /// </summary>
public TiffBitsPerPixel BitsPerPixel { get; set; } public TiffBitsPerPixel BitsPerPixel { get; set; }
/// <summary>
/// Gets or sets the compression scheme used on the image data.
/// </summary>
public TiffCompression Compression { get; set; }
/// <summary>
/// Gets or sets the fax compression options.
/// </summary>
public FaxCompressionOptions FaxCompressionOptions { get; set; }
/// <summary>
/// Gets or sets the color space of the image data.
/// </summary>
public TiffPhotometricInterpretation PhotometricInterpretation { get; set; }
/// <summary>
/// Gets or sets the logical order of bits within a byte.
/// </summary>
internal TiffFillOrder FillOrder { get; set; }
/// <summary>
/// Gets or sets for each strip, the byte offset of that strip.
/// </summary>
public Number[] StripOffsets { get; set; }
/// <summary>
/// Gets or sets the strip row counts.
/// </summary>
public uint[] StripRowCounts { get; set; }
/// <summary>
/// Gets or sets the number of components per pixel.
/// </summary>
public ushort? SamplesPerPixel { get; set; }
/// <summary>
/// Gets or sets the number of rows per strip.
/// </summary>
public Number RowsPerStrip { get; set; }
/// <summary>
/// Gets or sets for each strip, the number of bytes in the strip after compression.
/// </summary>
public Number[] StripByteCounts { get; set; }
/// <summary>
/// Gets or sets the resolution of the image in x-direction.
/// </summary>
public double? HorizontalResolution { get; set; }
/// <summary>
/// Gets or sets the resolution of the image in y-direction.
/// </summary>
public double? VerticalResolution { get; set; }
/// <summary>
/// Gets or sets how the components of each pixel are stored.
/// </summary>
public TiffPlanarConfiguration PlanarConfiguration { get; set; }
/// <summary>
/// Gets or sets the unit of measurement for XResolution and YResolution.
/// </summary>
public PixelResolutionUnit ResolutionUnit { get; set; }
/// <summary>
/// Gets or sets a color map for palette color images.
/// </summary>
public ushort[] ColorMap { get; set; }
/// <summary>
/// Gets or sets the description of extra components.
/// </summary>
public ushort[] ExtraSamples { get; set; }
/// <summary>
/// Gets or sets the tile offsets.
/// </summary>
public uint[] TileOffsets { get; set; }
/// <summary>
/// Gets or sets a mathematical operator that is applied to the image data before an encoding scheme is applied.
/// </summary>
public TiffPredictor Predictor { get; set; }
/// <summary>
/// Gets or sets the specifies how to interpret each data sample in a pixel.
/// </summary>
public TiffSampleFormat[] SampleFormat { get; set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TiffFrameMetadata"/> class with a given ExifProfile. /// Initializes a new instance of the <see cref="TiffFrameMetadata"/> class with a given ExifProfile.
/// </summary> /// </summary>
/// <param name="frameTags">The Tiff frame directory tags.</param> /// <param name="frameTags">The Tiff frame directory tags.</param>
public void Initialize(ExifProfile frameTags) public void Initialize(ExifProfile frameTags)
{ {
this.FillOrder = (TiffFillOrder?)frameTags.GetValue(ExifTag.FillOrder)?.Value ?? TiffFillOrder.MostSignificantBitFirst; TiffPhotometricInterpretation photometricInterpretation = frameTags.GetValue(ExifTag.PhotometricInterpretation) != null ?
this.Compression = frameTags.GetValue(ExifTag.Compression) != null ? (TiffCompression)frameTags.GetValue(ExifTag.Compression).Value : TiffCompression.None;
this.FaxCompressionOptions = frameTags.GetValue(ExifTag.T4Options) != null ? (FaxCompressionOptions)frameTags.GetValue(ExifTag.T4Options).Value : FaxCompressionOptions.None;
this.SubfileType = (TiffNewSubfileType?)frameTags.GetValue(ExifTag.SubfileType)?.Value ?? TiffNewSubfileType.FullImage;
this.OldSubfileType = (TiffSubfileType?)frameTags.GetValue(ExifTag.OldSubfileType)?.Value;
this.HorizontalResolution = frameTags.GetValue(ExifTag.XResolution)?.Value.ToDouble();
this.VerticalResolution = frameTags.GetValue(ExifTag.YResolution)?.Value.ToDouble();
this.ResolutionUnit = UnitConverter.ExifProfileToResolutionUnit(frameTags);
this.PlanarConfiguration = (TiffPlanarConfiguration?)frameTags.GetValue(ExifTag.PlanarConfiguration)?.Value ?? DefaultPlanarConfiguration;
this.ColorMap = frameTags.GetValue(ExifTag.ColorMap)?.Value;
this.ExtraSamples = frameTags.GetValue(ExifTag.ExtraSamples)?.Value;
this.Predictor = (TiffPredictor?)frameTags.GetValue(ExifTag.Predictor)?.Value ?? DefaultPredictor;
this.SampleFormat = frameTags.GetValue(ExifTag.SampleFormat)?.Value?.Select(a => (TiffSampleFormat)a).ToArray();
this.SamplesPerPixel = frameTags.GetValue(ExifTag.SamplesPerPixel)?.Value;
this.StripRowCounts = frameTags.GetValue(ExifTag.StripRowCounts)?.Value;
this.RowsPerStrip = frameTags.GetValue(ExifTag.RowsPerStrip) != null ? frameTags.GetValue(ExifTag.RowsPerStrip).Value : TiffConstants.RowsPerStripInfinity;
this.TileOffsets = frameTags.GetValue(ExifTag.TileOffsets)?.Value;
this.PhotometricInterpretation = frameTags.GetValue(ExifTag.PhotometricInterpretation) != null ?
(TiffPhotometricInterpretation)frameTags.GetValue(ExifTag.PhotometricInterpretation).Value : TiffPhotometricInterpretation.WhiteIsZero; (TiffPhotometricInterpretation)frameTags.GetValue(ExifTag.PhotometricInterpretation).Value : TiffPhotometricInterpretation.WhiteIsZero;
// Required Fields for decoding the image.
this.StripOffsets = frameTags.GetValue(ExifTag.StripOffsets)?.Value;
this.StripByteCounts = frameTags.GetValue(ExifTag.StripByteCounts)?.Value;
ushort[] bits = frameTags.GetValue(ExifTag.BitsPerSample)?.Value; ushort[] bits = frameTags.GetValue(ExifTag.BitsPerSample)?.Value;
if (bits == null) if (bits == null)
{ {
if (this.PhotometricInterpretation == TiffPhotometricInterpretation.WhiteIsZero || this.PhotometricInterpretation == TiffPhotometricInterpretation.BlackIsZero) if (photometricInterpretation == TiffPhotometricInterpretation.WhiteIsZero || photometricInterpretation == TiffPhotometricInterpretation.BlackIsZero)
{ {
this.BitsPerSample = TiffBitsPerSample.Bit1; this.BitsPerSample = TiffBitsPerSample.Bit1;
} }
@ -192,97 +61,15 @@ namespace SixLabors.ImageSharp.Formats.Tiff
this.BitsPerPixel = (TiffBitsPerPixel)this.BitsPerSample.GetValueOrDefault().BitsPerPixel(); this.BitsPerPixel = (TiffBitsPerPixel)this.BitsPerSample.GetValueOrDefault().BitsPerPixel();
} }
/// <summary>
/// Verifies that the required fields for decoding an image are present.
/// If not, a ImageFormatException will be thrown.
/// </summary>
public void VerifyRequiredFieldsArePresent()
{
if (this.StripOffsets == null)
{
TiffThrowHelper.ThrowImageFormatException("StripOffsets are missing and are required for decoding the TIFF image!");
}
if (this.StripByteCounts == null)
{
TiffThrowHelper.ThrowImageFormatException("StripByteCounts are missing and are required for decoding the TIFF image!");
}
if (this.BitsPerSample == null)
{
TiffThrowHelper.ThrowNotSupported("The TIFF BitsPerSample entry is missing which is required to decode the image!");
}
}
/// <inheritdoc/> /// <inheritdoc/>
public IDeepCloneable DeepClone() public IDeepCloneable DeepClone()
{ {
var clone = new TiffFrameMetadata var clone = new TiffFrameMetadata
{ {
FillOrder = this.FillOrder, BitsPerSample = this.BitsPerSample,
Compression = this.Compression, BitsPerPixel = this.BitsPerPixel
FaxCompressionOptions = this.FaxCompressionOptions,
SubfileType = this.SubfileType ?? TiffNewSubfileType.FullImage,
OldSubfileType = this.OldSubfileType ?? TiffSubfileType.FullImage,
HorizontalResolution = this.HorizontalResolution ?? ImageMetadata.DefaultHorizontalResolution,
VerticalResolution = this.VerticalResolution ?? ImageMetadata.DefaultVerticalResolution,
ResolutionUnit = this.ResolutionUnit,
PlanarConfiguration = this.PlanarConfiguration
}; };
if (this.ColorMap != null)
{
clone.ColorMap = new ushort[this.ColorMap.Length];
this.ColorMap.AsSpan().CopyTo(clone.ColorMap);
}
if (this.ExtraSamples != null)
{
clone.ExtraSamples = new ushort[this.ExtraSamples.Length];
this.ExtraSamples.AsSpan().CopyTo(clone.ExtraSamples);
}
clone.Predictor = this.Predictor;
if (this.SampleFormat != null)
{
clone.SampleFormat = new TiffSampleFormat[this.SampleFormat.Length];
this.SampleFormat.AsSpan().CopyTo(clone.SampleFormat);
}
clone.SamplesPerPixel = this.SamplesPerPixel;
if (this.StripRowCounts != null)
{
clone.StripRowCounts = new uint[this.StripRowCounts.Length];
this.StripRowCounts.AsSpan().CopyTo(clone.StripRowCounts);
}
clone.RowsPerStrip = this.RowsPerStrip;
if (this.TileOffsets != null)
{
clone.TileOffsets = new uint[this.TileOffsets.Length];
this.TileOffsets.AsSpan().CopyTo(clone.TileOffsets);
}
clone.PhotometricInterpretation = this.PhotometricInterpretation;
if (this.StripOffsets != null)
{
clone.StripOffsets = new Number[this.StripOffsets.Length];
this.StripOffsets.AsSpan().CopyTo(clone.StripOffsets);
}
if (this.StripByteCounts != null)
{
clone.StripByteCounts = new Number[this.StripByteCounts.Length];
this.StripByteCounts.AsSpan().CopyTo(clone.StripByteCounts);
}
clone.BitsPerSample = this.BitsPerSample;
clone.BitsPerPixel = this.BitsPerPixel;
return clone; return clone;
} }
} }

17
tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs

@ -340,6 +340,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
using Image<TPixel> input = provider.GetImage(); using Image<TPixel> input = provider.GetImage();
using var memStream = new MemoryStream(); using var memStream = new MemoryStream();
ExifProfile exifProfileInput = input.Frames.RootFrame.Metadata.ExifProfile; ExifProfile exifProfileInput = input.Frames.RootFrame.Metadata.ExifProfile;
var inputCompression = (TiffCompression)exifProfileInput.GetValue(ExifTag.Compression).Value;
var inputMeta = new TiffFrameMetadata(exifProfileInput); var inputMeta = new TiffFrameMetadata(exifProfileInput);
// act // act
@ -352,11 +353,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
var outputMeta = new TiffFrameMetadata(exifProfileOutput); var outputMeta = new TiffFrameMetadata(exifProfileOutput);
ImageFrame<Rgba32> rootFrame = output.Frames.RootFrame; ImageFrame<Rgba32> rootFrame = output.Frames.RootFrame;
Assert.True(output.Height > (int)outputMeta.RowsPerStrip); Number rowsPerStrip = exifProfileOutput.GetValue(ExifTag.RowsPerStrip) != null ? exifProfileOutput.GetValue(ExifTag.RowsPerStrip).Value : TiffConstants.RowsPerStripInfinity;
Assert.True(outputMeta.StripOffsets.Length > 1); Assert.True(output.Height > (int)rowsPerStrip);
Assert.True(outputMeta.StripByteCounts.Length > 1); Assert.True(exifProfileOutput.GetValue(ExifTag.StripOffsets)?.Value.Length > 1);
Number[] stripByteCounts = exifProfileOutput.GetValue(ExifTag.StripByteCounts)?.Value;
Assert.True(stripByteCounts.Length > 1);
foreach (Number sz in outputMeta.StripByteCounts) foreach (Number sz in stripByteCounts)
{ {
Assert.True((uint)sz <= TiffConstants.DefaultStripSize); Assert.True((uint)sz <= TiffConstants.DefaultStripSize);
} }
@ -364,10 +367,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
// For uncompressed more accurate test. // For uncompressed more accurate test.
if (compression == TiffCompression.None) if (compression == TiffCompression.None)
{ {
for (int i = 0; i < outputMeta.StripByteCounts.Length - 1; i++) for (int i = 0; i < stripByteCounts.Length - 1; i++)
{ {
// The difference must be less than one row. // The difference must be less than one row.
int stripBytes = (int)outputMeta.StripByteCounts[i]; int stripBytes = (int)stripByteCounts[i];
int widthBytes = ((int)outputMeta.BitsPerPixel + 7) / 8 * rootFrame.Width; int widthBytes = ((int)outputMeta.BitsPerPixel + 7) / 8 * rootFrame.Width;
Assert.True((TiffConstants.DefaultStripSize - stripBytes) < widthBytes); Assert.True((TiffConstants.DefaultStripSize - stripBytes) < widthBytes);
@ -379,7 +382,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
provider, provider,
inputMeta.BitsPerPixel, inputMeta.BitsPerPixel,
mode, mode,
inputMeta.Compression); inputCompression);
} }
private static void TestTiffEncoderCore<TPixel>( private static void TestTiffEncoderCore<TPixel>(

96
tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs

@ -3,7 +3,7 @@
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Tiff;
using SixLabors.ImageSharp.Formats.Tiff.Constants; using SixLabors.ImageSharp.Formats.Tiff.Constants;
using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata;
@ -55,15 +55,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
ExifProfile exifProfile = image.Frames.RootFrame.Metadata.ExifProfile; ExifProfile exifProfile = image.Frames.RootFrame.Metadata.ExifProfile;
var meta = new TiffFrameMetadata(exifProfile); var meta = new TiffFrameMetadata(exifProfile);
var cloneSameAsSampleMetaData = (TiffFrameMetadata)meta.DeepClone(); var cloneSameAsSampleMetaData = (TiffFrameMetadata)meta.DeepClone();
VerifyExpectedTiffFrameMetaDataIsPresent(cloneSameAsSampleMetaData); Assert.NotNull(cloneSameAsSampleMetaData);
Assert.Equal(TiffBitsPerSample.Bit4, cloneSameAsSampleMetaData.BitsPerSample);
var clone = (TiffFrameMetadata)meta.DeepClone(); var clone = (TiffFrameMetadata)meta.DeepClone();
clone.BitsPerSample = TiffBitsPerSample.Bit1; clone.BitsPerSample = TiffBitsPerSample.Bit1;
clone.ColorMap = new ushort[] { 1, 2, 3 };
Assert.False(meta.BitsPerSample == clone.BitsPerSample); Assert.False(meta.BitsPerSample == clone.BitsPerSample);
Assert.False(meta.ColorMap.SequenceEqual(clone.ColorMap));
} }
} }
@ -156,6 +155,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
ExifProfile exifProfile = rootFrame.Metadata.ExifProfile; ExifProfile exifProfile = rootFrame.Metadata.ExifProfile;
Assert.NotNull(exifProfile); Assert.NotNull(exifProfile);
Assert.Equal(30, exifProfile.Values.Count); Assert.Equal(30, exifProfile.Values.Count);
Assert.Equal(TiffCompression.Lzw, (TiffCompression)exifProfile.GetValue(ExifTag.Compression).Value);
Assert.Equal("This is Название", exifProfile.GetValue(ExifTag.ImageDescription).Value); Assert.Equal("This is Название", exifProfile.GetValue(ExifTag.ImageDescription).Value);
Assert.Equal("This is Изготовитель камеры", exifProfile.GetValue(ExifTag.Make).Value); Assert.Equal("This is Изготовитель камеры", exifProfile.GetValue(ExifTag.Make).Value);
Assert.Equal("This is Модель камеры", exifProfile.GetValue(ExifTag.Model).Value); Assert.Equal("This is Модель камеры", exifProfile.GetValue(ExifTag.Model).Value);
@ -166,6 +166,25 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
Assert.Equal("This is Авторские права", exifProfile.GetValue(ExifTag.Copyright).Value); Assert.Equal("This is Авторские права", exifProfile.GetValue(ExifTag.Copyright).Value);
Assert.Equal(4, exifProfile.GetValue(ExifTag.Rating).Value); Assert.Equal(4, exifProfile.GetValue(ExifTag.Rating).Value);
Assert.Equal(75, exifProfile.GetValue(ExifTag.RatingPercent).Value); Assert.Equal(75, exifProfile.GetValue(ExifTag.RatingPercent).Value);
var expectedResolution = new Rational(10000, 1000, simplify: false);
Assert.Equal(expectedResolution, exifProfile.GetValue(ExifTag.XResolution).Value);
Assert.Equal(expectedResolution, exifProfile.GetValue(ExifTag.YResolution).Value);
Assert.Equal(new Number[] { 8u }, exifProfile.GetValue(ExifTag.StripOffsets)?.Value, new NumberComparer());
Assert.Equal(new Number[] { 297u }, exifProfile.GetValue(ExifTag.StripByteCounts)?.Value, new NumberComparer());
Assert.Null(exifProfile.GetValue(ExifTag.ExtraSamples)?.Value);
Assert.Equal(32u, exifProfile.GetValue(ExifTag.RowsPerStrip).Value);
Assert.Null(exifProfile.GetValue(ExifTag.SampleFormat));
Assert.Equal(TiffPredictor.None, (TiffPredictor?)exifProfile.GetValue(ExifTag.Predictor)?.Value);
Assert.Equal(PixelResolutionUnit.PixelsPerInch, UnitConverter.ExifProfileToResolutionUnit(exifProfile));
ushort[] colorMap = exifProfile.GetValue(ExifTag.ColorMap)?.Value;
Assert.NotNull(colorMap);
Assert.Equal(48, colorMap.Length);
Assert.Equal(10537, colorMap[0]);
Assert.Equal(14392, colorMap[1]);
Assert.Equal(58596, colorMap[46]);
Assert.Equal(3855, colorMap[47]);
Assert.Equal(TiffPhotometricInterpretation.PaletteColor, (TiffPhotometricInterpretation)exifProfile.GetValue(ExifTag.PhotometricInterpretation).Value);
Assert.Equal(1u, exifProfile.GetValue(ExifTag.SamplesPerPixel).Value);
ImageMetadata imageMetaData = image.Metadata; ImageMetadata imageMetaData = image.Metadata;
Assert.NotNull(imageMetaData); Assert.NotNull(imageMetaData);
@ -181,35 +200,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
Assert.Equal(TiffBitsPerPixel.Bit4, frameMetaData.BitsPerPixel); Assert.Equal(TiffBitsPerPixel.Bit4, frameMetaData.BitsPerPixel);
var tiffFrameMetadata = new TiffFrameMetadata(exifProfile); var tiffFrameMetadata = new TiffFrameMetadata(exifProfile);
VerifyExpectedTiffFrameMetaDataIsPresent(tiffFrameMetadata); Assert.NotNull(frameMetaData);
Assert.Equal(TiffBitsPerSample.Bit4, frameMetaData.BitsPerSample);
} }
} }
private static void VerifyExpectedTiffFrameMetaDataIsPresent(TiffFrameMetadata frameMetaData)
{
Assert.NotNull(frameMetaData);
Assert.Equal(TiffBitsPerSample.Bit4, frameMetaData.BitsPerSample);
Assert.Equal(TiffCompression.Lzw, frameMetaData.Compression);
Assert.Equal(TiffPhotometricInterpretation.PaletteColor, frameMetaData.PhotometricInterpretation);
Assert.Equal(new Number[] { 8u }, frameMetaData.StripOffsets, new NumberComparer());
Assert.Equal(1, frameMetaData.SamplesPerPixel.GetValueOrDefault());
Assert.Equal(32u, frameMetaData.RowsPerStrip);
Assert.Equal(new Number[] { 297u }, frameMetaData.StripByteCounts, new NumberComparer());
Assert.Equal(PixelResolutionUnit.PixelsPerInch, frameMetaData.ResolutionUnit);
Assert.Equal(10, frameMetaData.HorizontalResolution);
Assert.Equal(10, frameMetaData.VerticalResolution);
Assert.Equal(TiffPlanarConfiguration.Chunky, frameMetaData.PlanarConfiguration);
Assert.Equal(48, frameMetaData.ColorMap.Length);
Assert.Equal(10537, frameMetaData.ColorMap[0]);
Assert.Equal(14392, frameMetaData.ColorMap[1]);
Assert.Equal(58596, frameMetaData.ColorMap[46]);
Assert.Equal(3855, frameMetaData.ColorMap[47]);
Assert.Null(frameMetaData.ExtraSamples);
Assert.Equal(TiffPredictor.None, frameMetaData.Predictor);
Assert.Null(frameMetaData.SampleFormat);
}
[Theory] [Theory]
[WithFile(MultiframeDeflateWithPreview, PixelTypes.Rgba32)] [WithFile(MultiframeDeflateWithPreview, PixelTypes.Rgba32)]
public void SubfileType<TPixel>(TestImageProvider<TPixel> provider) public void SubfileType<TPixel>(TestImageProvider<TPixel> provider)
@ -222,13 +217,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
Assert.Equal(2, image.Frames.Count); Assert.Equal(2, image.Frames.Count);
var frame0MetaData = new TiffFrameMetadata(image.Frames[0].Metadata.ExifProfile); ExifProfile frame0Exif = image.Frames[0].Metadata.ExifProfile;
Assert.Equal(TiffNewSubfileType.FullImage, frame0MetaData.SubfileType); Assert.Equal(TiffNewSubfileType.FullImage, (TiffNewSubfileType)frame0Exif.GetValue(ExifTag.SubfileType).Value);
Assert.Equal(255, image.Frames[0].Width); Assert.Equal(255, image.Frames[0].Width);
Assert.Equal(255, image.Frames[0].Height); Assert.Equal(255, image.Frames[0].Height);
var frame1MetaData = new TiffFrameMetadata(image.Frames[1].Metadata.ExifProfile); ExifProfile frame1Exif = image.Frames[1].Metadata.ExifProfile;
Assert.Equal(TiffNewSubfileType.Preview, frame1MetaData.SubfileType); Assert.Equal(TiffNewSubfileType.Preview, (TiffNewSubfileType)frame1Exif.GetValue(ExifTag.SubfileType).Value);
Assert.Equal(255, image.Frames[1].Width); Assert.Equal(255, image.Frames[1].Width);
Assert.Equal(255, image.Frames[1].Height); Assert.Equal(255, image.Frames[1].Height);
} }
@ -243,13 +238,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
using Image<TPixel> image = provider.GetImage(new TiffDecoder() { IgnoreMetadata = false }); using Image<TPixel> image = provider.GetImage(new TiffDecoder() { IgnoreMetadata = false });
ImageMetadata inputMetaData = image.Metadata; ImageMetadata inputMetaData = image.Metadata;
TiffMetadata tiffMetaInput = image.Metadata.GetTiffMetadata();
var frameMetaInput = new TiffFrameMetadata(image.Frames.RootFrame.Metadata.ExifProfile); var frameMetaInput = new TiffFrameMetadata(image.Frames.RootFrame.Metadata.ExifProfile);
ImageFrame<TPixel> rootFrameInput = image.Frames.RootFrame; ImageFrame<TPixel> rootFrameInput = image.Frames.RootFrame;
byte[] xmpProfileInput = rootFrameInput.Metadata.XmpProfile; byte[] xmpProfileInput = rootFrameInput.Metadata.XmpProfile;
ExifProfile rootFrameExifProfileInput = rootFrameInput.Metadata.ExifProfile; ExifProfile exifProfileInput = rootFrameInput.Metadata.ExifProfile;
Assert.Equal(TiffCompression.Lzw, frameMetaInput.Compression); Assert.Equal(TiffCompression.Lzw, (TiffCompression)exifProfileInput.GetValue(ExifTag.Compression).Value);
Assert.Equal(TiffBitsPerPixel.Bit4, frameMetaInput.BitsPerPixel); Assert.Equal(TiffBitsPerPixel.Bit4, frameMetaInput.BitsPerPixel);
// Save to Tiff // Save to Tiff
@ -262,14 +256,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
using var encodedImage = Image.Load<Rgba32>(this.configuration, ms); using var encodedImage = Image.Load<Rgba32>(this.configuration, ms);
ImageMetadata encodedImageMetaData = encodedImage.Metadata; ImageMetadata encodedImageMetaData = encodedImage.Metadata;
TiffMetadata tiffMetaDataEncodedImage = encodedImageMetaData.GetTiffMetadata();
ImageFrame<Rgba32> rootFrameEncodedImage = encodedImage.Frames.RootFrame; ImageFrame<Rgba32> rootFrameEncodedImage = encodedImage.Frames.RootFrame;
var tiffMetaDataEncodedRootFrame = new TiffFrameMetadata(rootFrameEncodedImage.Metadata.ExifProfile); var tiffMetaDataEncodedRootFrame = new TiffFrameMetadata(rootFrameEncodedImage.Metadata.ExifProfile);
ExifProfile encodedImageExifProfile = rootFrameEncodedImage.Metadata.ExifProfile; ExifProfile encodedImageExifProfile = rootFrameEncodedImage.Metadata.ExifProfile;
byte[] encodedImageXmpProfile = rootFrameEncodedImage.Metadata.XmpProfile; byte[] encodedImageXmpProfile = rootFrameEncodedImage.Metadata.XmpProfile;
Assert.Equal(TiffBitsPerPixel.Bit24, tiffMetaDataEncodedRootFrame.BitsPerPixel); Assert.Equal(TiffBitsPerPixel.Bit24, tiffMetaDataEncodedRootFrame.BitsPerPixel);
Assert.Equal(TiffCompression.None, tiffMetaDataEncodedRootFrame.Compression); Assert.Equal(TiffCompression.None, (TiffCompression)encodedImageExifProfile.GetValue(ExifTag.Compression).Value);
Assert.Equal(inputMetaData.HorizontalResolution, encodedImageMetaData.HorizontalResolution); Assert.Equal(inputMetaData.HorizontalResolution, encodedImageMetaData.HorizontalResolution);
Assert.Equal(inputMetaData.VerticalResolution, encodedImageMetaData.VerticalResolution); Assert.Equal(inputMetaData.VerticalResolution, encodedImageMetaData.VerticalResolution);
@ -277,21 +270,24 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
Assert.Equal(rootFrameInput.Width, rootFrameEncodedImage.Width); Assert.Equal(rootFrameInput.Width, rootFrameEncodedImage.Width);
Assert.Equal(rootFrameInput.Height, rootFrameEncodedImage.Height); Assert.Equal(rootFrameInput.Height, rootFrameEncodedImage.Height);
Assert.Equal(frameMetaInput.ResolutionUnit, tiffMetaDataEncodedRootFrame.ResolutionUnit);
Assert.Equal(frameMetaInput.HorizontalResolution, tiffMetaDataEncodedRootFrame.HorizontalResolution); PixelResolutionUnit resolutionUnitInput = UnitConverter.ExifProfileToResolutionUnit(exifProfileInput);
Assert.Equal(frameMetaInput.VerticalResolution, tiffMetaDataEncodedRootFrame.VerticalResolution); PixelResolutionUnit resolutionUnitEncoded = UnitConverter.ExifProfileToResolutionUnit(encodedImageExifProfile);
Assert.Equal(resolutionUnitInput, resolutionUnitEncoded);
Assert.Equal(exifProfileInput.GetValue(ExifTag.XResolution), encodedImageExifProfile.GetValue(ExifTag.XResolution));
Assert.Equal(exifProfileInput.GetValue(ExifTag.YResolution), encodedImageExifProfile.GetValue(ExifTag.YResolution));
Assert.Equal(xmpProfileInput, encodedImageXmpProfile); Assert.Equal(xmpProfileInput, encodedImageXmpProfile);
Assert.Equal("IrfanView", rootFrameExifProfileInput.GetValue(ExifTag.Software).Value); Assert.Equal("IrfanView", exifProfileInput.GetValue(ExifTag.Software).Value);
Assert.Equal("This is Название", rootFrameExifProfileInput.GetValue(ExifTag.ImageDescription).Value); Assert.Equal("This is Название", exifProfileInput.GetValue(ExifTag.ImageDescription).Value);
Assert.Equal("This is Изготовитель камеры", rootFrameExifProfileInput.GetValue(ExifTag.Make).Value); Assert.Equal("This is Изготовитель камеры", exifProfileInput.GetValue(ExifTag.Make).Value);
Assert.Equal("This is Авторские права", rootFrameExifProfileInput.GetValue(ExifTag.Copyright).Value); Assert.Equal("This is Авторские права", exifProfileInput.GetValue(ExifTag.Copyright).Value);
Assert.Equal(rootFrameExifProfileInput.Values.Count, encodedImageExifProfile.Values.Count); Assert.Equal(exifProfileInput.Values.Count, encodedImageExifProfile.Values.Count);
Assert.Equal(rootFrameExifProfileInput.GetValue(ExifTag.ImageDescription).Value, encodedImageExifProfile.GetValue(ExifTag.ImageDescription).Value); Assert.Equal(exifProfileInput.GetValue(ExifTag.ImageDescription).Value, encodedImageExifProfile.GetValue(ExifTag.ImageDescription).Value);
Assert.Equal(rootFrameExifProfileInput.GetValue(ExifTag.Make).Value, encodedImageExifProfile.GetValue(ExifTag.Make).Value); Assert.Equal(exifProfileInput.GetValue(ExifTag.Make).Value, encodedImageExifProfile.GetValue(ExifTag.Make).Value);
Assert.Equal(rootFrameExifProfileInput.GetValue(ExifTag.Copyright).Value, encodedImageExifProfile.GetValue(ExifTag.Copyright).Value); Assert.Equal(exifProfileInput.GetValue(ExifTag.Copyright).Value, encodedImageExifProfile.GetValue(ExifTag.Copyright).Value);
} }
} }
} }

Loading…
Cancel
Save