Browse Source

Drop all GetBlockDataReference() usages

af/merge-core
Anton Firszov 8 years ago
parent
commit
f1f0bc04f9
  1. 39
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentExtensions.cs
  2. 58
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs
  3. 22
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs
  4. 3
      tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.ComponentData.cs

39
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentExtensions.cs

@ -1,39 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
/// <summary>
/// Extension methods for <see cref="IJpegComponent"/>
/// </summary>
internal static class JpegComponentExtensions
{
/// <summary>
/// Gets a reference to the <see cref="Block8x8"/> at the given row and column index from <see cref="IJpegComponent.SpectralBlocks"/>
/// </summary>
/// <param name="component">The <see cref="IJpegComponent"/></param>
/// <param name="column">The column</param>
/// <param name="row">The row</param>
/// <returns>The <see cref="Block8x8"/></returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static ref Block8x8 GetBlockReference(this IJpegComponent component, int column, int row)
{
return ref component.SpectralBlocks.GetRowSpan(row)[column];
}
/// <summary>
/// Gets a reference to the first item in a block
/// at the given row and column index from <see cref="IJpegComponent.SpectralBlocks"/>
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public static ref short GetBlockDataReference(this IJpegComponent component, int column, int row)
{
ref Block8x8 blockRef = ref component.GetBlockReference(column, row);
return ref Unsafe.As<Block8x8, short>(ref blockRef);
}
}
}

58
src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs

