diff --git a/src/ImageSharp/Formats/Png/PngCompressionLevel.cs b/src/ImageSharp/Formats/Png/DeflateCompressionLevel.cs
similarity index 97%
rename from src/ImageSharp/Formats/Png/PngCompressionLevel.cs
rename to src/ImageSharp/Formats/Png/DeflateCompressionLevel.cs
index 7516e0987..9421bb19b 100644
--- a/src/ImageSharp/Formats/Png/PngCompressionLevel.cs
+++ b/src/ImageSharp/Formats/Png/DeflateCompressionLevel.cs
@@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// Provides enumeration of available PNG compression levels.
///
- public enum PngCompressionLevel
+ public enum DeflateCompressionLevel
{
///
/// Level 0. Equivalent to .
diff --git a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
index 2c05019ed..3a453d916 100644
--- a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
@@ -28,9 +28,9 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// Gets the compression level 1-9.
- /// Defaults to .
+ /// Defaults to .
///
- PngCompressionLevel CompressionLevel { get; }
+ DeflateCompressionLevel CompressionLevel { get; }
///
/// Gets the threshold of characters in text metadata, when compression should be used.
diff --git a/src/ImageSharp/Formats/Png/PngEncoder.cs b/src/ImageSharp/Formats/Png/PngEncoder.cs
index e72e8d3d5..b6cac806d 100644
--- a/src/ImageSharp/Formats/Png/PngEncoder.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoder.cs
@@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Formats.Png
public PngFilterMethod? FilterMethod { get; set; }
///
- public PngCompressionLevel CompressionLevel { get; set; } = PngCompressionLevel.DefaultCompression;
+ public DeflateCompressionLevel CompressionLevel { get; set; } = DeflateCompressionLevel.DefaultCompression;
///
public int TextCompressionThreshold { get; set; } = 1024;
diff --git a/src/ImageSharp/Formats/Png/PngEncoderOptions.cs b/src/ImageSharp/Formats/Png/PngEncoderOptions.cs
index 3c17c2463..2b8a6b192 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderOptions.cs
@@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Formats.Png
public PngFilterMethod? FilterMethod { get; }
///
- public PngCompressionLevel CompressionLevel { get; } = PngCompressionLevel.DefaultCompression;
+ public DeflateCompressionLevel CompressionLevel { get; } = DeflateCompressionLevel.DefaultCompression;
///
public int TextCompressionThreshold { get; }
diff --git a/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs b/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs
index 06c6e3dea..5ebbdf1f1 100644
--- a/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs
@@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// The memory allocator to use for buffer allocations.
/// The stream to compress.
/// The compression level.
- public ZlibDeflateStream(MemoryAllocator memoryAllocator, Stream stream, PngCompressionLevel level)
+ public ZlibDeflateStream(MemoryAllocator memoryAllocator, Stream stream, DeflateCompressionLevel level)
{
int compressionLevel = (int)level;
this.rawStream = stream;
diff --git a/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs b/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
index 78cf553d3..c3df04186 100644
--- a/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
+using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Processing.Processors.Quantization;
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
@@ -15,6 +16,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
///
TiffEncoderCompression Compression { get; }
+ ///
+ /// Gets the compression level 1-9 for the deflate compression mode.
+ /// Defaults to .
+ ///
+ DeflateCompressionLevel CompressionLevel { get; }
+
///
/// Gets the encoding mode to use. RGB, RGB with color palette or gray.
///
diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoder.cs b/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
index 0d1821704..479ff470b 100644
--- a/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffEncoder.cs
@@ -4,7 +4,9 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
+
using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Quantization;
@@ -15,25 +17,19 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
///
public class TiffEncoder : IImageEncoder, ITiffEncoderOptions
{
- ///
- /// Gets or sets a value indicating which compression to use.
- ///
+ ///
public TiffEncoderCompression Compression { get; set; } = TiffEncoderCompression.None;
- ///
- /// Gets or sets the encoding mode to use. RGB, RGB with a color palette or gray.
- ///
+ ///
+ public DeflateCompressionLevel CompressionLevel { get; } = DeflateCompressionLevel.DefaultCompression;
+
+ ///
public TiffEncodingMode Mode { get; set; }
- ///
- /// Gets or sets a value indicating whether to use horizontal prediction. This can improve the compression ratio with deflate or lzw compression.
- ///
+ ///
public bool UseHorizontalPredictor { get; set; }
- ///
- /// Gets or sets the quantizer for color images with a palette.
- /// Defaults to OctreeQuantizer.
- ///
+ ///
public IQuantizer Quantizer { get; set; }
///
diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
index 93deca380..277b833a6 100644
--- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
@@ -9,6 +9,7 @@ using System.Threading;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants;
using SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils;
+using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
@@ -51,7 +52,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
///
/// Indicating whether to use horizontal prediction. This can improve the compression ratio with deflate compression.
///
- private bool useHorizontalPredictor;
+ private readonly bool useHorizontalPredictor;
+
+ ///
+ /// Sets the deflate compression level.
+ ///
+ private readonly DeflateCompressionLevel compressionLevel;
///
/// Initializes a new instance of the class.
@@ -65,6 +71,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
this.Mode = options.Mode;
this.quantizer = options.Quantizer ?? KnownQuantizers.Octree;
this.useHorizontalPredictor = options.UseHorizontalPredictor;
+ this.compressionLevel = options.CompressionLevel;
}
///
@@ -165,16 +172,16 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
switch (this.Mode)
{
case TiffEncodingMode.ColorPalette:
- imageDataBytes = writer.WritePalettedRgb(image, this.quantizer, this.padding, this.CompressionType, this.useHorizontalPredictor, out colorMap);
+ imageDataBytes = writer.WritePalettedRgb(image, this.quantizer, this.padding, this.CompressionType, this.compressionLevel, this.useHorizontalPredictor, out colorMap);
break;
case TiffEncodingMode.Gray:
- imageDataBytes = writer.WriteGray(image, this.padding, this.CompressionType, this.useHorizontalPredictor);
+ imageDataBytes = writer.WriteGray(image, this.padding, this.CompressionType, this.compressionLevel, this.useHorizontalPredictor);
break;
case TiffEncodingMode.BiColor:
- imageDataBytes = writer.WriteBiColor(image, this.CompressionType);
+ imageDataBytes = writer.WriteBiColor(image, this.CompressionType, this.compressionLevel);
break;
default:
- imageDataBytes = writer.WriteRgb(image, this.padding, this.CompressionType, this.useHorizontalPredictor);
+ imageDataBytes = writer.WriteRgb(image, this.padding, this.CompressionType, this.compressionLevel, this.useHorizontalPredictor);
break;
}
diff --git a/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs b/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs
index db8bad133..d91de83e6 100644
--- a/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs
+++ b/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs
@@ -138,16 +138,17 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// The image to write to the stream.
/// The padding bytes for each row.
/// The compression to use.
+ /// The compression level for deflate compression.
/// Indicates if horizontal prediction should be used. Should only be used with deflate compression.
/// The number of bytes written.
- public int WriteRgb(Image image, int padding, TiffEncoderCompression compression, bool useHorizontalPredictor)
+ public int WriteRgb(Image image, int padding, TiffEncoderCompression compression, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor)
where TPixel : unmanaged, IPixel
{
using IManagedByteBuffer row = this.AllocateRow(image.Width, 3, padding);
Span rowSpan = row.GetSpan();
if (compression == TiffEncoderCompression.Deflate)
{
- return this.WriteDeflateCompressedRgb(image, rowSpan, useHorizontalPredictor);
+ return this.WriteDeflateCompressedRgb(image, rowSpan, compressionLevel, useHorizontalPredictor);
}
if (compression == TiffEncoderCompression.Lzw)
@@ -179,16 +180,15 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// The pixel data.
/// The image to write to the stream.
/// A Span for a pixel row.
+ /// The compression level for deflate compression.
/// Indicates if horizontal prediction should be used. Should only be used with deflate compression.
/// The number of bytes written.
- private int WriteDeflateCompressedRgb(Image image, Span rowSpan, bool useHorizontalPredictor)
+ private int WriteDeflateCompressedRgb(Image image, Span rowSpan, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor)
where TPixel : unmanaged, IPixel
{
int bytesWritten = 0;
using var memoryStream = new MemoryStream();
-
- // TODO: move zlib compression from png to a common place?
- using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, PngCompressionLevel.Level6); // TODO: make compression level configurable
+ using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, compressionLevel); // TODO: move zlib compression from png to a common place?
for (int y = 0; y < image.Height; y++)
{
@@ -286,10 +286,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// The quantizer to use.
/// The padding bytes for each row.
/// The compression to use.
+ /// The compression level for deflate compression.
/// Indicates if horizontal prediction should be used. Should only be used in combination with deflate or LZW compression.
/// The color map.
/// The number of bytes written.
- public int WritePalettedRgb(Image image, IQuantizer quantizer, int padding, TiffEncoderCompression compression, bool useHorizontalPredictor, out IExifValue colorMap)
+ public int WritePalettedRgb(Image image, IQuantizer quantizer, int padding, TiffEncoderCompression compression, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor, out IExifValue colorMap)
where TPixel : unmanaged, IPixel
{
int colorsPerChannel = 256;
@@ -341,7 +342,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
if (compression == TiffEncoderCompression.Deflate)
{
- return this.WriteDeflateCompressedPalettedRgb(image, quantized, padding, useHorizontalPredictor);
+ return this.WriteDeflateCompressedPalettedRgb(image, quantized, padding, compressionLevel, useHorizontalPredictor);
}
if (compression == TiffEncoderCompression.Lzw)
@@ -379,14 +380,15 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// The image to write to the stream.
/// The quantized frame.
/// The padding bytes for each row.
+ /// The compression level for deflate compression.
/// Indicates if horizontal prediction should be used.
/// The number of bytes written.
- public int WriteDeflateCompressedPalettedRgb(Image image, IndexedImageFrame quantized, int padding, bool useHorizontalPredictor)
+ public int WriteDeflateCompressedPalettedRgb(Image image, IndexedImageFrame quantized, int padding, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor)
where TPixel : unmanaged, IPixel
{
using IManagedByteBuffer tmpBuffer = this.memoryAllocator.AllocateManagedByteBuffer(image.Width);
using var memoryStream = new MemoryStream();
- using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, PngCompressionLevel.Level6); // TODO: make compression level configurable
+ using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, compressionLevel);
int bytesWritten = 0;
for (int y = 0; y < image.Height; y++)
@@ -513,9 +515,10 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// The image to write to the stream.
/// The padding bytes for each row.
/// The compression to use.
+ /// The compression level for deflate compression.
/// Indicates if horizontal prediction should be used. Should only be used with deflate or lzw compression.
/// The number of bytes written.
- public int WriteGray(Image image, int padding, TiffEncoderCompression compression, bool useHorizontalPredictor)
+ public int WriteGray(Image image, int padding, TiffEncoderCompression compression, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor)
where TPixel : unmanaged, IPixel
{
using IManagedByteBuffer row = this.AllocateRow(image.Width, 1, padding);
@@ -523,7 +526,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
if (compression == TiffEncoderCompression.Deflate)
{
- return this.WriteGrayDeflateCompressed(image, rowSpan, useHorizontalPredictor);
+ return this.WriteGrayDeflateCompressed(image, rowSpan, compressionLevel, useHorizontalPredictor);
}
if (compression == TiffEncoderCompression.Lzw)
@@ -553,16 +556,15 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
///
/// The image to write to the stream.
/// A span of a row of pixels.
+ /// The compression level for deflate compression.
/// Indicates if horizontal prediction should be used.
/// The number of bytes written.
- private int WriteGrayDeflateCompressed(Image image, Span rowSpan, bool useHorizontalPredictor)
+ private int WriteGrayDeflateCompressed(Image image, Span rowSpan, DeflateCompressionLevel compressionLevel, bool useHorizontalPredictor)
where TPixel : unmanaged, IPixel
{
int bytesWritten = 0;
using var memoryStream = new MemoryStream();
-
- // TODO: move zlib compression from png to a common place?
- using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, PngCompressionLevel.Level6); // TODO: make compression level configurable
+ using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, compressionLevel); // TODO: move zlib compression from png to a common place?
for (int y = 0; y < image.Height; y++)
{
@@ -656,8 +658,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// The pixel data.
/// The image to write to the stream.
/// The compression to use.
+ /// The compression level for deflate compression.
/// The number of bytes written.
- public int WriteBiColor(Image image, TiffEncoderCompression compression)
+ public int WriteBiColor(Image image, TiffEncoderCompression compression, DeflateCompressionLevel compressionLevel)
where TPixel : unmanaged, IPixel
{
int padding = image.Width % 8 == 0 ? 0 : 1;
@@ -674,7 +677,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
if (compression == TiffEncoderCompression.Deflate)
{
- return this.WriteBiColorDeflate(imageBlackWhite, pixelRowAsGraySpan, outputRow);
+ return this.WriteBiColorDeflate(imageBlackWhite, pixelRowAsGraySpan, outputRow, compressionLevel);
}
if (compression == TiffEncoderCompression.PackBits)
@@ -734,12 +737,13 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
/// The image to write to the stream.
/// A span for converting a pixel row to gray.
/// A span which will be used to store the output pixels.
+ /// The compression level for deflate compression.
/// The number of bytes written.
- public int WriteBiColorDeflate(Image image, Span pixelRowAsGraySpan, Span outputRow)
+ public int WriteBiColorDeflate(Image image, Span pixelRowAsGraySpan, Span outputRow, DeflateCompressionLevel compressionLevel)
where TPixel : unmanaged, IPixel
{
using var memoryStream = new MemoryStream();
- using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, PngCompressionLevel.Level6); // TODO: make compression level configurable
+ using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, compressionLevel);
int bytesWritten = 0;
for (int y = 0; y < image.Height; y++)
diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs
index 11bab17fb..5e062a649 100644
--- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs
@@ -62,19 +62,19 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
///
/// All types except Palette
///
- public static readonly TheoryData CompressionLevels
- = new TheoryData
+ public static readonly TheoryData CompressionLevels
+ = new TheoryData
{
- PngCompressionLevel.Level0,
- PngCompressionLevel.Level1,
- PngCompressionLevel.Level2,
- PngCompressionLevel.Level3,
- PngCompressionLevel.Level4,
- PngCompressionLevel.Level5,
- PngCompressionLevel.Level6,
- PngCompressionLevel.Level7,
- PngCompressionLevel.Level8,
- PngCompressionLevel.Level9,
+ DeflateCompressionLevel.Level0,
+ DeflateCompressionLevel.Level1,
+ DeflateCompressionLevel.Level2,
+ DeflateCompressionLevel.Level3,
+ DeflateCompressionLevel.Level4,
+ DeflateCompressionLevel.Level5,
+ DeflateCompressionLevel.Level6,
+ DeflateCompressionLevel.Level7,
+ DeflateCompressionLevel.Level8,
+ DeflateCompressionLevel.Level9,
};
public static readonly TheoryData PaletteSizes = new TheoryData
@@ -157,7 +157,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
[Theory]
[WithTestPatternImages(nameof(CompressionLevels), 24, 24, PixelTypes.Rgba32)]
- public void WorksWithAllCompressionLevels(TestImageProvider provider, PngCompressionLevel compressionLevel)
+ public void WorksWithAllCompressionLevels(TestImageProvider provider, DeflateCompressionLevel compressionLevel)
where TPixel : unmanaged, IPixel
{
foreach (PngInterlaceMode interlaceMode in InterlaceMode)
@@ -573,7 +573,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
PngFilterMethod pngFilterMethod,
PngBitDepth bitDepth,
PngInterlaceMode interlaceMode,
- PngCompressionLevel compressionLevel = PngCompressionLevel.DefaultCompression,
+ DeflateCompressionLevel compressionLevel = DeflateCompressionLevel.DefaultCompression,
int paletteSize = 255,
bool appendPngColorType = false,
bool appendPngFilterMethod = false,
diff --git a/tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs
index 692f92c9f..441328dfe 100644
--- a/tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs
@@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.Compression
Stream compressedStream = new MemoryStream();
using (Stream uncompressedStream = new MemoryStream(data),
- deflateStream = new ZlibDeflateStream(Configuration.Default.MemoryAllocator, compressedStream, ImageSharp.Formats.Png.PngCompressionLevel.Level6))
+ deflateStream = new ZlibDeflateStream(Configuration.Default.MemoryAllocator, compressedStream, ImageSharp.Formats.Png.DeflateCompressionLevel.Level6))
{
uncompressedStream.CopyTo(deflateStream);
}
diff --git a/tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs b/tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs
index 4e6b002d0..79bfdc054 100644
--- a/tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs
+++ b/tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs
@@ -138,7 +138,7 @@ namespace SixLabors.ImageSharp.Tests
public async Task SaveAsync_WithNonSeekableStream_IsCancellable()
{
using var image = new Image(4000, 4000);
- var encoder = new PngEncoder() { CompressionLevel = PngCompressionLevel.BestCompression };
+ var encoder = new PngEncoder() { CompressionLevel = DeflateCompressionLevel.BestCompression };
using var stream = new MemoryStream();
var asyncStream = new AsyncStreamWrapper(stream, () => false);
var cts = new CancellationTokenSource();