mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
22 changed files with 337 additions and 92 deletions
@ -0,0 +1,153 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using System.Runtime.InteropServices; |
|||
using SixLabors.ImageSharp.Formats.Exr.Constants; |
|||
using SixLabors.ImageSharp.IO; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Exr.Compression.Decompressors; |
|||
|
|||
/// <summary>
|
|||
/// Implementation of PXR24 decompressor for EXR image data.
|
|||
/// </summary>
|
|||
internal class Pxr24Compression : ExrBaseDecompressor |
|||
{ |
|||
private readonly IMemoryOwner<byte> tmpBuffer; |
|||
|
|||
private readonly int channelCount; |
|||
|
|||
private readonly ExrPixelType pixelType; |
|||
|
|||
/// <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>
|
|||
/// <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>
|
|||
/// <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, rowsPerBlock, width) |
|||
{ |
|||
this.tmpBuffer = allocator.Allocate<byte>((int)bytesPerBlock); |
|||
this.channelCount = channelCount; |
|||
this.pixelType = pixelType; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void Decompress(BufferedReadStream stream, uint compressedBytes, Span<byte> buffer) |
|||
{ |
|||
Span<byte> uncompressed = this.tmpBuffer.GetSpan(); |
|||
Span<ushort> outputBufferHalf = MemoryMarshal.Cast<byte, ushort>(buffer); |
|||
Span<uint> outputBufferFloat = MemoryMarshal.Cast<byte, uint>(buffer); |
|||
Span<uint> outputBufferUint = MemoryMarshal.Cast<byte, uint>(buffer); |
|||
|
|||
uint uncompressedBytes = this.BytesPerBlock; |
|||
UndoZipCompression(stream, compressedBytes, uncompressed, uncompressedBytes); |
|||
|
|||
int lastIn = 0; |
|||
int outputOffset = 0; |
|||
for (int y = 0; y < this.RowsPerBlock; y++) |
|||
{ |
|||
for (int c = 0; c < this.channelCount; c++) |
|||
{ |
|||
switch (this.pixelType) |
|||
{ |
|||
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; |
|||
outputBufferUint[outputOffset] = 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; |
|||
outputBufferHalf[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; |
|||
outputBufferFloat[outputOffset] = pixel; |
|||
|
|||
offsetT0++; |
|||
offsetT1++; |
|||
offsetT2++; |
|||
outputOffset++; |
|||
} |
|||
|
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void Dispose(bool disposing) => this.tmpBuffer.Dispose(); |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:f66bf45b5d80e412314341567b8cf240d56b5872f01ce9f3b0d6034d85e8e942 |
|||
size 163327 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:ca6c29eb36395b923298d2bf4ba1f73fd7f081f7b1af2e72b94b92ad2acb638b |
|||
size 226997 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:926996c647c1c54921db0a623e58e5edeb92b447cb4eceb53b8c0e86fd24f11e |
|||
size 720281 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:927778a73832b5ad68473e46df6be52076d98294271f2cd0ead66691db41b7bf |
|||
size 195063 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:fc72685224ba818ac77d914f5e4c91162503f88f775e16b5c745baef6bc7b790 |
|||
size 187914 |
|||
@ -1,3 +0,0 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:5ab8b71824ca384fc2cde1f74a6f34c38169fa328ccc67f17d08333e9de42f55 |
|||
size 243558 |
|||
Loading…
Reference in new issue