Browse Source

Review changes

pull/1553/head
Brian Popow 5 years ago
parent
commit
5fcb5fcf0f
  1. 2
      src/ImageSharp/Formats/Tiff/Compression/Compressors/DeflateCompressor.cs
  2. 2
      src/ImageSharp/Formats/Tiff/Compression/Compressors/LzwCompressor.cs
  3. 2
      src/ImageSharp/Formats/Tiff/Compression/Compressors/NoCompressor.cs
  4. 2
      src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsCompressor.cs
  5. 4
      src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsWriter.cs
  6. 8
      src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs
  7. 4
      src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs
  8. 5
      src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs
  9. 12
      src/ImageSharp/Formats/Tiff/Constants/TiffNewSubfileType.cs
  10. 2
      src/ImageSharp/Formats/Tiff/Constants/TiffPredictor.cs
  11. 4
      src/ImageSharp/Formats/Tiff/ITiffDecoderOptions.cs
  12. 5
      src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
  13. 6
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero1TiffColor.cs
  14. 6
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero4TiffColor.cs
  15. 6
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero8TiffColor.cs
  16. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZeroTiffColor.cs
  17. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/PaletteTiffColor.cs
  18. 6
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb888TiffColor.cs
  19. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbPlanarTiffColor.cs
  20. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbTiffColor.cs
  21. 16
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffBaseColorDecoder.cs
  22. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory.cs
  23. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
  24. 6
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero1TiffColor.cs
  25. 6
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero4TiffColor.cs
  26. 6
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero8TiffColor.cs
  27. 2
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZeroTiffColor.cs
  28. 5
      src/ImageSharp/Formats/Tiff/README.md
  29. 1
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
  30. 1
      src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
  31. 3
      src/ImageSharp/Formats/Tiff/TiffEncoder.cs
  32. 68
      src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
  33. 6
      src/ImageSharp/Formats/Tiff/Writers/TiffBaseColorWriter.cs
  34. 2
      src/ImageSharp/Formats/Tiff/Writers/TiffStreamWriter.cs
  35. 36
      src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs
  36. 2
      tests/ImageSharp.Tests/Formats/Tiff/PhotometricInterpretation/BlackIsZeroTiffColorTests.cs
  37. 21
      tests/ImageSharp.Tests/Formats/Tiff/PhotometricInterpretation/PaletteTiffColorTests.cs
  38. 2
      tests/ImageSharp.Tests/Formats/Tiff/PhotometricInterpretation/RgbPlanarTiffColorTests.cs
  39. 2
      tests/ImageSharp.Tests/Formats/Tiff/PhotometricInterpretation/RgbTiffColorTests.cs
  40. 2
      tests/ImageSharp.Tests/Formats/Tiff/PhotometricInterpretation/WhiteIsZeroTiffColorTests.cs
  41. 38
      tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
  42. 1
      tests/ImageSharp.Tests/ImageSharp.Tests.csproj

2
src/ImageSharp/Formats/Tiff/Compression/Compressors/DeflateCompressor.cs

