From 614a7f6e84bfe13b5224913490ffabd2601d1f1a Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sun, 22 Mar 2026 16:22:55 +0100 Subject: [PATCH] Re-arrange pixeldata and add predictor for zip compressed data --- .../Compressors/ZipExrCompressor.cs | 25 +++++++++++++++++-- .../Exr/Compression/ExrCompressorFactory.cs | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp/Formats/Exr/Compression/Compressors/ZipExrCompressor.cs b/src/ImageSharp/Formats/Exr/Compression/Compressors/ZipExrCompressor.cs index e7b695df0c..8373e92e2e 100644 --- a/src/ImageSharp/Formats/Exr/Compression/Compressors/ZipExrCompressor.cs +++ b/src/ImageSharp/Formats/Exr/Compression/Compressors/ZipExrCompressor.cs @@ -11,7 +11,7 @@ internal class ZipExrCompressor : ExrBaseCompressor { private readonly DeflateCompressionLevel compressionLevel; - private readonly MemoryStream memoryStream = new(); + private MemoryStream memoryStream = new(); public ZipExrCompressor(Stream output, MemoryAllocator allocator, uint bytesPerBlock, DeflateCompressionLevel compressionLevel) : base(output, allocator, bytesPerBlock) @@ -28,6 +28,25 @@ internal class ZipExrCompressor : ExrBaseCompressor /// public override uint CompressRowBlock(Span rows, int height) { + // Re-oder pixel values. + int n = rows.Length; + int t1 = 0; + int t2 = (n + 1) >> 1; + for (int i = 0; i < n; i++) + { + bool isOdd = (i & 1) == 1; + rows[isOdd ? t2++ : t1++] = rows[i]; + } + + // Predictor. + byte p = rows[0]; + for (int i = 1; i < rows.Length; i++) + { + int d = (rows[i] - p + 128 + 256) & 255; + p = rows[i]; + rows[i] = (byte)d; + } + this.memoryStream.Seek(0, SeekOrigin.Begin); using (ZlibDeflateStream stream = new(this.Allocator, this.memoryStream, this.compressionLevel)) { @@ -38,7 +57,9 @@ internal class ZipExrCompressor : ExrBaseCompressor int size = (int)this.memoryStream.Position; byte[] buffer = this.memoryStream.GetBuffer(); this.Output.Write(buffer, 0, size); - return (uint)buffer.Length; + + this.memoryStream = new(); + return (uint)size; } /// diff --git a/src/ImageSharp/Formats/Exr/Compression/ExrCompressorFactory.cs b/src/ImageSharp/Formats/Exr/Compression/ExrCompressorFactory.cs index e8e7af4712..a87372748a 100644 --- a/src/ImageSharp/Formats/Exr/Compression/ExrCompressorFactory.cs +++ b/src/ImageSharp/Formats/Exr/Compression/ExrCompressorFactory.cs @@ -25,7 +25,7 @@ internal static class ExrCompressorFactory { case ExrCompression.None: return new NoneExrCompressor(output, allocator, bytesPerBlock); - case ExrCompression.Zip: + case ExrCompression.Zips: return new ZipExrCompressor(output, allocator, bytesPerBlock, compressionLevel); default: