Browse Source

Split up WriteBiColor in Deflate and no compression

pull/1570/head
Brian Popow 6 years ago
parent
commit
3f612b736f
  1. 82
      src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs

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

@ -369,30 +369,33 @@ namespace SixLabors.ImageSharp.Formats.Tiff
{
int padding = image.Width % 8 == 0 ? 0 : 1;
int bytesPerRow = (image.Width / 8) + padding;
using IMemoryOwner<L8> rowL8 = this.memoryAllocator.Allocate<L8>(image.Width);
using IMemoryOwner<L8> pixelRowAsGray = this.memoryAllocator.Allocate<L8>(image.Width);
using IManagedByteBuffer row = this.memoryAllocator.AllocateManagedByteBuffer(bytesPerRow, AllocationOptions.Clean);
using var memoryStream = new MemoryStream();
using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, PngCompressionLevel.Level6); // TODO: make compression level configurable
Span<byte> rowSpan = row.GetSpan();
Span<L8> rowL8Span = rowL8.GetSpan();
Span<byte> outputRow = row.GetSpan();
Span<L8> pixelRowAsGraySpan = pixelRowAsGray.GetSpan();
// Convert image to black and white.
using Image<TPixel> imageClone = image.Clone();
imageClone.Mutate(img => img.BinaryDither(default(ErrorDither)));
if (compression == TiffEncoderCompression.Deflate)
{
return this.WriteBiColorDeflate(image, pixelRowAsGraySpan, outputRow);
}
int bytesWritten = 0;
for (int y = 0; y < image.Height; y++)
{
int bitIndex = 0;
int byteIndex = 0;
Span<TPixel> pixelRow = imageClone.GetPixelRowSpan(y);
PixelOperations<TPixel>.Instance.ToL8(this.configuration, pixelRow, rowL8Span);
PixelOperations<TPixel>.Instance.ToL8(this.configuration, pixelRow, pixelRowAsGraySpan);
for (int x = 0; x < pixelRow.Length; x++)
{
int shift = 7 - bitIndex;
if (rowL8Span[x].PackedValue == 255)
if (pixelRowAsGraySpan[x].PackedValue == 255)
{
rowSpan[byteIndex] |= (byte)(1 << shift);
outputRow[byteIndex] |= (byte)(1 << shift);
}
bitIndex++;
@ -403,27 +406,62 @@ namespace SixLabors.ImageSharp.Formats.Tiff
}
}
if (compression == TiffEncoderCompression.Deflate)
{
deflateStream.Write(row);
}
else
{
this.output.Write(row);
bytesWritten += row.Length();
}
this.output.Write(row);
bytesWritten += row.Length();
row.Clear();
}
if (compression == TiffEncoderCompression.Deflate)
return bytesWritten;
}
/// <summary>
/// Writes the image data as 1 bit black and white with deflate compression to the stream.
/// </summary>
/// <typeparam name="TPixel">The pixel data.</typeparam>
/// <param name="image">The image to write to the stream.</param>
/// <param name="pixelRowAsGraySpan">A span for converting a pixel row to gray.</param>
/// <param name="outputRow">A span which will be used to store the output pixels.</param>
/// <returns>The number of bytes written.</returns>
public int WriteBiColorDeflate<TPixel>(Image<TPixel> image, Span<L8> pixelRowAsGraySpan, Span<byte> outputRow)
where TPixel : unmanaged, IPixel<TPixel>
{
using var memoryStream = new MemoryStream();
using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, PngCompressionLevel.Level6); // TODO: make compression level configurable
int bytesWritten = 0;
for (int y = 0; y < image.Height; y++)
{
deflateStream.Flush();
byte[] buffer = memoryStream.ToArray();
this.output.Write(buffer);
bytesWritten += buffer.Length;
int bitIndex = 0;
int byteIndex = 0;
Span<TPixel> pixelRow = image.GetPixelRowSpan(y);
PixelOperations<TPixel>.Instance.ToL8(this.configuration, pixelRow, pixelRowAsGraySpan);
for (int x = 0; x < pixelRow.Length; x++)
{
int shift = 7 - bitIndex;
if (pixelRowAsGraySpan[x].PackedValue == 255)
{
outputRow[byteIndex] |= (byte)(1 << shift);
}
bitIndex++;
if (bitIndex == 8)
{
byteIndex++;
bitIndex = 0;
}
}
deflateStream.Write(outputRow);
outputRow.Clear();
}
deflateStream.Flush();
byte[] buffer = memoryStream.ToArray();
this.output.Write(buffer);
bytesWritten += buffer.Length;
return bytesWritten;
}

Loading…
Cancel
Save