mirror of https://github.com/SixLabors/ImageSharp
Browse Source
* Lazily derive the huffman tables. Fix #839 * Lazy invoke fast table * Add performance tweaks to scan decoder. * Remove unneccessary classes.af/merge-core
committed by
GitHub
9 changed files with 212 additions and 189 deletions
@ -0,0 +1,61 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder |
|||
{ |
|||
internal unsafe struct FastACTable |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the lookahead array
|
|||
/// </summary>
|
|||
public fixed short Lookahead[512]; |
|||
|
|||
/// <summary>
|
|||
/// Derives a lookup table for fast AC entropy scan decoding.
|
|||
/// This can happen multiple times during progressive decoding but always outside mcu loops.
|
|||
/// </summary>
|
|||
/// <param name="huffmanTable">The AC Huffman table.</param>
|
|||
public void Derive(ref HuffmanTable huffmanTable) |
|||
{ |
|||
const int FastBits = ScanDecoder.FastBits; |
|||
ref short fastACRef = ref this.Lookahead[0]; |
|||
ref byte huffmanLookaheadRef = ref huffmanTable.Lookahead[0]; |
|||
ref byte huffmanValuesRef = ref huffmanTable.Values[0]; |
|||
ref short huffmanSizesRef = ref huffmanTable.Sizes[0]; |
|||
|
|||
int i; |
|||
for (i = 0; i < (1 << FastBits); i++) |
|||
{ |
|||
byte fast = Unsafe.Add(ref huffmanLookaheadRef, i); |
|||
Unsafe.Add(ref fastACRef, i) = 0; |
|||
|
|||
if (fast < byte.MaxValue) |
|||
{ |
|||
int rs = Unsafe.Add(ref huffmanValuesRef, fast); |
|||
int run = (rs >> 4) & 15; |
|||
int magbits = rs & 15; |
|||
int len = Unsafe.Add(ref huffmanSizesRef, fast); |
|||
|
|||
if (magbits != 0 && len + magbits <= FastBits) |
|||
{ |
|||
// Magnitude code followed by receive_extend code
|
|||
int k = ((i << len) & ((1 << FastBits) - 1)) >> (FastBits - magbits); |
|||
int m = 1 << (magbits - 1); |
|||
if (k < m) |
|||
{ |
|||
k += (int)((~0U << magbits) + 1); |
|||
} |
|||
|
|||
// If the result is small enough, we can fit it in fastAC table
|
|||
if (k >= -128 && k <= 127) |
|||
{ |
|||
Unsafe.Add(ref fastACRef, i) = (short)((k << 8) + (run << 4) + (len + magbits)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,90 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder |
|||
{ |
|||
/// <summary>
|
|||
/// The collection of lookup tables used for fast AC entropy scan decoding.
|
|||
/// </summary>
|
|||
internal sealed class FastACTables : IDisposable |
|||
{ |
|||
private Buffer2D<short> tables; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="FastACTables"/> class.
|
|||
/// </summary>
|
|||
/// <param name="memoryAllocator">The memory allocator used to allocate memory for image processing operations.</param>
|
|||
public FastACTables(MemoryAllocator memoryAllocator) => this.tables = memoryAllocator.Allocate2D<short>(512, 4, AllocationOptions.Clean); |
|||
|
|||
/// <summary>
|
|||
/// Gets the <see cref="Span{Int16}"/> representing the table at the index in the collection.
|
|||
/// </summary>
|
|||
/// <param name="index">The table index.</param>
|
|||
/// <returns><see cref="Span{Int16}"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public ReadOnlySpan<short> GetTableSpan(int index) => this.tables.GetRowSpan(index); |
|||
|
|||
/// <summary>
|
|||
/// Gets a reference to the first element of the AC table indexed by <see cref="JpegComponent.ACHuffmanTableId"/>
|
|||
/// </summary>
|
|||
/// <param name="component">The frame component.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public ref short GetAcTableReference(JpegComponent component) => ref this.tables.GetRowSpan(component.ACHuffmanTableId)[0]; |
|||
|
|||
/// <summary>
|
|||
/// Builds a lookup table for fast AC entropy scan decoding.
|
|||
/// </summary>
|
|||
/// <param name="index">The table index.</param>
|
|||
/// <param name="acHuffmanTables">The collection of AC Huffman tables.</param>
|
|||
public unsafe void BuildACTableLut(int index, HuffmanTables acHuffmanTables) |
|||
{ |
|||
const int FastBits = ScanDecoder.FastBits; |
|||
Span<short> fastAC = this.tables.GetRowSpan(index); |
|||
ref HuffmanTable huffmanTable = ref acHuffmanTables[index]; |
|||
|
|||
int i; |
|||
for (i = 0; i < (1 << FastBits); i++) |
|||
{ |
|||
byte fast = huffmanTable.Lookahead[i]; |
|||
fastAC[i] = 0; |
|||
if (fast < byte.MaxValue) |
|||
{ |
|||
int rs = huffmanTable.Values[fast]; |
|||
int run = (rs >> 4) & 15; |
|||
int magbits = rs & 15; |
|||
int len = huffmanTable.Sizes[fast]; |
|||
|
|||
if (magbits != 0 && len + magbits <= FastBits) |
|||
{ |
|||
// Magnitude code followed by receive_extend code
|
|||
int k = ((i << len) & ((1 << FastBits) - 1)) >> (FastBits - magbits); |
|||
int m = 1 << (magbits - 1); |
|||
if (k < m) |
|||
{ |
|||
k += (int)((~0U << magbits) + 1); |
|||
} |
|||
|
|||
// if the result is small enough, we can fit it in fastAC table
|
|||
if (k >= -128 && k <= 127) |
|||
{ |
|||
fastAC[i] = (short)((k << 8) + (run << 4) + (len + magbits)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void Dispose() |
|||
{ |
|||
this.tables?.Dispose(); |
|||
this.tables = null; |
|||
} |
|||
} |
|||
} |
|||
@ -1,26 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder |
|||
{ |
|||
/// <summary>
|
|||
/// Defines a 2 pairs of huffman tables.
|
|||
/// </summary>
|
|||
internal sealed class HuffmanTables |
|||
{ |
|||
private readonly HuffmanTable[] tables = new HuffmanTable[4]; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the table at the given index.
|
|||
/// </summary>
|
|||
/// <param name="index">The index</param>
|
|||
/// <returns>The <see cref="HuffmanTable"/></returns>
|
|||
public ref HuffmanTable this[int index] |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => ref this.tables[index]; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:b37ac1cc34680db9721542ef5354f7509860afd37888a24f6350f29f5b63eea1 |
|||
size 397 |
|||
Loading…
Reference in new issue