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