@ -1,8 +1,10 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{ {
@ -179,10 +181,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
int h = component.HorizontalSamplingFactor; int h = component.HorizontalSamplingFactor;
int v = component.VerticalSamplingFactor; int v = component.VerticalSamplingFactor;
int mcuRow = mcu / mcusPerLine;
// Scan out an mcu's worth of this component; that's just determined // Scan out an mcu's worth of this component; that's just determined
// by the basic H and V specified for the component // by the basic H and V specified for the component
for (int y = 0; y < v; y++) for (int y = 0; y < v; y++)
{ {
int blockRow = (mcuRow * v) + y;
Span<Block8x8> blockSpan = component.SpectralBlocks.GetRowSpan(blockRow);
for (int x = 0; x < h; x++) for (int x = 0; x < h; x++)
{ {
if (this.eof) if (this.eof)
@ -190,15 +196,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
return; return;
} }
int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine; int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * v) + y;
int blockCol = (mcuCol * h) + x; int blockCol = (mcuCol * h) + x;
this.DecodeBlockBaseline( this.DecodeBlockBaseline(
component, component,
blockRow, ref blockSpan[blockCol],
blockCol,
ref dcHuffmanTable, ref dcHuffmanTable,
ref acHuffmanTable, ref acHuffmanTable,
ref fastACRef); ref fastACRef);
@ -236,6 +239,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
int mcu = 0; int mcu = 0;
for (int j = 0; j < h; j++) for (int j = 0; j < h; j++)
{ {
// TODO: Isn't blockRow == j actually?
int blockRow = mcu / w;
Span<Block8x8> blockSpan = component.SpectralBlocks.GetRowSpan(blockRow);
for (int i = 0; i < w; i++) for (int i = 0; i < w; i++)
{ {
if (this.eof) if (this.eof)
@ -243,13 +250,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
return; return;
} }
int blockRow = mcu / w; // TODO: Isn't blockCol == i actually?
int blockCol = mcu % w; int blockCol = mcu % w;
this.DecodeBlockBaseline( this.DecodeBlockBaseline(
component, component,
blockRow, ref blockSpan[blockCol],
blockCol,
ref dcHuffmanTable, ref dcHuffmanTable,
ref acHuffmanTable, ref acHuffmanTable,
ref fastACRef); ref fastACRef);
@ -299,6 +305,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
// by the basic H and V specified for the component // by the basic H and V specified for the component
for (int y = 0; y < v; y++) for (int y = 0; y < v; y++)
{ {
int mcuRow = mcu / mcusPerLine;
int blockRow = (mcuRow * v) + y;
Span<Block8x8> blockSpan = component.SpectralBlocks.GetRowSpan(blockRow);
for (int x = 0; x < h; x++) for (int x = 0; x < h; x++)
{ {
if (this.eof) if (this.eof)
@ -306,15 +316,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
return; return;
} }
int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine; int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * v) + y;
int blockCol = (mcuCol * h) + x; int blockCol = (mcuCol * h) + x;
this.DecodeBlockProgressiveDC( this.DecodeBlockProgressiveDC(
component, component,
blockRow, ref blockSpan[blockCol],
blockCol,
ref dcHuffmanTable); ref dcHuffmanTable);
} }
} }
@ -351,6 +358,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
int mcu = 0; int mcu = 0;
for (int j = 0; j < h; j++) for (int j = 0; j < h; j++)
{ {
// TODO: isn't blockRow == j actually?
int blockRow = mcu / w;
Span<Block8x8> blockSpan = component.SpectralBlocks.GetRowSpan(blockRow);
for (int i = 0; i < w; i++) for (int i = 0; i < w; i++)
{ {
if (this.eof) if (this.eof)
@ -358,23 +369,23 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
return; return;
} }
int blockRow = mcu / w; // TODO: isn't blockCol == i actually?
int blockCol = mcu % w; int blockCol = mcu % w;
ref Block8x8 block = ref blockSpan[blockCol];
if (this.spectralStart == 0) if (this.spectralStart == 0)
{ {
this.DecodeBlockProgressiveDC( this.DecodeBlockProgressiveDC(
component, component,
blockRow, ref block,
blockCol,
ref dcHuffmanTable); ref dcHuffmanTable);
} }
else else
{ {
this.DecodeBlockProgressiveAC( this.DecodeBlockProgressiveAC(
component, component,
blockRow, ref block,
blockCol,
ref acHuffmanTable, ref acHuffmanTable,
ref fastACRef); ref fastACRef);
} }
@ -391,8 +402,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
private void DecodeBlockBaseline( private void DecodeBlockBaseline(
JpegComponent component, JpegComponent component,
int row, ref Block8x8 block,
int col,
ref HuffmanTable dcTable, ref HuffmanTable dcTable,
ref HuffmanTable acTable, ref HuffmanTable acTable,
ref short fastACRef) ref short fastACRef)
@ -405,7 +415,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
JpegThrowHelper.ThrowBadHuffmanCode(); JpegThrowHelper.ThrowBadHuffmanCode();
} }
ref short blockDataRef = ref component.GetBlockDataReference(col, row); ref short blockDataRef = ref Unsafe.As<Block8x8, short>(ref block);
int diff = t != 0 ? this.ExtendReceive(t) : 0; int diff = t != 0 ? this.ExtendReceive(t) : 0;
int dc = component.DcPredictor + diff; int dc = component.DcPredictor + diff;
@ -470,8 +480,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
private void DecodeBlockProgressiveDC( private void DecodeBlockProgressiveDC(
JpegComponent component, JpegComponent component,
int row, ref Block8x8 block,
int col,
ref HuffmanTable dcTable) ref HuffmanTable dcTable)
{ {
if (this.spectralEnd != 0) if (this.spectralEnd != 0)
@ -481,7 +490,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
this.CheckBits(); this.CheckBits();
ref short blockDataRef = ref component.GetBlockDataReference(col, row); ref short blockDataRef = ref Unsafe.As<Block8x8, short>(ref block);
if (this.successiveHigh == 0) if (this.successiveHigh == 0)
{ {
@ -506,8 +515,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
private void DecodeBlockProgressiveAC( private void DecodeBlockProgressiveAC(
JpegComponent component, JpegComponent component,
int row, ref Block8x8 block,
int col,
ref HuffmanTable acTable, ref HuffmanTable acTable,
ref short fastACRef) ref short fastACRef)
{ {
@ -516,7 +524,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
JpegThrowHelper.ThrowImageFormatException("Can't merge DC and AC."); JpegThrowHelper.ThrowImageFormatException("Can't merge DC and AC.");
} }
ref short blockDataRef = ref component.GetBlockDataReference(col, row); ref short blockDataRef = ref Unsafe.As<Block8x8, short>(ref block);
if (this.successiveHigh == 0) if (this.successiveHigh == 0)
{ {

22
tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs

@ -46,15 +46,19 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage); private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);
// NOTE:
// The scaled result for very large image "TestImages.Jpeg.Issues.ExifGetString750Transform"
// is almost the same as the result for Jpeg420Exif,
// which proves that the execution time for the most common YCbCr 420 path scales linearly
[Params( [Params(
TestImages.Jpeg.Baseline.Lake, TestImages.Jpeg.Baseline.Lake,
TestImages.Jpeg.Issues.BadRstProgressive518, TestImages.Jpeg.Issues.BadRstProgressive518,
TestImages.Jpeg.Issues.ExifGetString750Transform,
TestImages.Jpeg.Baseline.Jpeg420Exif TestImages.Jpeg.Baseline.Jpeg420Exif
)] )]
public string TestImage { get; set; } public string TestImage { get; set; }
[GlobalSetup] [GlobalSetup]
public void ReadImages() public void ReadImages()
{ {
@ -110,16 +114,16 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
// RESULTS (2018 November 4): // RESULTS (2018 November 4):
// Method | TestImage | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Gen 1 | Gen 2 | Allocated | // Method | TestImage | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
// ------------------------------- |-------------------------------------------- |-----------:|-----------:|----------:|-------:|---------:|----------:|---------:|---------:|------------:| // ------------------------------- |-------------------------------------------- |-----------:|-----------:|----------:|-------:|---------:|----------:|---------:|---------:|------------:|
// 'Decode Jpeg - System.Drawing' | Jpg/baseline/Lake.jpg | 6.291 ms | 1.200 ms | 0.0678 ms | 1.00 | 0.00 | 62.5000 | - | - | 205.83 KB | // 'Decode Jpeg - System.Drawing' | Jpg/baseline/Lake.jpg | 6.117 ms | 0.3923 ms | 0.0222 ms | 1.00 | 0.00 | 62.5000 | - | - | 205.83 KB |
// 'Decode Jpeg - ImageSharp' | Jpg/baseline/Lake.jpg | 18.493 ms | 3.025 ms | 0.1709 ms | 2.94 | 0.03 | - | - | - | 19.97 KB | // 'Decode Jpeg - ImageSharp' | Jpg/baseline/Lake.jpg | 18.126 ms | 0.6023 ms | 0.0340 ms | 2.96 | 0.01 | - | - | - | 19.97 KB |
// | | | | | | | | | | | // | | | | | | | | | | |
// 'Decode Jpeg - System.Drawing' | Jpg/baseline/jpeg420exif.jpg | 16.962 ms | 1.446 ms | 0.0817 ms | 1.00 | 0.00 | 218.7500 | - | - | 757.04 KB | // 'Decode Jpeg - System.Drawing' | Jpg/baseline/jpeg420exif.jpg | 17.063 ms | 2.6096 ms | 0.1474 ms | 1.00 | 0.00 | 218.7500 | - | - | 757.04 KB |
// 'Decode Jpeg - ImageSharp' | Jpg/baseline/jpeg420exif.jpg | 42.105 ms | 4.496 ms | 0.2540 ms | 2.48 | 0.02 | - | - | - | 21.94 KB | // 'Decode Jpeg - ImageSharp' | Jpg/baseline/jpeg420exif.jpg | 41.366 ms | 1.0115 ms | 0.0572 ms | 2.42 | 0.02 | - | - | - | 21.94 KB |
// | | | | | | | | | | | // | | | | | | | | | | |
// 'Decode Jpeg - System.Drawing' | Jpg/issues/Issue518-Bad-RST-Progressive.jpg | 432.344 ms | 89.746 ms | 5.0708 ms | 1.00 | 0.00 | 2375.0000 | - | - | 7403.76 KB | // 'Decode Jpeg - System.Drawing' | Jpg/issues/Issue518-Bad-RST-Progressive.jpg | 428.282 ms | 94.9163 ms | 5.3629 ms | 1.00 | 0.00 | 2375.0000 | - | - | 7403.76 KB |
// 'Decode Jpeg - ImageSharp' | Jpg/issues/Issue518-Bad-RST-Progressive.jpg | 421.292 ms | 128.587 ms | 7.2654 ms | 0.97 | 0.02 | 125.0000 | 125.0000 | 125.0000 | 35186.98 KB | // 'Decode Jpeg - ImageSharp' | Jpg/issues/Issue518-Bad-RST-Progressive.jpg | 386.698 ms | 33.0065 ms | 1.8649 ms | 0.90 | 0.01 | 125.0000 | 125.0000 | 125.0000 | 35186.97 KB |
// | | | | | | | | | | | // | | | | | | | | | | |
// 'Decode Jpeg - System.Drawing' | Jpg/issues/issue750-exif-tranform.jpg | 94.723 ms | 4.663 ms | 0.2635 ms | 1.00 | 0.00 | 1750.0000 | - | - | 5492.63 KB | // 'Decode Jpeg - System.Drawing' | Jpg/issues/issue750-exif-tranform.jpg | 95.192 ms | 3.1762 ms | 0.1795 ms | 1.00 | 0.00 | 1750.0000 | - | - | 5492.63 KB |
// 'Decode Jpeg - ImageSharp' | Jpg/issues/issue750-exif-tranform.jpg | 234.071 ms | 37.979 ms | 2.1459 ms | 2.47 | 0.02 | 312.5000 | 312.5000 | 312.5000 | 58834.45 KB | // 'Decode Jpeg - ImageSharp' | Jpg/issues/issue750-exif-tranform.jpg | 230.158 ms | 48.8128 ms | 2.7580 ms | 2.42 | 0.02 | 312.5000 | 312.5000 | 312.5000 | 58834.66 KB |
} }
} }

3
tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.ComponentData.cs

@ -67,9 +67,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
for (int y = 0; y < result.HeightInBlocks; y++) for (int y = 0; y < result.HeightInBlocks; y++)
{ {
Span<Block8x8> blockRow = c.SpectralBlocks.GetRowSpan(y);
for (int x = 0; x < result.WidthInBlocks; x++) for (int x = 0; x < result.WidthInBlocks; x++)
{ {
short[] data = c.GetBlockReference(x, y).ToArray(); short[] data = blockRow[x].ToArray();
result.MakeBlock(data, y, x); result.MakeBlock(data, y, x);
} }
} }

Loading…
Cancel
Save