Browse Source

Add support for pallete color images

pull/1570/head
Andrew Wilkinson 9 years ago
parent
commit
80fb83d760
  1. 73
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/PaletteTiffColor.cs
  2. 7
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
  3. 154
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
  4. 144
      tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/PhotometricInterpretation/PaletteTiffColorTests.cs
  5. 118
      tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderImageTests.cs

73
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/PaletteTiffColor.cs

@ -0,0 +1,73 @@
// <copyright file="PaletteTiffColor.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Formats.Tiff
{
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using ImageSharp;
using ImageSharp.PixelFormats;
/// <summary>
/// Implements the 'PaletteTiffColor' photometric interpretation (for all bit depths).
/// </summary>
internal static class PaletteTiffColor
{
/// <summary>
/// Decodes pixel data using the current photometric interpretation.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="data">The buffer to read image data from.</param>
/// <param name="bitsPerSample">The number of bits per sample for each pixel.</param>
/// <param name="colorMap">The RGB color lookup table to use for decoding the image.</param>
/// <param name="pixels">The image buffer to write pixels to.</param>
/// <param name="left">The x-coordinate of the left-hand side of the image block.</param>
/// <param name="top">The y-coordinate of the top of the image block.</param>
/// <param name="width">The width of the image block.</param>
/// <param name="height">The height of the image block.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Decode<TPixel>(byte[] data, uint[] bitsPerSample, uint[] colorMap, PixelAccessor<TPixel> pixels, int left, int top, int width, int height)
where TPixel : struct, IPixel<TPixel>
{
int colorCount = (int)Math.Pow(2, bitsPerSample[0]);
TPixel[] palette = GeneratePalette<TPixel>(colorMap, colorCount);
BitReader bitReader = new BitReader(data);
for (int y = top; y < top + height; y++)
{
for (int x = left; x < left + width; x++)
{
int index = bitReader.ReadBits(bitsPerSample[0]);
pixels[x, y] = palette[index];
}
bitReader.NextRow();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static TPixel[] GeneratePalette<TPixel>(uint[] colorMap, int colorCount)
where TPixel : struct, IPixel<TPixel>
{
TPixel[] palette = new TPixel[colorCount];
int rOffset = 0;
int gOffset = colorCount;
int bOffset = colorCount * 2;
for (int i = 0; i < palette.Length; i++)
{
float r = colorMap[rOffset + i] / 65535F;
float g = colorMap[gOffset + i] / 65535F;
float b = colorMap[bOffset + i] / 65535F;
palette[i].PackFromVector4(new Vector4(r, g, b, 1.0f));
}
return palette;
}
}
}

7
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs

@ -48,6 +48,11 @@ namespace ImageSharp.Formats.Tiff
/// <summary>
/// Grayscale: 0 is imaged as white. The maximum value is imaged as black. Optimised implementation for 8-bit images.
/// </summary>
WhiteIsZero8
WhiteIsZero8,
/// <summary>
/// Palette-color.
/// </summary>
PaletteColor
}
}

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

