Browse Source

Initial version decode Pxr24 compression

pull/3124/head
Brian Popow 3 weeks ago
parent
commit
39b13a46c6
  1. 1
      src/ImageSharp/Formats/Exr/Compression/Decompressors/B44ExrCompression.cs
  2. 102
      src/ImageSharp/Formats/Exr/Compression/Decompressors/Pxr24Compression.cs
  3. 1
      src/ImageSharp/Formats/Exr/Compression/ExrDecompressorFactory.cs
  4. 2
      src/ImageSharp/Formats/Exr/ExrDecoderCore.cs

1
src/ImageSharp/Formats/Exr/Compression/Decompressors/B44ExrCompression.cs

@ -72,6 +72,7 @@ internal class B44ExrCompression : ExrBaseDecompressor
ExrThrowHelper.ThrowInvalidImageContentException("Could not read enough data from the stream!");
}
// Check if 3-byte encoded flat field.
if (this.scratch[2] >= 13 << 2)
{
Unpack3(this.scratch, this.s);

102
src/ImageSharp/Formats/Exr/Compression/Decompressors/Pxr24Compression.cs

@ -0,0 +1,102 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Buffers;
using System.IO.Compression;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Compression.Zlib;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Exr.Compression.Decompressors;
internal class Pxr24Compression : ExrBaseDecompressor
{
private readonly IMemoryOwner<byte> tmpBuffer;
private readonly uint rowsPerBlock;
private readonly int channelCount;
private readonly int width;
/// <summary>
/// Initializes a new instance of the <see cref="Pxr24Compression" /> class.
/// </summary>
/// <param name="allocator">The memory allocator.</param>
/// <param name="bytesPerBlock">The bytes per pixel row block.</param>
/// <param name="bytesPerRow">The bytes per pixel row.</param>
public Pxr24Compression(MemoryAllocator allocator, uint bytesPerBlock, uint bytesPerRow, uint rowsPerBlock, int width, int channelCount)
: base(allocator, bytesPerBlock, bytesPerRow)
{
this.tmpBuffer = allocator.Allocate<byte>((int)bytesPerBlock);
this.rowsPerBlock = rowsPerBlock;
this.width = width;
this.channelCount = channelCount;
}
/// <inheritdoc/>
public override void Decompress(BufferedReadStream stream, uint compressedBytes, Span<byte> buffer)
{
Span<byte> uncompressed = this.tmpBuffer.GetSpan();
Span<ushort> outputBuffer = MemoryMarshal.Cast<byte, ushort>(buffer);
long pos = stream.Position;
using ZlibInflateStream inflateStream = new(
stream,
() =>
{
int left = (int)(compressedBytes - (stream.Position - pos));
return left > 0 ? left : 0;
});
inflateStream.AllocateNewBytes((int)this.BytesPerBlock, true);
using DeflateStream dataStream = inflateStream.CompressedStream!;
int totalRead = 0;
while (totalRead < buffer.Length)
{
int bytesRead = dataStream.Read(uncompressed, totalRead, buffer.Length - totalRead);
if (bytesRead <= 0)
{
break;
}
totalRead += bytesRead;
}
if (totalRead == 0)
{
ExrThrowHelper.ThrowInvalidImageContentException("Could not read enough data for zip compressed image data!");
}
int lastIn = 0;
int outputOffset = 0;
for (int y = 0; y < this.rowsPerBlock; y++)
{
for (int c = 0; c < this.channelCount; c++)
{
int offsetT1 = lastIn;
lastIn += this.width;
int offsetT2 = lastIn;
lastIn += this.width;
uint pixel = 0;
for (int x = 0; x < this.width; x++)
{
uint t1 = uncompressed[offsetT1];
uint t2 = uncompressed[offsetT2];
uint diff = (t1 << 8) | t2;
pixel += diff;
outputBuffer[outputOffset] = (ushort)pixel;
offsetT1++;
offsetT2++;
outputOffset++;
}
}
}
}
/// <inheritdoc/>
protected override void Dispose(bool disposing) => this.tmpBuffer.Dispose();
}

1
src/ImageSharp/Formats/Exr/Compression/ExrDecompressorFactory.cs

@ -37,6 +37,7 @@ internal static class ExrDecompressorFactory
ExrCompression.Zip => new ZipExrCompression(memoryAllocator, bytesPerBlock, bytesPerRow),
ExrCompression.RunLengthEncoded => new RunLengthExrCompression(memoryAllocator, bytesPerBlock, bytesPerRow),
ExrCompression.B44 => new B44ExrCompression(memoryAllocator, bytesPerBlock, bytesPerRow, rowsPerBlock, width, channelCount),
ExrCompression.Pxr24 => new Pxr24Compression(memoryAllocator, bytesPerBlock, bytesPerRow, rowsPerBlock, width, channelCount),
_ => throw ExrThrowHelper.NotSupportedDecompressor(nameof(method)),
};
}

2
src/ImageSharp/Formats/Exr/ExrDecoderCore.cs

@ -846,7 +846,7 @@ internal sealed class ExrDecoderCore : ImageDecoderCore
/// <returns> True if the compression is supported; otherwise, false>. </returns>
private bool IsSupportedCompression() => this.Compression switch
{
ExrCompression.None or ExrCompression.Zip or ExrCompression.Zips or ExrCompression.RunLengthEncoded or ExrCompression.B44 => true,
ExrCompression.None or ExrCompression.Zip or ExrCompression.Zips or ExrCompression.RunLengthEncoded or ExrCompression.B44 or ExrCompression.Pxr24 => true,
_ => false,
};

Loading…
Cancel
Save