diff --git a/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs b/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
index 98efa52cdc..dcb8a5c440 100644
--- a/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Formats.Tiff
@@ -8,5 +8,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff
///
public interface ITiffEncoderOptions
{
+ ///
+ /// Gets the number of bits per pixel.
+ ///
+ TiffBitsPerPixel? BitsPerPixel { get; }
}
}
diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs
index 57a6eda5f3..502c2e425c 100644
--- a/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs
@@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
public enum TiffBitsPerPixel
{
///
- /// 8 bits per pixel. Each pixel consists of 1 byte.
+ /// 8 bits per pixel, grayscale image. Each pixel consists of 1 byte.
///
Pixel8 = 8,
diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoder.cs b/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
index 17ed52182a..881b3cc4ee 100644
--- a/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
@@ -14,6 +14,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff
///
public class TiffEncoder : IImageEncoder, ITiffEncoderOptions
{
+ ///
+ /// Gets or sets the number of bits per pixel. 8 bit implies a grayscale image.
+ ///
+ public TiffBitsPerPixel? BitsPerPixel { get; set; }
+
///
public void Encode(Image image, Stream stream)
where TPixel : unmanaged, IPixel
diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
index 10d22b25b8..d81acf6c6a 100644
--- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
@@ -47,12 +47,21 @@ namespace SixLabors.ImageSharp.Formats.Tiff
public TiffEncoderCore(ITiffEncoderOptions options, MemoryAllocator memoryAllocator)
{
this.memoryAllocator = memoryAllocator;
+
+ if (options.BitsPerPixel == TiffBitsPerPixel.Pixel8)
+ {
+ this.PhotometricInterpretation = TiffPhotometricInterpretation.BlackIsZero;
+ }
+ else
+ {
+ this.PhotometricInterpretation = TiffPhotometricInterpretation.Rgb;
+ }
}
///
- /// Gets or sets the photometric interpretation implementation to use when encoding the image.
+ /// Gets the photometric interpretation implementation to use when encoding the image.
///
- public TiffColorType ColorType { get; set; }
+ private TiffPhotometricInterpretation PhotometricInterpretation { get; }
///
/// Gets or sets the compression implementation to use when encoding the image.
@@ -123,14 +132,22 @@ namespace SixLabors.ImageSharp.Formats.Tiff
// Write the image bytes to the steam.
var imageDataStart = (uint)writer.Position;
- int imageData = writer.WriteRgbImageData(image, this.padding);
+ int imageDataBytes;
+ if (this.PhotometricInterpretation == TiffPhotometricInterpretation.Rgb)
+ {
+ imageDataBytes = writer.WriteRgbImageData(image, this.padding);
+ }
+ else
+ {
+ imageDataBytes = writer.WriteGrayImageData(image, this.padding);
+ }
// Write info's about the image to the stream.
- this.AddImageFormat(image, ifdEntries, imageDataStart, imageData);
+ this.AddImageFormat(image, ifdEntries, imageDataStart, imageDataBytes);
writer.WriteMarker(ifdOffset, (uint)writer.Position);
long nextIfdMarker = this.WriteIfd(writer, ifdEntries);
- return nextIfdMarker + imageData;
+ return nextIfdMarker + imageDataBytes;
}
///
@@ -211,9 +228,10 @@ namespace SixLabors.ImageSharp.Formats.Tiff
Value = (uint)image.Height
};
+ ushort[] bitsPerSampleValue = this.PhotometricInterpretation == TiffPhotometricInterpretation.Rgb ? new ushort[] { 8, 8, 8 } : new ushort[] { 8 };
var bitPerSample = new ExifShortArray(ExifTagValue.BitsPerSample)
{
- Value = new ushort[] { 8, 8, 8 }
+ Value = bitsPerSampleValue
};
var compression = new ExifShort(ExifTagValue.Compression)
@@ -224,8 +242,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
var photometricInterpretation = new ExifShort(ExifTagValue.PhotometricInterpretation)
{
- // TODO: only rgb for now.
- Value = (ushort)TiffPhotometricInterpretation.Rgb
+ Value = (ushort)this.PhotometricInterpretation
};
var stripOffsets = new ExifLongArray(ExifTagValue.StripOffsets)
diff --git a/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs b/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs
index 1908d38ae8..7578c82135 100644
--- a/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs
+++ b/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs
@@ -145,6 +145,28 @@ namespace SixLabors.ImageSharp.Formats.Tiff
return image.Width * image.Height * 3;
}
+ ///
+ /// Writes the image data as 8 bit gray to the stream.
+ ///
+ /// The pixel data.
+ /// The image to write to the stream.
+ /// The padding bytes for each row.
+ /// The number of bytes written
+ public int WriteGrayImageData(Image image, int padding)
+ where TPixel : unmanaged, IPixel
+ {
+ using IManagedByteBuffer row = this.AllocateRow(image.Width, 1, padding);
+ Span rowSpan = row.GetSpan();
+ for (int y = 0; y < image.Height; y++)
+ {
+ Span pixelRow = image.GetPixelRowSpan(y);
+ PixelOperations.Instance.ToL8Bytes(this.configuration, pixelRow, rowSpan, pixelRow.Length);
+ this.output.Write(rowSpan);
+ }
+
+ return image.Width * image.Height;
+ }
+
private IManagedByteBuffer AllocateRow(int width, int bytesPerPixel, int padding) => this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, padding);
///