|
|
@ -240,8 +240,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Utils |
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
{ |
|
|
{ |
|
|
int colorPaletteSize = 256 * 3 * 2; |
|
|
int colorPaletteSize = 256 * 3 * 2; |
|
|
using var memoryStream = new MemoryStream(); |
|
|
|
|
|
using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, PngCompressionLevel.Level6); // TODO: make compression level configurable
|
|
|
|
|
|
using IManagedByteBuffer row = this.AllocateRow(image.Width, 1, padding); |
|
|
using IManagedByteBuffer row = this.AllocateRow(image.Width, 1, padding); |
|
|
using IQuantizer<TPixel> frameQuantizer = quantizer.CreatePixelSpecificQuantizer<TPixel>(this.configuration); |
|
|
using IQuantizer<TPixel> frameQuantizer = quantizer.CreatePixelSpecificQuantizer<TPixel>(this.configuration); |
|
|
using IndexedImageFrame<TPixel> quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(image.Frames.RootFrame, image.Bounds()); |
|
|
using IndexedImageFrame<TPixel> quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(image.Frames.RootFrame, image.Bounds()); |
|
|
@ -286,44 +284,59 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Utils |
|
|
Value = palette |
|
|
Value = palette |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
if (compression == TiffEncoderCompression.Deflate) |
|
|
|
|
|
{ |
|
|
|
|
|
return this.WriteDeflateCompressedPalettedRgb(image, quantized, padding); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// No compression.
|
|
|
int bytesWritten = 0; |
|
|
int bytesWritten = 0; |
|
|
for (int y = 0; y < image.Height; y++) |
|
|
for (int y = 0; y < image.Height; y++) |
|
|
{ |
|
|
{ |
|
|
ReadOnlySpan<byte> pixelSpan = quantized.GetPixelRowSpan(y); |
|
|
ReadOnlySpan<byte> pixelSpan = quantized.GetPixelRowSpan(y); |
|
|
|
|
|
this.output.Write(pixelSpan); |
|
|
|
|
|
bytesWritten += pixelSpan.Length; |
|
|
|
|
|
|
|
|
if (compression == TiffEncoderCompression.Deflate) |
|
|
for (int i = 0; i < padding; i++) |
|
|
{ |
|
|
|
|
|
deflateStream.Write(pixelSpan); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
{ |
|
|
// No compression.
|
|
|
this.output.WriteByte(0); |
|
|
this.output.Write(pixelSpan); |
|
|
bytesWritten++; |
|
|
bytesWritten += pixelSpan.Length; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return bytesWritten; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Writes the image data as indices into a color map compressed 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="quantized">The quantized frame.</param>
|
|
|
|
|
|
/// <param name="padding">The padding bytes for each row.</param>
|
|
|
|
|
|
/// <returns>The number of bytes written.</returns>
|
|
|
|
|
|
public int WriteDeflateCompressedPalettedRgb<TPixel>(Image<TPixel> image, IndexedImageFrame<TPixel> quantized, int padding) |
|
|
|
|
|
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++) |
|
|
|
|
|
{ |
|
|
|
|
|
ReadOnlySpan<byte> pixelSpan = quantized.GetPixelRowSpan(y); |
|
|
|
|
|
deflateStream.Write(pixelSpan); |
|
|
|
|
|
|
|
|
for (int i = 0; i < padding; i++) |
|
|
for (int i = 0; i < padding; i++) |
|
|
{ |
|
|
{ |
|
|
if (compression == TiffEncoderCompression.Deflate) |
|
|
deflateStream.WriteByte(0); |
|
|
{ |
|
|
|
|
|
deflateStream.WriteByte(0); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
// no compression.
|
|
|
|
|
|
this.output.WriteByte(0); |
|
|
|
|
|
bytesWritten++; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (compression == TiffEncoderCompression.Deflate) |
|
|
deflateStream.Flush(); |
|
|
{ |
|
|
byte[] buffer = memoryStream.ToArray(); |
|
|
deflateStream.Flush(); |
|
|
this.output.Write(buffer); |
|
|
byte[] buffer = memoryStream.ToArray(); |
|
|
bytesWritten += buffer.Length; |
|
|
this.output.Write(buffer); |
|
|
|
|
|
bytesWritten += buffer.Length; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return bytesWritten; |
|
|
return bytesWritten; |
|
|
} |
|
|
} |
|
|
@ -337,7 +350,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Utils |
|
|
/// <param name="compression">The compression to use.</param>
|
|
|
/// <param name="compression">The compression to use.</param>
|
|
|
/// <returns>The number of bytes written.</returns>
|
|
|
/// <returns>The number of bytes written.</returns>
|
|
|
public int WriteGray<TPixel>(Image<TPixel> image, int padding, TiffEncoderCompression compression) |
|
|
public int WriteGray<TPixel>(Image<TPixel> image, int padding, TiffEncoderCompression compression) |
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
{ |
|
|
{ |
|
|
using IManagedByteBuffer row = this.AllocateRow(image.Width, 1, padding); |
|
|
using IManagedByteBuffer row = this.AllocateRow(image.Width, 1, padding); |
|
|
Span<byte> rowSpan = row.GetSpan(); |
|
|
Span<byte> rowSpan = row.GetSpan(); |
|
|
|