|
|
@ -9,7 +9,6 @@ using System.Runtime.CompilerServices; |
|
|
using System.Text; |
|
|
using System.Text; |
|
|
using System.Threading; |
|
|
using System.Threading; |
|
|
using SixLabors.ImageSharp.Formats.OpenExr.Compression; |
|
|
using SixLabors.ImageSharp.Formats.OpenExr.Compression; |
|
|
using SixLabors.ImageSharp.Formats.OpenExr.Compression.Compressors; |
|
|
|
|
|
using SixLabors.ImageSharp.Formats.Pbm; |
|
|
using SixLabors.ImageSharp.Formats.Pbm; |
|
|
using SixLabors.ImageSharp.IO; |
|
|
using SixLabors.ImageSharp.IO; |
|
|
using SixLabors.ImageSharp.Memory; |
|
|
using SixLabors.ImageSharp.Memory; |
|
|
@ -77,7 +76,7 @@ namespace SixLabors.ImageSharp.Formats.OpenExr |
|
|
{ |
|
|
{ |
|
|
this.ReadExrHeader(stream); |
|
|
this.ReadExrHeader(stream); |
|
|
|
|
|
|
|
|
if (this.Compression is not ExrCompressionType.None and not ExrCompressionType.Zips and not ExrCompressionType.RunLengthEncoded) |
|
|
if (this.Compression is not ExrCompressionType.None and not ExrCompressionType.Zips and not ExrCompressionType.Zip and not ExrCompressionType.RunLengthEncoded) |
|
|
{ |
|
|
{ |
|
|
ExrThrowHelper.ThrowNotSupported($"Compression {this.Compression} is not yet supported"); |
|
|
ExrThrowHelper.ThrowNotSupported($"Compression {this.Compression} is not yet supported"); |
|
|
} |
|
|
} |
|
|
@ -109,19 +108,21 @@ namespace SixLabors.ImageSharp.Formats.OpenExr |
|
|
{ |
|
|
{ |
|
|
bool hasAlpha = this.HasAlpha(); |
|
|
bool hasAlpha = this.HasAlpha(); |
|
|
uint bytesPerRow = this.CalculateBytesPerRow(); |
|
|
uint bytesPerRow = this.CalculateBytesPerRow(); |
|
|
|
|
|
uint rowsPerBlock = this.RowsPerBlock(); |
|
|
|
|
|
uint bytesPerBlock = bytesPerRow * rowsPerBlock; |
|
|
|
|
|
|
|
|
using IMemoryOwner<float> rowBuffer = this.memoryAllocator.Allocate<float>(this.Width * 4); |
|
|
using IMemoryOwner<float> rowBuffer = this.memoryAllocator.Allocate<float>(this.Width * 4); |
|
|
using IMemoryOwner<byte> decompressedPixelDataBuffer = this.memoryAllocator.Allocate<byte>((int)bytesPerRow); |
|
|
using IMemoryOwner<byte> decompressedPixelDataBuffer = this.memoryAllocator.Allocate<byte>((int)bytesPerBlock); |
|
|
Span<byte> decompressedPixelData = decompressedPixelDataBuffer.GetSpan(); |
|
|
Span<byte> decompressedPixelData = decompressedPixelDataBuffer.GetSpan(); |
|
|
Span<float> redPixelData = rowBuffer.GetSpan().Slice(0, this.Width); |
|
|
Span<float> redPixelData = rowBuffer.GetSpan().Slice(0, this.Width); |
|
|
Span<float> greenPixelData = rowBuffer.GetSpan().Slice(this.Width, this.Width); |
|
|
Span<float> greenPixelData = rowBuffer.GetSpan().Slice(this.Width, this.Width); |
|
|
Span<float> bluePixelData = rowBuffer.GetSpan().Slice(this.Width * 2, this.Width); |
|
|
Span<float> bluePixelData = rowBuffer.GetSpan().Slice(this.Width * 2, this.Width); |
|
|
Span<float> alphaPixelData = rowBuffer.GetSpan().Slice(this.Width * 3, this.Width); |
|
|
Span<float> alphaPixelData = rowBuffer.GetSpan().Slice(this.Width * 3, this.Width); |
|
|
|
|
|
|
|
|
using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(this.Compression, this.memoryAllocator, bytesPerRow); |
|
|
using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(this.Compression, this.memoryAllocator, bytesPerBlock); |
|
|
|
|
|
|
|
|
TPixel color = default; |
|
|
TPixel color = default; |
|
|
for (int y = 0; y < this.Height; y++) |
|
|
for (uint y = 0; y < this.Height; y += rowsPerBlock) |
|
|
{ |
|
|
{ |
|
|
stream.Read(this.buffer, 0, 8); |
|
|
stream.Read(this.buffer, 0, 8); |
|
|
ulong rowOffset = BinaryPrimitives.ReadUInt64LittleEndian(this.buffer); |
|
|
ulong rowOffset = BinaryPrimitives.ReadUInt64LittleEndian(this.buffer); |
|
|
@ -129,100 +130,102 @@ namespace SixLabors.ImageSharp.Formats.OpenExr |
|
|
|
|
|
|
|
|
stream.Position = (long)rowOffset; |
|
|
stream.Position = (long)rowOffset; |
|
|
stream.Read(this.buffer, 0, 4); |
|
|
stream.Read(this.buffer, 0, 4); |
|
|
uint rowIndex = BinaryPrimitives.ReadUInt32LittleEndian(this.buffer); |
|
|
uint rowStartIndex = BinaryPrimitives.ReadUInt32LittleEndian(this.buffer); |
|
|
|
|
|
|
|
|
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan((int)rowIndex); |
|
|
|
|
|
|
|
|
|
|
|
stream.Read(this.buffer, 0, 4); |
|
|
stream.Read(this.buffer, 0, 4); |
|
|
uint compressedBytesCount = BinaryPrimitives.ReadUInt32LittleEndian(this.buffer); |
|
|
uint compressedBytesCount = BinaryPrimitives.ReadUInt32LittleEndian(this.buffer); |
|
|
decompressor.Decompress(stream, compressedBytesCount, decompressedPixelData); |
|
|
decompressor.Decompress(stream, compressedBytesCount, decompressedPixelData); |
|
|
|
|
|
|
|
|
int offset = 0; |
|
|
int offset = 0; |
|
|
for (int channelIdx = 0; channelIdx < this.Channels.Count; channelIdx++) |
|
|
for (uint rowIndex = rowStartIndex; rowIndex < rowStartIndex + rowsPerBlock && rowIndex < this.Height; rowIndex++) |
|
|
{ |
|
|
{ |
|
|
ExrChannelInfo channel = this.Channels[channelIdx]; |
|
|
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan((int)rowIndex); |
|
|
switch (channel.ChannelName) |
|
|
for (int channelIdx = 0; channelIdx < this.Channels.Count; channelIdx++) |
|
|
{ |
|
|
{ |
|
|
case ExrConstants.ChannelNames.Red: |
|
|
ExrChannelInfo channel = this.Channels[channelIdx]; |
|
|
switch (channel.PixelType) |
|
|
switch (channel.ChannelName) |
|
|
{ |
|
|
{ |
|
|
case ExrPixelType.Half: |
|
|
case ExrConstants.ChannelNames.Red: |
|
|
offset += this.ReadPixelRowChannelHalfSingle(decompressedPixelData.Slice(offset), redPixelData); |
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
case ExrPixelType.Float: |
|
|
case ExrPixelType.Half: |
|
|
offset += this.ReadPixelRowChannelSingle(decompressedPixelData.Slice(offset), redPixelData); |
|
|
offset += this.ReadPixelRowChannelHalfSingle(decompressedPixelData.Slice(offset), redPixelData); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
case ExrPixelType.Float: |
|
|
|
|
|
offset += this.ReadPixelRowChannelSingle(decompressedPixelData.Slice(offset), redPixelData); |
|
|
break; |
|
|
break; |
|
|
|
|
|
} |
|
|
case ExrConstants.ChannelNames.Blue: |
|
|
|
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
|
|
|
case ExrPixelType.Half: |
|
|
case ExrConstants.ChannelNames.Blue: |
|
|
offset += this.ReadPixelRowChannelHalfSingle(decompressedPixelData.Slice(offset), bluePixelData); |
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
case ExrPixelType.Float: |
|
|
case ExrPixelType.Half: |
|
|
offset += this.ReadPixelRowChannelSingle(decompressedPixelData.Slice(offset), bluePixelData); |
|
|
offset += this.ReadPixelRowChannelHalfSingle(decompressedPixelData.Slice(offset), bluePixelData); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
case ExrPixelType.Float: |
|
|
|
|
|
offset += this.ReadPixelRowChannelSingle(decompressedPixelData.Slice(offset), bluePixelData); |
|
|
break; |
|
|
break; |
|
|
|
|
|
} |
|
|
case ExrConstants.ChannelNames.Green: |
|
|
|
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
|
|
|
case ExrPixelType.Half: |
|
|
case ExrConstants.ChannelNames.Green: |
|
|
offset += this.ReadPixelRowChannelHalfSingle(decompressedPixelData.Slice(offset), greenPixelData); |
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
case ExrPixelType.Float: |
|
|
case ExrPixelType.Half: |
|
|
offset += this.ReadPixelRowChannelSingle(decompressedPixelData.Slice(offset), greenPixelData); |
|
|
offset += this.ReadPixelRowChannelHalfSingle(decompressedPixelData.Slice(offset), greenPixelData); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
case ExrPixelType.Float: |
|
|
|
|
|
offset += this.ReadPixelRowChannelSingle(decompressedPixelData.Slice(offset), greenPixelData); |
|
|
break; |
|
|
break; |
|
|
|
|
|
} |
|
|
case ExrConstants.ChannelNames.Alpha: |
|
|
|
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
|
|
|
case ExrPixelType.Half: |
|
|
case ExrConstants.ChannelNames.Alpha: |
|
|
offset += this.ReadPixelRowChannelHalfSingle(decompressedPixelData.Slice(offset), alphaPixelData); |
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
case ExrPixelType.Float: |
|
|
case ExrPixelType.Half: |
|
|
offset += this.ReadPixelRowChannelSingle(decompressedPixelData.Slice(offset), alphaPixelData); |
|
|
offset += this.ReadPixelRowChannelHalfSingle(decompressedPixelData.Slice(offset), alphaPixelData); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
case ExrPixelType.Float: |
|
|
|
|
|
offset += this.ReadPixelRowChannelSingle(decompressedPixelData.Slice(offset), alphaPixelData); |
|
|
break; |
|
|
break; |
|
|
|
|
|
} |
|
|
default: |
|
|
|
|
|
// Skip unknown channel.
|
|
|
break; |
|
|
int channelDataSizeInBytes = channel.PixelType is ExrPixelType.Float or ExrPixelType.UnsignedInt ? 4 : 2; |
|
|
|
|
|
stream.Position += this.Width * channelDataSizeInBytes; |
|
|
default: |
|
|
break; |
|
|
// Skip unknown channel.
|
|
|
|
|
|
int channelDataSizeInBytes = channel.PixelType is ExrPixelType.Float or ExrPixelType.UnsignedInt ? 4 : 2; |
|
|
|
|
|
stream.Position += this.Width * channelDataSizeInBytes; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
stream.Position = nextRowOffsetPosition; |
|
|
|
|
|
|
|
|
|
|
|
if (hasAlpha) |
|
|
if (hasAlpha) |
|
|
{ |
|
|
|
|
|
for (int x = 0; x < this.Width; x++) |
|
|
|
|
|
{ |
|
|
{ |
|
|
var pixelValue = new HalfVector4(redPixelData[x], greenPixelData[x], bluePixelData[x], alphaPixelData[x]); |
|
|
for (int x = 0; x < this.Width; x++) |
|
|
color.FromVector4(pixelValue.ToVector4()); |
|
|
{ |
|
|
pixelRow[x] = color; |
|
|
var pixelValue = new HalfVector4(redPixelData[x], greenPixelData[x], bluePixelData[x], alphaPixelData[x]); |
|
|
|
|
|
color.FromVector4(pixelValue.ToVector4()); |
|
|
|
|
|
pixelRow[x] = color; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
for (int x = 0; x < this.Width; x++) |
|
|
|
|
|
{ |
|
|
{ |
|
|
var pixelValue = new HalfVector4(redPixelData[x], greenPixelData[x], bluePixelData[x], 1.0f); |
|
|
for (int x = 0; x < this.Width; x++) |
|
|
color.FromVector4(pixelValue.ToVector4()); |
|
|
{ |
|
|
pixelRow[x] = color; |
|
|
var pixelValue = new HalfVector4(redPixelData[x], greenPixelData[x], bluePixelData[x], 1.0f); |
|
|
|
|
|
color.FromVector4(pixelValue.ToVector4()); |
|
|
|
|
|
pixelRow[x] = color; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
stream.Position = nextRowOffsetPosition; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -231,19 +234,21 @@ namespace SixLabors.ImageSharp.Formats.OpenExr |
|
|
{ |
|
|
{ |
|
|
bool hasAlpha = this.HasAlpha(); |
|
|
bool hasAlpha = this.HasAlpha(); |
|
|
uint bytesPerRow = this.CalculateBytesPerRow(); |
|
|
uint bytesPerRow = this.CalculateBytesPerRow(); |
|
|
|
|
|
uint rowsPerBlock = this.RowsPerBlock(); |
|
|
|
|
|
uint bytesPerBlock = bytesPerRow * rowsPerBlock; |
|
|
|
|
|
|
|
|
using IMemoryOwner<uint> rowBuffer = this.memoryAllocator.Allocate<uint>(this.Width * 4); |
|
|
using IMemoryOwner<uint> rowBuffer = this.memoryAllocator.Allocate<uint>(this.Width * 4); |
|
|
using IMemoryOwner<byte> decompressedPixelDataBuffer = this.memoryAllocator.Allocate<byte>((int)bytesPerRow); |
|
|
using IMemoryOwner<byte> decompressedPixelDataBuffer = this.memoryAllocator.Allocate<byte>((int)bytesPerBlock); |
|
|
Span<byte> decompressedPixelData = decompressedPixelDataBuffer.GetSpan(); |
|
|
Span<byte> decompressedPixelData = decompressedPixelDataBuffer.GetSpan(); |
|
|
Span<uint> redPixelData = rowBuffer.GetSpan().Slice(0, this.Width); |
|
|
Span<uint> redPixelData = rowBuffer.GetSpan().Slice(0, this.Width); |
|
|
Span<uint> greenPixelData = rowBuffer.GetSpan().Slice(this.Width, this.Width); |
|
|
Span<uint> greenPixelData = rowBuffer.GetSpan().Slice(this.Width, this.Width); |
|
|
Span<uint> bluePixelData = rowBuffer.GetSpan().Slice(this.Width * 2, this.Width); |
|
|
Span<uint> bluePixelData = rowBuffer.GetSpan().Slice(this.Width * 2, this.Width); |
|
|
Span<uint> alphaPixelData = rowBuffer.GetSpan().Slice(this.Width * 3, this.Width); |
|
|
Span<uint> alphaPixelData = rowBuffer.GetSpan().Slice(this.Width * 3, this.Width); |
|
|
|
|
|
|
|
|
using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(this.Compression, this.memoryAllocator, bytesPerRow); |
|
|
using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(this.Compression, this.memoryAllocator, bytesPerBlock); |
|
|
|
|
|
|
|
|
TPixel color = default; |
|
|
TPixel color = default; |
|
|
for (int y = 0; y < this.Height; y++) |
|
|
for (uint y = 0; y < this.Height; y += rowsPerBlock) |
|
|
{ |
|
|
{ |
|
|
stream.Read(this.buffer, 0, 8); |
|
|
stream.Read(this.buffer, 0, 8); |
|
|
ulong rowOffset = BinaryPrimitives.ReadUInt64LittleEndian(this.buffer); |
|
|
ulong rowOffset = BinaryPrimitives.ReadUInt64LittleEndian(this.buffer); |
|
|
@ -251,86 +256,88 @@ namespace SixLabors.ImageSharp.Formats.OpenExr |
|
|
|
|
|
|
|
|
stream.Position = (long)rowOffset; |
|
|
stream.Position = (long)rowOffset; |
|
|
stream.Read(this.buffer, 0, 4); |
|
|
stream.Read(this.buffer, 0, 4); |
|
|
uint rowIndex = BinaryPrimitives.ReadUInt32LittleEndian(this.buffer); |
|
|
uint rowStartIndex = BinaryPrimitives.ReadUInt32LittleEndian(this.buffer); |
|
|
|
|
|
|
|
|
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan((int)rowIndex); |
|
|
|
|
|
|
|
|
|
|
|
stream.Read(this.buffer, 0, 4); |
|
|
stream.Read(this.buffer, 0, 4); |
|
|
uint compressedBytesCount = BinaryPrimitives.ReadUInt32LittleEndian(this.buffer); |
|
|
uint compressedBytesCount = BinaryPrimitives.ReadUInt32LittleEndian(this.buffer); |
|
|
decompressor.Decompress(stream, compressedBytesCount, decompressedPixelData); |
|
|
decompressor.Decompress(stream, compressedBytesCount, decompressedPixelData); |
|
|
|
|
|
|
|
|
int offset = 0; |
|
|
int offset = 0; |
|
|
for (int channelIdx = 0; channelIdx < this.Channels.Count; channelIdx++) |
|
|
for (uint rowIndex = rowStartIndex; rowIndex < rowStartIndex + rowsPerBlock && rowIndex < this.Height; rowIndex++) |
|
|
{ |
|
|
{ |
|
|
ExrChannelInfo channel = this.Channels[channelIdx]; |
|
|
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan((int)rowIndex); |
|
|
switch (channel.ChannelName) |
|
|
for (int channelIdx = 0; channelIdx < this.Channels.Count; channelIdx++) |
|
|
{ |
|
|
{ |
|
|
case ExrConstants.ChannelNames.Red: |
|
|
ExrChannelInfo channel = this.Channels[channelIdx]; |
|
|
switch (channel.PixelType) |
|
|
switch (channel.ChannelName) |
|
|
{ |
|
|
{ |
|
|
case ExrPixelType.UnsignedInt: |
|
|
case ExrConstants.ChannelNames.Red: |
|
|
offset += this.ReadPixelRowChannelUnsignedInt(decompressedPixelData.Slice(offset), redPixelData); |
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
} |
|
|
case ExrPixelType.UnsignedInt: |
|
|
|
|
|
offset += this.ReadPixelRowChannelUnsignedInt(decompressedPixelData.Slice(offset), redPixelData); |
|
|
break; |
|
|
break; |
|
|
|
|
|
} |
|
|
case ExrConstants.ChannelNames.Blue: |
|
|
|
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
|
|
|
case ExrPixelType.UnsignedInt: |
|
|
case ExrConstants.ChannelNames.Blue: |
|
|
offset += this.ReadPixelRowChannelUnsignedInt(decompressedPixelData.Slice(offset), bluePixelData); |
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
} |
|
|
case ExrPixelType.UnsignedInt: |
|
|
|
|
|
offset += this.ReadPixelRowChannelUnsignedInt(decompressedPixelData.Slice(offset), bluePixelData); |
|
|
break; |
|
|
break; |
|
|
|
|
|
} |
|
|
case ExrConstants.ChannelNames.Green: |
|
|
|
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
|
|
|
case ExrPixelType.UnsignedInt: |
|
|
case ExrConstants.ChannelNames.Green: |
|
|
offset += this.ReadPixelRowChannelUnsignedInt(decompressedPixelData.Slice(offset), greenPixelData); |
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
} |
|
|
case ExrPixelType.UnsignedInt: |
|
|
|
|
|
offset += this.ReadPixelRowChannelUnsignedInt(decompressedPixelData.Slice(offset), greenPixelData); |
|
|
break; |
|
|
break; |
|
|
|
|
|
} |
|
|
case ExrConstants.ChannelNames.Alpha: |
|
|
|
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
|
|
|
case ExrPixelType.UnsignedInt: |
|
|
case ExrConstants.ChannelNames.Alpha: |
|
|
offset += this.ReadPixelRowChannelUnsignedInt(decompressedPixelData.Slice(offset), alphaPixelData); |
|
|
switch (channel.PixelType) |
|
|
break; |
|
|
{ |
|
|
} |
|
|
case ExrPixelType.UnsignedInt: |
|
|
|
|
|
offset += this.ReadPixelRowChannelUnsignedInt(decompressedPixelData.Slice(offset), alphaPixelData); |
|
|
break; |
|
|
break; |
|
|
|
|
|
} |
|
|
default: |
|
|
|
|
|
// Skip unknown channel.
|
|
|
break; |
|
|
int channelDataSizeInBytes = channel.PixelType is ExrPixelType.Float or ExrPixelType.UnsignedInt ? 4 : 2; |
|
|
|
|
|
stream.Position += this.Width * channelDataSizeInBytes; |
|
|
default: |
|
|
break; |
|
|
// Skip unknown channel.
|
|
|
|
|
|
int channelDataSizeInBytes = channel.PixelType is ExrPixelType.Float or ExrPixelType.UnsignedInt ? 4 : 2; |
|
|
|
|
|
stream.Position += this.Width * channelDataSizeInBytes; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
stream.Position = nextRowOffsetPosition; |
|
|
stream.Position = nextRowOffsetPosition; |
|
|
|
|
|
|
|
|
if (hasAlpha) |
|
|
if (hasAlpha) |
|
|
{ |
|
|
|
|
|
for (int x = 0; x < this.Width; x++) |
|
|
|
|
|
{ |
|
|
{ |
|
|
var pixelValue = new Rgba128(redPixelData[x], greenPixelData[x], bluePixelData[x], alphaPixelData[x]); |
|
|
for (int x = 0; x < this.Width; x++) |
|
|
color.FromVector4(pixelValue.ToVector4()); |
|
|
{ |
|
|
pixelRow[x] = color; |
|
|
var pixelValue = new Rgba128(redPixelData[x], greenPixelData[x], bluePixelData[x], alphaPixelData[x]); |
|
|
|
|
|
color.FromVector4(pixelValue.ToVector4()); |
|
|
|
|
|
pixelRow[x] = color; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
for (int x = 0; x < this.Width; x++) |
|
|
|
|
|
{ |
|
|
{ |
|
|
var pixelValue = new Rgb96(redPixelData[x], greenPixelData[x], bluePixelData[x]); |
|
|
for (int x = 0; x < this.Width; x++) |
|
|
color.FromVector4(pixelValue.ToVector4()); |
|
|
{ |
|
|
pixelRow[x] = color; |
|
|
var pixelValue = new Rgb96(redPixelData[x], greenPixelData[x], bluePixelData[x]); |
|
|
|
|
|
color.FromVector4(pixelValue.ToVector4()); |
|
|
|
|
|
pixelRow[x] = color; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -339,10 +346,9 @@ namespace SixLabors.ImageSharp.Formats.OpenExr |
|
|
private int ReadPixelRowChannelHalfSingle(Span<byte> decompressedPixelData, Span<float> channelData) |
|
|
private int ReadPixelRowChannelHalfSingle(Span<byte> decompressedPixelData, Span<float> channelData) |
|
|
{ |
|
|
{ |
|
|
int offset = 0; |
|
|
int offset = 0; |
|
|
ushort shortValue = 0; |
|
|
|
|
|
for (int x = 0; x < this.Width; x++) |
|
|
for (int x = 0; x < this.Width; x++) |
|
|
{ |
|
|
{ |
|
|
shortValue = BinaryPrimitives.ReadUInt16LittleEndian(decompressedPixelData.Slice(offset, 2)); |
|
|
ushort shortValue = BinaryPrimitives.ReadUInt16LittleEndian(decompressedPixelData.Slice(offset, 2)); |
|
|
channelData[x] = HalfTypeHelper.Unpack(shortValue); |
|
|
channelData[x] = HalfTypeHelper.Unpack(shortValue); |
|
|
offset += 2; |
|
|
offset += 2; |
|
|
} |
|
|
} |
|
|
@ -353,10 +359,9 @@ namespace SixLabors.ImageSharp.Formats.OpenExr |
|
|
private int ReadPixelRowChannelSingle(Span<byte> decompressedPixelData, Span<float> channelData) |
|
|
private int ReadPixelRowChannelSingle(Span<byte> decompressedPixelData, Span<float> channelData) |
|
|
{ |
|
|
{ |
|
|
int offset = 0; |
|
|
int offset = 0; |
|
|
int intValue = 0; |
|
|
|
|
|
for (int x = 0; x < this.Width; x++) |
|
|
for (int x = 0; x < this.Width; x++) |
|
|
{ |
|
|
{ |
|
|
intValue = BinaryPrimitives.ReadInt32LittleEndian(decompressedPixelData.Slice(offset, 4)); |
|
|
int intValue = BinaryPrimitives.ReadInt32LittleEndian(decompressedPixelData.Slice(offset, 4)); |
|
|
channelData[x] = Unsafe.As<int, float>(ref intValue); |
|
|
channelData[x] = Unsafe.As<int, float>(ref intValue); |
|
|
offset += 4; |
|
|
offset += 4; |
|
|
} |
|
|
} |
|
|
@ -668,5 +673,22 @@ namespace SixLabors.ImageSharp.Formats.OpenExr |
|
|
|
|
|
|
|
|
return bytesPerRow; |
|
|
return bytesPerRow; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private uint RowsPerBlock() |
|
|
|
|
|
{ |
|
|
|
|
|
switch (this.Compression) |
|
|
|
|
|
{ |
|
|
|
|
|
case ExrCompressionType.Zip: |
|
|
|
|
|
case ExrCompressionType.Pxr24: |
|
|
|
|
|
return 16; |
|
|
|
|
|
case ExrCompressionType.B44: |
|
|
|
|
|
case ExrCompressionType.B44A: |
|
|
|
|
|
case ExrCompressionType.Piz: |
|
|
|
|
|
return 32; |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|