diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/NoCompressor.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/NoCompressor.cs
index f4a902b46a..79fbd29b4d 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/NoCompressor.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/NoCompressor.cs
@@ -3,13 +3,14 @@
using System;
using System.IO;
+using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression.Compressors
{
internal class NoCompressor : TiffBaseCompressor
{
- public NoCompressor(Stream output)
- : base(output, default, default, default)
+ public NoCompressor(Stream output, MemoryAllocator memoryAllocator, int width, int bitsPerPixel)
+ : base(output, memoryAllocator, width, bitsPerPixel)
{
}
diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs
index 13d19f7ff8..bb631c5a9a 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs
@@ -201,8 +201,10 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression.Compressors
this.useModifiedHuffman = useModifiedHuffman;
}
+ ///
public override TiffEncoderCompression Method => this.useModifiedHuffman ? TiffEncoderCompression.ModifiedHuffman : TiffEncoderCompression.CcittGroup3Fax;
+ ///
public override void Initialize(int rowsPerStrip)
{
// This is too much memory allocated, but just 1 bit per pixel will not do, if the compression rate is not good.
diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs
index be63bdad86..a6ca8c78db 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression.Decompresso
///
/// Note that the 'OldDeflate' compression type is identical to the 'Deflate' compression type.
///
- internal class DeflateTiffCompression : TiffBaseDecompresor
+ internal class DeflateTiffCompression : TiffBaseDecompressor
{
///
/// Initializes a new instance of the class.
diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwTiffCompression.cs
index a14738e44a..f3b37b09cf 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwTiffCompression.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwTiffCompression.cs
@@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression.Decompresso
///
/// Class to handle cases where TIFF image data is compressed using LZW compression.
///
- internal class LzwTiffCompression : TiffBaseDecompresor
+ internal class LzwTiffCompression : TiffBaseDecompressor
{
///
/// Initializes a new instance of the class.
diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/ModifiedHuffmanTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/ModifiedHuffmanTiffCompression.cs
index 7a7cd20f78..9c2495efc2 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/ModifiedHuffmanTiffCompression.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/ModifiedHuffmanTiffCompression.cs
@@ -22,10 +22,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression.Decompresso
/// Initializes a new instance of the class.
///
/// The memory allocator.
- /// The photometric interpretation.
/// The image width.
- public ModifiedHuffmanTiffCompression(MemoryAllocator allocator, TiffPhotometricInterpretation photometricInterpretation, int width)
- : base(allocator, FaxCompressionOptions.None, photometricInterpretation, width)
+ /// The number of bits per pixel.
+ /// The photometric interpretation.
+ public ModifiedHuffmanTiffCompression(MemoryAllocator allocator, int width, int bitsPerPixel, TiffPhotometricInterpretation photometricInterpretation)
+ : base(allocator, width, bitsPerPixel, FaxCompressionOptions.None, photometricInterpretation)
{
bool isWhiteZero = photometricInterpretation == TiffPhotometricInterpretation.WhiteIsZero;
this.whiteValue = (byte)(isWhiteZero ? 0 : 1);
diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/NoneTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/NoneTiffCompression.cs
index f041a00e9e..3475b74cee 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/NoneTiffCompression.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/NoneTiffCompression.cs
@@ -4,19 +4,23 @@
using System;
using SixLabors.ImageSharp.IO;
+using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression.Decompressors
{
///
/// Class to handle cases where TIFF image data is not compressed.
///
- internal class NoneTiffCompression : TiffBaseDecompresor
+ internal class NoneTiffCompression : TiffBaseDecompressor
{
///
/// Initializes a new instance of the class.
///
- public NoneTiffCompression()
- : base(default, default, default)
+ /// The memory allocator.
+ /// The width of the image.
+ /// The bits per pixel.
+ public NoneTiffCompression(MemoryAllocator memoryAllocator, int width, int bitsPerPixel)
+ : base(memoryAllocator, width, bitsPerPixel)
{
}
diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/PackBitsTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/PackBitsTiffCompression.cs
index c7461a8073..727e0eeb77 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/PackBitsTiffCompression.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/PackBitsTiffCompression.cs
@@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression.Decompresso
///
/// Class to handle cases where TIFF image data is compressed using PackBits compression.
///
- internal class PackBitsTiffCompression : TiffBaseDecompresor
+ internal class PackBitsTiffCompression : TiffBaseDecompressor
{
private IMemoryOwner compressedDataMemory;
@@ -20,8 +20,10 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression.Decompresso
/// Initializes a new instance of the class.
///
/// The memoryAllocator to use for buffer allocations.
- public PackBitsTiffCompression(MemoryAllocator memoryAllocator)
- : base(memoryAllocator, default, default)
+ /// The width of the image.
+ /// The number of bits per pixel.
+ public PackBitsTiffCompression(MemoryAllocator memoryAllocator, int width, int bitsPerPixel)
+ : base(memoryAllocator, width, bitsPerPixel)
{
}
diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/T4TiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/T4TiffCompression.cs
index 275e3d598d..549f75846b 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/T4TiffCompression.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/T4TiffCompression.cs
@@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression.Decompresso
///
/// Class to handle cases where TIFF image data is compressed using CCITT T4 compression.
///
- internal class T4TiffCompression : TiffBaseDecompresor
+ internal class T4TiffCompression : TiffBaseDecompressor
{
private readonly FaxCompressionOptions faxCompressionOptions;
@@ -24,11 +24,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression.Decompresso
/// Initializes a new instance of the class.
///
/// The memory allocator.
+ /// The image width.
+ /// The number of bits per pixel.
/// Fax compression options.
/// The photometric interpretation.
- /// The image width.
- public T4TiffCompression(MemoryAllocator allocator, FaxCompressionOptions faxOptions, TiffPhotometricInterpretation photometricInterpretation, int width)
- : base(allocator, width, default)
+ public T4TiffCompression(MemoryAllocator allocator, int width, int bitsPerPixel, FaxCompressionOptions faxOptions, TiffPhotometricInterpretation photometricInterpretation)
+ : base(allocator, width, bitsPerPixel)
{
this.faxCompressionOptions = faxOptions;
diff --git a/src/ImageSharp/Formats/Tiff/Compression/TiffBaseDecompresor.cs b/src/ImageSharp/Formats/Tiff/Compression/TiffBaseDecompressor.cs
similarity index 90%
rename from src/ImageSharp/Formats/Tiff/Compression/TiffBaseDecompresor.cs
rename to src/ImageSharp/Formats/Tiff/Compression/TiffBaseDecompressor.cs
index 5f981911df..2f40214ebe 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/TiffBaseDecompresor.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/TiffBaseDecompressor.cs
@@ -13,9 +13,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
///
/// The base tiff decompressor class.
///
- internal abstract class TiffBaseDecompresor : TiffBaseCompression
+ internal abstract class TiffBaseDecompressor : TiffBaseCompression
{
- protected TiffBaseDecompresor(MemoryAllocator allocator, int width, int bitsPerPixel, TiffPredictor predictor = TiffPredictor.None)
+ protected TiffBaseDecompressor(MemoryAllocator allocator, int width, int bitsPerPixel, TiffPredictor predictor = TiffPredictor.None)
: base(allocator, width, bitsPerPixel, predictor)
{
}
diff --git a/src/ImageSharp/Formats/Tiff/Compression/TiffCompressorFactory.cs b/src/ImageSharp/Formats/Tiff/Compression/TiffCompressorFactory.cs
index eeb14fb749..7cd39d8cbe 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/TiffCompressorFactory.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/TiffCompressorFactory.cs
@@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
DebugGuard.IsTrue(compressionLevel == DeflateCompressionLevel.DefaultCompression, "No deflate compression level is expected to be set");
DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");
- return new NoCompressor(output);
+ return new NoCompressor(output, allocator, width, bitsPerPixel);
case TiffEncoderCompression.PackBits:
DebugGuard.IsTrue(compressionLevel == DeflateCompressionLevel.DefaultCompression, "No deflate compression level is expected to be set");
diff --git a/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs b/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs
index 130205b5b2..641142d4c7 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs
@@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
{
internal static class TiffDecompressorsFactory
{
- public static TiffBaseDecompresor Create(
+ public static TiffBaseDecompressor Create(
TiffDecoderCompressionType method,
MemoryAllocator allocator,
TiffPhotometricInterpretation photometricInterpretation,
@@ -23,12 +23,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
case TiffDecoderCompressionType.None:
DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");
DebugGuard.IsTrue(faxOptions == FaxCompressionOptions.None, "No fax compression options are expected");
- return new NoneTiffCompression();
+ return new NoneTiffCompression(allocator, width, bitsPerPixel);
case TiffDecoderCompressionType.PackBits:
DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");
DebugGuard.IsTrue(faxOptions == FaxCompressionOptions.None, "No fax compression options are expected");
- return new PackBitsTiffCompression(allocator);
+ return new PackBitsTiffCompression(allocator, width, bitsPerPixel);
case TiffDecoderCompressionType.Deflate:
DebugGuard.IsTrue(faxOptions == FaxCompressionOptions.None, "No fax compression options are expected");
@@ -40,11 +40,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
case TiffDecoderCompressionType.T4:
DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");
- return new T4TiffCompression(allocator, faxOptions, photometricInterpretation, width);
+ return new T4TiffCompression(allocator, width, bitsPerPixel, faxOptions, photometricInterpretation);
case TiffDecoderCompressionType.HuffmanRle:
DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");
- return new ModifiedHuffmanTiffCompression(allocator, photometricInterpretation, width);
+ return new ModifiedHuffmanTiffCompression(allocator, width, bitsPerPixel, photometricInterpretation);
default:
throw TiffThrowHelper.NotSupportedDecompressor(nameof(method));
diff --git a/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs b/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs
index 8a591fc838..894a6d3486 100644
--- a/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs
+++ b/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs
@@ -75,6 +75,26 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants
///
public const int SizeOfDouble = 8;
+ ///
+ /// The bits per sample for 1 bit bicolor images.
+ ///
+ public static readonly ushort[] BitsPerSample1Bit = { 1 };
+
+ ///
+ /// The bits per sample for images with a 4 color palette.
+ ///
+ public static readonly ushort[] BitsPerSample4Bit = { 4 };
+
+ ///
+ /// The bits per sample for 8 bit images.
+ ///
+ public static readonly ushort[] BitsPerSample8Bit = { 8 };
+
+ ///
+ /// The bits per sample for images with 8 bits for each color channel.
+ ///
+ public static readonly ushort[] BitsPerSampleRgb8Bit = { 8, 8, 8 };
+
///
/// The list of mimetypes that equate to a tiff.
///
diff --git a/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs b/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
index de1095eee7..efa5dcf85b 100644
--- a/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
@@ -11,6 +11,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
///
internal interface ITiffEncoderOptions
{
+ ///
+ /// Gets or sets the number of bits per pixel.
+ ///
+ TiffBitsPerPixel? BitsPerPixel { get; set; }
+
///
/// Gets the compression type to use.
///
diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs
index 884481b982..307ae4ee9d 100644
--- a/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs
@@ -3,19 +3,12 @@
using System;
using SixLabors.ImageSharp.Formats.Experimental.Tiff;
+using SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants;
namespace SixLabors.ImageSharp.Formats.Tiff
{
internal static class TiffBitsPerSampleExtensions
{
- private static readonly ushort[] One = { 1 };
-
- private static readonly ushort[] Four = { 4 };
-
- private static readonly ushort[] Eight = { 8 };
-
- private static readonly ushort[] Rgb888 = { 8, 8, 8 };
-
///
/// Gets the bits per channel array for a given BitsPerSample value, e,g, for RGB888: [8, 8, 8]
///
@@ -26,13 +19,13 @@ namespace SixLabors.ImageSharp.Formats.Tiff
switch (tiffBitsPerSample)
{
case TiffBitsPerSample.One:
- return One;
+ return TiffConstants.BitsPerSample1Bit;
case TiffBitsPerSample.Four:
- return Four;
+ return TiffConstants.BitsPerSample4Bit;
case TiffBitsPerSample.Eight:
- return Eight;
+ return TiffConstants.BitsPerSample8Bit;
case TiffBitsPerSample.Rgb888:
- return Rgb888;
+ return TiffConstants.BitsPerSampleRgb8Bit;
default:
TiffThrowHelper.ThrowNotSupported("The bits per pixels are not supported");
@@ -50,7 +43,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff
switch (bitsPerSample.Length)
{
case 3:
- if (bitsPerSample[0] == Rgb888[0] && bitsPerSample[1] == Rgb888[1] && bitsPerSample[2] == Rgb888[2])
+ if (bitsPerSample[0] == TiffConstants.BitsPerSampleRgb8Bit[0] &&
+ bitsPerSample[1] == TiffConstants.BitsPerSampleRgb8Bit[1] &&
+ bitsPerSample[2] == TiffConstants.BitsPerSampleRgb8Bit[2])
{
return TiffBitsPerSample.Rgb888;
}
@@ -58,17 +53,17 @@ namespace SixLabors.ImageSharp.Formats.Tiff
break;
case 1:
- if (bitsPerSample[0] == One[0])
+ if (bitsPerSample[0] == TiffConstants.BitsPerSample1Bit[0])
{
return TiffBitsPerSample.One;
}
- if (bitsPerSample[0] == Four[0])
+ if (bitsPerSample[0] == TiffConstants.BitsPerSample4Bit[0])
{
return TiffBitsPerSample.Four;
}
- if (bitsPerSample[0] == Eight[0])
+ if (bitsPerSample[0] == TiffConstants.BitsPerSample8Bit[0])
{
return TiffBitsPerSample.Eight;
}
diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
index 876816a36f..bedd132fa5 100644
--- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
@@ -250,7 +250,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
stripBuffers[stripIndex] = this.memoryAllocator.AllocateManagedByteBuffer(uncompressedStripSize);
}
- using TiffBaseDecompresor decompressor = TiffDecompressorsFactory.Create(this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, frame.Width, bitsPerPixel, this.Predictor, this.FaxCompressionOptions);
+ using TiffBaseDecompressor decompressor = TiffDecompressorsFactory.Create(this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, frame.Width, bitsPerPixel, this.Predictor, this.FaxCompressionOptions);
RgbPlanarTiffColor colorDecoder = TiffColorDecoderFactory.CreatePlanar(this.ColorType, this.BitsPerSample.Bits(), this.ColorMap);
@@ -293,7 +293,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
Buffer2D pixels = frame.PixelBuffer;
- using TiffBaseDecompresor decompressor = TiffDecompressorsFactory.Create(this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, frame.Width, bitsPerPixel, this.Predictor, this.FaxCompressionOptions);
+ using TiffBaseDecompressor decompressor = TiffDecompressorsFactory.Create(this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, frame.Width, bitsPerPixel, this.Predictor, this.FaxCompressionOptions);
TiffBaseColorDecoder colorDecoder = TiffColorDecoderFactory.Create(this.ColorType, this.BitsPerSample.Bits(), this.ColorMap);
diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoder.cs b/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
index 88204eb556..7e075c2e66 100644
--- a/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
@@ -17,6 +17,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
///
public class TiffEncoder : IImageEncoder, ITiffEncoderOptions
{
+ ///
+ public TiffBitsPerPixel? BitsPerPixel { get; set; }
+
///
public TiffEncoderCompression Compression { get; set; } = TiffEncoderCompression.None;
diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
index 6e80899e47..a04b8a809f 100644
--- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
@@ -12,6 +12,7 @@ using SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression;
using SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants;
using SixLabors.ImageSharp.Formats.Experimental.Tiff.Writers;
using SixLabors.ImageSharp.Memory;
+using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
@@ -40,11 +41,6 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
///
private Configuration configuration;
- ///
- /// The color depth, in number of bits per pixel.
- ///
- private TiffBitsPerPixel bitsPerPixel;
-
///
/// The quantizer for creating color palette image.
///
@@ -70,6 +66,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
this.memoryAllocator = memoryAllocator;
this.Mode = options.Mode;
this.quantizer = options.Quantizer ?? KnownQuantizers.Octree;
+ this.BitsPerPixel = options.BitsPerPixel;
this.UseHorizontalPredictor = options.UseHorizontalPredictor;
this.CompressionType = options.Compression;
this.compressionLevel = options.CompressionLevel;
@@ -82,9 +79,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
internal TiffPhotometricInterpretation PhotometricInterpretation { get; private set; }
///
- /// Gets the compression implementation to use when encoding the image.
+ /// Gets or sets the compression implementation to use when encoding the image.
///
- internal TiffEncoderCompression CompressionType { get; }
+ internal TiffEncoderCompression CompressionType { get; set; }
///
/// Gets the encoding mode to use. RGB, RGB with color palette or gray.
@@ -97,6 +94,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
///
internal bool UseHorizontalPredictor { get; }
+ ///
+ /// Gets the bits per pixel.
+ ///
+ internal TiffBitsPerPixel? BitsPerPixel { get; private set; }
+
///
/// Encodes the image to the specified stream from the .
///
@@ -111,8 +113,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
Guard.NotNull(stream, nameof(stream));
this.configuration = image.GetConfiguration();
+ ImageMetadata metadata = image.Metadata;
+ TiffMetadata tiffMetadata = metadata.GetTiffMetadata();
+ this.BitsPerPixel ??= tiffMetadata.BitsPerPixel;
- this.SetMode(image);
+ this.SetMode(tiffMetadata);
+ this.SetBitsPerPixel();
this.SetPhotometricInterpretation();
using (var writer = new TiffStreamWriter(stream))
@@ -155,20 +161,31 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
// Write the image bytes to the steam.
var imageDataStart = (uint)writer.Position;
- using TiffBaseCompressor compressor = TiffCompressorFactory.Create(
- this.CompressionType,
- writer.BaseStream,
- this.memoryAllocator,
- image.Width,
- (int)this.bitsPerPixel,
- this.compressionLevel,
- this.UseHorizontalPredictor ? TiffPredictor.Horizontal : TiffPredictor.None);
-
- using TiffBaseColorWriter colorWriter = TiffColorWriterFactory.Create(this.Mode, image.Frames.RootFrame, this.quantizer, this.memoryAllocator, this.configuration, entriesCollector);
-
- int rowsPerStrip = this.CalcRowsPerStrip(image.Frames.RootFrame, colorWriter.BytesPerRow);
-
- colorWriter.Write(compressor, rowsPerStrip);
+ TiffBitsPerPixel? tiffBitsPerPixel = this.BitsPerPixel;
+ if (tiffBitsPerPixel != null)
+ {
+ using TiffBaseCompressor compressor = TiffCompressorFactory.Create(
+ this.CompressionType,
+ writer.BaseStream,
+ this.memoryAllocator,
+ image.Width,
+ (int)tiffBitsPerPixel,
+ this.compressionLevel,
+ this.UseHorizontalPredictor ? TiffPredictor.Horizontal : TiffPredictor.None);
+
+ using TiffBaseColorWriter colorWriter = TiffColorWriterFactory.Create(
+ this.Mode,
+ image.Frames.RootFrame,
+ this.quantizer,
+ this.memoryAllocator,
+ this.configuration,
+ entriesCollector,
+ (int)tiffBitsPerPixel);
+
+ int rowsPerStrip = this.CalcRowsPerStrip(image.Frames.RootFrame.Height, colorWriter.BytesPerRow);
+
+ colorWriter.Write(compressor, rowsPerStrip);
+ }
entriesCollector.ProcessImageFormat(this);
entriesCollector.ProcessGeneral(image);
@@ -177,12 +194,21 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
long nextIfdMarker = this.WriteIfd(writer, entriesCollector.Entries);
}
- private int CalcRowsPerStrip(ImageFrame image, int bytesPerRow)
+ ///
+ /// Calculates the number of rows written per strip.
+ ///
+ /// The height of the image.
+ /// The number of bytes per row.
+ /// Number of rows per strip.
+ private int CalcRowsPerStrip(int height, int bytesPerRow)
{
- int sz = this.maxStripBytes > 0 ? this.maxStripBytes : DefaultStripSize;
- int height = sz / bytesPerRow;
+ DebugGuard.MustBeGreaterThan(height, 0, nameof(height));
+ DebugGuard.MustBeGreaterThan(bytesPerRow, 0, nameof(bytesPerRow));
+
+ int stripBytes = this.maxStripBytes > 0 ? this.maxStripBytes : DefaultStripSize;
+ int rowsPerStrip = stripBytes / bytesPerRow;
- return height > 0 ? (height < image.Height ? height : image.Height) : 1;
+ return rowsPerStrip > 0 ? (rowsPerStrip < height ? rowsPerStrip : height) : 1;
}
///
@@ -242,14 +268,15 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
return nextIfdMarker;
}
- private void SetMode(Image image)
+ private void SetMode(TiffMetadata tiffMetadata)
{
+ // Make sure, that the fax compressions are only used together with the BiColor mode.
if (this.CompressionType == TiffEncoderCompression.CcittGroup3Fax || this.CompressionType == TiffEncoderCompression.ModifiedHuffman)
{
+ // Default means the user has not specified a preferred encoding mode.
if (this.Mode == TiffEncodingMode.Default)
{
this.Mode = TiffEncodingMode.BiColor;
- this.bitsPerPixel = TiffBitsPerPixel.Pixel1;
return;
}
@@ -262,36 +289,48 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
if (this.Mode == TiffEncodingMode.Default)
{
// Preserve input bits per pixel, if no mode was specified.
- TiffMetadata tiffMetadata = image.Metadata.GetTiffMetadata();
switch (tiffMetadata.BitsPerPixel)
{
case TiffBitsPerPixel.Pixel1:
this.Mode = TiffEncodingMode.BiColor;
break;
+ case TiffBitsPerPixel.Pixel4:
+ this.Mode = TiffEncodingMode.ColorPalette;
+ break;
case TiffBitsPerPixel.Pixel8:
- this.Mode = tiffMetadata.PhotometricInterpretation != TiffPhotometricInterpretation.PaletteColor ? TiffEncodingMode.Gray : TiffEncodingMode.Rgb;
+ this.Mode = tiffMetadata.PhotometricInterpretation == TiffPhotometricInterpretation.PaletteColor ? TiffEncodingMode.ColorPalette : TiffEncodingMode.Gray;
+
break;
default:
this.Mode = TiffEncodingMode.Rgb;
break;
}
}
+ }
+ private void SetBitsPerPixel()
+ {
switch (this.Mode)
{
case TiffEncodingMode.BiColor:
- this.bitsPerPixel = TiffBitsPerPixel.Pixel1;
+ this.BitsPerPixel = TiffBitsPerPixel.Pixel1;
break;
case TiffEncodingMode.ColorPalette:
+ if (this.BitsPerPixel != TiffBitsPerPixel.Pixel8 && this.BitsPerPixel != TiffBitsPerPixel.Pixel4)
+ {
+ this.BitsPerPixel = TiffBitsPerPixel.Pixel8;
+ }
+
+ break;
case TiffEncodingMode.Gray:
- this.bitsPerPixel = TiffBitsPerPixel.Pixel8;
+ this.BitsPerPixel = TiffBitsPerPixel.Pixel8;
break;
case TiffEncodingMode.Rgb:
- this.bitsPerPixel = TiffBitsPerPixel.Pixel24;
+ this.BitsPerPixel = TiffBitsPerPixel.Pixel24;
break;
default:
this.Mode = TiffEncodingMode.Rgb;
- this.bitsPerPixel = TiffBitsPerPixel.Pixel24;
+ this.BitsPerPixel = TiffBitsPerPixel.Pixel24;
break;
}
}
diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs
index f2e3d9faf7..c8ad38db36 100644
--- a/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs
@@ -298,25 +298,33 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
switch (encoder.PhotometricInterpretation)
{
case TiffPhotometricInterpretation.PaletteColor:
- return new ushort[] { 8 };
+ if (encoder.BitsPerPixel == TiffBitsPerPixel.Pixel4)
+ {
+ return TiffConstants.BitsPerSample4Bit;
+ }
+ else
+ {
+ return TiffConstants.BitsPerSample8Bit;
+ }
+
case TiffPhotometricInterpretation.Rgb:
- return new ushort[] { 8, 8, 8 };
+ return TiffConstants.BitsPerSampleRgb8Bit;
case TiffPhotometricInterpretation.WhiteIsZero:
if (encoder.Mode == TiffEncodingMode.BiColor)
{
- return new ushort[] { 1 };
+ return TiffConstants.BitsPerSample1Bit;
}
- return new ushort[] { 8 };
+ return TiffConstants.BitsPerSample8Bit;
case TiffPhotometricInterpretation.BlackIsZero:
if (encoder.Mode == TiffEncodingMode.BiColor)
{
- return new ushort[] { 1 };
+ return TiffConstants.BitsPerSample1Bit;
}
- return new ushort[] { 8 };
+ return TiffConstants.BitsPerSample8Bit;
default:
- return new ushort[] { 8, 8, 8 };
+ return TiffConstants.BitsPerSampleRgb8Bit;
}
}
diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffBaseColorWriter.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffBaseColorWriter.cs
index f61b294364..70c91fa892 100644
--- a/src/ImageSharp/Formats/Tiff/Writers/TiffBaseColorWriter.cs
+++ b/src/ImageSharp/Formats/Tiff/Writers/TiffBaseColorWriter.cs
@@ -20,13 +20,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Writers
this.MemoryAllocator = memoryAllocator;
this.Configuration = configuration;
this.EntriesCollector = entriesCollector;
-
- this.BytesPerRow = ((image.Width * this.BitsPerPixel) + 7) / 8;
}
public abstract int BitsPerPixel { get; }
- public int BytesPerRow { get; }
+ public int BytesPerRow => ((this.Image.Width * this.BitsPerPixel) + 7) / 8;
protected ImageFrame Image { get; }
@@ -38,7 +36,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Writers
public virtual void Write(TiffBaseCompressor compressor, int rowsPerStrip)
{
- DebugGuard.IsTrue(this.BytesPerRow == compressor.BytesPerRow || compressor.BytesPerRow == 0, "Values must be equals");
+ DebugGuard.IsTrue(this.BytesPerRow == compressor.BytesPerRow, "bytes per row of the compressor does not match tiff color writer");
int stripsCount = (this.Image.Height + rowsPerStrip - 1) / rowsPerStrip;
uint[] stripOffsets = new uint[stripsCount];
@@ -59,7 +57,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Writers
stripIndex++;
}
- DebugGuard.IsTrue(stripIndex == stripsCount, "Values must be equals");
+ DebugGuard.IsTrue(stripIndex == stripsCount, "stripIndex and stripsCount should match");
this.AddStripTags(rowsPerStrip, stripOffsets, stripByteCounts);
}
diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffColorWriterFactory.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffColorWriterFactory.cs
index 10bb9b96ed..4dcb47b47d 100644
--- a/src/ImageSharp/Formats/Tiff/Writers/TiffColorWriterFactory.cs
+++ b/src/ImageSharp/Formats/Tiff/Writers/TiffColorWriterFactory.cs
@@ -15,13 +15,14 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Writers
IQuantizer quantizer,
MemoryAllocator memoryAllocator,
Configuration configuration,
- TiffEncoderEntriesCollector entriesCollector)
+ TiffEncoderEntriesCollector entriesCollector,
+ int bitsPerPixel)
where TPixel : unmanaged, IPixel
{
switch (mode)
{
case TiffEncodingMode.ColorPalette:
- return new TiffPaletteWriter(image, quantizer, memoryAllocator, configuration, entriesCollector);
+ return new TiffPaletteWriter(image, quantizer, memoryAllocator, configuration, entriesCollector, bitsPerPixel);
case TiffEncodingMode.Gray:
return new TiffGrayWriter(image, memoryAllocator, configuration, entriesCollector);
case TiffEncodingMode.BiColor:
diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter.cs
index d15bc5e17a..b094c22fc0 100644
--- a/src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter.cs
+++ b/src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter.cs
@@ -4,6 +4,7 @@
using System;
using System.Buffers;
using System.Runtime.InteropServices;
+
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression;
using SixLabors.ImageSharp.Memory;
@@ -16,52 +17,85 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Writers
internal sealed class TiffPaletteWriter : TiffBaseColorWriter
where TPixel : unmanaged, IPixel
{
- private const int ColorsPerChannel = 256;
- private const int ColorPaletteSize = ColorsPerChannel * 3;
- private const int ColorPaletteBytes = ColorPaletteSize * 2;
-
- private readonly IndexedImageFrame quantized;
-
- public TiffPaletteWriter(ImageFrame image, IQuantizer quantizer, MemoryAllocator memoryAllocator, Configuration configuration, TiffEncoderEntriesCollector entriesCollector)
+ private readonly int maxColors;
+ private readonly int colorPaletteSize;
+ private readonly int colorPaletteBytes;
+ private readonly IndexedImageFrame quantizedImage;
+
+ public TiffPaletteWriter(
+ ImageFrame image,
+ IQuantizer quantizer,
+ MemoryAllocator memoryAllocator,
+ Configuration configuration,
+ TiffEncoderEntriesCollector entriesCollector,
+ int bitsPerPixel)
: base(image, memoryAllocator, configuration, entriesCollector)
{
- using IQuantizer frameQuantizer = quantizer.CreatePixelSpecificQuantizer(this.Configuration);
- this.quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(image, image.Bounds());
+ DebugGuard.NotNull(quantizer, nameof(quantizer));
+ DebugGuard.NotNull(configuration, nameof(configuration));
+ DebugGuard.NotNull(entriesCollector, nameof(entriesCollector));
+ DebugGuard.MustBeBetweenOrEqualTo(bitsPerPixel, 4, 8, nameof(bitsPerPixel));
+
+ this.BitsPerPixel = bitsPerPixel;
+ this.maxColors = this.BitsPerPixel == 4 ? 16 : 256;
+ this.colorPaletteSize = this.maxColors * 3;
+ this.colorPaletteBytes = this.colorPaletteSize * 2;
+ using IQuantizer frameQuantizer = quantizer.CreatePixelSpecificQuantizer(this.Configuration, new QuantizerOptions()
+ {
+ MaxColors = this.maxColors
+ });
+ this.quantizedImage = frameQuantizer.BuildPaletteAndQuantizeFrame(image, image.Bounds());
- this.AddTag(this.quantized);
+ this.AddColorMapTag();
}
///
- public override int BitsPerPixel => 8;
+ public override int BitsPerPixel { get; }
///
protected override void EncodeStrip(int y, int height, TiffBaseCompressor compressor)
{
- Span pixels = GetStripPixels(((IPixelSource)this.quantized).PixelBuffer, y, height);
- compressor.CompressStrip(pixels, height);
+ Span pixels = GetStripPixels(((IPixelSource)this.quantizedImage).PixelBuffer, y, height);
+ if (this.BitsPerPixel == 4)
+ {
+ using IMemoryOwner rows4bitBuffer = this.MemoryAllocator.Allocate(pixels.Length / 2);
+ Span rows4bit = rows4bitBuffer.GetSpan();
+ int idx = 0;
+ for (int i = 0; i < rows4bit.Length; i++)
+ {
+ rows4bit[i] = (byte)((pixels[idx] << 4) | (pixels[idx + 1] & 0xF));
+ idx += 2;
+ }
+
+ compressor.CompressStrip(rows4bit, height);
+ }
+ else
+ {
+ compressor.CompressStrip(pixels, height);
+ }
}
///
- protected override void Dispose(bool disposing) => this.quantized?.Dispose();
+ protected override void Dispose(bool disposing) => this.quantizedImage?.Dispose();
- private void AddTag(IndexedImageFrame quantized)
+ private void AddColorMapTag()
{
- using IMemoryOwner colorPaletteBuffer = this.MemoryAllocator.AllocateManagedByteBuffer(ColorPaletteBytes);
+ using IMemoryOwner colorPaletteBuffer = this.MemoryAllocator.AllocateManagedByteBuffer(this.colorPaletteBytes);
Span colorPalette = colorPaletteBuffer.GetSpan();
- ReadOnlySpan quantizedColors = quantized.Palette.Span;
+ ReadOnlySpan quantizedColors = this.quantizedImage.Palette.Span;
int quantizedColorBytes = quantizedColors.Length * 3 * 2;
- // In the ColorMap, black is represented by 0,0,0 and white is represented by 65535, 65535, 65535.
+ // In the ColorMap, black is represented by 0, 0, 0 and white is represented by 65535, 65535, 65535.
Span quantizedColorRgb48 = MemoryMarshal.Cast(colorPalette.Slice(0, quantizedColorBytes));
PixelOperations.Instance.ToRgb48(this.Configuration, quantizedColors, quantizedColorRgb48);
- // It can happen that the quantized colors are less than the expected 256 per channel.
- var diffToMaxColors = ColorsPerChannel - quantizedColors.Length;
+ // It can happen that the quantized colors are less than the expected maximum per channel.
+ var diffToMaxColors = this.maxColors - quantizedColors.Length;
// In a TIFF ColorMap, all the Red values come first, followed by the Green values,
// then the Blue values. Convert the quantized palette to this format.
- var palette = new ushort[ColorPaletteSize];
+ var palette = new ushort[this.colorPaletteSize];
int paletteIdx = 0;
for (int i = 0; i < quantizedColors.Length; i++)
{
diff --git a/tests/ImageSharp.Tests/Formats/Tiff/Compression/NoneTiffCompressionTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/Compression/NoneTiffCompressionTests.cs
index 466027bee4..d5435a8a4d 100644
--- a/tests/ImageSharp.Tests/Formats/Tiff/Compression/NoneTiffCompressionTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Tiff/Compression/NoneTiffCompressionTests.cs
@@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.Compression
var stream = new BufferedReadStream(Configuration.Default, new MemoryStream(inputData));
var buffer = new byte[expectedResult.Length];
- new NoneTiffCompression().Decompress(stream, 0, byteCount, buffer);
+ new NoneTiffCompression(default, default, default).Decompress(stream, 0, byteCount, buffer);
Assert.Equal(expectedResult, buffer);
}
diff --git a/tests/ImageSharp.Tests/Formats/Tiff/Compression/PackBitsTiffCompressionTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/Compression/PackBitsTiffCompressionTests.cs
index a211bde535..d0649934d5 100644
--- a/tests/ImageSharp.Tests/Formats/Tiff/Compression/PackBitsTiffCompressionTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Tiff/Compression/PackBitsTiffCompressionTests.cs
@@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.Compression
var stream = new BufferedReadStream(Configuration.Default, new MemoryStream(inputData));
var buffer = new byte[expectedResult.Length];
- using var decompressor = new PackBitsTiffCompression(new ArrayPoolMemoryAllocator());
+ using var decompressor = new PackBitsTiffCompression(new ArrayPoolMemoryAllocator(), default, default);
decompressor.Decompress(stream, 0, (uint)inputData.Length, buffer);
Assert.Equal(expectedResult, buffer);
diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
index d4f68ff660..57a4356298 100644
--- a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
@@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
-using System;
using System.IO;
using SixLabors.ImageSharp.Formats;
@@ -38,7 +37,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[InlineData(TiffEncodingMode.BiColor, TiffEncoderCompression.None, TiffBitsPerPixel.Pixel1, TiffCompression.None)]
[InlineData(TiffEncodingMode.Default, TiffEncoderCompression.Deflate, TiffBitsPerPixel.Pixel24, TiffCompression.Deflate)]
[InlineData(TiffEncodingMode.Rgb, TiffEncoderCompression.Deflate, TiffBitsPerPixel.Pixel24, TiffCompression.Deflate)]
- [InlineData(TiffEncodingMode.ColorPalette, TiffEncoderCompression.Deflate, TiffBitsPerPixel.Pixel8, TiffCompression.Deflate)]
[InlineData(TiffEncodingMode.Gray, TiffEncoderCompression.Deflate, TiffBitsPerPixel.Pixel8, TiffCompression.Deflate)]
[InlineData(TiffEncodingMode.BiColor, TiffEncoderCompression.Deflate, TiffBitsPerPixel.Pixel1, TiffCompression.Deflate)]
[InlineData(TiffEncodingMode.Default, TiffEncoderCompression.PackBits, TiffBitsPerPixel.Pixel24, TiffCompression.PackBits)]
@@ -47,7 +45,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[InlineData(TiffEncodingMode.Gray, TiffEncoderCompression.PackBits, TiffBitsPerPixel.Pixel8, TiffCompression.PackBits)]
[InlineData(TiffEncodingMode.BiColor, TiffEncoderCompression.PackBits, TiffBitsPerPixel.Pixel1, TiffCompression.PackBits)]
[InlineData(TiffEncodingMode.Rgb, TiffEncoderCompression.Lzw, TiffBitsPerPixel.Pixel24, TiffCompression.Lzw)]
- [InlineData(TiffEncodingMode.ColorPalette, TiffEncoderCompression.Lzw, TiffBitsPerPixel.Pixel8, TiffCompression.Lzw)]
[InlineData(TiffEncodingMode.Gray, TiffEncoderCompression.Lzw, TiffBitsPerPixel.Pixel8, TiffCompression.Lzw)]
[InlineData(TiffEncodingMode.BiColor, TiffEncoderCompression.CcittGroup3Fax, TiffBitsPerPixel.Pixel1, TiffCompression.CcittGroup3Fax)]
[InlineData(TiffEncodingMode.BiColor, TiffEncoderCompression.ModifiedHuffman, TiffBitsPerPixel.Pixel1, TiffCompression.Ccitt1D)]
@@ -73,7 +70,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[WithFile(Calliphora_BiColorUncompressed, PixelTypes.Rgba32, TiffBitsPerPixel.Pixel1)]
[WithFile(GrayscaleUncompressed, PixelTypes.Rgba32, TiffBitsPerPixel.Pixel8)]
[WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffBitsPerPixel.Pixel24)]
- [WithFile(Calliphora_PaletteUncompressed, PixelTypes.Rgba32, TiffBitsPerPixel.Pixel24)]
+ [WithFile(Rgb4BitPalette, PixelTypes.Rgba32, TiffBitsPerPixel.Pixel4)]
+ [WithFile(RgbPalette, PixelTypes.Rgba32, TiffBitsPerPixel.Pixel8)]
+ [WithFile(Calliphora_PaletteUncompressed, PixelTypes.Rgba32, TiffBitsPerPixel.Pixel8)]
public void TiffEncoder_PreserveBitsPerPixel(TestImageProvider provider, TiffBitsPerPixel expectedBitsPerPixel)
where TPixel : unmanaged, IPixel
{
@@ -97,7 +96,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffEncoderCompression.ModifiedHuffman, TiffCompression.Ccitt1D)]
[WithFile(GrayscaleUncompressed, PixelTypes.L8, TiffEncoderCompression.CcittGroup3Fax, TiffCompression.CcittGroup3Fax)]
[WithFile(PaletteDeflateMultistrip, PixelTypes.L8, TiffEncoderCompression.ModifiedHuffman, TiffCompression.Ccitt1D)]
- public void TiffEncoder_CorrectBiMode(TestImageProvider provider, TiffEncoderCompression compression, TiffCompression expectedCompression)
+ public void TiffEncoder_EncodesWithCorrectBiColorModeCompression(TestImageProvider provider, TiffEncoderCompression compression, TiffCompression expectedCompression)
where TPixel : unmanaged, IPixel
{
// arrange
@@ -197,37 +196,19 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[WithFile(Calliphora_PaletteUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeColorPalette_Works(TestImageProvider provider)
where TPixel : unmanaged, IPixel =>
- TestTiffEncoderCore(provider, TiffBitsPerPixel.Pixel24, TiffEncodingMode.ColorPalette, useExactComparer: false, compareTolerance: 0.001f);
+ TestTiffEncoderCore(provider, TiffBitsPerPixel.Pixel8, TiffEncodingMode.ColorPalette, useExactComparer: false, compareTolerance: 0.001f);
[Theory]
- [WithFile(Calliphora_PaletteUncompressed, PixelTypes.Rgba32)]
- public void TiffEncoder_EncodeColorPalette_WithDeflateCompression_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel =>
- TestTiffEncoderCore(provider, TiffBitsPerPixel.Pixel24, TiffEncodingMode.ColorPalette, TiffEncoderCompression.Deflate, useExactComparer: false, compareTolerance: 0.001f);
-
- [Theory]
- [WithFile(Calliphora_PaletteUncompressed, PixelTypes.Rgba32)]
- public void TiffEncoder_EncodeColorPalette_WithDeflateCompressionAndPredictor_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel =>
- TestTiffEncoderCore(provider, TiffBitsPerPixel.Pixel24, TiffEncodingMode.ColorPalette, TiffEncoderCompression.Deflate, usePredictor: true, useExactComparer: false, compareTolerance: 0.001f);
-
- [Theory]
- [WithFile(Calliphora_PaletteUncompressed, PixelTypes.Rgba32)]
- public void TiffEncoder_EncodeColorPalette_WithLzwCompression_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel =>
- TestTiffEncoderCore(provider, TiffBitsPerPixel.Pixel24, TiffEncodingMode.ColorPalette, TiffEncoderCompression.Lzw, useExactComparer: false, compareTolerance: 0.001f);
-
- [Theory]
- [WithFile(Calliphora_PaletteUncompressed, PixelTypes.Rgba32)]
- public void TiffEncoder_EncodeColorPalette_WithLzwCompressionAndPredictor_Works(TestImageProvider provider)
+ [WithFile(Rgb4BitPalette, PixelTypes.Rgba32)]
+ public void TiffEncoder_EncodeColorPalette_With4Bit_Works(TestImageProvider provider)
where TPixel : unmanaged, IPixel =>
- TestTiffEncoderCore(provider, TiffBitsPerPixel.Pixel24, TiffEncodingMode.ColorPalette, TiffEncoderCompression.Lzw, usePredictor: true, useExactComparer: false, compareTolerance: 0.001f);
+ TestTiffEncoderCore(provider, TiffBitsPerPixel.Pixel8, TiffEncodingMode.ColorPalette, useExactComparer: false, compareTolerance: 0.001f);
[Theory]
[WithFile(Calliphora_PaletteUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeColorPalette_WithPackBitsCompression_Works(TestImageProvider provider)
where TPixel : unmanaged, IPixel =>
- TestTiffEncoderCore(provider, TiffBitsPerPixel.Pixel24, TiffEncodingMode.ColorPalette, TiffEncoderCompression.PackBits, useExactComparer: false, compareTolerance: 0.001f);
+ TestTiffEncoderCore(provider, TiffBitsPerPixel.Pixel8, TiffEncodingMode.ColorPalette, TiffEncoderCompression.PackBits, useExactComparer: false, compareTolerance: 0.001f);
[Theory]
[WithFile(Calliphora_BiColorUncompressed, PixelTypes.Rgba32)]
@@ -335,6 +316,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
var encoder = new TiffEncoder
{
Mode = mode,
+ BitsPerPixel = bitsPerPixel,
Compression = compression,
UseHorizontalPredictor = usePredictor,
MaxStripBytes = maxStripSize
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index aa9883e96e..49d0e759cd 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/tests/ImageSharp.Tests/TestImages.cs
@@ -556,6 +556,7 @@ namespace SixLabors.ImageSharp.Tests
public const string RgbPackbitsMultistrip = "Tiff/rgb_packbits_multistrip.tiff";
public const string RgbUncompressed = "Tiff/rgb_uncompressed.tiff";
public const string RgbPalette = "Tiff/rgb_palette.tiff";
+ public const string Rgb4BitPalette = "Tiff/bike_colorpalette_4bit.tiff";
public const string RgbPaletteDeflate = "Tiff/rgb_palette_deflate.tiff";
public const string SmallRgbDeflate = "Tiff/rgb_small_deflate.tiff";
diff --git a/tests/Images/Input/Tiff/bike_colorpalette_4bit.tiff b/tests/Images/Input/Tiff/bike_colorpalette_4bit.tiff
new file mode 100644
index 0000000000..d76966336d
--- /dev/null
+++ b/tests/Images/Input/Tiff/bike_colorpalette_4bit.tiff
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bc9047bc28ff5256530a7203bf73fa0a7ed1545736cd57fabdaff2d600cfa3f1
+size 132265