@ -57,6 +57,11 @@ namespace ImageSharp.Formats
/// </summary>
public uint[] BitsPerSample { get; set; }
/// <summary>
/// Gets or sets the lookup table for RGB palette colored images.
/// </summary>
public uint[] ColorMap { get; set; }
/// <summary>
/// Gets or sets the photometric interpretation implementation to use when decoding the image.
/// </summary>
@ -287,93 +292,128 @@ namespace ImageSharp.Formats
}
}
if (ifd.TryGetIfdEntry(TiffTags.BitsPerSample, out TiffIfdEntry bitsPerSampleEntry))
{
this.BitsPerSample = this.ReadUnsignedIntegerArray(ref bitsPerSampleEntry);
}
else
{
if (photometricInterpretation == TiffPhotometricInterpretation.WhiteIsZero ||
photometricInterpretation == TiffPhotometricInterpretation.BlackIsZero)
{
this.BitsPerSample = new[] { 1u };
}
else
{
throw new ImageFormatException("The TIFF BitsPerSample entry is missing.");
}
}
switch (photometricInterpretation)
{
case TiffPhotometricInterpretation.WhiteIsZero:
{
if (ifd.TryGetIfdEntry(TiffTags.BitsPerSample, out TiffIfdEntry bitsPerSampleEntry))
if (this.BitsPerSample.Length == 1)
{
this.BitsPerSample = this.ReadUnsignedIntegerArray(ref bitsPerSampleEntry);
if (this.BitsPerSample.Length == 1)
switch (this.BitsPerSample[0])
{
switch (this.BitsPerSample[0])
{
case 8:
{
this.ColorType = TiffColorType.WhiteIsZero8;
break;
}
case 4:
{
this.ColorType = TiffColorType.WhiteIsZero4;
break;
}
case 8:
{
this.ColorType = TiffColorType.WhiteIsZero8;
break;
}
case 4:
{
this.ColorType = TiffColorType.WhiteIsZero4;
break;
}
case 1:
{
this.ColorType = TiffColorType.WhiteIsZero1;
break;
}
default:
{
this.ColorType = TiffColorType.WhiteIsZero;
break;
}
}
}
else
{
throw new NotSupportedException("The number of samples in the TIFF BitsPerSample entry is not supported.");
}
case 1:
{
this.ColorType = TiffColorType.WhiteIsZero1;
break;
}
break;
}
default:
{
this.ColorType = TiffColorType.WhiteIsZero;
break;
}
}
case TiffPhotometricInterpretation.BlackIsZero:
{
if (this.BitsPerSample.Length == 1)
{
switch (this.BitsPerSample[0])
{
case 8:
{
this.ColorType = TiffColorType.BlackIsZero8;
break;
}
case 4:
{
this.ColorType = TiffColorType.BlackIsZero4;
break;
}
case 1:
{
this.ColorType = TiffColorType.BlackIsZero1;
break;
}
default:
{
this.ColorType = TiffColorType.BlackIsZero;
break;
}
}
}
else
{
this.ColorType = TiffColorType.WhiteIsZero1;
this.BitsPerSample = new[] { 1u };
throw new NotSupportedException("The number of samples in the TIFF BitsPerSample entry is not supported.");
}
break;
}
case TiffPhotometricInterpretation.BlackIsZero:
case TiffPhotometricInterpretation.PaletteColor:
{
if (ifd.TryGetIfdEntry(TiffTags.BitsPerSample, out TiffIfdEntry bitsPerSampleEntry))
if (ifd.TryGetIfdEntry(TiffTags.ColorMap, out TiffIfdEntry colorMapEntry))
{
this.BitsPerSample = this.ReadUnsignedIntegerArray(ref bitsPerSampleEntry);
this.ColorMap = this.ReadUnsignedIntegerArray(ref colorMapEntry);
if (this.BitsPerSample.Length == 1)
{
switch (this.BitsPerSample[0])
{
case 8:
{
this.ColorType = TiffColorType.BlackIsZero8;
break;
}
case 4:
{
this.ColorType = TiffColorType.BlackIsZero4;
break;
}
case 1:
{
this.ColorType = TiffColorType.BlackIsZero1;
break;
}
default:
{
this.ColorType = TiffColorType.BlackIsZero;
this.ColorType = TiffColorType.PaletteColor;
break;
}
}
}
else
{
throw new NotSupportedException("The number of samples in the TIFF BitsPerSample entry is not supported.");
}
}
else
{
this.ColorType = TiffColorType.BlackIsZero1;
this.BitsPerSample = new[] { 1u };
throw new ImageFormatException("The TIFF ColorMap entry is missing for a pallete color image.");
}
break;
@ -398,7 +438,8 @@ namespace ImageSharp.Formats
bitsPerPixel += this.BitsPerSample[i];
}
int bytesPerRow = ((width * (int)bitsPerPixel) + 7) / 8;
int sampleMultiplier = this.ColorType == TiffColorType.PaletteColor ? 3 : 1;
int bytesPerRow = ((width * (int)bitsPerPixel * sampleMultiplier) + 7) / 8;
return bytesPerRow * height;
}
@ -464,6 +505,9 @@ namespace ImageSharp.Formats
case TiffColorType.BlackIsZero8:
BlackIsZero8TiffColor.Decode(data, pixels, left, top, width, height);
break;
case TiffColorType.PaletteColor:
PaletteTiffColor.Decode(data, this.BitsPerSample, this.ColorMap, pixels, left, top, width, height);
break;
default:
throw new InvalidOperationException();
}

144
tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/PhotometricInterpretation/PaletteTiffColorTests.cs

