Browse Source

Read baseline TIFF metadata

pull/1570/head
Andrew Wilkinson 9 years ago
parent
commit
53d17fc40e
  1. 16
      src/ImageSharp/Formats/Tiff/README.md
  2. 49
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
  3. 53
      src/ImageSharp/Formats/Tiff/TiffMetadataNames.cs
  4. 74
      tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderMetadataTests.cs

16
src/ImageSharp/Formats/Tiff/README.md

@ -79,9 +79,9 @@
|CellWidth | | | |
|CellLength | | | |
|FillOrder | | | |
|ImageDescription | | | |
|Make | | | |
|Model | | | |
|ImageDescription | | Y | |
|Make | | Y | |
|Model | | Y | |
|StripOffsets | | Y | |
|Orientation | | | |
|SamplesPerPixel | | | Currently ignored, as can be inferred from count of BitsPerSample |
@ -97,13 +97,13 @@
|GrayResponseUnit | | | |
|GrayResponseCurve | | | |
|ResolutionUnit | | Y | |
|Software | | | |
|DateTime | | | |
|Artist | | | |
|HostComputer | | | |
|Software | | Y | |
|DateTime | | Y | |
|Artist | | Y | |
|HostComputer | | Y | |
|ColorMap | | Y | |
|ExtraSamples | | | |
|Copyright | | | |
|Copyright | | Y | |
### Extension TIFF Tags

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

@ -224,6 +224,12 @@ namespace ImageSharp.Formats
return image;
}
/// <summary>
/// Reads the image metadata from a specified IFD.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="ifd">The IFD to read the image from.</param>
/// <param name="image">The image to write the metadata to.</param>
public void ReadMetadata<TPixel>(TiffIfd ifd, Image<TPixel> image)
where TPixel : struct, IPixel<TPixel>
{
@ -245,6 +251,49 @@ namespace ImageSharp.Formats
image.MetaData.VerticalResolution = yResolution.ToDouble() * resolutionUnitFactor;
}
}
if (!this.options.IgnoreMetadata)
{
if (ifd.TryGetIfdEntry(TiffTags.Artist, out TiffIfdEntry artistEntry))
{
image.MetaData.Properties.Add(new ImageProperty(TiffMetadataNames.Artist, this.ReadString(ref artistEntry)));
}
if (ifd.TryGetIfdEntry(TiffTags.Copyright, out TiffIfdEntry copyrightEntry))
{
image.MetaData.Properties.Add(new ImageProperty(TiffMetadataNames.Copyright, this.ReadString(ref copyrightEntry)));
}
if (ifd.TryGetIfdEntry(TiffTags.DateTime, out TiffIfdEntry dateTimeEntry))
{
image.MetaData.Properties.Add(new ImageProperty(TiffMetadataNames.DateTime, this.ReadString(ref dateTimeEntry)));
}
if (ifd.TryGetIfdEntry(TiffTags.HostComputer, out TiffIfdEntry hostComputerEntry))
{
image.MetaData.Properties.Add(new ImageProperty(TiffMetadataNames.HostComputer, this.ReadString(ref hostComputerEntry)));
}
if (ifd.TryGetIfdEntry(TiffTags.ImageDescription, out TiffIfdEntry imageDescriptionEntry))
{
image.MetaData.Properties.Add(new ImageProperty(TiffMetadataNames.ImageDescription, this.ReadString(ref imageDescriptionEntry)));
}
if (ifd.TryGetIfdEntry(TiffTags.Make, out TiffIfdEntry makeEntry))
{
image.MetaData.Properties.Add(new ImageProperty(TiffMetadataNames.Make, this.ReadString(ref makeEntry)));
}
if (ifd.TryGetIfdEntry(TiffTags.Model, out TiffIfdEntry modelEntry))
{
image.MetaData.Properties.Add(new ImageProperty(TiffMetadataNames.Model, this.ReadString(ref modelEntry)));
}
if (ifd.TryGetIfdEntry(TiffTags.Software, out TiffIfdEntry softwareEntry))
{
image.MetaData.Properties.Add(new ImageProperty(TiffMetadataNames.Software, this.ReadString(ref softwareEntry)));
}
}
}
/// <summary>

53
src/ImageSharp/Formats/Tiff/TiffMetadataNames.cs

@ -0,0 +1,53 @@
// <copyright file="TiffMetadataNames.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Formats
{
/// <summary>
/// Defines constants for each of the supported TIFF metadata types.
/// </summary>
public static class TiffMetadataNames
{
/// <summary>
/// Person who created the image.
/// </summary>
public const string Artist = "Artist";
/// <summary>
/// Copyright notice.
/// </summary>
public const string Copyright = "Copyright";
/// <summary>
/// Date and time of image creation.
/// </summary>
public const string DateTime = "DateTime";
/// <summary>
/// The computer and/or operating system in use at the time of image creation.
/// </summary>
public const string HostComputer = "HostComputer";
/// <summary>
/// A string that describes the subject of the image.
/// </summary>
public const string ImageDescription = "ImageDescription";
/// <summary>
/// The scanner/camera manufacturer.
/// </summary>
public const string Make = "Make";
/// <summary>
/// The scanner/camera model name or number.
/// </summary>
public const string Model = "Model";
/// <summary>
/// Name and version number of the software package(s) used to create the image.
/// </summary>
public const string Software = "Software";
}
}

74
tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderMetadataTests.cs

