diff --git a/src/ImageSharp/Formats/Exr/ExrDecoderCore.cs b/src/ImageSharp/Formats/Exr/ExrDecoderCore.cs index 44db67b618..52a08e495d 100644 --- a/src/ImageSharp/Formats/Exr/ExrDecoderCore.cs +++ b/src/ImageSharp/Formats/Exr/ExrDecoderCore.cs @@ -149,7 +149,8 @@ internal sealed class ExrDecoderCore : ImageDecoderCore using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(this.Compression, this.memoryAllocator, width, bytesPerBlock, bytesPerRow, rowsPerBlock, channelCount); - for (uint y = 0; y < height; y += rowsPerBlock) + int decodedRows = 0; + while (decodedRows < height) { ulong rowOffset = this.ReadUnsignedLong(stream); long nextRowOffsetPosition = stream.Position; @@ -175,6 +176,8 @@ internal sealed class ExrDecoderCore : ImageDecoderCore HalfVector4 pixelValue = new(redPixelData[x], greenPixelData[x], bluePixelData[x], hasAlpha ? alphaPixelData[x] : 1.0f); pixelRow[x] = TPixel.FromVector4(pixelValue.ToVector4()); } + + decodedRows++; } stream.Position = nextRowOffsetPosition; @@ -202,7 +205,8 @@ internal sealed class ExrDecoderCore : ImageDecoderCore using ExrBaseDecompressor decompressor = ExrDecompressorFactory.Create(this.Compression, this.memoryAllocator, width, bytesPerBlock, bytesPerRow, rowsPerBlock, channelCount); - for (uint y = 0; y < height; y += rowsPerBlock) + int decodedRows = 0; + while (decodedRows < height) { ulong rowOffset = this.ReadUnsignedLong(stream); long nextRowOffsetPosition = stream.Position; @@ -223,13 +227,15 @@ internal sealed class ExrDecoderCore : ImageDecoderCore offset += this.ReadUnsignedIntChannelData(stream, channel, decompressedPixelData.Slice(offset), redPixelData, greenPixelData, bluePixelData, alphaPixelData, width); } - stream.Position = nextRowOffsetPosition; - for (int x = 0; x < width; x++) { pixelRow[x] = ColorScaleTo32Bit(redPixelData[x], greenPixelData[x], bluePixelData[x], hasAlpha ? alphaPixelData[x] : uint.MaxValue); } + + decodedRows++; } + + stream.Position = nextRowOffsetPosition; } } diff --git a/src/ImageSharp/Formats/Exr/ExrEncoderCore.cs b/src/ImageSharp/Formats/Exr/ExrEncoderCore.cs index 2705a2057c..ff606b677a 100644 --- a/src/ImageSharp/Formats/Exr/ExrEncoderCore.cs +++ b/src/ImageSharp/Formats/Exr/ExrEncoderCore.cs @@ -201,10 +201,10 @@ internal sealed class ExrEncoderCore switch (this.pixelType) { case ExrPixelType.Float: - this.WriteSingleRow(rowBlockSpan, width, blueBuffer, greenBuffer, redBuffer); + WriteSingleRow(rowBlockSpan, width, blueBuffer, greenBuffer, redBuffer); break; case ExrPixelType.Half: - this.WriteHalfSingleRow(rowBlockSpan, width, blueBuffer, greenBuffer, redBuffer); + WriteHalfSingleRow(rowBlockSpan, width, blueBuffer, greenBuffer, redBuffer); break; } @@ -277,7 +277,7 @@ internal sealed class ExrEncoderCore // Write row data to row block buffer. Span rowBlockSpan = rowBlockBuffer.GetSpan().Slice((int)(rowsInBlockCount * bytesPerRow), (int)bytesPerRow); - this.WriteUnsignedIntRow(rowBlockSpan, width, blueBuffer, greenBuffer, redBuffer); + WriteUnsignedIntRow(rowBlockSpan, width, blueBuffer, greenBuffer, redBuffer); rowsInBlockCount++; } @@ -308,68 +308,68 @@ internal sealed class ExrEncoderCore stream.WriteByte(0); } - private void WriteSingleRow(Span buffer, int width, Span blueBuffer, Span greenBuffer, Span redBuffer) + private static void WriteSingleRow(Span buffer, int width, Span blueBuffer, Span greenBuffer, Span redBuffer) { int offset = 0; for (int x = 0; x < width; x++) { - this.WriteSingle(buffer.Slice(offset), blueBuffer[x]); + WriteSingleToBuffer(buffer.Slice(offset, 4), blueBuffer[x]); offset += 4; } for (int x = 0; x < width; x++) { - this.WriteSingle(buffer.Slice(offset), greenBuffer[x]); + WriteSingleToBuffer(buffer.Slice(offset, 4), greenBuffer[x]); offset += 4; } for (int x = 0; x < width; x++) { - this.WriteSingle(buffer.Slice(offset), redBuffer[x]); + WriteSingleToBuffer(buffer.Slice(offset, 4), redBuffer[x]); offset += 4; } } - private void WriteHalfSingleRow(Span buffer, int width, Span blueBuffer, Span greenBuffer, Span redBuffer) + private static void WriteHalfSingleRow(Span buffer, int width, Span blueBuffer, Span greenBuffer, Span redBuffer) { int offset = 0; for (int x = 0; x < width; x++) { - WriteHalfSingle(buffer.Slice(offset), blueBuffer[x]); + WriteHalfSingleToBuffer(buffer.Slice(offset, 2), blueBuffer[x]); offset += 2; } for (int x = 0; x < width; x++) { - WriteHalfSingle(buffer.Slice(offset), greenBuffer[x]); + WriteHalfSingleToBuffer(buffer.Slice(offset, 2), greenBuffer[x]); offset += 2; } for (int x = 0; x < width; x++) { - WriteHalfSingle(buffer.Slice(offset), redBuffer[x]); + WriteHalfSingleToBuffer(buffer.Slice(offset, 2), redBuffer[x]); offset += 2; } } - private void WriteUnsignedIntRow(Span buffer, int width, Span blueBuffer, Span greenBuffer, Span redBuffer) + private static void WriteUnsignedIntRow(Span buffer, int width, Span blueBuffer, Span greenBuffer, Span redBuffer) { int offset = 0; for (int x = 0; x < width; x++) { - WriteUnsignedInt(buffer.Slice(offset), blueBuffer[x]); + WriteUnsignedIntToBuffer(buffer.Slice(offset, 4), blueBuffer[x]); offset += 4; } for (int x = 0; x < width; x++) { - WriteUnsignedInt(buffer.Slice(offset), greenBuffer[x]); + WriteUnsignedIntToBuffer(buffer.Slice(offset, 4), greenBuffer[x]); offset += 4; } for (int x = 0; x < width; x++) { - WriteUnsignedInt(buffer.Slice(offset), redBuffer[x]); + WriteUnsignedIntToBuffer(buffer.Slice(offset, 4), redBuffer[x]); offset += 4; } } @@ -518,22 +518,15 @@ internal sealed class ExrEncoderCore } [MethodImpl(InliningOptions.ShortMethod)] - private unsafe void WriteSingle(Span buffer, float value) => BinaryPrimitives.WriteInt32LittleEndian(buffer, *(int*)&value); + private static unsafe void WriteSingleToBuffer(Span buffer, float value) => BinaryPrimitives.WriteInt32LittleEndian(buffer, *(int*)&value); [MethodImpl(InliningOptions.ShortMethod)] - private static void WriteHalfSingle(Span buffer, float value) + private static void WriteHalfSingleToBuffer(Span buffer, float value) { ushort valueAsShort = HalfTypeHelper.Pack(value); BinaryPrimitives.WriteUInt16LittleEndian(buffer, valueAsShort); } [MethodImpl(InliningOptions.ShortMethod)] - private void WriteUnsignedInt(Stream stream, uint value) - { - BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, value); - stream.Write(this.buffer.AsSpan(0, 4)); - } - - [MethodImpl(InliningOptions.ShortMethod)] - private static void WriteUnsignedInt(Span buffer, uint value) => BinaryPrimitives.WriteUInt32LittleEndian(buffer, value); + private static void WriteUnsignedIntToBuffer(Span buffer, uint value) => BinaryPrimitives.WriteUInt32LittleEndian(buffer, value); }