@ -9,7 +9,7 @@ using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors
{ {
internal class DeflateCompressor : TiffBaseCompressor internal sealed class DeflateCompressor : TiffBaseCompressor
{ {
private readonly DeflateCompressionLevel compressionLevel; private readonly DeflateCompressionLevel compressionLevel;

2
src/ImageSharp/Formats/Tiff/Compression/Compressors/LzwCompressor.cs

@ -8,7 +8,7 @@ using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors
{ {
internal class LzwCompressor : TiffBaseCompressor internal sealed class LzwCompressor : TiffBaseCompressor
{ {
private TiffLzwEncoder lzwEncoder; private TiffLzwEncoder lzwEncoder;

2
src/ImageSharp/Formats/Tiff/Compression/Compressors/NoCompressor.cs

@ -8,7 +8,7 @@ using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors
{ {
internal class NoCompressor : TiffBaseCompressor internal sealed class NoCompressor : TiffBaseCompressor
{ {
public NoCompressor(Stream output, MemoryAllocator memoryAllocator, int width, int bitsPerPixel) public NoCompressor(Stream output, MemoryAllocator memoryAllocator, int width, int bitsPerPixel)
: base(output, memoryAllocator, width, bitsPerPixel) : base(output, memoryAllocator, width, bitsPerPixel)

2
src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsCompressor.cs

@ -8,7 +8,7 @@ using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors
{ {
internal class PackBitsCompressor : TiffBaseCompressor internal sealed class PackBitsCompressor : TiffBaseCompressor
{ {
private IManagedByteBuffer pixelData; private IManagedByteBuffer pixelData;

4
src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsWriter.cs

@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors
while (posInRowSpan < rowSpan.Length) while (posInRowSpan < rowSpan.Length)
{ {
var useReplicateRun = IsReplicateRun(rowSpan, posInRowSpan); bool useReplicateRun = IsReplicateRun(rowSpan, posInRowSpan);
if (useReplicateRun) if (useReplicateRun)
{ {
if (literalRunLength > 0) if (literalRunLength > 0)
@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors
} }
// Write a run with the same bytes. // Write a run with the same bytes.
var runLength = FindRunLength(rowSpan, posInRowSpan, maxRunLength); int runLength = FindRunLength(rowSpan, posInRowSpan, maxRunLength);
WriteRun(rowSpan, posInRowSpan, runLength, compressedRowSpan, bytesWritten); WriteRun(rowSpan, posInRowSpan, runLength, compressedRowSpan, bytesWritten);
bytesWritten += 2; bytesWritten += 2;

8
src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs

@ -13,13 +13,13 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors
/// <summary> /// <summary>
/// Bitwriter for writing compressed CCITT T4 1D data. /// Bitwriter for writing compressed CCITT T4 1D data.
/// </summary> /// </summary>
internal class T4BitCompressor : TiffBaseCompressor internal sealed class T4BitCompressor : TiffBaseCompressor
{ {
private const uint WhiteZeroRunTermCode = 0x35; private const uint WhiteZeroRunTermCode = 0x35;
private const uint BlackZeroRunTermCode = 0x37; private const uint BlackZeroRunTermCode = 0x37;
private static readonly List<uint> MakeupRunLength = new List<uint>() private static readonly uint[] MakeupRunLength =
{ {
64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792, 1856, 1920, 1984, 2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496, 2560 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792, 1856, 1920, 1984, 2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496, 2560
}; };
@ -368,7 +368,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors
private uint GetBestFittingMakeupRunLength(uint runLength) private uint GetBestFittingMakeupRunLength(uint runLength)
{ {
for (int i = 0; i < MakeupRunLength.Count - 1; i++) for (int i = 0; i < MakeupRunLength.Length - 1; i++)
{ {
if (MakeupRunLength[i] <= runLength && MakeupRunLength[i + 1] > runLength) if (MakeupRunLength[i] <= runLength && MakeupRunLength[i + 1] > runLength)
{ {
@ -376,7 +376,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors
} }
} }
return MakeupRunLength[MakeupRunLength.Count - 1]; return MakeupRunLength[MakeupRunLength.Length - 1];
} }
private uint GetTermCode(uint runLength, out uint codeLength, bool isWhiteRun) private uint GetTermCode(uint runLength, out uint codeLength, bool isWhiteRun)

4
src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs

@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression
private static void Undo8Bit(Span<byte> pixelBytes, int width) private static void Undo8Bit(Span<byte> pixelBytes, int width)
{ {
var rowBytesCount = width; int rowBytesCount = width;
int height = pixelBytes.Length / rowBytesCount; int height = pixelBytes.Length / rowBytesCount;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression
private static void Undo24Bit(Span<byte> pixelBytes, int width) private static void Undo24Bit(Span<byte> pixelBytes, int width)
{ {
var rowBytesCount = width * 3; int rowBytesCount = width * 3;
int height = pixelBytes.Length / rowBytesCount; int height = pixelBytes.Length / rowBytesCount;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {

5
src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs

@ -75,6 +75,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Constants
/// </summary> /// </summary>
public const int SizeOfDouble = 8; public const int SizeOfDouble = 8;
/// <summary>
/// The default strip size is 8k.
/// </summary>
public const int DefaultStripSize = 8 * 1024;
/// <summary> /// <summary>
/// The bits per sample for 1 bit bicolor images. /// The bits per sample for 1 bit bicolor images.
/// </summary> /// </summary>

12
src/ImageSharp/Formats/Tiff/Constants/TiffNewSubfileType.cs

@ -14,31 +14,31 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Constants
/// <summary> /// <summary>
/// A full-resolution image. /// A full-resolution image.
/// </summary> /// </summary>
FullImage = 0x0000, FullImage = 0,
/// <summary> /// <summary>
/// Reduced-resolution version of another image in this TIFF file. /// Reduced-resolution version of another image in this TIFF file.
/// </summary> /// </summary>
Preview = 0x0001, Preview = 1,
/// <summary> /// <summary>
/// A single page of a multi-page image. /// A single page of a multi-page image.
/// </summary> /// </summary>
SinglePage = 0x0002, SinglePage = 2,
/// <summary> /// <summary>
/// A transparency mask for another image in this TIFF file. /// A transparency mask for another image in this TIFF file.
/// </summary> /// </summary>
TransparencyMask = 0x0004, TransparencyMask = 4,
/// <summary> /// <summary>
/// Alternative reduced-resolution version of another image in this TIFF file (see DNG specification). /// Alternative reduced-resolution version of another image in this TIFF file (see DNG specification).
/// </summary> /// </summary>
AlternativePreview = 0x10000, AlternativePreview = 65536,
/// <summary> /// <summary>
/// Mixed raster content (see RFC2301). /// Mixed raster content (see RFC2301).
/// </summary> /// </summary>
MixedRasterContent = 0x0008 MixedRasterContent = 8
} }
} }

2
src/ImageSharp/Formats/Tiff/Constants/TiffPredictor.cs

@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Constants
public enum TiffPredictor : ushort public enum TiffPredictor : ushort
{ {
/// <summary> /// <summary>
/// No prediction scheme used before coding /// No prediction.
/// </summary> /// </summary>
None = 1, None = 1,

4
src/ImageSharp/Formats/Tiff/ITiffDecoderOptions.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff
@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// <summary> /// <summary>
/// Encapsulates the options for the <see cref="TiffDecoder"/>. /// Encapsulates the options for the <see cref="TiffDecoder"/>.
/// </summary> /// </summary>
public interface ITiffDecoderOptions internal interface ITiffDecoderOptions
{ {
/// <summary> /// <summary>
/// Gets a value indicating whether the metadata should be ignored when the image is being decoded. /// Gets a value indicating whether the metadata should be ignored when the image is being decoded.

5
src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs

@ -43,10 +43,5 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// Gets the quantizer for creating a color palette image. /// Gets the quantizer for creating a color palette image.
/// </summary> /// </summary>
IQuantizer Quantizer { get; } IQuantizer Quantizer { get; }
/// <summary>
/// Gets the maximum size of strip (bytes).
/// </summary>
int MaxStripBytes { get; }
} }
} }

6
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero1TiffColor.cs

@ -6,7 +6,7 @@ using System;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// Implements the 'BlackIsZero' photometric interpretation (optimized for bilevel images). /// Implements the 'BlackIsZero' photometric interpretation (optimized for bilevel images).
@ -15,10 +15,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
internal class BlackIsZero1TiffColor<TPixel> : TiffBaseColorDecoder<TPixel> internal class BlackIsZero1TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
public BlackIsZero1TiffColor()
{
}
/// <inheritdoc/> /// <inheritdoc/>
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height)
{ {

6
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero4TiffColor.cs

@ -6,7 +6,7 @@ using System;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// Implements the 'BlackIsZero' photometric interpretation (optimized for 4-bit grayscale images). /// Implements the 'BlackIsZero' photometric interpretation (optimized for 4-bit grayscale images).
@ -14,10 +14,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
internal class BlackIsZero4TiffColor<TPixel> : TiffBaseColorDecoder<TPixel> internal class BlackIsZero4TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
public BlackIsZero4TiffColor()
{
}
/// <inheritdoc/> /// <inheritdoc/>
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height)
{ {

6
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero8TiffColor.cs

@ -6,7 +6,7 @@ using System;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// Implements the 'BlackIsZero' photometric interpretation (optimized for 8-bit grayscale images). /// Implements the 'BlackIsZero' photometric interpretation (optimized for 8-bit grayscale images).
@ -14,10 +14,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
internal class BlackIsZero8TiffColor<TPixel> : TiffBaseColorDecoder<TPixel> internal class BlackIsZero8TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
public BlackIsZero8TiffColor()
{
}
/// <inheritdoc/> /// <inheritdoc/>
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height)
{ {

2
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZeroTiffColor.cs

@ -7,7 +7,7 @@ using SixLabors.ImageSharp.Formats.Tiff.Utils;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// Implements the 'BlackIsZero' photometric interpretation (for all bit depths). /// Implements the 'BlackIsZero' photometric interpretation (for all bit depths).

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

@ -7,7 +7,7 @@ using SixLabors.ImageSharp.Formats.Tiff.Utils;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// Implements the 'PaletteTiffColor' photometric interpretation (for all bit depths). /// Implements the 'PaletteTiffColor' photometric interpretation (for all bit depths).

6
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb888TiffColor.cs

@ -6,7 +6,7 @@ using System;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// Implements the 'RGB' photometric interpretation (optimized for 8-bit full color images). /// Implements the 'RGB' photometric interpretation (optimized for 8-bit full color images).
@ -14,10 +14,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
internal class Rgb888TiffColor<TPixel> : TiffBaseColorDecoder<TPixel> internal class Rgb888TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
public Rgb888TiffColor()
{
}
/// <inheritdoc/> /// <inheritdoc/>
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height)
{ {

2
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbPlanarTiffColor.cs

@ -6,7 +6,7 @@ using SixLabors.ImageSharp.Formats.Tiff.Utils;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// Implements the 'RGB' photometric interpretation with 'Planar' layout (for all bit depths). /// Implements the 'RGB' photometric interpretation with 'Planar' layout (for all bit depths).

2
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbTiffColor.cs

@ -7,7 +7,7 @@ using SixLabors.ImageSharp.Formats.Tiff.Utils;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// Implements the 'RGB' photometric interpretation (for all bit depths). /// Implements the 'RGB' photometric interpretation (for all bit depths).

16
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffBaseColorDecoder.cs

@ -5,7 +5,7 @@ using System;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// The base class for photometric interpretation decoders. /// The base class for photometric interpretation decoders.
@ -14,20 +14,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
internal abstract class TiffBaseColorDecoder<TPixel> internal abstract class TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
protected TiffBaseColorDecoder()
{
}
/*
/// <summary>
/// Gets the photometric interpretation value.
/// </summary>
/// <value>
/// The photometric interpretation value.
/// </value>
public TiffColorType ColorType { get; }
*/
/// <summary> /// <summary>
/// Decodes source raw pixel data using the current photometric interpretation. /// Decodes source raw pixel data using the current photometric interpretation.
/// </summary> /// </summary>

2
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory.cs

@ -3,7 +3,7 @@
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
internal static class TiffColorDecoderFactory<TPixel> internal static class TiffColorDecoderFactory<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>

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

@ -1,7 +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.
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// Provides enumeration of the various TIFF photometric interpretation implementation types. /// Provides enumeration of the various TIFF photometric interpretation implementation types.

6
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero1TiffColor.cs

@ -6,7 +6,7 @@ using System;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// Implements the 'WhiteIsZero' photometric interpretation (optimized for bilevel images). /// Implements the 'WhiteIsZero' photometric interpretation (optimized for bilevel images).
@ -14,10 +14,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
internal class WhiteIsZero1TiffColor<TPixel> : TiffBaseColorDecoder<TPixel> internal class WhiteIsZero1TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
public WhiteIsZero1TiffColor()
{
}
/// <inheritdoc/> /// <inheritdoc/>
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height)
{ {

6
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero4TiffColor.cs

@ -6,7 +6,7 @@ using System;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// Implements the 'WhiteIsZero' photometric interpretation (optimized for 4-bit grayscale images). /// Implements the 'WhiteIsZero' photometric interpretation (optimized for 4-bit grayscale images).
@ -14,10 +14,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
internal class WhiteIsZero4TiffColor<TPixel> : TiffBaseColorDecoder<TPixel> internal class WhiteIsZero4TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
public WhiteIsZero4TiffColor()
{
}
/// <inheritdoc/> /// <inheritdoc/>
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height)
{ {

6
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero8TiffColor.cs

@ -6,7 +6,7 @@ using System;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// Implements the 'WhiteIsZero' photometric interpretation (optimized for 8-bit grayscale images). /// Implements the 'WhiteIsZero' photometric interpretation (optimized for 8-bit grayscale images).
@ -14,10 +14,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
internal class WhiteIsZero8TiffColor<TPixel> : TiffBaseColorDecoder<TPixel> internal class WhiteIsZero8TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
public WhiteIsZero8TiffColor()
{
}
/// <inheritdoc/> /// <inheritdoc/>
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height)
{ {

2
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZeroTiffColor.cs

@ -7,7 +7,7 @@ using SixLabors.ImageSharp.Formats.Tiff.Utils;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{ {
/// <summary> /// <summary>
/// Implements the 'WhiteIsZero' photometric interpretation (for all bit depths). /// Implements the 'WhiteIsZero' photometric interpretation (for all bit depths).

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

@ -25,6 +25,9 @@
## Implementation Status ## Implementation Status
- The Decoder and Encoder currently only supports a single frame per image.
- Some compression formats are not yet supported. See the list below.
### Deviations from the TIFF spec (to be fixed) ### Deviations from the TIFF spec (to be fixed)
- Decoder - Decoder
@ -46,7 +49,7 @@
|Lzw | Y | Y | Based on ImageSharp GIF LZW implementation - this code could be modified to be (i) shared, or (ii) optimised for each case | |Lzw | Y | Y | Based on ImageSharp GIF LZW implementation - this code could be modified to be (i) shared, or (ii) optimised for each case |
|Old Jpeg | | | We should not even try to support this | |Old Jpeg | | | We should not even try to support this |
|Jpeg (Technote 2) | | | | |Jpeg (Technote 2) | | | |
|Deflate (Technote 2) | Y | Y | Based on PNG Deflate. | |Deflate (Technote 2) | Y | Y | Based on PNG Deflate. |
|Old Deflate (Technote 2) | | Y | | |Old Deflate (Technote 2) | | Y | |
### Photometric Interpretation Formats ### Photometric Interpretation Formats

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

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Threading; using System.Threading;
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.IO; using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata;

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

@ -3,6 +3,7 @@
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.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Exif;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff

3
src/ImageSharp/Formats/Tiff/TiffEncoder.cs

@ -36,9 +36,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// <inheritdoc/> /// <inheritdoc/>
public IQuantizer Quantizer { get; set; } public IQuantizer Quantizer { get; set; }
/// <inheritdoc/>
public int MaxStripBytes { get; set; } = TiffEncoderCore.DefaultStripSize;
/// <inheritdoc/> /// <inheritdoc/>
public void Encode<TPixel>(Image<TPixel> image, Stream stream) public void Encode<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>

68
src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs

@ -25,8 +25,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// </summary> /// </summary>
internal sealed class TiffEncoderCore : IImageEncoderInternals internal sealed class TiffEncoderCore : IImageEncoderInternals
{ {
public const int DefaultStripSize = 8 * 1024;
private static readonly ushort ByteOrderMarker = BitConverter.IsLittleEndian private static readonly ushort ByteOrderMarker = BitConverter.IsLittleEndian
? TiffConstants.ByteOrderLittleEndianShort ? TiffConstants.ByteOrderLittleEndianShort
: TiffConstants.ByteOrderBigEndianShort; : TiffConstants.ByteOrderBigEndianShort;
@ -56,11 +54,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// </summary> /// </summary>
private readonly DeflateCompressionLevel compressionLevel; private readonly DeflateCompressionLevel compressionLevel;
/// <summary>
/// The maximum number of bytes for a strip.
/// </summary>
private readonly int maxStripBytes;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TiffEncoderCore"/> class. /// Initializes a new instance of the <see cref="TiffEncoderCore"/> class.
/// </summary> /// </summary>
@ -75,7 +68,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
this.HorizontalPredictor = options.HorizontalPredictor; this.HorizontalPredictor = options.HorizontalPredictor;
this.CompressionType = options.Compression; this.CompressionType = options.Compression;
this.compressionLevel = options.CompressionLevel; this.compressionLevel = options.CompressionLevel;
this.maxStripBytes = options.MaxStripBytes;
} }
/// <summary> /// <summary>
@ -120,10 +112,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff
this.configuration = image.GetConfiguration(); this.configuration = image.GetConfiguration();
ImageMetadata metadata = image.Metadata; ImageMetadata metadata = image.Metadata;
TiffMetadata tiffMetadata = metadata.GetTiffMetadata(); TiffMetadata tiffMetadata = metadata.GetTiffMetadata();
this.BitsPerPixel ??= tiffMetadata.BitsPerPixel;
this.SetMode(tiffMetadata); this.SetMode(tiffMetadata);
this.SetBitsPerPixel(); this.SetBitsPerPixel(tiffMetadata);
this.SetPhotometricInterpretation(); this.SetPhotometricInterpretation();
using (var writer = new TiffStreamWriter(stream)) using (var writer = new TiffStreamWriter(stream))
@ -176,7 +167,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
image.Width, image.Width,
(int)tiffBitsPerPixel, (int)tiffBitsPerPixel,
this.compressionLevel, this.compressionLevel,
this.HorizontalPredictor != TiffPredictor.FloatingPoint ? this.HorizontalPredictor : TiffPredictor.None); this.HorizontalPredictor == TiffPredictor.Horizontal ? this.HorizontalPredictor : TiffPredictor.None);
using TiffBaseColorWriter<TPixel> colorWriter = TiffColorWriterFactory.Create( using TiffBaseColorWriter<TPixel> colorWriter = TiffColorWriterFactory.Create(
this.Mode, this.Mode,
@ -210,8 +201,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
DebugGuard.MustBeGreaterThan(height, 0, nameof(height)); DebugGuard.MustBeGreaterThan(height, 0, nameof(height));
DebugGuard.MustBeGreaterThan(bytesPerRow, 0, nameof(bytesPerRow)); DebugGuard.MustBeGreaterThan(bytesPerRow, 0, nameof(bytesPerRow));
int stripBytes = this.maxStripBytes > 0 ? this.maxStripBytes : DefaultStripSize; int rowsPerStrip = TiffConstants.DefaultStripSize / bytesPerRow;
int rowsPerStrip = stripBytes / bytesPerRow;
return rowsPerStrip > 0 ? (rowsPerStrip < height ? rowsPerStrip : height) : 1; return rowsPerStrip > 0 ? (rowsPerStrip < height ? rowsPerStrip : height) : 1;
} }
@ -293,30 +283,46 @@ namespace SixLabors.ImageSharp.Formats.Tiff
} }
} }
if (this.Mode == TiffEncodingMode.Default && this.BitsPerPixel != null) if (this.Mode == TiffEncodingMode.Default && tiffMetadata.BitsPerPixel != null)
{ {
// Preserve input bits per pixel, if no encoding mode was specified. // Preserve input bits per pixel, if no encoding mode was specified.
switch (this.BitsPerPixel) this.SetModeWithBitsPerPixel(tiffMetadata.BitsPerPixel, tiffMetadata.PhotometricInterpretation);
{
case TiffBitsPerPixel.Bit1: return;
this.Mode = TiffEncodingMode.BiColor; }
break;
case TiffBitsPerPixel.Bit4: if (this.BitsPerPixel != null)
this.Mode = TiffEncodingMode.ColorPalette; {
break; // The user has specified a bits per pixel, so use that to determine the encoding mode.
case TiffBitsPerPixel.Bit8: this.SetModeWithBitsPerPixel(this.BitsPerPixel, tiffMetadata.PhotometricInterpretation);
this.Mode = tiffMetadata.PhotometricInterpretation == TiffPhotometricInterpretation.PaletteColor ? TiffEncodingMode.ColorPalette : TiffEncodingMode.Gray;
break;
default:
this.Mode = TiffEncodingMode.Rgb;
break;
}
} }
} }
private void SetBitsPerPixel() private void SetModeWithBitsPerPixel(TiffBitsPerPixel? bitsPerPixel, TiffPhotometricInterpretation photometricInterpretation)
{ {
switch (bitsPerPixel)
{
case TiffBitsPerPixel.Bit1:
this.Mode = TiffEncodingMode.BiColor;
break;
case TiffBitsPerPixel.Bit4:
this.Mode = TiffEncodingMode.ColorPalette;
break;
case TiffBitsPerPixel.Bit8:
this.Mode = photometricInterpretation == TiffPhotometricInterpretation.PaletteColor
? TiffEncodingMode.ColorPalette
: TiffEncodingMode.Gray;
break;
default:
this.Mode = TiffEncodingMode.Rgb;
break;
}
}
private void SetBitsPerPixel(TiffMetadata tiffMetadata)
{
this.BitsPerPixel ??= tiffMetadata.BitsPerPixel;
switch (this.Mode) switch (this.Mode)
{ {
case TiffEncodingMode.BiColor: case TiffEncodingMode.BiColor:

6
src/ImageSharp/Formats/Tiff/Writers/TiffBaseColorWriter.cs

@ -22,8 +22,14 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers
this.EntriesCollector = entriesCollector; this.EntriesCollector = entriesCollector;
} }
/// <summary>
/// Gets the bits per pixel.
/// </summary>
public abstract int BitsPerPixel { get; } public abstract int BitsPerPixel { get; }
/// <summary>
/// Gets the bytes per row.
/// </summary>
public int BytesPerRow => ((this.Image.Width * this.BitsPerPixel) + 7) / 8; public int BytesPerRow => ((this.Image.Width * this.BitsPerPixel) + 7) / 8;
protected ImageFrame<TPixel> Image { get; } protected ImageFrame<TPixel> Image { get; }

2
src/ImageSharp/Formats/Tiff/Writers/TiffStreamWriter.cs

@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers
/// <summary> /// <summary>
/// Utility class for writing TIFF data to a <see cref="Stream"/>. /// Utility class for writing TIFF data to a <see cref="Stream"/>.
/// </summary> /// </summary>
internal class TiffStreamWriter : IDisposable internal sealed class TiffStreamWriter : IDisposable
{ {
private static readonly byte[] PaddingBytes = new byte[4]; private static readonly byte[] PaddingBytes = new byte[4];

36
src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs

@ -91,9 +91,6 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
private readonly byte[] buf2 = new byte[2]; private readonly byte[] buf2 = new byte[2];
private readonly Stream data; private readonly Stream data;
private bool isBigEndian;
private List<ExifTag> invalidTags; private List<ExifTag> invalidTags;
private uint exifOffset; private uint exifOffset;
@ -120,11 +117,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
/// </summary> /// </summary>
public uint ThumbnailOffset { get; protected set; } public uint ThumbnailOffset { get; protected set; }
public bool IsBigEndian public bool IsBigEndian { get; protected set; }
{
get => this.isBigEndian;
protected set => this.isBigEndian = value;
}
protected abstract void RegisterExtLoader(uint offset, Action loader); protected abstract void RegisterExtLoader(uint offset, Action loader);
@ -330,7 +323,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{ {
uint newOffset = this.ConvertToUInt32(this.offsetBuffer); uint newOffset = this.ConvertToUInt32(this.offsetBuffer);
// Ensure that the new index does not overrun the data // Ensure that the new index does not overrun the data.
if (newOffset > int.MaxValue || (newOffset + size) > this.data.Length) if (newOffset > int.MaxValue || (newOffset + size) > this.data.Length)
{ {
this.AddInvalidTag(new UnkownExifTag(tag)); this.AddInvalidTag(new UnkownExifTag(tag));
@ -339,7 +332,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
this.RegisterExtLoader(newOffset, () => this.RegisterExtLoader(newOffset, () =>
{ {
var dataBuffer = new byte[size]; byte[] dataBuffer = new byte[size];
this.Seek(newOffset); this.Seek(newOffset);
if (this.TryReadSpan(dataBuffer)) if (this.TryReadSpan(dataBuffer))
{ {
@ -365,8 +358,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
foreach (IExifValue val in values) foreach (IExifValue val in values)
{ {
// sometimes duplicates appear, // Sometimes duplicates appear, can compare val.Tag == exif.Tag
// can compare val.Tag == exif.Tag
if (val == exif) if (val == exif)
{ {
Debug.WriteLine($"Duplicate Exif tag: tag={exif.Tag}, dataType={exif.DataType}"); Debug.WriteLine($"Duplicate Exif tag: tag={exif.Tag}, dataType={exif.DataType}");
@ -403,11 +395,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
return false; return false;
} }
int readed = this.data.Read(span); int read = this.data.Read(span);
return readed == length; return read == length;
} }
// Known as Long in Exif Specification // Known as Long in Exif Specification.
protected uint ReadUInt32() => protected uint ReadUInt32() =>
this.TryReadSpan(this.buf4) this.TryReadSpan(this.buf4)
? this.ConvertToUInt32(this.buf4) ? this.ConvertToUInt32(this.buf4)
@ -424,7 +416,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
return default; return default;
} }
long intValue = this.isBigEndian long intValue = this.IsBigEndian
? BinaryPrimitives.ReadInt64BigEndian(buffer) ? BinaryPrimitives.ReadInt64BigEndian(buffer)
: BinaryPrimitives.ReadInt64LittleEndian(buffer); : BinaryPrimitives.ReadInt64LittleEndian(buffer);
@ -433,13 +425,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
private uint ConvertToUInt32(ReadOnlySpan<byte> buffer) private uint ConvertToUInt32(ReadOnlySpan<byte> buffer)
{ {
// Known as Long in Exif Specification // Known as Long in Exif Specification.
if (buffer.Length < 4) if (buffer.Length < 4)
{ {
return default; return default;
} }
return this.isBigEndian return this.IsBigEndian
? BinaryPrimitives.ReadUInt32BigEndian(buffer) ? BinaryPrimitives.ReadUInt32BigEndian(buffer)
: BinaryPrimitives.ReadUInt32LittleEndian(buffer); : BinaryPrimitives.ReadUInt32LittleEndian(buffer);
} }
@ -451,7 +443,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
return default; return default;
} }
return this.isBigEndian return this.IsBigEndian
? BinaryPrimitives.ReadUInt16BigEndian(buffer) ? BinaryPrimitives.ReadUInt16BigEndian(buffer)
: BinaryPrimitives.ReadUInt16LittleEndian(buffer); : BinaryPrimitives.ReadUInt16LittleEndian(buffer);
} }
@ -463,7 +455,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
return default; return default;
} }
int intValue = this.isBigEndian int intValue = this.IsBigEndian
? BinaryPrimitives.ReadInt32BigEndian(buffer) ? BinaryPrimitives.ReadInt32BigEndian(buffer)
: BinaryPrimitives.ReadInt32LittleEndian(buffer); : BinaryPrimitives.ReadInt32LittleEndian(buffer);
@ -492,7 +484,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
return default; return default;
} }
return this.isBigEndian return this.IsBigEndian
? BinaryPrimitives.ReadInt32BigEndian(buffer) ? BinaryPrimitives.ReadInt32BigEndian(buffer)
: BinaryPrimitives.ReadInt32LittleEndian(buffer); : BinaryPrimitives.ReadInt32LittleEndian(buffer);
} }
@ -517,7 +509,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
return default; return default;
} }
return this.isBigEndian return this.IsBigEndian
? BinaryPrimitives.ReadInt16BigEndian(buffer) ? BinaryPrimitives.ReadInt16BigEndian(buffer)
: BinaryPrimitives.ReadInt16LittleEndian(buffer); : BinaryPrimitives.ReadInt16LittleEndian(buffer);
} }

2
tests/ImageSharp.Tests/Formats/Tiff/PhotometricInterpretation/BlackIsZeroTiffColorTests.cs

@ -3,7 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using Xunit; using Xunit;

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

@ -3,7 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using Xunit; using Xunit;
@ -13,9 +13,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.PhotometricInterpretation
[Trait("Format", "Tiff")] [Trait("Format", "Tiff")]
public class PaletteTiffColorTests : PhotometricInterpretationTestBase public class PaletteTiffColorTests : PhotometricInterpretationTestBase
{ {
public static uint[][] Palette4ColorPalette { get => GeneratePalette(16); } public static uint[][] Palette4ColorPalette => GeneratePalette(16);
public static ushort[] Palette4ColorMap { get => GenerateColorMap(Palette4ColorPalette); } public static ushort[] Palette4ColorMap => GenerateColorMap(Palette4ColorPalette);
private static readonly byte[] Palette4Bytes4X4 = private static readonly byte[] Palette4Bytes4X4 =
{ {
@ -54,9 +54,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.PhotometricInterpretation
} }
} }
public static uint[][] Palette8ColorPalette { get => GeneratePalette(256); } public static uint[][] Palette8ColorPalette => GeneratePalette(256);
public static ushort[] Palette8ColorMap { get => GenerateColorMap(Palette8ColorPalette); } public static ushort[] Palette8ColorMap => GenerateColorMap(Palette8ColorPalette);
private static readonly byte[] Palette8Bytes4X4 = private static readonly byte[] Palette8Bytes4X4 =
{ {
@ -83,13 +83,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.PhotometricInterpretation
[Theory] [Theory]
[MemberData(nameof(Palette4Data))] [MemberData(nameof(Palette4Data))]
[MemberData(nameof(Palette8Data))] [MemberData(nameof(Palette8Data))]
public void Decode_WritesPixelData(byte[] inputData, ushort bitsPerSample, ushort[] colorMap, int left, int top, int width, int height, Rgba32[][] expectedResult) public void Decode_WritesPixelData(byte[] inputData, ushort bitsPerSample, ushort[] colorMap, int left, int top, int width, int height, Rgba32[][] expectedResult) => AssertDecode(expectedResult, pixels =>
{ {
AssertDecode(expectedResult, pixels => new PaletteTiffColor<Rgba32>(new[] { bitsPerSample }, colorMap).Decode(inputData, pixels, left, top, width, height);
{ });
new PaletteTiffColor<Rgba32>(new[] { bitsPerSample }, colorMap).Decode(inputData, pixels, left, top, width, height);
});
}
private static uint[][] GeneratePalette(int count) private static uint[][] GeneratePalette(int count)
{ {

2
tests/ImageSharp.Tests/Formats/Tiff/PhotometricInterpretation/RgbPlanarTiffColorTests.cs

@ -4,7 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;

2
tests/ImageSharp.Tests/Formats/Tiff/PhotometricInterpretation/RgbTiffColorTests.cs

@ -3,7 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using Xunit; using Xunit;

2
tests/ImageSharp.Tests/Formats/Tiff/PhotometricInterpretation/WhiteIsZeroTiffColorTests.cs

@ -3,7 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using Xunit; using Xunit;

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

@ -309,28 +309,28 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
where TPixel : unmanaged, IPixel<TPixel> => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit1, TiffEncodingMode.BiColor, TiffCompression.Ccitt1D); where TPixel : unmanaged, IPixel<TPixel> => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit1, TiffEncodingMode.BiColor, TiffCompression.Ccitt1D);
[Theory] [Theory]
[WithFile(GrayscaleUncompressed, PixelTypes.L8, TiffEncodingMode.Gray, TiffCompression.PackBits, 16 * 1024)] [WithFile(GrayscaleUncompressed, PixelTypes.L8, TiffEncodingMode.Gray, TiffCompression.PackBits)]
[WithFile(PaletteDeflateMultistrip, PixelTypes.L8, TiffEncodingMode.ColorPalette, TiffCompression.Lzw, 32 * 1024)] [WithFile(PaletteDeflateMultistrip, PixelTypes.L8, TiffEncodingMode.ColorPalette, TiffCompression.Lzw)]
[WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffEncodingMode.Rgb, TiffCompression.Deflate, 64 * 1024)] [WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffEncodingMode.Rgb, TiffCompression.Deflate)]
[WithFile(RgbUncompressed, PixelTypes.Rgb24, TiffEncodingMode.Rgb, TiffCompression.None, 10 * 1024)] [WithFile(RgbUncompressed, PixelTypes.Rgb24, TiffEncodingMode.Rgb, TiffCompression.None)]
[WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffEncodingMode.Rgb, TiffCompression.None, 30 * 1024)] [WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffEncodingMode.Rgb, TiffCompression.None)]
[WithFile(RgbUncompressed, PixelTypes.Rgb48, TiffEncodingMode.Rgb, TiffCompression.None, 70 * 1024)] [WithFile(RgbUncompressed, PixelTypes.Rgb48, TiffEncodingMode.Rgb, TiffCompression.None)]
public void TiffEncoder_StripLength<TPixel>(TestImageProvider<TPixel> provider, TiffEncodingMode mode, TiffCompression compression, int maxSize) public void TiffEncoder_StripLength<TPixel>(TestImageProvider<TPixel> provider, TiffEncodingMode mode, TiffCompression compression)
where TPixel : unmanaged, IPixel<TPixel> => where TPixel : unmanaged, IPixel<TPixel> =>
TestStripLength(provider, mode, compression, maxSize); TestStripLength(provider, mode, compression);
[Theory] [Theory]
[WithFile(Calliphora_BiColorUncompressed, PixelTypes.L8, TiffEncodingMode.BiColor, TiffCompression.CcittGroup3Fax, 9 * 1024)] [WithFile(Calliphora_BiColorUncompressed, PixelTypes.L8, TiffEncodingMode.BiColor, TiffCompression.CcittGroup3Fax)]
public void TiffEncoder_StripLength_OutOfBounds<TPixel>(TestImageProvider<TPixel> provider, TiffEncodingMode mode, TiffCompression compression, int maxSize) public void TiffEncoder_StripLength_OutOfBounds<TPixel>(TestImageProvider<TPixel> provider, TiffEncodingMode mode, TiffCompression compression)
where TPixel : unmanaged, IPixel<TPixel> => where TPixel : unmanaged, IPixel<TPixel> =>
//// CcittGroup3Fax compressed data length can be larger than the original length //// CcittGroup3Fax compressed data length can be larger than the original length
Assert.Throws<Xunit.Sdk.TrueException>(() => TestStripLength(provider, mode, compression, maxSize)); Assert.Throws<Xunit.Sdk.TrueException>(() => TestStripLength(provider, mode, compression));
private static void TestStripLength<TPixel>(TestImageProvider<TPixel> provider, TiffEncodingMode mode, TiffCompression compression, int maxSize) private static void TestStripLength<TPixel>(TestImageProvider<TPixel> provider, TiffEncodingMode mode, TiffCompression compression)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
// arrange // arrange
var tiffEncoder = new TiffEncoder() { Mode = mode, Compression = compression, MaxStripBytes = maxSize }; var tiffEncoder = new TiffEncoder() { Mode = mode, Compression = compression };
Image<TPixel> input = provider.GetImage(); Image<TPixel> input = provider.GetImage();
using var memStream = new MemoryStream(); using var memStream = new MemoryStream();
TiffFrameMetadata inputMeta = input.Frames.RootFrame.Metadata.GetTiffMetadata(); TiffFrameMetadata inputMeta = input.Frames.RootFrame.Metadata.GetTiffMetadata();
@ -349,7 +349,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
foreach (Number sz in meta.StripByteCounts) foreach (Number sz in meta.StripByteCounts)
{ {
Assert.True((uint)sz <= maxSize); Assert.True((uint)sz <= TiffConstants.DefaultStripSize);
} }
// For uncompressed more accurate test. // For uncompressed more accurate test.
@ -359,9 +359,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
{ {
// The difference must be less than one row. // The difference must be less than one row.
int stripBytes = (int)meta.StripByteCounts[i]; int stripBytes = (int)meta.StripByteCounts[i];
var widthBytes = (meta.BitsPerPixel + 7) / 8 * (int)meta.Width; int widthBytes = (meta.BitsPerPixel + 7) / 8 * (int)meta.Width;
Assert.True((maxSize - stripBytes) < widthBytes); Assert.True((TiffConstants.DefaultStripSize - stripBytes) < widthBytes);
} }
} }
@ -370,8 +370,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
provider, provider,
(TiffBitsPerPixel)inputMeta.BitsPerPixel, (TiffBitsPerPixel)inputMeta.BitsPerPixel,
mode, mode,
inputMeta.Compression, inputMeta.Compression);
maxStripSize: maxSize);
} }
private static void TestTiffEncoderCore<TPixel>( private static void TestTiffEncoderCore<TPixel>(
@ -391,8 +390,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
Mode = mode, Mode = mode,
BitsPerPixel = bitsPerPixel, BitsPerPixel = bitsPerPixel,
Compression = compression, Compression = compression,
HorizontalPredictor = predictor, HorizontalPredictor = predictor
MaxStripBytes = maxStripSize
}; };
// Does DebugSave & load reference CompareToReferenceInput(): // Does DebugSave & load reference CompareToReferenceInput():

1
tests/ImageSharp.Tests/ImageSharp.Tests.csproj

@ -23,7 +23,6 @@
</Choose> </Choose>
<ItemGroup> <ItemGroup>
<DotNetCliToolReference Include="dotnet-xunit" />
<InternalsVisibleTo Include="ImageSharp.Tests.ProfilingSandbox" Key="$(SixLaborsPublicKey)" /> <InternalsVisibleTo Include="ImageSharp.Tests.ProfilingSandbox" Key="$(SixLaborsPublicKey)" />
</ItemGroup> </ItemGroup>

Loading…
Cancel
Save