@ -0,0 +1,144 @@
// <copyright file="PaletteTiffColorTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests
{
using System.Collections.Generic;
using Xunit;
using ImageSharp.Formats.Tiff;
using ImageSharp.PixelFormats;
public class PaletteTiffColorTests : PhotometricInterpretationTestBase
{
public static uint[][] Palette4_ColorPalette { get => GeneratePalette(16); }
public static uint[] Palette4_ColorMap { get => GenerateColorMap(Palette4_ColorPalette); }
private static byte[] Palette4_Bytes4x4 = new byte[] { 0x01, 0x23,
0x4A, 0xD2,
0x12, 0x34,
0xAB, 0xEF };
private static Rgba32[][] Palette4_Result4x4 = GenerateResult(Palette4_ColorPalette,
new[] { new[] { 0x00, 0x01, 0x02, 0x03 },
new[] { 0x04, 0x0A, 0x0D, 0x02 },
new[] { 0x01, 0x02, 0x03, 0x04 },
new[] { 0x0A, 0x0B, 0x0E, 0x0F }});
private static byte[] Palette4_Bytes3x4 = new byte[] { 0x01, 0x20,
0x4A, 0xD0,
0x12, 0x30,
0xAB, 0xE0 };
private static Rgba32[][] Palette4_Result3x4 = GenerateResult(Palette4_ColorPalette,
new[] { new[] { 0x00, 0x01, 0x02 },
new[] { 0x04, 0x0A, 0x0D },
new[] { 0x01, 0x02, 0x03 },
new[] { 0x0A, 0x0B, 0x0E }});
public static IEnumerable<object[]> Palette4_Data
{
get
{
yield return new object[] { Palette4_Bytes4x4, 4, Palette4_ColorMap, 0, 0, 4, 4, Palette4_Result4x4 };
yield return new object[] { Palette4_Bytes4x4, 4, Palette4_ColorMap, 0, 0, 4, 4, Offset(Palette4_Result4x4, 0, 0, 6, 6) };
yield return new object[] { Palette4_Bytes4x4, 4, Palette4_ColorMap, 1, 0, 4, 4, Offset(Palette4_Result4x4, 1, 0, 6, 6) };
yield return new object[] { Palette4_Bytes4x4, 4, Palette4_ColorMap, 0, 1, 4, 4, Offset(Palette4_Result4x4, 0, 1, 6, 6) };
yield return new object[] { Palette4_Bytes4x4, 4, Palette4_ColorMap, 1, 1, 4, 4, Offset(Palette4_Result4x4, 1, 1, 6, 6) };
yield return new object[] { Palette4_Bytes3x4, 4, Palette4_ColorMap, 0, 0, 3, 4, Palette4_Result3x4 };
yield return new object[] { Palette4_Bytes3x4, 4, Palette4_ColorMap, 0, 0, 3, 4, Offset(Palette4_Result3x4, 0, 0, 6, 6) };
yield return new object[] { Palette4_Bytes3x4, 4, Palette4_ColorMap, 1, 0, 3, 4, Offset(Palette4_Result3x4, 1, 0, 6, 6) };
yield return new object[] { Palette4_Bytes3x4, 4, Palette4_ColorMap, 0, 1, 3, 4, Offset(Palette4_Result3x4, 0, 1, 6, 6) };
yield return new object[] { Palette4_Bytes3x4, 4, Palette4_ColorMap, 1, 1, 3, 4, Offset(Palette4_Result3x4, 1, 1, 6, 6) };
}
}
public static uint[][] Palette8_ColorPalette { get => GeneratePalette(256); }
public static uint[] Palette8_ColorMap { get => GenerateColorMap(Palette8_ColorPalette); }
private static byte[] Palette8_Bytes4x4 = new byte[] { 000, 001, 002, 003,
100, 110, 120, 130,
000, 255, 128, 255,
050, 100, 150, 200 };
private static Rgba32[][] Palette8_Result4x4 = GenerateResult(Palette8_ColorPalette,
new[] { new[] { 000, 001, 002, 003 },
new[] { 100, 110, 120, 130 },
new[] { 000, 255, 128, 255 },
new[] { 050, 100, 150, 200 }});
public static IEnumerable<object[]> Palette8_Data
{
get
{
yield return new object[] { Palette8_Bytes4x4, 8, Palette8_ColorMap, 0, 0, 4, 4, Palette8_Result4x4 };
yield return new object[] { Palette8_Bytes4x4, 8, Palette8_ColorMap, 0, 0, 4, 4, Offset(Palette8_Result4x4, 0, 0, 6, 6) };
yield return new object[] { Palette8_Bytes4x4, 8, Palette8_ColorMap, 1, 0, 4, 4, Offset(Palette8_Result4x4, 1, 0, 6, 6) };
yield return new object[] { Palette8_Bytes4x4, 8, Palette8_ColorMap, 0, 1, 4, 4, Offset(Palette8_Result4x4, 0, 1, 6, 6) };
yield return new object[] { Palette8_Bytes4x4, 8, Palette8_ColorMap, 1, 1, 4, 4, Offset(Palette8_Result4x4, 1, 1, 6, 6) };
}
}
[Theory]
[MemberData(nameof(Palette4_Data))]
[MemberData(nameof(Palette8_Data))]
public void Decode_WritesPixelData(byte[] inputData, int bitsPerSample, uint[] colorMap, int left, int top, int width, int height, Rgba32[][] expectedResult)
{
AssertDecode(expectedResult, pixels =>
{
PaletteTiffColor.Decode(inputData, new[] { (uint)bitsPerSample }, colorMap, pixels, left, top, width, height);
});
}
private static uint[][] GeneratePalette(int count)
{
uint[][] palette = new uint[count][];
for (uint i = 0; i < count; i++)
{
palette[i] = new uint[] { (i * 2u) % 65536u, (i * 2625u) % 65536u, (i * 29401u) % 65536u };
}
return palette;
}
private static uint[] GenerateColorMap(uint[][] colorPalette)
{
int colorCount = colorPalette.Length;
uint[] colorMap = new uint[colorCount * 3];
for (int i = 0; i < colorCount; i++)
{
colorMap[colorCount * 0 + i] = colorPalette[i][0];
colorMap[colorCount * 1 + i] = colorPalette[i][1];
colorMap[colorCount * 2 + i] = colorPalette[i][2];
}
return colorMap;
}
private static Rgba32[][] GenerateResult(uint[][] colorPalette, int[][] pixelLookup)
{
Rgba32[][] result = new Rgba32[pixelLookup.Length][];
for (int y = 0; y < pixelLookup.Length; y++)
{
result[y] = new Rgba32[pixelLookup[y].Length];
for (int x = 0; x < pixelLookup[y].Length; x++)
{
uint[] sourceColor = colorPalette[pixelLookup[y][x]];
result[y][x] = new Rgba32(sourceColor[0] / 65535F, sourceColor[1] / 65535F, sourceColor[2] / 65535F);
}
}
return result;
}
}
}

