diff --git a/src/ImageSharp/Formats/Exr/Compression/Compressors/NoneExrCompressor.cs b/src/ImageSharp/Formats/Exr/Compression/Compressors/NoneExrCompressor.cs index 40ee81cf03..cd9bec6131 100644 --- a/src/ImageSharp/Formats/Exr/Compression/Compressors/NoneExrCompressor.cs +++ b/src/ImageSharp/Formats/Exr/Compression/Compressors/NoneExrCompressor.cs @@ -8,8 +8,8 @@ namespace SixLabors.ImageSharp.Formats.Exr.Compression.Compressors; internal class NoneExrCompressor : ExrBaseCompressor { - public NoneExrCompressor(Stream output, MemoryAllocator allocator, uint bytesPerBlock) - : base(output, allocator, bytesPerBlock) + public NoneExrCompressor(Stream output, MemoryAllocator allocator, uint bytesPerBlock, uint bytesPerRow) + : base(output, allocator, bytesPerBlock, bytesPerRow) { } @@ -17,12 +17,7 @@ internal class NoneExrCompressor : ExrBaseCompressor public override ExrCompression Method => ExrCompression.Zip; /// - public override void Initialize(int rowsPerBlock) - { - } - - /// - public override uint CompressRowBlock(Span rows, int height) + public override uint CompressRowBlock(Span rows, int rowCount) { this.Output.Write(rows); return (uint)rows.Length; diff --git a/src/ImageSharp/Formats/Exr/Compression/Compressors/ZipExrCompressor.cs b/src/ImageSharp/Formats/Exr/Compression/Compressors/ZipExrCompressor.cs index 17203b6ba3..6b82b70777 100644 --- a/src/ImageSharp/Formats/Exr/Compression/Compressors/ZipExrCompressor.cs +++ b/src/ImageSharp/Formats/Exr/Compression/Compressors/ZipExrCompressor.cs @@ -15,8 +15,8 @@ internal class ZipExrCompressor : ExrBaseCompressor private readonly System.Buffers.IMemoryOwner buffer; - public ZipExrCompressor(Stream output, MemoryAllocator allocator, uint bytesPerBlock, DeflateCompressionLevel compressionLevel) - : base(output, allocator, bytesPerBlock) + public ZipExrCompressor(Stream output, MemoryAllocator allocator, uint bytesPerBlock, uint bytesPerRow, DeflateCompressionLevel compressionLevel) + : base(output, allocator, bytesPerBlock, bytesPerRow) { this.compressionLevel = compressionLevel; this.buffer = allocator.Allocate((int)bytesPerBlock); @@ -26,12 +26,7 @@ internal class ZipExrCompressor : ExrBaseCompressor public override ExrCompression Method => ExrCompression.Zip; /// - public override void Initialize(int rowsPerBlock) - { - } - - /// - public override uint CompressRowBlock(Span rows, int height) + public override uint CompressRowBlock(Span rows, int rowCount) { // Re-oder pixel values. int n = rows.Length; diff --git a/src/ImageSharp/Formats/Exr/Compression/Decompressors/B44ExrCompression.cs b/src/ImageSharp/Formats/Exr/Compression/Decompressors/B44ExrCompression.cs index 1c6afdfd91..bf6d9929e2 100644 --- a/src/ImageSharp/Formats/Exr/Compression/Decompressors/B44ExrCompression.cs +++ b/src/ImageSharp/Formats/Exr/Compression/Decompressors/B44ExrCompression.cs @@ -12,28 +12,26 @@ internal class B44ExrCompression : ExrBaseDecompressor { private readonly int width; - private readonly int height; - private readonly uint rowsPerBlock; private readonly int channelCount; - private byte[] scratch = new byte[14]; + private readonly byte[] scratch = new byte[14]; private ushort[] s = new ushort[16]; - private IMemoryOwner tmpBuffer; + private readonly IMemoryOwner tmpBuffer; - public B44ExrCompression(MemoryAllocator allocator, uint bytesPerBlock, int width, int height, uint rowsPerBlock, int channelCount) - : base(allocator, bytesPerBlock) + public B44ExrCompression(MemoryAllocator allocator, uint bytesPerBlock, uint bytesPerRow, uint rowsPerBlock, int width, int channelCount) + : base(allocator, bytesPerBlock, bytesPerRow) { this.width = width; - this.height = height; this.rowsPerBlock = rowsPerBlock; this.channelCount = channelCount; this.tmpBuffer = allocator.Allocate((int)(width * rowsPerBlock * channelCount)); } + /// public override void Decompress(BufferedReadStream stream, uint compressedBytes, Span buffer) { Span outputBuffer = MemoryMarshal.Cast(buffer); @@ -187,5 +185,6 @@ internal class B44ExrCompression : ExrBaseDecompressor } } + /// protected override void Dispose(bool disposing) => this.tmpBuffer.Dispose(); } diff --git a/src/ImageSharp/Formats/Exr/Compression/Decompressors/NoneExrCompression.cs b/src/ImageSharp/Formats/Exr/Compression/Decompressors/NoneExrCompression.cs index 75bf67cb24..26c69db8c6 100644 --- a/src/ImageSharp/Formats/Exr/Compression/Decompressors/NoneExrCompression.cs +++ b/src/ImageSharp/Formats/Exr/Compression/Decompressors/NoneExrCompression.cs @@ -8,14 +8,16 @@ namespace SixLabors.ImageSharp.Formats.Exr.Compression.Decompressors; internal class NoneExrCompression : ExrBaseDecompressor { - public NoneExrCompression(MemoryAllocator allocator, uint bytesPerBlock) - : base(allocator, bytesPerBlock) + public NoneExrCompression(MemoryAllocator allocator, uint bytesPerBlock, uint bytesPerRow) + : base(allocator, bytesPerBlock, bytesPerRow) { } + /// public override void Decompress(BufferedReadStream stream, uint compressedBytes, Span buffer) => stream.Read(buffer, 0, Math.Min(buffer.Length, (int)this.BytesPerBlock)); + /// protected override void Dispose(bool disposing) { } diff --git a/src/ImageSharp/Formats/Exr/Compression/Decompressors/RunLengthExrCompression.cs b/src/ImageSharp/Formats/Exr/Compression/Decompressors/RunLengthExrCompression.cs index bc5a9a5579..12f5fc8ab6 100644 --- a/src/ImageSharp/Formats/Exr/Compression/Decompressors/RunLengthExrCompression.cs +++ b/src/ImageSharp/Formats/Exr/Compression/Decompressors/RunLengthExrCompression.cs @@ -13,9 +13,10 @@ internal class RunLengthExrCompression : ExrBaseDecompressor private readonly ushort[] s = new ushort[16]; - public RunLengthExrCompression(MemoryAllocator allocator, uint uncompressedBytes) - : base(allocator, uncompressedBytes) => this.tmpBuffer = allocator.Allocate((int)uncompressedBytes); + public RunLengthExrCompression(MemoryAllocator allocator, uint bytesPerBlock, uint bytesPerRow) + : base(allocator, bytesPerBlock, bytesPerRow) => this.tmpBuffer = allocator.Allocate((int)bytesPerBlock); + /// public override void Decompress(BufferedReadStream stream, uint compressedBytes, Span buffer) { Span uncompressed = this.tmpBuffer.GetSpan(); @@ -78,5 +79,6 @@ internal class RunLengthExrCompression : ExrBaseDecompressor return (byte)nextByte; } + /// protected override void Dispose(bool disposing) => this.tmpBuffer.Dispose(); } diff --git a/src/ImageSharp/Formats/Exr/Compression/Decompressors/ZipExrCompression.cs b/src/ImageSharp/Formats/Exr/Compression/Decompressors/ZipExrCompression.cs index 95d4c03137..5424634523 100644 --- a/src/ImageSharp/Formats/Exr/Compression/Decompressors/ZipExrCompression.cs +++ b/src/ImageSharp/Formats/Exr/Compression/Decompressors/ZipExrCompression.cs @@ -13,9 +13,10 @@ internal class ZipExrCompression : ExrBaseDecompressor { private readonly IMemoryOwner tmpBuffer; - public ZipExrCompression(MemoryAllocator allocator, uint bytesPerBlock) - : base(allocator, bytesPerBlock) => this.tmpBuffer = allocator.Allocate((int)bytesPerBlock); + public ZipExrCompression(MemoryAllocator allocator, uint bytesPerBlock, uint bytesPerRow) + : base(allocator, bytesPerBlock, bytesPerRow) => this.tmpBuffer = allocator.Allocate((int)bytesPerBlock); + /// public override void Decompress(BufferedReadStream stream, uint compressedBytes, Span buffer) { Span uncompressed = this.tmpBuffer.GetSpan(); @@ -52,5 +53,6 @@ internal class ZipExrCompression : ExrBaseDecompressor Interleave(uncompressed, (uint)totalRead, buffer); } + /// protected override void Dispose(bool disposing) => this.tmpBuffer.Dispose(); } diff --git a/src/ImageSharp/Formats/Exr/Compression/ExrBaseCompression.cs b/src/ImageSharp/Formats/Exr/Compression/ExrBaseCompression.cs index e510135c2c..57e6b2a26c 100644 --- a/src/ImageSharp/Formats/Exr/Compression/ExrBaseCompression.cs +++ b/src/ImageSharp/Formats/Exr/Compression/ExrBaseCompression.cs @@ -9,10 +9,11 @@ internal abstract class ExrBaseCompression : IDisposable { private bool isDisposed; - protected ExrBaseCompression(MemoryAllocator allocator, uint bytesPerBlock) + protected ExrBaseCompression(MemoryAllocator allocator, uint bytesPerBlock, uint bytesPerRow) { this.Allocator = allocator; this.BytesPerBlock = bytesPerBlock; + this.BytesPerRow = bytesPerRow; } /// @@ -28,7 +29,7 @@ internal abstract class ExrBaseCompression : IDisposable /// /// Gets the bytes per row. /// - public int BytesPerRow { get; } + public uint BytesPerRow { get; } /// /// Gets the uncompressed bytes per block. diff --git a/src/ImageSharp/Formats/Exr/Compression/ExrBaseDecompressor.cs b/src/ImageSharp/Formats/Exr/Compression/ExrBaseDecompressor.cs index 0dd7d01108..1bbf36d768 100644 --- a/src/ImageSharp/Formats/Exr/Compression/ExrBaseDecompressor.cs +++ b/src/ImageSharp/Formats/Exr/Compression/ExrBaseDecompressor.cs @@ -8,8 +8,8 @@ namespace SixLabors.ImageSharp.Formats.Exr.Compression; internal abstract class ExrBaseDecompressor : ExrBaseCompression { - protected ExrBaseDecompressor(MemoryAllocator allocator, uint bytesPerBlock) - : base(allocator, bytesPerBlock) + protected ExrBaseDecompressor(MemoryAllocator allocator, uint bytesPerBlock, uint bytesPerRow) + : base(allocator, bytesPerBlock, bytesPerRow) { } diff --git a/src/ImageSharp/Formats/Exr/Compression/ExrCompressorFactory.cs b/src/ImageSharp/Formats/Exr/Compression/ExrCompressorFactory.cs index a87372748a..24f396e16f 100644 --- a/src/ImageSharp/Formats/Exr/Compression/ExrCompressorFactory.cs +++ b/src/ImageSharp/Formats/Exr/Compression/ExrCompressorFactory.cs @@ -14,19 +14,18 @@ internal static class ExrCompressorFactory ExrCompression method, MemoryAllocator allocator, Stream output, - int width, - int height, uint bytesPerBlock, - uint rowsPerBlock, - int channelCount, + uint bytesPerRow, DeflateCompressionLevel compressionLevel = DeflateCompressionLevel.DefaultCompression) { switch (method) { case ExrCompression.None: - return new NoneExrCompressor(output, allocator, bytesPerBlock); + return new NoneExrCompressor(output, allocator, bytesPerBlock, bytesPerRow); case ExrCompression.Zips: - return new ZipExrCompressor(output, allocator, bytesPerBlock, compressionLevel); + return new ZipExrCompressor(output, allocator, bytesPerBlock, bytesPerRow, compressionLevel); + case ExrCompression.Zip: + return new ZipExrCompressor(output, allocator, bytesPerBlock, bytesPerRow, compressionLevel); default: throw ExrThrowHelper.NotSupportedCompressor(method.ToString()); diff --git a/src/ImageSharp/Formats/Exr/Compression/ExrDecompressorFactory.cs b/src/ImageSharp/Formats/Exr/Compression/ExrDecompressorFactory.cs index fb620e9854..2696a289cd 100644 --- a/src/ImageSharp/Formats/Exr/Compression/ExrDecompressorFactory.cs +++ b/src/ImageSharp/Formats/Exr/Compression/ExrDecompressorFactory.cs @@ -13,23 +13,23 @@ internal static class ExrDecompressorFactory ExrCompression method, MemoryAllocator memoryAllocator, int width, - int height, uint bytesPerBlock, + uint bytesPerRow, uint rowsPerBlock, int channelCount) { switch (method) { case ExrCompression.None: - return new NoneExrCompression(memoryAllocator, bytesPerBlock); + return new NoneExrCompression(memoryAllocator, bytesPerBlock, bytesPerRow); case ExrCompression.Zips: - return new ZipExrCompression(memoryAllocator, bytesPerBlock); + return new ZipExrCompression(memoryAllocator, bytesPerBlock, bytesPerRow); case ExrCompression.Zip: - return new ZipExrCompression(memoryAllocator, bytesPerBlock); + return new ZipExrCompression(memoryAllocator, bytesPerBlock, bytesPerRow); case ExrCompression.RunLengthEncoded: - return new RunLengthExrCompression(memoryAllocator, bytesPerBlock); + return new RunLengthExrCompression(memoryAllocator, bytesPerBlock, bytesPerRow); case ExrCompression.B44: - return new B44ExrCompression(memoryAllocator, bytesPerBlock, width, height, rowsPerBlock, channelCount); + return new B44ExrCompression(memoryAllocator, bytesPerBlock, bytesPerRow, rowsPerBlock, width, channelCount); default: throw ExrThrowHelper.NotSupportedDecompressor(nameof(method)); } diff --git a/src/ImageSharp/Formats/Exr/ExrBaseCompressor.cs b/src/ImageSharp/Formats/Exr/ExrBaseCompressor.cs index cf547eddb9..1f464ec675 100644 --- a/src/ImageSharp/Formats/Exr/ExrBaseCompressor.cs +++ b/src/ImageSharp/Formats/Exr/ExrBaseCompressor.cs @@ -13,9 +13,10 @@ internal abstract class ExrBaseCompressor : ExrBaseCompression /// /// The output stream to write the compressed image to. /// The memory allocator. - /// Bytes per block. - protected ExrBaseCompressor(Stream output, MemoryAllocator allocator, uint bytesPerBlock) - : base(allocator, bytesPerBlock) + /// Bytes per row block. + /// Bytes per pixel row. + protected ExrBaseCompressor(Stream output, MemoryAllocator allocator, uint bytesPerBlock, uint bytesPerRow) + : base(allocator, bytesPerBlock, bytesPerRow) => this.Output = output; /// @@ -28,17 +29,11 @@ internal abstract class ExrBaseCompressor : ExrBaseCompression /// public Stream Output { get; } - /// - /// Does any initialization required for the compression. - /// - /// The number of rows per block. - public abstract void Initialize(int rowsPerBlock); - /// /// Compresses a block of rows of the image. /// /// Image rows to compress. - /// Image height. + /// The number of rows to compress. /// Number of bytes of of the compressed data. - public abstract uint CompressRowBlock(Span rows, int height); + public abstract uint CompressRowBlock(Span rows, int rowCount); } diff --git a/src/ImageSharp/Formats/Exr/ExrDecoderCore.cs b/src/ImageSharp/Formats/Exr/ExrDecoderCore.cs index 7165720d30..dbc6b7bf71 100644 --- a/src/ImageSharp/Formats/Exr/ExrDecoderCore.cs +++ b/src/ImageSharp/Formats/Exr/ExrDecoderCore.cs @@ -147,7 +147,7 @@ internal sealed class ExrDecoderCore : ImageDecoderCore Span bluePixelData = rowBuffer.GetSpan().Slice(width * 2, width); Span alphaPixelData = rowBuffer.GetSpan().Slice(width * 3, width); - using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(this.Compression, this.memoryAllocator, width, height, bytesPerBlock, rowsPerBlock, channelCount); + using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(this.Compression, this.memoryAllocator, width, bytesPerBlock, bytesPerRow, rowsPerBlock, channelCount); for (uint y = 0; y < height; y += rowsPerBlock) { @@ -200,7 +200,7 @@ internal sealed class ExrDecoderCore : ImageDecoderCore Span bluePixelData = rowBuffer.GetSpan().Slice(width * 2, width); Span alphaPixelData = rowBuffer.GetSpan().Slice(width * 3, width); - using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(this.Compression, this.memoryAllocator, width, height, bytesPerBlock, rowsPerBlock, channelCount); + using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(this.Compression, this.memoryAllocator, width, bytesPerBlock, bytesPerRow, rowsPerBlock, channelCount); for (uint y = 0; y < height; y += rowsPerBlock) { diff --git a/src/ImageSharp/Formats/Exr/ExrEncoderCore.cs b/src/ImageSharp/Formats/Exr/ExrEncoderCore.cs index 9e63413445..a7b37eda28 100644 --- a/src/ImageSharp/Formats/Exr/ExrEncoderCore.cs +++ b/src/ImageSharp/Formats/Exr/ExrEncoderCore.cs @@ -5,7 +5,6 @@ using System.Buffers; using System.Buffers.Binary; using System.Numerics; using System.Runtime.CompilerServices; -using System.Threading.Channels; using SixLabors.ImageSharp.Formats.Exr.Compression; using SixLabors.ImageSharp.Formats.Exr.Constants; using SixLabors.ImageSharp.Memory; @@ -32,7 +31,7 @@ internal sealed class ExrEncoderCore /// /// The global configuration. /// - private Configuration configuration; + private readonly Configuration configuration; /// /// The encoder with options. @@ -170,7 +169,7 @@ internal sealed class ExrEncoderCore Span greenBuffer = rgbBuffer.GetSpan().Slice(width, width); Span blueBuffer = rgbBuffer.GetSpan().Slice(width * 2, width); - using ExrBaseCompressor compressor = ExrCompressorFactory.Create(compression, this.memoryAllocator, stream, width, height, bytesPerBlock, rowsPerBlock, channelCount); + using ExrBaseCompressor compressor = ExrCompressorFactory.Create(compression, this.memoryAllocator, stream, bytesPerBlock, bytesPerRow); ulong[] rowOffsets = new ulong[height]; for (int y = 0; y < height; y++) @@ -181,7 +180,7 @@ internal sealed class ExrEncoderCore BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, (uint)y); stream.Write(this.buffer.AsSpan(0, 4)); - // At this point, it is not yet known how mcuh bytes the compressed data will take up, keep stream position. + // At this point, it is not yet known how much bytes the compressed data will take up, keep stream position. long pixelDataSizePos = stream.Position; Span pixelRowSpan = pixels.DangerousGetRowSpan(y); stream.Position = pixelDataSizePos + 4; @@ -195,18 +194,19 @@ internal sealed class ExrEncoderCore } // Write pixel data to buffer. + Span rowBlockSpan = rowBlockBuffer.GetSpan(); switch (this.pixelType) { case ExrPixelType.Float: - this.WriteSingleRow(rowBlockBuffer.GetSpan(), width, blueBuffer, greenBuffer, redBuffer); + this.WriteSingleRow(rowBlockSpan, width, blueBuffer, greenBuffer, redBuffer); break; case ExrPixelType.Half: - this.WriteHalfSingleRow(rowBlockBuffer.GetSpan(), width, blueBuffer, greenBuffer, redBuffer); + this.WriteHalfSingleRow(rowBlockSpan, width, blueBuffer, greenBuffer, redBuffer); break; } - // Write compressed pixel row data to stream. - uint compressedBytes = compressor.CompressRowBlock(rowBlockBuffer.GetSpan(), 1); + // Write compressed pixel row data to the stream. + uint compressedBytes = compressor.CompressRowBlock(rowBlockSpan, (int)rowsPerBlock); long positionAfterPixelData = stream.Position; // Write pixel row data size. @@ -239,7 +239,7 @@ internal sealed class ExrEncoderCore Span greenBuffer = rgbBuffer.GetSpan().Slice(width, width); Span blueBuffer = rgbBuffer.GetSpan().Slice(width * 2, width); - using ExrBaseCompressor compressor = ExrCompressorFactory.Create(compression, this.memoryAllocator, stream, width, height, bytesPerBlock, rowsPerBlock, channelCount); + using ExrBaseCompressor compressor = ExrCompressorFactory.Create(compression, this.memoryAllocator, stream, bytesPerBlock, bytesPerRow); Rgb96 rgb = default; ulong[] rowOffsets = new ulong[height]; @@ -251,7 +251,7 @@ internal sealed class ExrEncoderCore BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, (uint)y); stream.Write(this.buffer.AsSpan(0, 4)); - // At this point, it is not yet known how mcuh bytes the compressed data will take up, keep stream position. + // At this point, it is not yet known how much bytes the compressed data will take up, keep stream position. long pixelDataSizePos = stream.Position; Span pixelRowSpan = pixels.DangerousGetRowSpan(y); stream.Position = pixelDataSizePos + 4;