diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs
index a016fb712..3e9b7f4e6 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs
@@ -344,8 +344,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors
{
while (codeLength > 0)
{
- var bitNumber = (int)codeLength;
- var bit = (code & (1 << (bitNumber - 1))) != 0;
+ int bitNumber = (int)codeLength;
+ bool bit = (code & (1 << (bitNumber - 1))) != 0;
if (bit)
{
BitWriterUtils.WriteBit(compressedData, this.bytePosition, this.bitPosition);
diff --git a/src/ImageSharp/Formats/Tiff/Constants/TiffPhotometricInterpretation.cs b/src/ImageSharp/Formats/Tiff/Constants/TiffPhotometricInterpretation.cs
index b39e1003a..6dab7de6e 100644
--- a/src/ImageSharp/Formats/Tiff/Constants/TiffPhotometricInterpretation.cs
+++ b/src/ImageSharp/Formats/Tiff/Constants/TiffPhotometricInterpretation.cs
@@ -10,6 +10,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Constants
{
///
/// Bilevel and grayscale: 0 is imaged as white. The maximum value is imaged as black.
+ ///
+ /// Not supported by the TiffEncoder.
///
WhiteIsZero = 0,
@@ -29,42 +31,58 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Constants
PaletteColor = 3,
///
- /// A transparency mask
+ /// A transparency mask.
+ ///
+ /// Not supported by the TiffEncoder.
///
TransparencyMask = 4,
///
/// Separated: usually CMYK (see Section 16 of the TIFF 6.0 specification).
+ ///
+ /// Not supported by the TiffEncoder.
///
Separated = 5,
///
/// YCbCr (see Section 21 of the TIFF 6.0 specification).
+ ///
+ /// Not supported by the TiffEncoder.
///
YCbCr = 6,
///
/// 1976 CIE L*a*b* (see Section 23 of the TIFF 6.0 specification).
+ ///
+ /// Not supported by the TiffEncoder.
///
CieLab = 8,
///
/// ICC L*a*b* (see TIFF Specification, supplement 1).
+ ///
+ /// Not supported by the TiffEncoder.
///
IccLab = 9,
///
/// ITU L*a*b* (see RFC2301).
+ ///
+ /// Not supported by the TiffEncoder.
///
ItuLab = 10,
///
/// Color Filter Array (see the DNG specification).
+ ///
+ /// Not supported by the TiffEncoder.
///
ColorFilterArray = 32803,
///
/// Linear Raw (see the DNG specification).
+ ///
+ /// Not supported by the TiffEncoder.
///
LinearRaw = 34892
}
diff --git a/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs b/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
index 03c25ea13..d56a587df 100644
--- a/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
@@ -20,24 +20,24 @@ namespace SixLabors.ImageSharp.Formats.Tiff
///
/// Gets the compression type to use.
///
- TiffCompression Compression { get; }
+ TiffCompression? Compression { get; }
///
/// Gets the compression level 1-9 for the deflate compression mode.
/// Defaults to .
///
- DeflateCompressionLevel CompressionLevel { get; }
+ DeflateCompressionLevel? CompressionLevel { get; }
///
- /// Gets the encoding mode to use. Possible options are RGB, RGB with a color palette, gray or BiColor.
- /// If no mode is specified in the options, RGB will be used.
+ /// Gets the PhotometricInterpretation to use. Possible options are RGB, RGB with a color palette, gray or BiColor.
+ /// If no PhotometricInterpretation is specified or it is unsupported by the encoder, RGB will be used.
///
- TiffEncodingMode Mode { get; }
+ TiffPhotometricInterpretation? PhotometricInterpretation { get; }
///
/// Gets a value indicating which horizontal prediction to use. This can improve the compression ratio with deflate or lzw compression.
///
- TiffPredictor HorizontalPredictor { get; }
+ TiffPredictor? HorizontalPredictor { get; }
///
/// Gets the quantizer for creating a color palette image.
diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
index 7111f5d36..88a2d194d 100644
--- a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
@@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
options.PlanarConfiguration = (TiffPlanarConfiguration?)exifProfile.GetValue(ExifTag.PlanarConfiguration)?.Value ?? DefaultPlanarConfiguration;
options.Predictor = predictor;
options.PhotometricInterpretation = exifProfile.GetValue(ExifTag.PhotometricInterpretation) != null ?
- (TiffPhotometricInterpretation)exifProfile.GetValue(ExifTag.PhotometricInterpretation).Value : TiffPhotometricInterpretation.WhiteIsZero;
+ (TiffPhotometricInterpretation)exifProfile.GetValue(ExifTag.PhotometricInterpretation).Value : TiffPhotometricInterpretation.BlackIsZero;
options.BitsPerPixel = entries.BitsPerPixel != null ? (int)entries.BitsPerPixel.Value : (int)TiffBitsPerPixel.Bit24;
options.BitsPerSample = GetBitsPerSample(entries.BitsPerPixel);
diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoder.cs b/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
index b66ba339c..7d5ccdb94 100644
--- a/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
@@ -22,16 +22,16 @@ namespace SixLabors.ImageSharp.Formats.Tiff
public TiffBitsPerPixel? BitsPerPixel { get; set; }
///
- public TiffCompression Compression { get; set; } = TiffCompression.None;
+ public TiffCompression? Compression { get; set; }
///
- public DeflateCompressionLevel CompressionLevel { get; set; } = DeflateCompressionLevel.DefaultCompression;
+ public DeflateCompressionLevel? CompressionLevel { get; set; }
///
- public TiffEncodingMode Mode { get; set; }
+ public TiffPhotometricInterpretation? PhotometricInterpretation { get; set; }
///
- public TiffPredictor HorizontalPredictor { get; set; }
+ public TiffPredictor? HorizontalPredictor { get; set; }
///
public IQuantizer Quantizer { get; set; }
diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
index 878bd99a9..f9402e4d4 100644
--- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
@@ -12,6 +12,7 @@ using SixLabors.ImageSharp.Formats.Tiff.Compression;
using SixLabors.ImageSharp.Formats.Tiff.Constants;
using SixLabors.ImageSharp.Formats.Tiff.Writers;
using SixLabors.ImageSharp.Memory;
+using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
@@ -61,34 +62,28 @@ namespace SixLabors.ImageSharp.Formats.Tiff
public TiffEncoderCore(ITiffEncoderOptions options, MemoryAllocator memoryAllocator)
{
this.memoryAllocator = memoryAllocator;
- this.Mode = options.Mode;
+ this.PhotometricInterpretation = options.PhotometricInterpretation;
this.quantizer = options.Quantizer ?? KnownQuantizers.Octree;
this.BitsPerPixel = options.BitsPerPixel;
this.HorizontalPredictor = options.HorizontalPredictor;
- this.CompressionType = options.Compression != TiffCompression.Invalid ? options.Compression : TiffCompression.None;
- this.compressionLevel = options.CompressionLevel;
+ this.CompressionType = options.Compression;
+ this.compressionLevel = options.CompressionLevel ?? DeflateCompressionLevel.DefaultCompression;
}
///
/// Gets the photometric interpretation implementation to use when encoding the image.
///
- internal TiffPhotometricInterpretation PhotometricInterpretation { get; private set; }
+ internal TiffPhotometricInterpretation? PhotometricInterpretation { get; private set; }
///
/// Gets or sets the compression implementation to use when encoding the image.
///
- internal TiffCompression CompressionType { get; set; }
+ internal TiffCompression? CompressionType { get; set; }
///
- /// Gets the encoding mode to use. RGB, RGB with color palette or gray.
- /// If no mode is specified in the options, RGB will be used.
+ /// Gets or sets a value indicating which horizontal predictor to use. This can improve the compression ratio with deflate compression.
///
- internal TiffEncodingMode Mode { get; private set; }
-
- ///
- /// Gets a value indicating which horizontal predictor to use. This can improve the compression ratio with deflate compression.
- ///
- internal TiffPredictor HorizontalPredictor { get; }
+ internal TiffPredictor? HorizontalPredictor { get; set; }
///
/// Gets the bits per pixel.
@@ -111,18 +106,27 @@ namespace SixLabors.ImageSharp.Formats.Tiff
this.configuration = image.GetConfiguration();
TiffPhotometricInterpretation rootFramePhotometricInterpretation = GetRootFramePhotometricInterpretation(image);
- TiffPhotometricInterpretation photometricInterpretation = this.Mode == TiffEncodingMode.ColorPalette
+ TiffPhotometricInterpretation photometricInterpretation = this.PhotometricInterpretation == TiffPhotometricInterpretation.PaletteColor
? TiffPhotometricInterpretation.PaletteColor
: rootFramePhotometricInterpretation;
- TiffBitsPerPixel? rootFrameBitsPerPixel = image.Frames.RootFrame.Metadata.GetTiffMetadata().BitsPerPixel;
+ ImageFrameMetadata rootFrameMetaData = image.Frames.RootFrame.Metadata;
+ ExifProfile rootFrameExifProfile = image.Frames.RootFrame.Metadata.ExifProfile;
+ TiffBitsPerPixel? rootFrameBitsPerPixel = rootFrameMetaData.GetTiffMetadata().BitsPerPixel;
+
+ // If the user has not chosen a predictor or compression, set the values from the decoded image, if present.
+ if (!this.HorizontalPredictor.HasValue && rootFrameExifProfile?.GetValue(ExifTag.Predictor) != null)
+ {
+ this.HorizontalPredictor = (TiffPredictor)rootFrameExifProfile?.GetValue(ExifTag.Predictor).Value;
+ }
+
+ if (!this.CompressionType.HasValue && rootFrameExifProfile?.GetValue(ExifTag.Compression) != null)
+ {
+ this.CompressionType = (TiffCompression)rootFrameExifProfile?.GetValue(ExifTag.Compression).Value;
+ }
- // TODO: This isn't correct.
- // We're overwriting explicit BPP based upon the Mode. It should be the other way around.
- // BPP should also be nullable and based upon the current TPixel if not set.
- this.SetBitsPerPixel(rootFrameBitsPerPixel, photometricInterpretation);
- this.SetMode(photometricInterpretation);
- this.SetPhotometricInterpretation();
+ this.SetBitsPerPixel(rootFrameBitsPerPixel, image.PixelType.BitsPerPixel, photometricInterpretation);
+ this.SetPhotometricInterpretation(photometricInterpretation);
using (var writer = new TiffStreamWriter(stream))
{
@@ -159,20 +163,17 @@ namespace SixLabors.ImageSharp.Formats.Tiff
{
var entriesCollector = new TiffEncoderEntriesCollector();
- // Write the image bytes to the steam.
- uint imageDataStart = (uint)writer.Position;
-
using TiffBaseCompressor compressor = TiffCompressorFactory.Create(
- this.CompressionType,
+ this.CompressionType ?? TiffCompression.None,
writer.BaseStream,
this.memoryAllocator,
image.Width,
(int)this.BitsPerPixel,
this.compressionLevel,
- this.HorizontalPredictor == TiffPredictor.Horizontal ? this.HorizontalPredictor : TiffPredictor.None);
+ this.HorizontalPredictor == TiffPredictor.Horizontal ? this.HorizontalPredictor.Value : TiffPredictor.None);
using TiffBaseColorWriter colorWriter = TiffColorWriterFactory.Create(
- this.Mode,
+ this.PhotometricInterpretation,
image.Frames.RootFrame,
this.quantizer,
this.memoryAllocator,
@@ -227,8 +228,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
{
if (entries.Count == 0)
{
- // TODO: Perf. Throwhelper
- throw new ArgumentException("There must be at least one entry per IFD.", nameof(entries));
+ TiffThrowHelper.ThrowArgumentException("There must be at least one entry per IFD.");
}
uint dataOffset = (uint)writer.Position + (uint)(6 + (entries.Count * 12));
@@ -277,52 +277,73 @@ namespace SixLabors.ImageSharp.Formats.Tiff
return nextIfdMarker;
}
- private void SetMode(TiffPhotometricInterpretation photometricInterpretation)
+ private void SetPhotometricInterpretation(TiffPhotometricInterpretation? photometricInterpretation)
{
- // Make sure, that the fax compressions are only used together with the BiColor mode.
+ // Make sure, that the fax compressions are only used together with the WhiteIsZero.
if (this.CompressionType == TiffCompression.CcittGroup3Fax || this.CompressionType == TiffCompression.Ccitt1D)
{
- // Default means the user has not specified a preferred encoding mode.
- if (this.Mode == TiffEncodingMode.Default)
+ // The user has not specified a preferred photometric interpretation.
+ if (this.PhotometricInterpretation == null)
{
- this.Mode = TiffEncodingMode.BiColor;
+ this.PhotometricInterpretation = TiffPhotometricInterpretation.WhiteIsZero;
this.BitsPerPixel = TiffBitsPerPixel.Bit1;
return;
}
- if (this.Mode != TiffEncodingMode.BiColor)
+ if (this.PhotometricInterpretation != TiffPhotometricInterpretation.WhiteIsZero && this.PhotometricInterpretation != TiffPhotometricInterpretation.BlackIsZero)
{
- TiffThrowHelper.ThrowImageFormatException($"The {this.CompressionType} compression and {this.Mode} aren't compatible. Please use {this.CompressionType} only with {TiffEncodingMode.BiColor} or {TiffEncodingMode.Default} mode.");
+ TiffThrowHelper.ThrowImageFormatException(
+ $"The {this.CompressionType} compression and {this.PhotometricInterpretation} aren't compatible. Please use {this.CompressionType} only with {TiffPhotometricInterpretation.BlackIsZero} or {TiffPhotometricInterpretation.WhiteIsZero}.");
}
+ else
+ {
+ // The “normal” PhotometricInterpretation for bilevel CCITT compressed data is WhiteIsZero.
+ this.PhotometricInterpretation = TiffPhotometricInterpretation.WhiteIsZero;
+ }
+
+ return;
+ }
+
+ switch (this.PhotometricInterpretation)
+ {
+ // The currently supported values by the encoder for photometric interpretation:
+ case TiffPhotometricInterpretation.PaletteColor:
+ case TiffPhotometricInterpretation.BlackIsZero:
+ case TiffPhotometricInterpretation.WhiteIsZero:
+ break;
+
+ default:
+ this.PhotometricInterpretation = TiffPhotometricInterpretation.Rgb;
+ break;
}
- // Use the bits per pixel to determine the encoding mode.
- this.SetModeWithBitsPerPixel(this.BitsPerPixel, photometricInterpretation);
+ // Use the bits per pixel to determine the photometric interpretation.
+ this.SetPhotometricInterpretationWithBitsPerPixel(this.BitsPerPixel, photometricInterpretation);
}
- private void SetModeWithBitsPerPixel(TiffBitsPerPixel? bitsPerPixel, TiffPhotometricInterpretation photometricInterpretation)
+ private void SetPhotometricInterpretationWithBitsPerPixel(TiffBitsPerPixel? bitsPerPixel, TiffPhotometricInterpretation? photometricInterpretation)
{
switch (bitsPerPixel)
{
case TiffBitsPerPixel.Bit1:
- this.Mode = TiffEncodingMode.BiColor;
+ this.PhotometricInterpretation = TiffPhotometricInterpretation.BlackIsZero;
break;
case TiffBitsPerPixel.Bit4:
- this.Mode = TiffEncodingMode.ColorPalette;
+ this.PhotometricInterpretation = TiffPhotometricInterpretation.PaletteColor;
break;
case TiffBitsPerPixel.Bit8:
- this.Mode = photometricInterpretation == TiffPhotometricInterpretation.PaletteColor
- ? TiffEncodingMode.ColorPalette
- : TiffEncodingMode.Gray;
+ this.PhotometricInterpretation = photometricInterpretation == TiffPhotometricInterpretation.PaletteColor
+ ? TiffPhotometricInterpretation.PaletteColor
+ : TiffPhotometricInterpretation.BlackIsZero;
break;
default:
- this.Mode = TiffEncodingMode.Rgb;
+ this.PhotometricInterpretation = TiffPhotometricInterpretation.Rgb;
break;
}
}
- private void SetBitsPerPixel(TiffBitsPerPixel? rootFrameBitsPerPixel, TiffPhotometricInterpretation photometricInterpretation)
+ private void SetBitsPerPixel(TiffBitsPerPixel? rootFrameBitsPerPixel, int inputBitsPerPixel, TiffPhotometricInterpretation photometricInterpretation)
{
this.BitsPerPixel ??= rootFrameBitsPerPixel;
@@ -341,56 +362,41 @@ namespace SixLabors.ImageSharp.Formats.Tiff
return;
}
- switch (this.Mode)
+ if (this.PhotometricInterpretation == null && inputBitsPerPixel == 8)
{
- case TiffEncodingMode.BiColor:
- this.BitsPerPixel = TiffBitsPerPixel.Bit1;
- break;
- case TiffEncodingMode.ColorPalette:
- if (this.BitsPerPixel != TiffBitsPerPixel.Bit8 && this.BitsPerPixel != TiffBitsPerPixel.Bit4)
- {
- this.BitsPerPixel = TiffBitsPerPixel.Bit8;
- }
-
- break;
- case TiffEncodingMode.Gray:
- this.BitsPerPixel = TiffBitsPerPixel.Bit8;
- break;
- case TiffEncodingMode.Rgb:
- this.BitsPerPixel = TiffBitsPerPixel.Bit24;
- break;
- default:
- this.Mode = TiffEncodingMode.Rgb;
- this.BitsPerPixel = TiffBitsPerPixel.Bit24;
- break;
+ this.BitsPerPixel = TiffBitsPerPixel.Bit8;
+ return;
}
- }
- private void SetPhotometricInterpretation()
- {
- switch (this.Mode)
+ switch (this.PhotometricInterpretation)
{
- case TiffEncodingMode.ColorPalette:
- this.PhotometricInterpretation = TiffPhotometricInterpretation.PaletteColor;
- break;
- case TiffEncodingMode.BiColor:
- if (this.CompressionType == TiffCompression.CcittGroup3Fax || this.CompressionType == TiffCompression.Ccitt1D)
+ case TiffPhotometricInterpretation.BlackIsZero:
+ case TiffPhotometricInterpretation.WhiteIsZero:
+ if (this.CompressionType == TiffCompression.Ccitt1D ||
+ this.CompressionType == TiffCompression.CcittGroup3Fax ||
+ this.CompressionType == TiffCompression.CcittGroup4Fax)
{
- // The “normal” PhotometricInterpretation for bilevel CCITT compressed data is WhiteIsZero.
- this.PhotometricInterpretation = TiffPhotometricInterpretation.WhiteIsZero;
+ this.BitsPerPixel = TiffBitsPerPixel.Bit1;
}
else
{
- this.PhotometricInterpretation = TiffPhotometricInterpretation.BlackIsZero;
+ this.BitsPerPixel = TiffBitsPerPixel.Bit8;
}
break;
+ case TiffPhotometricInterpretation.PaletteColor:
+ if (this.BitsPerPixel != TiffBitsPerPixel.Bit8 && this.BitsPerPixel != TiffBitsPerPixel.Bit4)
+ {
+ this.BitsPerPixel = TiffBitsPerPixel.Bit8;
+ }
- case TiffEncodingMode.Gray:
- this.PhotometricInterpretation = TiffPhotometricInterpretation.BlackIsZero;
+ break;
+ case TiffPhotometricInterpretation.Rgb:
+ this.BitsPerPixel = TiffBitsPerPixel.Bit24;
break;
default:
this.PhotometricInterpretation = TiffPhotometricInterpretation.Rgb;
+ this.BitsPerPixel = TiffBitsPerPixel.Bit24;
break;
}
}
@@ -400,7 +406,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
ExifProfile exifProfile = image.Frames.RootFrame.Metadata.ExifProfile;
return exifProfile?.GetValue(ExifTag.PhotometricInterpretation) != null
? (TiffPhotometricInterpretation)exifProfile?.GetValue(ExifTag.PhotometricInterpretation).Value
- : TiffPhotometricInterpretation.WhiteIsZero;
+ : TiffPhotometricInterpretation.BlackIsZero;
}
}
}
diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs
index 391f7d541..09605bc69 100644
--- a/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs
@@ -281,7 +281,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff
if (encoder.HorizontalPredictor == TiffPredictor.Horizontal)
{
- if (encoder.Mode == TiffEncodingMode.Rgb || encoder.Mode == TiffEncodingMode.Gray || encoder.Mode == TiffEncodingMode.ColorPalette)
+ if (encoder.PhotometricInterpretation == TiffPhotometricInterpretation.Rgb ||
+ encoder.PhotometricInterpretation == TiffPhotometricInterpretation.PaletteColor ||
+ encoder.PhotometricInterpretation == TiffPhotometricInterpretation.BlackIsZero)
{
var predictor = new ExifShort(ExifTagValue.Predictor) { Value = (ushort)TiffPredictor.Horizontal };
@@ -320,20 +322,23 @@ namespace SixLabors.ImageSharp.Formats.Tiff
case TiffPhotometricInterpretation.Rgb:
return TiffConstants.BitsPerSampleRgb8Bit;
+
case TiffPhotometricInterpretation.WhiteIsZero:
- if (encoder.Mode == TiffEncodingMode.BiColor)
+ if (encoder.BitsPerPixel == TiffBitsPerPixel.Bit1)
{
return TiffConstants.BitsPerSample1Bit;
}
return TiffConstants.BitsPerSample8Bit;
+
case TiffPhotometricInterpretation.BlackIsZero:
- if (encoder.Mode == TiffEncodingMode.BiColor)
+ if (encoder.BitsPerPixel == TiffBitsPerPixel.Bit1)
{
return TiffConstants.BitsPerSample1Bit;
}
return TiffConstants.BitsPerSample8Bit;
+
default:
return TiffConstants.BitsPerSampleRgb8Bit;
}
@@ -350,7 +355,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff
// PackBits is allowed for all modes.
return (ushort)TiffCompression.PackBits;
case TiffCompression.Lzw:
- if (encoder.Mode == TiffEncodingMode.Rgb || encoder.Mode == TiffEncodingMode.Gray || encoder.Mode == TiffEncodingMode.ColorPalette)
+ if (encoder.PhotometricInterpretation == TiffPhotometricInterpretation.Rgb ||
+ encoder.PhotometricInterpretation == TiffPhotometricInterpretation.PaletteColor ||
+ encoder.PhotometricInterpretation == TiffPhotometricInterpretation.BlackIsZero)
{
return (ushort)TiffCompression.Lzw;
}
@@ -358,20 +365,10 @@ namespace SixLabors.ImageSharp.Formats.Tiff
break;
case TiffCompression.CcittGroup3Fax:
- if (encoder.Mode == TiffEncodingMode.BiColor)
- {
- return (ushort)TiffCompression.CcittGroup3Fax;
- }
-
- break;
+ return (ushort)TiffCompression.CcittGroup3Fax;
case TiffCompression.Ccitt1D:
- if (encoder.Mode == TiffEncodingMode.BiColor)
- {
- return (ushort)TiffCompression.Ccitt1D;
- }
-
- break;
+ return (ushort)TiffCompression.Ccitt1D;
}
return (ushort)TiffCompression.None;
diff --git a/src/ImageSharp/Formats/Tiff/TiffEncodingMode.cs b/src/ImageSharp/Formats/Tiff/TiffEncodingMode.cs
deleted file mode 100644
index 374505195..000000000
--- a/src/ImageSharp/Formats/Tiff/TiffEncodingMode.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Formats.Tiff
-{
- ///
- /// Enum for the different tiff encoding options.
- ///
- public enum TiffEncodingMode
- {
- ///
- /// No mode specified. Will preserve the bits per pixels of the input image.
- ///
- Default = 0,
-
- ///
- /// The image will be encoded as RGB, 8 bit per channel.
- ///
- Rgb = 1,
-
- ///
- /// The image will be encoded as RGB with a color palette.
- ///
- ColorPalette = 2,
-
- ///
- /// The image will be encoded as 8 bit gray.
- ///
- Gray = 3,
-
- ///
- /// The image will be written as a white and black image.
- ///
- BiColor = 4,
- }
-}
diff --git a/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs b/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs
index c5ebf481a..3c541a786 100644
--- a/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs
@@ -32,5 +32,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowNotSupported(string message) => throw new NotSupportedException(message);
+
+ [MethodImpl(InliningOptions.ColdPath)]
+ public static void ThrowArgumentException(string message) => throw new ArgumentException(message);
}
}
diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffBiColorWriter{TPixel}.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffBiColorWriter{TPixel}.cs
index e37cba7cf..be5c837ea 100644
--- a/src/ImageSharp/Formats/Tiff/Writers/TiffBiColorWriter{TPixel}.cs
+++ b/src/ImageSharp/Formats/Tiff/Writers/TiffBiColorWriter{TPixel}.cs
@@ -36,16 +36,13 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers
///
protected override void EncodeStrip(int y, int height, TiffBaseCompressor compressor)
{
- if (this.pixelsAsGray == null)
- {
- this.pixelsAsGray = this.MemoryAllocator.Allocate(height * this.Image.Width);
- }
+ this.pixelsAsGray ??= this.MemoryAllocator.Allocate(height * this.Image.Width);
Span pixelAsGraySpan = this.pixelsAsGray.Slice(0, height * this.Image.Width);
- Span pixels = GetStripPixels(this.imageBlackWhite.GetRootFramePixelBuffer(), y, height);
+ Span pixelsBlackWhite = GetStripPixels(this.imageBlackWhite.GetRootFramePixelBuffer(), y, height);
- PixelOperations.Instance.ToL8Bytes(this.Configuration, pixels, pixelAsGraySpan, pixels.Length);
+ PixelOperations.Instance.ToL8Bytes(this.Configuration, pixelsBlackWhite, pixelAsGraySpan, pixelsBlackWhite.Length);
if (compressor.Method == TiffCompression.CcittGroup3Fax || compressor.Method == TiffCompression.Ccitt1D)
{
@@ -54,11 +51,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers
}
else
{
+ // Write uncompressed image.
int bytesPerStrip = this.BytesPerRow * height;
- if (this.bitStrip == null)
- {
- this.bitStrip = this.MemoryAllocator.AllocateManagedByteBuffer(bytesPerStrip);
- }
+ this.bitStrip ??= this.MemoryAllocator.AllocateManagedByteBuffer(bytesPerStrip);
Span rows = this.bitStrip.Slice(0, bytesPerStrip);
rows.Clear();
diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffColorWriterFactory.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffColorWriterFactory.cs
index 01c1833f1..e53f4b420 100644
--- a/src/ImageSharp/Formats/Tiff/Writers/TiffColorWriterFactory.cs
+++ b/src/ImageSharp/Formats/Tiff/Writers/TiffColorWriterFactory.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
+using SixLabors.ImageSharp.Formats.Tiff.Constants;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Quantization;
@@ -10,7 +11,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers
internal static class TiffColorWriterFactory
{
public static TiffBaseColorWriter Create(
- TiffEncodingMode mode,
+ TiffPhotometricInterpretation? photometricInterpretation,
ImageFrame image,
IQuantizer quantizer,
MemoryAllocator memoryAllocator,
@@ -19,14 +20,18 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers
int bitsPerPixel)
where TPixel : unmanaged, IPixel
{
- switch (mode)
+ switch (photometricInterpretation)
{
- case TiffEncodingMode.ColorPalette:
+ case TiffPhotometricInterpretation.PaletteColor:
return new TiffPaletteWriter(image, quantizer, memoryAllocator, configuration, entriesCollector, bitsPerPixel);
- case TiffEncodingMode.Gray:
+ case TiffPhotometricInterpretation.BlackIsZero:
+ case TiffPhotometricInterpretation.WhiteIsZero:
+ if (bitsPerPixel == 1)
+ {
+ return new TiffBiColorWriter(image, memoryAllocator, configuration, entriesCollector);
+ }
+
return new TiffGrayWriter(image, memoryAllocator, configuration, entriesCollector);
- case TiffEncodingMode.BiColor:
- return new TiffBiColorWriter(image, memoryAllocator, configuration, entriesCollector);
default:
return new TiffRgbWriter(image, memoryAllocator, configuration, entriesCollector);
}
diff --git a/tests/ImageSharp.Benchmarks/Codecs/EncodeTiff.cs b/tests/ImageSharp.Benchmarks/Codecs/EncodeTiff.cs
index 3c318e229..7154b2310 100644
--- a/tests/ImageSharp.Benchmarks/Codecs/EncodeTiff.cs
+++ b/tests/ImageSharp.Benchmarks/Codecs/EncodeTiff.cs
@@ -61,8 +61,10 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
public void SystemDrawing()
{
ImageCodecInfo codec = FindCodecForType("image/tiff");
- using var parameters = new EncoderParameters(1);
- parameters.Param[0] = new EncoderParameter(Encoder.Compression, (long)Cast(this.Compression));
+ using var parameters = new EncoderParameters(1)
+ {
+ Param = {[0] = new EncoderParameter(Encoder.Compression, (long)Cast(this.Compression))}
+ };
using var memoryStream = new MemoryStream();
this.drawing.Save(memoryStream, codec, parameters);
@@ -71,15 +73,15 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
[Benchmark(Description = "ImageSharp Tiff")]
public void TiffCore()
{
- TiffEncodingMode mode = TiffEncodingMode.Default;
+ TiffPhotometricInterpretation photometricInterpretation = TiffPhotometricInterpretation.Rgb;
- // workaround for 1-bit bug
+ // Workaround for 1-bit bug
if (this.Compression == TiffCompression.CcittGroup3Fax || this.Compression == TiffCompression.Ccitt1D)
{
- mode = TiffEncodingMode.BiColor;
+ photometricInterpretation = TiffPhotometricInterpretation.WhiteIsZero;
}
- var encoder = new TiffEncoder() { Compression = this.Compression, Mode = mode };
+ var encoder = new TiffEncoder() { Compression = this.Compression, PhotometricInterpretation = photometricInterpretation };
using var memoryStream = new MemoryStream();
this.core.SaveAsTiff(memoryStream, encoder);
}
diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
index fb8354b18..99a74182d 100644
--- a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
@@ -31,15 +31,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
}
[Theory]
- [InlineData(TiffEncodingMode.Default, TiffBitsPerPixel.Bit24)]
- [InlineData(TiffEncodingMode.Rgb, TiffBitsPerPixel.Bit24)]
- [InlineData(TiffEncodingMode.ColorPalette, TiffBitsPerPixel.Bit8)]
- [InlineData(TiffEncodingMode.Gray, TiffBitsPerPixel.Bit8)]
- [InlineData(TiffEncodingMode.BiColor, TiffBitsPerPixel.Bit1)]
- public void EncoderOptions_SetEncodingMode_Works(TiffEncodingMode mode, TiffBitsPerPixel expectedBitsPerPixel)
+ [InlineData(null, TiffBitsPerPixel.Bit24)]
+ [InlineData(TiffPhotometricInterpretation.Rgb, TiffBitsPerPixel.Bit24)]
+ [InlineData(TiffPhotometricInterpretation.PaletteColor, TiffBitsPerPixel.Bit8)]
+ [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffBitsPerPixel.Bit8)]
+ public void EncoderOptions_SetPhotometricInterpretation_Works(TiffPhotometricInterpretation? photometricInterpretation, TiffBitsPerPixel expectedBitsPerPixel)
{
// arrange
- var tiffEncoder = new TiffEncoder { Mode = mode };
+ var tiffEncoder = new TiffEncoder { PhotometricInterpretation = photometricInterpretation };
using Image input = new Image(10, 10);
using var memStream = new MemoryStream();
@@ -81,30 +80,29 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
}
[Theory]
- [InlineData(TiffEncodingMode.Default, TiffCompression.Deflate, TiffBitsPerPixel.Bit24, TiffCompression.Deflate)]
- [InlineData(TiffEncodingMode.Rgb, TiffCompression.Deflate, TiffBitsPerPixel.Bit24, TiffCompression.Deflate)]
- [InlineData(TiffEncodingMode.Gray, TiffCompression.Deflate, TiffBitsPerPixel.Bit8, TiffCompression.Deflate)]
- [InlineData(TiffEncodingMode.BiColor, TiffCompression.Deflate, TiffBitsPerPixel.Bit1, TiffCompression.Deflate)]
- [InlineData(TiffEncodingMode.ColorPalette, TiffCompression.Deflate, TiffBitsPerPixel.Bit8, TiffCompression.Deflate)]
- [InlineData(TiffEncodingMode.Default, TiffCompression.PackBits, TiffBitsPerPixel.Bit24, TiffCompression.PackBits)]
- [InlineData(TiffEncodingMode.Rgb, TiffCompression.PackBits, TiffBitsPerPixel.Bit24, TiffCompression.PackBits)]
- [InlineData(TiffEncodingMode.ColorPalette, TiffCompression.PackBits, TiffBitsPerPixel.Bit8, TiffCompression.PackBits)]
- [InlineData(TiffEncodingMode.Gray, TiffCompression.PackBits, TiffBitsPerPixel.Bit8, TiffCompression.PackBits)]
- [InlineData(TiffEncodingMode.BiColor, TiffCompression.PackBits, TiffBitsPerPixel.Bit1, TiffCompression.PackBits)]
- [InlineData(TiffEncodingMode.Rgb, TiffCompression.Lzw, TiffBitsPerPixel.Bit24, TiffCompression.Lzw)]
- [InlineData(TiffEncodingMode.Gray, TiffCompression.Lzw, TiffBitsPerPixel.Bit8, TiffCompression.Lzw)]
- [InlineData(TiffEncodingMode.ColorPalette, TiffCompression.Lzw, TiffBitsPerPixel.Bit8, TiffCompression.Lzw)]
- [InlineData(TiffEncodingMode.BiColor, TiffCompression.CcittGroup3Fax, TiffBitsPerPixel.Bit1, TiffCompression.CcittGroup3Fax)]
- [InlineData(TiffEncodingMode.BiColor, TiffCompression.Ccitt1D, TiffBitsPerPixel.Bit1, TiffCompression.Ccitt1D)]
- [InlineData(TiffEncodingMode.Rgb, TiffCompression.ItuTRecT43, TiffBitsPerPixel.Bit24, TiffCompression.None)]
- [InlineData(TiffEncodingMode.Rgb, TiffCompression.ItuTRecT82, TiffBitsPerPixel.Bit24, TiffCompression.None)]
- [InlineData(TiffEncodingMode.Rgb, TiffCompression.Jpeg, TiffBitsPerPixel.Bit24, TiffCompression.None)]
- [InlineData(TiffEncodingMode.Rgb, TiffCompression.OldDeflate, TiffBitsPerPixel.Bit24, TiffCompression.None)]
- [InlineData(TiffEncodingMode.Rgb, TiffCompression.OldJpeg, TiffBitsPerPixel.Bit24, TiffCompression.None)]
- public void EncoderOptions_SetEncodingModeAndCompression_Works(TiffEncodingMode mode, TiffCompression compression, TiffBitsPerPixel expectedBitsPerPixel, TiffCompression expectedCompression)
+ [InlineData(null, TiffCompression.Deflate, TiffBitsPerPixel.Bit24, TiffCompression.Deflate)]
+ [InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.Deflate, TiffBitsPerPixel.Bit24, TiffCompression.Deflate)]
+ [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Deflate, TiffBitsPerPixel.Bit8, TiffCompression.Deflate)]
+ [InlineData(TiffPhotometricInterpretation.PaletteColor, TiffCompression.Deflate, TiffBitsPerPixel.Bit8, TiffCompression.Deflate)]
+ [InlineData(null, TiffCompression.PackBits, TiffBitsPerPixel.Bit24, TiffCompression.PackBits)]
+ [InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.PackBits, TiffBitsPerPixel.Bit24, TiffCompression.PackBits)]
+ [InlineData(TiffPhotometricInterpretation.PaletteColor, TiffCompression.PackBits, TiffBitsPerPixel.Bit8, TiffCompression.PackBits)]
+ [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffCompression.PackBits, TiffBitsPerPixel.Bit8, TiffCompression.PackBits)]
+ [InlineData(null, TiffCompression.Lzw, TiffBitsPerPixel.Bit24, TiffCompression.Lzw)]
+ [InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.Lzw, TiffBitsPerPixel.Bit24, TiffCompression.Lzw)]
+ [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Lzw, TiffBitsPerPixel.Bit8, TiffCompression.Lzw)]
+ [InlineData(TiffPhotometricInterpretation.PaletteColor, TiffCompression.Lzw, TiffBitsPerPixel.Bit8, TiffCompression.Lzw)]
+ [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffCompression.CcittGroup3Fax, TiffBitsPerPixel.Bit1, TiffCompression.CcittGroup3Fax)]
+ [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Ccitt1D, TiffBitsPerPixel.Bit1, TiffCompression.Ccitt1D)]
+ [InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.ItuTRecT43, TiffBitsPerPixel.Bit24, TiffCompression.None)]
+ [InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.ItuTRecT82, TiffBitsPerPixel.Bit24, TiffCompression.None)]
+ [InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.Jpeg, TiffBitsPerPixel.Bit24, TiffCompression.None)]
+ [InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.OldDeflate, TiffBitsPerPixel.Bit24, TiffCompression.None)]
+ [InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.OldJpeg, TiffBitsPerPixel.Bit24, TiffCompression.None)]
+ public void EncoderOptions_SetPhotometricInterpretationAndCompression_Works(TiffPhotometricInterpretation? photometricInterpretation, TiffCompression compression, TiffBitsPerPixel expectedBitsPerPixel, TiffCompression expectedCompression)
{
// arrange
- var tiffEncoder = new TiffEncoder { Mode = mode, Compression = compression };
+ var tiffEncoder = new TiffEncoder { PhotometricInterpretation = photometricInterpretation, Compression = compression };
using Image input = new Image(10, 10);
using var memStream = new MemoryStream();
@@ -115,8 +113,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
memStream.Position = 0;
using var output = Image.Load(Configuration, memStream);
ExifProfile exifProfile = output.Frames.RootFrame.Metadata.ExifProfile;
- var frameMetaData = TiffFrameMetadata.Parse(exifProfile);
- Assert.Equal(expectedBitsPerPixel, frameMetaData.BitsPerPixel);
+ TiffFrameMetadata rootFrameMetaData = output.Frames.RootFrame.Metadata.GetTiffMetadata();
+ Assert.Equal(expectedBitsPerPixel, rootFrameMetaData.BitsPerPixel);
Assert.Equal(expectedCompression, (TiffCompression)exifProfile.GetValue(ExifTag.Compression).Value);
}
@@ -146,6 +144,72 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
Assert.Equal(expectedBitsPerPixel, frameMetaData.BitsPerPixel);
}
+ [Fact]
+ public void TiffEncoder_PreservesBitsPerPixel_WhenInputIsL8()
+ {
+ // arrange
+ var tiffEncoder = new TiffEncoder();
+ using Image input = new Image(10, 10);
+ using var memStream = new MemoryStream();
+ var expectedBitsPerPixel = TiffBitsPerPixel.Bit8;
+
+ // act
+ input.Save(memStream, tiffEncoder);
+
+ // assert
+ memStream.Position = 0;
+ using var output = Image.Load(Configuration, memStream);
+ ExifProfile exifProfile = output.Frames.RootFrame.Metadata.ExifProfile;
+ var frameMetaData = TiffFrameMetadata.Parse(exifProfile);
+ Assert.Equal(expectedBitsPerPixel, frameMetaData.BitsPerPixel);
+ }
+
+ [Theory]
+ [WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffCompression.None)]
+ [WithFile(RgbLzwNoPredictor, PixelTypes.Rgba32, TiffCompression.Lzw)]
+ [WithFile(RgbDeflate, PixelTypes.Rgba32, TiffCompression.Deflate)]
+ [WithFile(RgbPackbits, PixelTypes.Rgba32, TiffCompression.PackBits)]
+ public void TiffEncoder_PreservesCompression(TestImageProvider provider, TiffCompression expectedCompression)
+ where TPixel : unmanaged, IPixel
+ {
+ // arrange
+ var tiffEncoder = new TiffEncoder();
+ using Image input = provider.GetImage();
+ using var memStream = new MemoryStream();
+
+ // act
+ input.Save(memStream, tiffEncoder);
+
+ // assert
+ memStream.Position = 0;
+ using var output = Image.Load(Configuration, memStream);
+ ExifProfile exifProfile = output.Frames.RootFrame.Metadata.ExifProfile;
+ Assert.Equal(expectedCompression, (TiffCompression)exifProfile.GetValue(ExifTag.Compression).Value);
+ }
+
+ [Theory]
+ [WithFile(RgbLzwNoPredictor, PixelTypes.Rgba32, TiffPredictor.None)]
+ [WithFile(RgbLzwPredictor, PixelTypes.Rgba32, TiffPredictor.Horizontal)]
+ [WithFile(RgbDeflate, PixelTypes.Rgba32, TiffPredictor.None)]
+ [WithFile(RgbDeflatePredictor, PixelTypes.Rgba32, TiffPredictor.Horizontal)]
+ public void TiffEncoder_PreservesPredictor(TestImageProvider provider, TiffPredictor expectedPredictor)
+ where TPixel : unmanaged, IPixel
+ {
+ // arrange
+ var tiffEncoder = new TiffEncoder();
+ using Image input = provider.GetImage();
+ using var memStream = new MemoryStream();
+
+ // act
+ input.Save(memStream, tiffEncoder);
+
+ // assert
+ memStream.Position = 0;
+ using var output = Image.Load(Configuration, memStream);
+ ExifProfile exifProfile = output.Frames.RootFrame.Metadata.ExifProfile;
+ Assert.Equal(expectedPredictor, (TiffPredictor)exifProfile.GetValue(ExifTag.Predictor).Value);
+ }
+
[Theory]
[WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffCompression.CcittGroup3Fax, TiffCompression.CcittGroup3Fax)]
[WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffCompression.Ccitt1D, TiffCompression.Ccitt1D)]
@@ -172,15 +236,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
}
[Theory]
- [InlineData(TiffEncodingMode.ColorPalette, TiffCompression.CcittGroup3Fax)]
- [InlineData(TiffEncodingMode.ColorPalette, TiffCompression.Ccitt1D)]
- [InlineData(TiffEncodingMode.Gray, TiffCompression.Ccitt1D)]
- [InlineData(TiffEncodingMode.Rgb, TiffCompression.Ccitt1D)]
- public void TiffEncoder_IncompatibilityOptions(TiffEncodingMode mode, TiffCompression compression)
+ [InlineData(TiffPhotometricInterpretation.PaletteColor, TiffCompression.CcittGroup3Fax)]
+ [InlineData(TiffPhotometricInterpretation.PaletteColor, TiffCompression.Ccitt1D)]
+ public void TiffEncoder_IncompatibilityOptions_ThrowsImageFormatException(TiffPhotometricInterpretation photometricInterpretation, TiffCompression compression)
{
// arrange
using var input = new Image(10, 10);
- var encoder = new TiffEncoder() { Mode = mode, Compression = compression };
+ var encoder = new TiffEncoder() { PhotometricInterpretation = photometricInterpretation, Compression = compression };
using var memStream = new MemoryStream();
// act
@@ -190,154 +252,154 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[Theory]
[WithFile(Calliphora_RgbUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeRgb_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffEncodingMode.Rgb);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffPhotometricInterpretation.Rgb);
[Theory]
[WithFile(Calliphora_RgbUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeRgb_WithDeflateCompression_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffEncodingMode.Rgb, TiffCompression.Deflate);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffPhotometricInterpretation.Rgb, TiffCompression.Deflate);
[Theory]
[WithFile(Calliphora_RgbUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeRgb_WithDeflateCompressionAndPredictor_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffEncodingMode.Rgb, TiffCompression.Deflate, TiffPredictor.Horizontal);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffPhotometricInterpretation.Rgb, TiffCompression.Deflate, TiffPredictor.Horizontal);
[Theory]
[WithFile(Calliphora_RgbUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeRgb_WithLzwCompression_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffEncodingMode.Rgb, TiffCompression.Lzw);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffPhotometricInterpretation.Rgb, TiffCompression.Lzw);
[Theory]
[WithFile(Calliphora_RgbUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeRgb_WithLzwCompressionAndPredictor_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffEncodingMode.Rgb, TiffCompression.Lzw, TiffPredictor.Horizontal);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffPhotometricInterpretation.Rgb, TiffCompression.Lzw, TiffPredictor.Horizontal);
[Theory]
[WithFile(Calliphora_RgbUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeRgb_WithPackBitsCompression_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffEncodingMode.Rgb, TiffCompression.PackBits);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffPhotometricInterpretation.Rgb, TiffCompression.PackBits);
[Theory]
[WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeGray_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffEncodingMode.Gray);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.BlackIsZero);
[Theory]
[WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeGray_WithDeflateCompression_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffEncodingMode.Gray, TiffCompression.Deflate);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Deflate);
[Theory]
[WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeGray_WithDeflateCompressionAndPredictor_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffEncodingMode.Gray, TiffCompression.Deflate, TiffPredictor.Horizontal);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Deflate, TiffPredictor.Horizontal);
[Theory]
[WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeGray_WithLzwCompression_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffEncodingMode.Gray, TiffCompression.Lzw);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Lzw);
[Theory]
[WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeGray_WithLzwCompressionAndPredictor_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffEncodingMode.Gray, TiffCompression.Lzw, TiffPredictor.Horizontal);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Lzw, TiffPredictor.Horizontal);
[Theory]
[WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeGray_WithPackBitsCompression_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffEncodingMode.Gray, TiffCompression.PackBits);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.PackBits);
[Theory]
[WithFile(Calliphora_PaletteUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeColorPalette_Works(TestImageProvider provider)
where TPixel : unmanaged, IPixel =>
- TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffEncodingMode.ColorPalette, useExactComparer: false, compareTolerance: 0.001f);
+ TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.PaletteColor, useExactComparer: false, compareTolerance: 0.001f);
[Theory]
[WithFile(Rgb4BitPalette, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeColorPalette_With4Bit_Works(TestImageProvider provider)
where TPixel : unmanaged, IPixel =>
//// Note: The magick reference decoder does not support 4 bit tiff's, so we use our TIFF decoder instead.
- TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit4, TiffEncodingMode.ColorPalette, useExactComparer: false, compareTolerance: 0.001f, imageDecoder: new TiffDecoder());
+ TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit4, TiffPhotometricInterpretation.PaletteColor, useExactComparer: false, compareTolerance: 0.001f, imageDecoder: new TiffDecoder());
[Theory]
[WithFile(Calliphora_PaletteUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeColorPalette_WithPackBitsCompression_Works(TestImageProvider provider)
where TPixel : unmanaged, IPixel =>
- TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffEncodingMode.ColorPalette, TiffCompression.PackBits, useExactComparer: false, compareTolerance: 0.001f);
+ TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.PaletteColor, TiffCompression.PackBits, 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.Bit8, TiffEncodingMode.ColorPalette, TiffCompression.Deflate, useExactComparer: false, compareTolerance: 0.001f);
+ TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.PaletteColor, TiffCompression.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.Bit8, TiffEncodingMode.ColorPalette, TiffCompression.Deflate, TiffPredictor.Horizontal, useExactComparer: false, compareTolerance: 0.001f);
+ TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.PaletteColor, TiffCompression.Deflate, TiffPredictor.Horizontal, 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.Bit8, TiffEncodingMode.ColorPalette, TiffCompression.Lzw, useExactComparer: false, compareTolerance: 0.001f);
+ TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.PaletteColor, TiffCompression.Lzw, useExactComparer: false, compareTolerance: 0.001f);
[Theory]
[WithFile(Calliphora_PaletteUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeColorPalette_WithLzwCompressionAndPredictor_Works(TestImageProvider provider)
where TPixel : unmanaged, IPixel =>
- TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffEncodingMode.ColorPalette, TiffCompression.Lzw, TiffPredictor.Horizontal, useExactComparer: false, compareTolerance: 0.001f);
+ TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.PaletteColor, TiffCompression.Lzw, TiffPredictor.Horizontal, useExactComparer: false, compareTolerance: 0.001f);
[Theory]
[WithFile(Calliphora_BiColorUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeBiColor_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffEncodingMode.BiColor);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffPhotometricInterpretation.BlackIsZero);
[Theory]
[WithFile(Calliphora_BiColorUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeBiColor_WithDeflateCompression_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit1, TiffEncodingMode.BiColor, TiffCompression.Deflate);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit1, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Deflate);
[Theory]
[WithFile(Calliphora_BiColorUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeBiColor_WithPackBitsCompression_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit1, TiffEncodingMode.BiColor, TiffCompression.PackBits);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit1, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.PackBits);
[Theory]
[WithFile(Calliphora_BiColorUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeBiColor_WithCcittGroup3FaxCompression_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit1, TiffEncodingMode.BiColor, TiffCompression.CcittGroup3Fax);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit1, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.CcittGroup3Fax);
[Theory]
[WithFile(Calliphora_BiColorUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeBiColor_WithModifiedHuffmanCompression_Works(TestImageProvider provider)
- where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit1, TiffEncodingMode.BiColor, TiffCompression.Ccitt1D);
+ where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit1, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Ccitt1D);
[Theory]
- [WithFile(GrayscaleUncompressed, PixelTypes.L8, TiffEncodingMode.Gray, TiffCompression.PackBits)]
- [WithFile(PaletteDeflateMultistrip, PixelTypes.L8, TiffEncodingMode.ColorPalette, TiffCompression.Lzw)]
- [WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffEncodingMode.Rgb, TiffCompression.Deflate)]
- [WithFile(RgbUncompressed, PixelTypes.Rgb24, TiffEncodingMode.Rgb, TiffCompression.None)]
- [WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffEncodingMode.Rgb, TiffCompression.None)]
- [WithFile(RgbUncompressed, PixelTypes.Rgb48, TiffEncodingMode.Rgb, TiffCompression.None)]
- public void TiffEncoder_StripLength(TestImageProvider provider, TiffEncodingMode mode, TiffCompression compression)
+ [WithFile(GrayscaleUncompressed, PixelTypes.L8, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.PackBits)]
+ [WithFile(PaletteDeflateMultistrip, PixelTypes.L8, TiffPhotometricInterpretation.PaletteColor, TiffCompression.Lzw)]
+ [WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffPhotometricInterpretation.Rgb, TiffCompression.Deflate)]
+ [WithFile(RgbUncompressed, PixelTypes.Rgb24, TiffPhotometricInterpretation.Rgb, TiffCompression.None)]
+ [WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffPhotometricInterpretation.Rgb, TiffCompression.None)]
+ [WithFile(RgbUncompressed, PixelTypes.Rgb48, TiffPhotometricInterpretation.Rgb, TiffCompression.None)]
+ public void TiffEncoder_StripLength(TestImageProvider provider, TiffPhotometricInterpretation photometricInterpretation, TiffCompression compression)
where TPixel : unmanaged, IPixel =>
- TestStripLength(provider, mode, compression);
+ TestStripLength(provider, photometricInterpretation, compression);
[Theory]
- [WithFile(Calliphora_BiColorUncompressed, PixelTypes.L8, TiffEncodingMode.BiColor, TiffCompression.CcittGroup3Fax)]
- public void TiffEncoder_StripLength_OutOfBounds(TestImageProvider provider, TiffEncodingMode mode, TiffCompression compression)
+ [WithFile(Calliphora_BiColorUncompressed, PixelTypes.L8, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.CcittGroup3Fax)]
+ public void TiffEncoder_StripLength_OutOfBounds(TestImageProvider provider, TiffPhotometricInterpretation photometricInterpretation, TiffCompression compression)
where TPixel : unmanaged, IPixel =>
- //// CcittGroup3Fax compressed data length can be larger than the original length
- Assert.Throws(() => TestStripLength(provider, mode, compression));
+ //// CcittGroup3Fax compressed data length can be larger than the original length.
+ Assert.Throws(() => TestStripLength(provider, photometricInterpretation, compression));
- private static void TestStripLength(TestImageProvider provider, TiffEncodingMode mode, TiffCompression compression)
+ private static void TestStripLength(TestImageProvider provider, TiffPhotometricInterpretation photometricInterpretation, TiffCompression compression)
where TPixel : unmanaged, IPixel
{
// arrange
- var tiffEncoder = new TiffEncoder() { Mode = mode, Compression = compression };
+ var tiffEncoder = new TiffEncoder() { PhotometricInterpretation = photometricInterpretation, Compression = compression };
using Image input = provider.GetImage();
using var memStream = new MemoryStream();
ExifProfile exifProfileInput = input.Frames.RootFrame.Metadata.ExifProfile;
@@ -384,14 +446,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
TestTiffEncoderCore(
provider,
inputMeta.BitsPerPixel,
- mode,
+ photometricInterpretation,
inputCompression);
}
private static void TestTiffEncoderCore(
TestImageProvider provider,
TiffBitsPerPixel? bitsPerPixel,
- TiffEncodingMode mode,
+ TiffPhotometricInterpretation photometricInterpretation,
TiffCompression compression = TiffCompression.None,
TiffPredictor predictor = TiffPredictor.None,
bool useExactComparer = true,
@@ -402,7 +464,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
using Image image = provider.GetImage();
var encoder = new TiffEncoder
{
- Mode = mode,
+ PhotometricInterpretation = photometricInterpretation,
BitsPerPixel = bitsPerPixel,
Compression = compression,
HorizontalPredictor = predictor
diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs
index 228eec078..25f0521f9 100644
--- a/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs
@@ -222,7 +222,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
Assert.Equal(TiffBitsPerPixel.Bit4, frameMetaInput.BitsPerPixel);
// Save to Tiff
- var tiffEncoder = new TiffEncoder() { Mode = TiffEncodingMode.Rgb };
+ var tiffEncoder = new TiffEncoder() { PhotometricInterpretation = TiffPhotometricInterpretation.Rgb };
using var ms = new MemoryStream();
image.Save(ms, tiffEncoder);
@@ -237,7 +237,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
byte[] encodedImageXmpProfile = rootFrameEncodedImage.Metadata.XmpProfile;
Assert.Equal(TiffBitsPerPixel.Bit4, tiffMetaDataEncodedRootFrame.BitsPerPixel);
- Assert.Equal(TiffCompression.None, (TiffCompression)encodedImageExifProfile.GetValue(ExifTag.Compression).Value);
+ Assert.Equal(TiffCompression.Lzw, (TiffCompression)encodedImageExifProfile.GetValue(ExifTag.Compression).Value);
Assert.Equal(inputMetaData.HorizontalResolution, encodedImageMetaData.HorizontalResolution);
Assert.Equal(inputMetaData.VerticalResolution, encodedImageMetaData.VerticalResolution);