118
tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderImageTests.cs

@ -192,6 +192,14 @@ namespace ImageSharp.Tests
[InlineData(true, TiffPhotometricInterpretation.BlackIsZero, new[] { 4 }, TiffColorType.BlackIsZero4)]
[InlineData(false, TiffPhotometricInterpretation.BlackIsZero, new[] { 1 }, TiffColorType.BlackIsZero1)]
[InlineData(true, TiffPhotometricInterpretation.BlackIsZero, new[] { 1 }, TiffColorType.BlackIsZero1)]
[InlineData(false, TiffPhotometricInterpretation.PaletteColor, new[] { 3 }, TiffColorType.PaletteColor)]
[InlineData(true, TiffPhotometricInterpretation.PaletteColor, new[] { 3 }, TiffColorType.PaletteColor)]
[InlineData(false, TiffPhotometricInterpretation.PaletteColor, new[] { 8 }, TiffColorType.PaletteColor)]
[InlineData(true, TiffPhotometricInterpretation.PaletteColor, new[] { 8 }, TiffColorType.PaletteColor)]
[InlineData(false, TiffPhotometricInterpretation.PaletteColor, new[] { 4 }, TiffColorType.PaletteColor)]
[InlineData(true, TiffPhotometricInterpretation.PaletteColor, new[] { 4 }, TiffColorType.PaletteColor)]
[InlineData(false, TiffPhotometricInterpretation.PaletteColor, new[] { 1 }, TiffColorType.PaletteColor)]
[InlineData(true, TiffPhotometricInterpretation.PaletteColor, new[] { 1 }, TiffColorType.PaletteColor)]
public void ReadImageFormat_DeterminesCorrectColorImplementation(bool isLittleEndian, ushort photometricInterpretation, int[] bitsPerSample, int colorType)
{
Stream stream = CreateTiffGenIfd()
@ -265,7 +273,6 @@ namespace ImageSharp.Tests
[InlineData(false, TiffPhotometricInterpretation.IccLab)]
[InlineData(false, TiffPhotometricInterpretation.ItuLab)]
[InlineData(false, TiffPhotometricInterpretation.LinearRaw)]
[InlineData(false, TiffPhotometricInterpretation.PaletteColor)]
[InlineData(false, TiffPhotometricInterpretation.Rgb)]
[InlineData(false, TiffPhotometricInterpretation.Separated)]
[InlineData(false, TiffPhotometricInterpretation.TransparencyMask)]
@ -276,7 +283,6 @@ namespace ImageSharp.Tests
[InlineData(true, TiffPhotometricInterpretation.IccLab)]
[InlineData(true, TiffPhotometricInterpretation.ItuLab)]
[InlineData(true, TiffPhotometricInterpretation.LinearRaw)]
[InlineData(true, TiffPhotometricInterpretation.PaletteColor)]
[InlineData(true, TiffPhotometricInterpretation.Rgb)]
[InlineData(true, TiffPhotometricInterpretation.Separated)]
[InlineData(true, TiffPhotometricInterpretation.TransparencyMask)]
@ -303,10 +309,10 @@ namespace ImageSharp.Tests
[InlineData(true, new[] { 4u })]
[InlineData(false, new[] { 1u })]
[InlineData(true, new[] { 1u })]
[InlineData(false, new[] { 1u, 2u, 3u })]
[InlineData(true, new[] { 1u, 2u, 3u })]
[InlineData(false, new[] { 8u, 8u, 8u })]
[InlineData(true, new[] { 8u, 8u, 8u })]
// [InlineData(false, new[] { 1u, 2u, 3u })]
// [InlineData(true, new[] { 1u, 2u, 3u })]
// [InlineData(false, new[] { 8u, 8u, 8u })]
// [InlineData(true, new[] { 8u, 8u, 8u })]
public void ReadImageFormat_ReadsBitsPerSample(bool isLittleEndian, uint[] bitsPerSample)
{
Stream stream = CreateTiffGenIfd()
@ -339,6 +345,84 @@ namespace ImageSharp.Tests
Assert.Equal(new[] { 1u }, decoder.BitsPerSample);
}
[Theory]
[MemberData(nameof(IsLittleEndianValues))]
public void ReadImageFormat_ThrowsExceptionForMissingBitsPerSample(bool isLittleEndian)
{
Stream stream = CreateTiffGenIfd()
.WithEntry(TiffGenEntry.Integer(TiffTags.PhotometricInterpretation, TiffType.Short, (int)TiffPhotometricInterpretation.PaletteColor))
.WithoutEntry(TiffTags.BitsPerSample)
.ToStream(isLittleEndian);
TiffDecoderCore decoder = new TiffDecoderCore(stream, isLittleEndian, null, null);
TiffIfd ifd = decoder.ReadIfd(0);
var e = Assert.Throws<ImageFormatException>(() => decoder.ReadImageFormat(ifd));
Assert.Equal("The TIFF BitsPerSample entry is missing.", e.Message);
}
[Theory]
[InlineData(false, TiffPhotometricInterpretation.WhiteIsZero, new int[] { })]
[InlineData(true, TiffPhotometricInterpretation.WhiteIsZero, new int[] { })]
[InlineData(false, TiffPhotometricInterpretation.BlackIsZero, new int[] { })]
[InlineData(true, TiffPhotometricInterpretation.BlackIsZero, new int[] { })]
[InlineData(false, TiffPhotometricInterpretation.PaletteColor, new int[] { })]
[InlineData(true, TiffPhotometricInterpretation.PaletteColor, new int[] { })]
[InlineData(false, TiffPhotometricInterpretation.WhiteIsZero, new[] { 8, 8 })]
[InlineData(true, TiffPhotometricInterpretation.WhiteIsZero, new[] { 8, 8 })]
[InlineData(false, TiffPhotometricInterpretation.BlackIsZero, new[] { 8, 8 })]
[InlineData(true, TiffPhotometricInterpretation.BlackIsZero, new[] { 8, 8 })]
[InlineData(false, TiffPhotometricInterpretation.PaletteColor, new[] { 8, 8 })]
[InlineData(true, TiffPhotometricInterpretation.PaletteColor, new[] { 8, 8 })]
public void ReadImageFormat_ThrowsExceptionForUnsupportedNumberOfSamples(bool isLittleEndian, ushort photometricInterpretation, int[] bitsPerSample)
{
Stream stream = CreateTiffGenIfd()
.WithEntry(TiffGenEntry.Integer(TiffTags.PhotometricInterpretation, TiffType.Short, photometricInterpretation))
.WithEntry(TiffGenEntry.Integer(TiffTags.BitsPerSample, TiffType.Short, bitsPerSample))
.ToStream(isLittleEndian);
TiffDecoderCore decoder = new TiffDecoderCore(stream, isLittleEndian, null, null);
TiffIfd ifd = decoder.ReadIfd(0);
var e = Assert.Throws<NotSupportedException>(() => decoder.ReadImageFormat(ifd));
Assert.Equal("The number of samples in the TIFF BitsPerSample entry is not supported.", e.Message);
}
[Theory]
[MemberData(nameof(IsLittleEndianValues))]
public void ReadImageFormat_ReadsColorMap(bool isLittleEndian)
{
Stream stream = CreateTiffGenIfd()
.WithEntry(TiffGenEntry.Integer(TiffTags.PhotometricInterpretation, TiffType.Short, (int)TiffPhotometricInterpretation.PaletteColor))
.WithEntry(TiffGenEntry.Integer(TiffTags.ColorMap, TiffType.Short, new int[] { 10, 20, 30, 40, 50, 60 }))
.ToStream(isLittleEndian);
TiffDecoderCore decoder = new TiffDecoderCore(stream, isLittleEndian, null, null);
TiffIfd ifd = decoder.ReadIfd(0);
decoder.ReadImageFormat(ifd);
Assert.Equal(new uint[] { 10, 20, 30, 40, 50, 60 }, decoder.ColorMap);
}
[Theory]
[MemberData(nameof(IsLittleEndianValues))]
public void ReadImageFormat_ThrowsExceptionForMissingColorMap(bool isLittleEndian)
{
Stream stream = CreateTiffGenIfd()
.WithEntry(TiffGenEntry.Integer(TiffTags.PhotometricInterpretation, TiffType.Short, (int)TiffPhotometricInterpretation.PaletteColor))
.WithoutEntry(TiffTags.ColorMap)
.ToStream(isLittleEndian);
TiffDecoderCore decoder = new TiffDecoderCore(stream, isLittleEndian, null, null);
TiffIfd ifd = decoder.ReadIfd(0);
var e = Assert.Throws<ImageFormatException>(() => decoder.ReadImageFormat(ifd));
Assert.Equal("The TIFF ColorMap entry is missing for a pallete color image.", e.Message);
}
[Theory]
[InlineData(new uint[] { 1 }, 160, 80, 20 * 80)]
[InlineData(new uint[] { 1 }, 153, 80, 20 * 80)]
@ -349,6 +433,25 @@ namespace ImageSharp.Tests
public void CalculateImageBufferSize_ReturnsCorrectSize(uint[] bitsPerSample, int width, int height, int expectedResult)
{
TiffDecoderCore decoder = new TiffDecoderCore(null, null);
decoder.ColorType = TiffColorType.WhiteIsZero;
decoder.BitsPerSample = bitsPerSample;
int bufferSize = decoder.CalculateImageBufferSize(width, height);
Assert.Equal(expectedResult, bufferSize);
}
[Theory]
[InlineData(new uint[] { 1 }, 160, 80, 60 * 80)]
[InlineData(new uint[] { 1 }, 153, 80, 58 * 80)]
[InlineData(new uint[] { 3 }, 100, 80, 113 * 80)]
[InlineData(new uint[] { 4 }, 100, 80, 150 * 80)]
[InlineData(new uint[] { 4 }, 99, 80, 149 * 80)]
[InlineData(new uint[] { 8 }, 100, 80, 300 * 80)]
public void CalculateImageBufferSize_ReturnsCorrectSize_ForPaletteColor(uint[] bitsPerSample, int width, int height, int expectedResult)
{
TiffDecoderCore decoder = new TiffDecoderCore(null, null);
decoder.ColorType = TiffColorType.PaletteColor;
decoder.BitsPerSample = bitsPerSample;
int bufferSize = decoder.CalculateImageBufferSize(width, height);
@ -369,7 +472,8 @@ namespace ImageSharp.Tests
TiffGenEntry.Integer(TiffTags.ResolutionUnit, TiffType.Short, 2),
TiffGenEntry.Integer(TiffTags.PhotometricInterpretation, TiffType.Short, (int)TiffPhotometricInterpretation.WhiteIsZero),
TiffGenEntry.Integer(TiffTags.BitsPerSample, TiffType.Short, new int[] { 8 }),
TiffGenEntry.Integer(TiffTags.Compression, TiffType.Short, (int)TiffCompression.None)
TiffGenEntry.Integer(TiffTags.Compression, TiffType.Short, (int)TiffCompression.None),
TiffGenEntry.Integer(TiffTags.ColorMap, TiffType.Short, new int[256])
}
};
}

Loading…
Cancel
Save