Browse Source

Read strings from TIFF IFDs

pull/1570/head
Andrew Wilkinson 9 years ago
parent
commit
a27964aabe
  1. 14
      src/ImageSharp.Formats.Tiff/TiffDecoderCore.cs
  2. 59
      tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderIfdEntryTests.cs

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

@ -8,6 +8,7 @@ namespace ImageSharp.Formats
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
/// <summary>
@ -250,6 +251,19 @@ namespace ImageSharp.Formats
return result;
}
public string ReadString(ref TiffIfdEntry entry)
{
if (entry.Type != TiffType.Ascii)
throw new ImageFormatException($"A value of type '{entry.Type}' cannot be converted to a string.");
byte[] bytes = ReadBytes(ref entry);
if (bytes[entry.Count - 1] != 0)
throw new ImageFormatException("The retrieved string is not null terminated.");
return Encoding.UTF8.GetString(bytes, 0, (int)entry.Count - 1);
}
private SByte ToSByte(byte[] bytes, int offset)
{
return (sbyte)bytes[offset];

59
tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderIfdEntryTests.cs

@ -364,6 +364,65 @@ namespace ImageSharp.Tests
Assert.Equal($"A value of type '{(TiffType)type}' cannot be converted to a signed integer.", e.Message);
}
[Theory]
[InlineDataAttribute(true, new byte[] { 0 }, "")]
[InlineDataAttribute(true, new byte[] { (byte)'A', (byte)'B', (byte)'C', 0 }, "ABC")]
[InlineDataAttribute(true, new byte[] { (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', 0 }, "ABCDEF")]
[InlineDataAttribute(true, new byte[] { (byte)'A', (byte)'B', (byte)'C', (byte)'D', 0, (byte)'E', (byte)'F', (byte)'G', (byte)'H', 0 }, "ABCD\0EFGH")]
[InlineDataAttribute(false, new byte[] { 0 }, "")]
[InlineDataAttribute(false, new byte[] { (byte)'A', (byte)'B', (byte)'C', 0 }, "ABC")]
[InlineDataAttribute(false, new byte[] { (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', 0 }, "ABCDEF")]
[InlineDataAttribute(false, new byte[] { (byte)'A', (byte)'B', (byte)'C', (byte)'D', 0, (byte)'E', (byte)'F', (byte)'G', (byte)'H', 0 }, "ABCD\0EFGH")]
public void ReadString_ReturnsValue(bool isLittleEndian, byte[] bytes, string expectedValue)
{
(TiffDecoderCore decoder, TiffIfdEntry entry) = GenerateTestIfdEntry(TiffGenEntry.Bytes(TiffTags.ImageWidth, TiffType.Ascii, (uint)bytes.Length, bytes), isLittleEndian);
string result = decoder.ReadString(ref entry);
Assert.Equal(expectedValue, result);
}
[Theory]
[InlineDataAttribute(TiffType.Byte)]
[InlineDataAttribute(TiffType.Short)]
[InlineDataAttribute(TiffType.Long)]
[InlineDataAttribute(TiffType.Rational)]
[InlineDataAttribute(TiffType.SByte)]
[InlineDataAttribute(TiffType.Undefined)]
[InlineDataAttribute(TiffType.SShort)]
[InlineDataAttribute(TiffType.SLong)]
[InlineDataAttribute(TiffType.SRational)]
[InlineDataAttribute(TiffType.Float)]
[InlineDataAttribute(TiffType.Double)]
[InlineDataAttribute(TiffType.Ifd)]
[InlineDataAttribute((TiffType)99)]
public void ReadString_ThrowsExceptionIfInvalidType(ushort type)
{
(TiffDecoderCore decoder, TiffIfdEntry entry) = GenerateTestIfdEntry(TiffGenEntry.Bytes(TiffTags.ImageWidth, (TiffType)type, 1, new byte[4]), true);
var e = Assert.Throws<ImageFormatException>(() => decoder.ReadString(ref entry));
Assert.Equal($"A value of type '{(TiffType)type}' cannot be converted to a string.", e.Message);
}
[Theory]
[InlineDataAttribute(true, new byte[] { (byte)'A' })]
[InlineDataAttribute(true, new byte[] { (byte)'A', (byte)'B', (byte)'C' })]
[InlineDataAttribute(true, new byte[] { (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F' })]
[InlineDataAttribute(true, new byte[] { (byte)'A', (byte)'B', (byte)'C', (byte)'D', 0, (byte)'E', (byte)'F', (byte)'G', (byte)'H' })]
[InlineDataAttribute(false, new byte[] { (byte)'A' })]
[InlineDataAttribute(false, new byte[] { (byte)'A', (byte)'B', (byte)'C' })]
[InlineDataAttribute(false, new byte[] { (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F' })]
[InlineDataAttribute(false, new byte[] { (byte)'A', (byte)'B', (byte)'C', (byte)'D', 0, (byte)'E', (byte)'F', (byte)'G', (byte)'H' })]
public void ReadString_ThrowsExceptionIfStringIsNotNullTerminated(bool isLittleEndian, byte[] bytes)
{
(TiffDecoderCore decoder, TiffIfdEntry entry) = GenerateTestIfdEntry(TiffGenEntry.Bytes(TiffTags.ImageWidth, TiffType.Ascii, (uint)bytes.Length, bytes), isLittleEndian);
var e = Assert.Throws<ImageFormatException>(() => decoder.ReadString(ref entry));
Assert.Equal($"The retrieved string is not null terminated.", e.Message);
}
private (TiffDecoderCore, TiffIfdEntry) GenerateTestIfdEntry(TiffGenEntry entry, bool isLittleEndian)
{
Stream stream = new TiffGenIfd()

Loading…
Cancel
Save