Browse Source

Add support for writing 8bit gray tiff images

pull/1570/head
Brian Popow 5 years ago
parent
commit
d90c17d0cd
  1. 6
      src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
  2. 2
      src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs
  3. 5
      src/ImageSharp/Formats/Tiff/TiffEncoder.cs
  4. 33
      src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
  5. 22
      src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs

6
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
/// </summary>
public interface ITiffEncoderOptions
{
/// <summary>
/// Gets the number of bits per pixel.
/// </summary>
TiffBitsPerPixel? BitsPerPixel { get; }
}
}

2
src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs

@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
public enum TiffBitsPerPixel
{
/// <summary>
/// 8 bits per pixel. Each pixel consists of 1 byte.
/// 8 bits per pixel, grayscale image. Each pixel consists of 1 byte.
/// </summary>
Pixel8 = 8,

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

@ -14,6 +14,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// </summary>
public class TiffEncoder : IImageEncoder, ITiffEncoderOptions
{
/// <summary>
/// Gets or sets the number of bits per pixel. 8 bit implies a grayscale image.
/// </summary>
public TiffBitsPerPixel? BitsPerPixel { get; set; }
/// <inheritdoc/>
public void Encode<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>

33
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;
}
}
/// <summary>
/// Gets or sets the photometric interpretation implementation to use when encoding the image.
/// Gets the photometric interpretation implementation to use when encoding the image.
/// </summary>
public TiffColorType ColorType { get; set; }
private TiffPhotometricInterpretation PhotometricInterpretation { get; }
/// <summary>
/// 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;
}
/// <summary>
@ -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)

22
src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs

@ -145,6 +145,28 @@ namespace SixLabors.ImageSharp.Formats.Tiff
return image.Width * image.Height * 3;
}
/// <summary>
/// Writes the image data as 8 bit gray to the stream.
/// </summary>
/// <typeparam name="TPixel">The pixel data.</typeparam>
/// <param name="image">The image to write to the stream.</param>
/// <param name="padding">The padding bytes for each row.</param>
/// <returns>The number of bytes written</returns>
public int WriteGrayImageData<TPixel>(Image<TPixel> image, int padding)
where TPixel : unmanaged, IPixel<TPixel>
{
using IManagedByteBuffer row = this.AllocateRow(image.Width, 1, padding);
Span<byte> rowSpan = row.GetSpan();
for (int y = 0; y < image.Height; y++)
{
Span<TPixel> pixelRow = image.GetPixelRowSpan(y);
PixelOperations<TPixel>.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);
/// <summary>

Loading…
Cancel
Save