Browse Source

Remove writing padding bytes, this seems not necessary

pull/1570/head
Brian Popow 5 years ago
parent
commit
cff52ba6f5
  1. 15
      src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
  2. 57
      src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs

15
src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs

@ -24,11 +24,6 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// </summary>
internal sealed class TiffEncoderCore : IImageEncoderInternals
{
/// <summary>
/// The amount to pad each row by in bytes.
/// </summary>
private int padding;
/// <summary>
/// Used for allocating memory during processing operations.
/// </summary>
@ -121,10 +116,6 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
this.SetPhotometricInterpretation();
short bpp = (short)this.bitsPerPixel;
int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32);
this.padding = bytesPerLine - (int)(image.Width * (bpp / 8F));
using (var writer = new TiffWriter(stream, this.memoryAllocator, this.configuration))
{
long firstIfdMarker = this.WriteHeader(writer);
@ -172,16 +163,16 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
switch (this.Mode)
{
case TiffEncodingMode.ColorPalette:
imageDataBytes = writer.WritePalettedRgb(image, this.quantizer, this.padding, this.CompressionType, this.compressionLevel, this.useHorizontalPredictor, out colorMap);
imageDataBytes = writer.WritePalettedRgb(image, this.quantizer, this.CompressionType, this.compressionLevel, this.useHorizontalPredictor, out colorMap);
break;
case TiffEncodingMode.Gray:
imageDataBytes = writer.WriteGray(image, this.padding, this.CompressionType, this.compressionLevel, this.useHorizontalPredictor);
imageDataBytes = writer.WriteGray(image, this.CompressionType, this.compressionLevel, this.useHorizontalPredictor);
break;
case TiffEncodingMode.BiColor:
imageDataBytes = writer.WriteBiColor(image, this.CompressionType, this.compressionLevel);
break;
default:
imageDataBytes = writer.WriteRgb(image, this.padding, this.CompressionType, this.compressionLevel, this.useHorizontalPredictor);
imageDataBytes = writer.WriteRgb(image, this.CompressionType, this.compressionLevel, this.useHorizontalPredictor);
break;
}

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

@ -136,15 +136,14 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// </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>
/// <param name="compression">The compression to use.</param>
/// <param name="compressionLevel">The compression level for deflate compression.</param>
/// <param name="useHorizontalPredictor">Indicates if horizontal prediction should be used. Should only be used with deflate compression.</param>
/// <returns>The number of bytes written.</returns>
public int WriteRgb<TPixel>(Image<TPixel> image, int padding, TiffEncoderCompression compression, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor)
public int WriteRgb<TPixel>(Image<TPixel> image, TiffEncoderCompression compression, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor)
where TPixel : unmanaged, IPixel<TPixel>
{
using IManagedByteBuffer row = this.AllocateRow(image.Width, 3, padding);
using IManagedByteBuffer row = this.memoryAllocator.AllocateManagedByteBuffer(image.Width * 3);
Span<byte> rowSpan = row.GetSpan();
if (compression == TiffEncoderCompression.Deflate)
{
@ -284,19 +283,18 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// <typeparam name="TPixel">The pixel data.</typeparam>
/// <param name="image">The image to write to the stream.</param>
/// <param name="quantizer">The quantizer to use.</param>
/// <param name="padding">The padding bytes for each row.</param>
/// <param name="compression">The compression to use.</param>
/// <param name="compressionLevel">The compression level for deflate compression.</param>
/// <param name="useHorizontalPredictor">Indicates if horizontal prediction should be used. Should only be used in combination with deflate or LZW compression.</param>
/// <param name="colorMap">The color map.</param>
/// <returns>The number of bytes written.</returns>
public int WritePalettedRgb<TPixel>(Image<TPixel> image, IQuantizer quantizer, int padding, TiffEncoderCompression compression, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor, out IExifValue colorMap)
public int WritePalettedRgb<TPixel>(Image<TPixel> image, IQuantizer quantizer, TiffEncoderCompression compression, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor, out IExifValue colorMap)
where TPixel : unmanaged, IPixel<TPixel>
{
int colorsPerChannel = 256;
int colorPaletteSize = colorsPerChannel * 3;
int colorPaletteBytes = colorPaletteSize * 2;
using IManagedByteBuffer row = this.AllocateRow(image.Width, 1, padding);
using IManagedByteBuffer row = this.memoryAllocator.AllocateManagedByteBuffer(image.Width);
using IQuantizer<TPixel> frameQuantizer = quantizer.CreatePixelSpecificQuantizer<TPixel>(this.configuration);
using IndexedImageFrame<TPixel> quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(image.Frames.RootFrame, image.Bounds());
using IMemoryOwner<byte> colorPaletteBuffer = this.memoryAllocator.AllocateManagedByteBuffer(colorPaletteBytes);
@ -342,17 +340,17 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
if (compression == TiffEncoderCompression.Deflate)
{
return this.WriteDeflateCompressedPalettedRgb(image, quantized, padding, compressionLevel, useHorizontalPredictor);
return this.WriteDeflateCompressedPalettedRgb(image, quantized, compressionLevel, useHorizontalPredictor);
}
if (compression == TiffEncoderCompression.Lzw)
{
return this.WriteLzwCompressedPalettedRgb(image, quantized, padding, useHorizontalPredictor);
return this.WriteLzwCompressedPalettedRgb(image, quantized, useHorizontalPredictor);
}
if (compression == TiffEncoderCompression.PackBits)
{
return this.WritePackBitsCompressedPalettedRgb(image, quantized, padding);
return this.WritePackBitsCompressedPalettedRgb(image, quantized);
}
// No compression.
@ -362,12 +360,6 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
ReadOnlySpan<byte> pixelSpan = quantized.GetPixelRowSpan(y);
this.output.Write(pixelSpan);
bytesWritten += pixelSpan.Length;
for (int i = 0; i < padding; i++)
{
this.output.WriteByte(0);
bytesWritten++;
}
}
return bytesWritten;
@ -379,11 +371,10 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// <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>
/// <param name="compressionLevel">The compression level for deflate compression.</param>
/// <param name="useHorizontalPredictor">Indicates if horizontal prediction should be used.</param>
/// <returns>The number of bytes written.</returns>
public int WriteDeflateCompressedPalettedRgb<TPixel>(Image<TPixel> image, IndexedImageFrame<TPixel> quantized, int padding, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor)
public int WriteDeflateCompressedPalettedRgb<TPixel>(Image<TPixel> image, IndexedImageFrame<TPixel> quantized, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor)
where TPixel : unmanaged, IPixel<TPixel>
{
using IManagedByteBuffer tmpBuffer = this.memoryAllocator.AllocateManagedByteBuffer(image.Width);
@ -406,11 +397,6 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
{
deflateStream.Write(pixelRow);
}
for (int i = 0; i < padding; i++)
{
deflateStream.WriteByte(0);
}
}
deflateStream.Flush();
@ -427,10 +413,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// <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>
/// <param name="useHorizontalPredictor">Indicates if horizontal prediction should be used.</param>
/// <returns>The number of bytes written.</returns>
public int WriteLzwCompressedPalettedRgb<TPixel>(Image<TPixel> image, IndexedImageFrame<TPixel> quantized, int padding, bool useHorizontalPredictor)
public int WriteLzwCompressedPalettedRgb<TPixel>(Image<TPixel> image, IndexedImageFrame<TPixel> quantized, bool useHorizontalPredictor)
where TPixel : unmanaged, IPixel<TPixel>
{
IMemoryOwner<byte> pixelData = this.memoryAllocator.Allocate<byte>(image.Width * image.Height);
@ -473,34 +458,21 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// <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 WritePackBitsCompressedPalettedRgb<TPixel>(Image<TPixel> image, IndexedImageFrame<TPixel> quantized, int padding)
public int WritePackBitsCompressedPalettedRgb<TPixel>(Image<TPixel> image, IndexedImageFrame<TPixel> quantized)
where TPixel : unmanaged, IPixel<TPixel>
{
// Worst case is that the actual compressed data is larger then the input data. In this case we need 1 additional byte per 127 bytes.
int additionalBytes = ((image.Width * 3) / 127) + 1;
using IManagedByteBuffer compressedRow = this.memoryAllocator.AllocateManagedByteBuffer((image.Width * 3) + additionalBytes, AllocationOptions.Clean);
using IManagedByteBuffer pixelRowWithPadding = this.memoryAllocator.AllocateManagedByteBuffer((image.Width * 3) + padding, AllocationOptions.Clean);
Span<byte> compressedRowSpan = compressedRow.GetSpan();
Span<byte> pixelRowWithPaddingSpan = pixelRowWithPadding.GetSpan();
int bytesWritten = 0;
for (int y = 0; y < image.Height; y++)
{
ReadOnlySpan<byte> pixelSpan = quantized.GetPixelRowSpan(y);
int size;
if (padding != 0)
{
pixelSpan.CopyTo(pixelRowWithPaddingSpan);
size = PackBitsWriter.PackBits(pixelRowWithPaddingSpan, compressedRowSpan);
}
else
{
size = PackBitsWriter.PackBits(pixelSpan, compressedRowSpan);
}
int size = PackBitsWriter.PackBits(pixelSpan, compressedRowSpan);
this.output.Write(compressedRowSpan.Slice(0, size));
bytesWritten += size;
}
@ -513,15 +485,14 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// </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>
/// <param name="compression">The compression to use.</param>
/// <param name="compressionLevel">The compression level for deflate compression.</param>
/// <param name="useHorizontalPredictor">Indicates if horizontal prediction should be used. Should only be used with deflate or lzw compression.</param>
/// <returns>The number of bytes written.</returns>
public int WriteGray<TPixel>(Image<TPixel> image, int padding, TiffEncoderCompression compression, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor)
public int WriteGray<TPixel>(Image<TPixel> image, TiffEncoderCompression compression, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor)
where TPixel : unmanaged, IPixel<TPixel>
{
using IManagedByteBuffer row = this.AllocateRow(image.Width, 1, padding);
using IManagedByteBuffer row = this.memoryAllocator.AllocateManagedByteBuffer(image.Width);
Span<byte> rowSpan = row.GetSpan();
if (compression == TiffEncoderCompression.Deflate)
@ -831,8 +802,6 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
return bytesWritten;
}
private IManagedByteBuffer AllocateRow(int width, int bytesPerPixel, int padding) => this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, padding);
/// <summary>
/// Disposes <see cref="TiffWriter"/> instance, ensuring any unwritten data is flushed.
/// </summary>

Loading…
Cancel
Save