@ -7,6 +7,7 @@ namespace ImageSharp.Tests
{
using System;
using System.IO;
using System.Linq;
using Xunit;
using ImageSharp.Formats;
@ -14,8 +15,22 @@ namespace ImageSharp.Tests
public class TiffDecoderMetadataTests
{
public static object[][] IsLittleEndianValues = new[] { new object[] { false },
new object[] { true } };
public static object[][] BaselineMetadataValues = new[] { new object[] { false, TiffTags.Artist, TiffMetadataNames.Artist, "My Artist Name" },
new object[] { false, TiffTags.Copyright, TiffMetadataNames.Copyright, "My Copyright Statement" },
new object[] { false, TiffTags.DateTime, TiffMetadataNames.DateTime, "My DateTime Value" },
new object[] { false, TiffTags.HostComputer, TiffMetadataNames.HostComputer, "My Host Computer Name" },
new object[] { false, TiffTags.ImageDescription, TiffMetadataNames.ImageDescription, "My Image Description" },
new object[] { false, TiffTags.Make, TiffMetadataNames.Make, "My Camera Make" },
new object[] { false, TiffTags.Model, TiffMetadataNames.Model, "My Camera Model" },
new object[] { false, TiffTags.Software, TiffMetadataNames.Software, "My Imaging Software" },
new object[] { true, TiffTags.Artist, TiffMetadataNames.Artist, "My Artist Name" },
new object[] { true, TiffTags.Copyright, TiffMetadataNames.Copyright, "My Copyright Statement" },
new object[] { true, TiffTags.DateTime, TiffMetadataNames.DateTime, "My DateTime Value" },
new object[] { true, TiffTags.HostComputer, TiffMetadataNames.HostComputer, "My Host Computer Name" },
new object[] { true, TiffTags.ImageDescription, TiffMetadataNames.ImageDescription, "My Image Description" },
new object[] { true, TiffTags.Make, TiffMetadataNames.Make, "My Camera Make" },
new object[] { true, TiffTags.Model, TiffMetadataNames.Model, "My Camera Model" },
new object[] { true, TiffTags.Software, TiffMetadataNames.Software, "My Imaging Software" }};
[Theory]
[InlineData(false, 150u, 1u, 200u, 1u, 2u /* Inch */, 150.0, 200.0)]
@ -34,7 +49,7 @@ namespace ImageSharp.Tests
[InlineData(true, null, null, null, null, null /* Inch */, 96.0, 96.0)]
[InlineData(true, 150u, 1u, null, null, 2u /* Inch */, 150.0, 96.0)]
[InlineData(true, null, null, 200u, 1u, 2u /* Inch */, 96.0, 200.0)]
public void DecodeImage_SetsImageResolution(bool isLittleEndian, uint? xResolutionNumerator, uint? xResolutionDenominator,
public void ReadMetadata_SetsImageResolution(bool isLittleEndian, uint? xResolutionNumerator, uint? xResolutionDenominator,
uint? yResolutionNumerator, uint? yResolutionDenominator, uint? resolutionUnit,
double expectedHorizonalResolution, double expectedVerticalResolution)
{
@ -66,5 +81,58 @@ namespace ImageSharp.Tests
Assert.Equal(expectedHorizonalResolution, image.MetaData.HorizontalResolution, 10);
Assert.Equal(expectedVerticalResolution, image.MetaData.VerticalResolution, 10);
}
[Theory]
[MemberData(nameof(BaselineMetadataValues))]
public void ReadMetadata_SetsAsciiMetadata(bool isLittleEndian, ushort tag, string metadataName, string metadataValue)
{
Stream stream = new TiffGenIfd()
{
Entries =
{
TiffGenEntry.Integer(TiffTags.ImageWidth, TiffType.Long, 150),
TiffGenEntry.Integer(TiffTags.ImageLength, TiffType.Long, 210),
TiffGenEntry.Ascii(tag, metadataValue),
TiffGenEntry.Integer(TiffTags.Orientation, TiffType.Short, 1)
}
}
.ToStream(isLittleEndian);
TiffDecoderCore decoder = new TiffDecoderCore(stream, isLittleEndian, null, null);
TiffIfd ifd = decoder.ReadIfd(0);
Image<Rgba32> image = new Image<Rgba32>(null, 20, 20);
decoder.ReadMetadata<Rgba32>(ifd, image);
var metadata = image.MetaData.Properties.FirstOrDefault(m => m.Name == metadataName)?.Value;
Assert.Equal(metadataValue, metadata);
}
[Theory]
[MemberData(nameof(BaselineMetadataValues))]
public void ReadMetadata_DoesntSetMetadataIfIgnoring(bool isLittleEndian, ushort tag, string metadataName, string metadataValue)
{
Stream stream = new TiffGenIfd()
{
Entries =
{
TiffGenEntry.Integer(TiffTags.ImageWidth, TiffType.Long, 150),
TiffGenEntry.Integer(TiffTags.ImageLength, TiffType.Long, 210),
TiffGenEntry.Ascii(tag, metadataValue),
TiffGenEntry.Integer(TiffTags.Orientation, TiffType.Short, 1)
}
}
.ToStream(isLittleEndian);
DecoderOptions options = new DecoderOptions() { IgnoreMetadata = true };
TiffDecoderCore decoder = new TiffDecoderCore(stream, isLittleEndian, options, null);
TiffIfd ifd = decoder.ReadIfd(0);
Image<Rgba32> image = new Image<Rgba32>(null, 20, 20);
decoder.ReadMetadata<Rgba32>(ifd, image);
var metadata = image.MetaData.Properties.FirstOrDefault(m => m.Name == metadataName)?.Value;
Assert.Equal(null, metadata);
}
}
}
Loading…
Cancel
Save