Browse Source

Implement pxr decompression for pixel type uint and float

pull/3124/head
Brian Popow 2 weeks ago
parent
commit
95ee73e241
  1. 106
      src/ImageSharp/Formats/Exr/Compression/Decompressors/Pxr24Compression.cs
  2. 5
      src/ImageSharp/Formats/Exr/Compression/ExrDecompressorFactory.cs
  3. 20
      src/ImageSharp/Formats/Exr/ExrDecoderCore.cs

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

@ -5,6 +5,7 @@ using System.Buffers;
using System.IO.Compression;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Compression.Zlib;
using SixLabors.ImageSharp.Formats.Exr.Constants;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory;
@ -21,6 +22,8 @@ internal class Pxr24Compression : ExrBaseDecompressor
private readonly int channelCount;
private readonly ExrPixelType pixelType;
/// <summary>
/// Initializes a new instance of the <see cref="Pxr24Compression" /> class.
/// </summary>
@ -30,12 +33,14 @@ internal class Pxr24Compression : ExrBaseDecompressor
/// <param name="rowsPerBlock">The pixel rows per block.</param>
/// <param name="width">The witdh of one row in pixels.</param>
/// <param name="channelCount">The number of channels for a pixel.</param>
public Pxr24Compression(MemoryAllocator allocator, uint bytesPerBlock, uint bytesPerRow, uint rowsPerBlock, int width, int channelCount)
/// <param name="pixelType">The pixel type.</param>
public Pxr24Compression(MemoryAllocator allocator, uint bytesPerBlock, uint bytesPerRow, uint rowsPerBlock, int width, int channelCount, ExrPixelType pixelType)
: base(allocator, bytesPerBlock, bytesPerRow, width)
{
this.tmpBuffer = allocator.Allocate<byte>((int)bytesPerBlock);
this.rowsPerBlock = rowsPerBlock;
this.channelCount = channelCount;
this.pixelType = pixelType;
}
/// <inheritdoc/>
@ -78,23 +83,94 @@ internal class Pxr24Compression : ExrBaseDecompressor
{
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++)
switch (this.pixelType)
{
uint t1 = uncompressed[offsetT1];
uint t2 = uncompressed[offsetT2];
uint diff = (t1 << 8) | t2;
case ExrPixelType.UnsignedInt:
{
int offsetT0 = lastIn;
lastIn += this.Width;
int offsetT1 = lastIn;
lastIn += this.Width;
int offsetT2 = lastIn;
lastIn += this.Width;
int offsetT3 = lastIn;
lastIn += this.Width;
uint pixel = 0;
for (int x = 0; x < this.Width; x++)
{
uint t0 = uncompressed[offsetT0];
uint t1 = uncompressed[offsetT1];
uint t2 = uncompressed[offsetT2];
uint t3 = uncompressed[offsetT3];
uint diff = (t0 << 24) | (t1 << 16) | (t2 << 8) | t3;
pixel += diff;
outputBuffer[outputOffset] = (ushort)pixel;
offsetT0++;
offsetT1++;
offsetT2++;
offsetT3++;
outputOffset++;
}
break;
}
case ExrPixelType.Half:
{
int offsetT0 = lastIn;
lastIn += this.Width;
int offsetT1 = lastIn;
lastIn += this.Width;
uint pixel = 0;
for (int x = 0; x < this.Width; x++)
{
uint t0 = uncompressed[offsetT0];
uint t1 = uncompressed[offsetT1];
uint diff = (t0 << 8) | t1;
pixel += diff;
outputBuffer[outputOffset] = (ushort)pixel;
offsetT0++;
offsetT1++;
outputOffset++;
}
break;
}
case ExrPixelType.Float:
{
int offsetT0 = lastIn;
lastIn += this.Width;
int offsetT1 = lastIn;
lastIn += this.Width;
int offsetT2 = lastIn;
lastIn += this.Width;
uint pixel = 0;
for (int x = 0; x < this.Width; x++)
{
uint t0 = uncompressed[offsetT0];
uint t1 = uncompressed[offsetT1];
uint t2 = uncompressed[offsetT2];
uint diff = (t0 << 24) | (t1 << 16) | (t2 << 8);
pixel += diff;
outputBuffer[outputOffset] = (ushort)pixel;
pixel += diff;
outputBuffer[outputOffset] = (ushort)pixel;
offsetT0++;
offsetT1++;
offsetT2++;
outputOffset++;
}
offsetT1++;
offsetT2++;
outputOffset++;
break;
}
}
}
}

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

@ -30,14 +30,15 @@ internal static class ExrDecompressorFactory
uint bytesPerBlock,
uint bytesPerRow,
uint rowsPerBlock,
int channelCount) => method switch
int channelCount,
ExrPixelType pixelType) => method switch
{
ExrCompression.None => new NoneExrCompression(memoryAllocator, bytesPerBlock, bytesPerRow, width),
ExrCompression.Zips => new ZipExrCompression(memoryAllocator, bytesPerBlock, bytesPerRow, width),
ExrCompression.Zip => new ZipExrCompression(memoryAllocator, bytesPerBlock, bytesPerRow, width),
ExrCompression.RunLengthEncoded => new RunLengthExrCompression(memoryAllocator, bytesPerBlock, bytesPerRow, width),
ExrCompression.B44 => new B44ExrCompression(memoryAllocator, bytesPerBlock, bytesPerRow, rowsPerBlock, width, channelCount),
ExrCompression.Pxr24 => new Pxr24Compression(memoryAllocator, bytesPerBlock, bytesPerRow, rowsPerBlock, width, channelCount),
ExrCompression.Pxr24 => new Pxr24Compression(memoryAllocator, bytesPerBlock, bytesPerRow, rowsPerBlock, width, channelCount, pixelType),
_ => throw ExrThrowHelper.NotSupportedDecompressor(nameof(method)),
};
}

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

@ -154,7 +154,15 @@ internal sealed class ExrDecoderCore : ImageDecoderCore
Span<float> bluePixelData = rowBuffer.GetSpan().Slice(width * 2, width);
Span<float> alphaPixelData = rowBuffer.GetSpan().Slice(width * 3, width);
using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(this.Compression, this.memoryAllocator, width, bytesPerBlock, bytesPerRow, rowsPerBlock, channelCount);
using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(
this.Compression,
this.memoryAllocator,
width,
bytesPerBlock,
bytesPerRow,
rowsPerBlock,
channelCount,
this.PixelType);
int decodedRows = 0;
while (decodedRows < height)
@ -219,7 +227,15 @@ internal sealed class ExrDecoderCore : ImageDecoderCore
Span<uint> bluePixelData = rowBuffer.GetSpan().Slice(width * 2, width);
Span<uint> alphaPixelData = rowBuffer.GetSpan().Slice(width * 3, width);
using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(this.Compression, this.memoryAllocator, width, bytesPerBlock, bytesPerRow, rowsPerBlock, channelCount);
using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(
this.Compression,
this.memoryAllocator,
width,
bytesPerBlock,
bytesPerRow,
rowsPerBlock,
channelCount,
this.PixelType);
int decodedRows = 0;
while (decodedRows < height)

Loading…
Cancel
Save