Skip to content

Commit 5ed6f24

Browse files
Reintroduce scanline optimizations
1 parent 0385ad0 commit 5ed6f24

File tree

3 files changed

+59
-28
lines changed

3 files changed

+59
-28
lines changed

src/ImageSharp/Formats/Png/PngDecoderCore.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ private void InitializeImage<TPixel>(ImageMetadata metadata, FrameControl? frame
567567
if (frameControl is { } control)
568568
{
569569
PngFrameMetadata frameMetadata = image.Frames.RootFrame.Metadata.GetPngFrameMetadata();
570-
frameMetadata.FromChunk(control);
570+
frameMetadata.FromChunk(in control);
571571
}
572572

573573
this.bytesPerPixel = this.CalculateBytesPerPixel();
@@ -837,7 +837,13 @@ private void DecodeInterlacedPixelData<TPixel>(in FrameControl frameControl, Def
837837
}
838838

839839
Span<TPixel> rowSpan = imageBuffer.DangerousGetRowSpan(currentRow);
840-
this.ProcessInterlacedDefilteredScanline(frameControl, this.scanline.GetSpan(), rowSpan, pngMetadata, pixelOffset: Adam7.FirstColumn[pass], increment: Adam7.ColumnIncrement[pass]);
840+
this.ProcessInterlacedDefilteredScanline(
841+
frameControl,
842+
this.scanline.GetSpan(),
843+
rowSpan,
844+
pngMetadata,
845+
pixelOffset: Adam7.FirstColumn[pass],
846+
increment: Adam7.ColumnIncrement[pass]);
841847

842848
this.SwapScanlineBuffers();
843849

@@ -935,6 +941,7 @@ private void ProcessDefilteredScanline<TPixel>(in FrameControl frameControl, int
935941

936942
case PngColorType.RgbWithAlpha:
937943
PngScanlineProcessor.ProcessRgbaScanline(
944+
this.configuration,
938945
this.header.BitDepth,
939946
in frameControl,
940947
scanlineSpan,
@@ -961,7 +968,13 @@ private void ProcessDefilteredScanline<TPixel>(in FrameControl frameControl, int
961968
/// <param name="pngMetadata">The png metadata.</param>
962969
/// <param name="pixelOffset">The column start index. Always 0 for none interlaced images.</param>
963970
/// <param name="increment">The column increment. Always 1 for none interlaced images.</param>
964-
private void ProcessInterlacedDefilteredScanline<TPixel>(in FrameControl frameControl, ReadOnlySpan<byte> defilteredScanline, Span<TPixel> rowSpan, PngMetadata pngMetadata, int pixelOffset = 0, int increment = 1)
971+
private void ProcessInterlacedDefilteredScanline<TPixel>(
972+
in FrameControl frameControl,
973+
ReadOnlySpan<byte> defilteredScanline,
974+
Span<TPixel> rowSpan,
975+
PngMetadata pngMetadata,
976+
int pixelOffset = 0,
977+
int increment = 1)
965978
where TPixel : unmanaged, IPixel<TPixel>
966979
{
967980
// Trim the first marker byte from the buffer
@@ -1034,6 +1047,7 @@ private void ProcessInterlacedDefilteredScanline<TPixel>(in FrameControl frameCo
10341047

10351048
case PngColorType.RgbWithAlpha:
10361049
PngScanlineProcessor.ProcessInterlacedRgbaScanline(
1050+
this.configuration,
10371051
this.header.BitDepth,
10381052
in frameControl,
10391053
scanlineSpan,

src/ImageSharp/Formats/Png/PngFrameMetadata.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ private PngFrameMetadata(PngFrameMetadata other)
5353
/// Initializes a new instance of the <see cref="PngFrameMetadata"/> class.
5454
/// </summary>
5555
/// <param name="frameControl">The chunk to create an instance from.</param>
56-
internal void FromChunk(FrameControl frameControl)
56+
internal void FromChunk(in FrameControl frameControl)
5757
{
5858
this.DelayNumerator = frameControl.DelayNumerator;
5959
this.DelayDenominator = frameControl.DelayDenominator;

src/ImageSharp/Formats/Png/PngScanlineProcessor.cs

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -216,18 +216,18 @@ public static void ProcessRgbScanline<TPixel>(
216216
int bytesPerPixel,
217217
int bytesPerSample,
218218
Color? transparentColor)
219-
where TPixel : unmanaged, IPixel<TPixel> =>
220-
ProcessInterlacedRgbScanline(
221-
configuration,
222-
bitDepth,
223-
frameControl,
224-
scanlineSpan,
225-
rowSpan,
226-
0,
227-
1,
228-
bytesPerPixel,
229-
bytesPerSample,
230-
transparentColor);
219+
where TPixel : unmanaged, IPixel<TPixel> =>
220+
ProcessInterlacedRgbScanline(
221+
configuration,
222+
bitDepth,
223+
frameControl,
224+
scanlineSpan,
225+
rowSpan,
226+
0,
227+
1,
228+
bytesPerPixel,
229+
bytesPerSample,
230+
transparentColor);
231231

232232
public static void ProcessInterlacedRgbScanline<TPixel>(
233233
Configuration configuration,
@@ -264,9 +264,16 @@ public static void ProcessInterlacedRgbScanline<TPixel>(
264264
Unsafe.Add(ref rowSpanRef, x) = pixel;
265265
}
266266
}
267+
else if (pixelOffset == 0 && increment == 1)
268+
{
269+
PixelOperations<TPixel>.Instance.FromRgb24Bytes(
270+
configuration,
271+
scanlineSpan[..(int)(frameControl.Width * bytesPerPixel)],
272+
rowSpan.Slice((int)frameControl.XOffset, (int)frameControl.Width),
273+
(int)frameControl.Width);
274+
}
267275
else
268276
{
269-
// TODO: Investigate reintroducing bulk operations optimization here.
270277
Rgb24 rgb = default;
271278
int o = 0;
272279
for (nuint x = offset; x < frameControl.XMax; x += increment, o += bytesPerPixel)
@@ -323,24 +330,27 @@ public static void ProcessInterlacedRgbScanline<TPixel>(
323330
}
324331

325332
public static void ProcessRgbaScanline<TPixel>(
333+
Configuration configuration,
326334
int bitDepth,
327335
in FrameControl frameControl,
328336
ReadOnlySpan<byte> scanlineSpan,
329337
Span<TPixel> rowSpan,
330338
int bytesPerPixel,
331339
int bytesPerSample)
332-
where TPixel : unmanaged, IPixel<TPixel> =>
333-
ProcessInterlacedRgbaScanline(
334-
bitDepth,
335-
frameControl,
336-
scanlineSpan,
337-
rowSpan,
338-
0,
339-
1,
340-
bytesPerPixel,
341-
bytesPerSample);
340+
where TPixel : unmanaged, IPixel<TPixel> =>
341+
ProcessInterlacedRgbaScanline(
342+
configuration,
343+
bitDepth,
344+
frameControl,
345+
scanlineSpan,
346+
rowSpan,
347+
0,
348+
1,
349+
bytesPerPixel,
350+
bytesPerSample);
342351

343352
public static void ProcessInterlacedRgbaScanline<TPixel>(
353+
Configuration configuration,
344354
int bitDepth,
345355
in FrameControl frameControl,
346356
ReadOnlySpan<byte> scanlineSpan,
@@ -370,9 +380,16 @@ public static void ProcessInterlacedRgbaScanline<TPixel>(
370380
Unsafe.Add(ref rowSpanRef, x) = pixel;
371381
}
372382
}
383+
else if (pixelOffset == 0 && increment == 1)
384+
{
385+
PixelOperations<TPixel>.Instance.FromRgba32Bytes(
386+
configuration,
387+
scanlineSpan[..(int)(frameControl.Width * bytesPerPixel)],
388+
rowSpan.Slice((int)frameControl.XOffset, (int)frameControl.Width),
389+
(int)frameControl.Width);
390+
}
373391
else
374392
{
375-
// TODO: Investigate reintroducing bulk operations optimization here.
376393
ref byte scanlineSpanRef = ref MemoryMarshal.GetReference(scanlineSpan);
377394
Rgba32 rgba = default;
378395
int o = 0;

0 commit comments

Comments
 (0)