Browse Source

Use ZigZag and reduce aggressive inlining

pull/525/head
James Jackson-South 8 years ago
parent
commit
5d0c94068c
  1. 6
      src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
  2. 48
      src/ImageSharp/Formats/Jpeg/Common/ZigZag.cs
  3. 4
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.DataPointers.cs
  4. 2
      src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs
  5. 34
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs
  6. 6
      tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.cs

6
src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs

@ -353,13 +353,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
/// <param name="qtPtr">Qt pointer</param> /// <param name="qtPtr">Qt pointer</param>
/// <param name="unzigPtr">Unzig pointer</param> /// <param name="unzigPtr">Unzig pointer</param>
// [MethodImpl(MethodImplOptions.AggressiveInlining)] // [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void DequantizeBlock(Block8x8F* blockPtr, Block8x8F* qtPtr, int* unzigPtr) public static unsafe void DequantizeBlock(Block8x8F* blockPtr, Block8x8F* qtPtr, byte* unzigPtr)
{ {
float* b = (float*)blockPtr; float* b = (float*)blockPtr;
float* qtp = (float*)qtPtr; float* qtp = (float*)qtPtr;
for (int qtIndex = 0; qtIndex < Size; qtIndex++) for (int qtIndex = 0; qtIndex < Size; qtIndex++)
{ {
int blockIndex = unzigPtr[qtIndex]; byte blockIndex = unzigPtr[qtIndex];
float* unzigPos = b + blockIndex; float* unzigPos = b + blockIndex;
float val = *unzigPos; float val = *unzigPos;
@ -381,7 +381,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
Block8x8F* block, Block8x8F* block,
Block8x8F* dest, Block8x8F* dest,
Block8x8F* qt, Block8x8F* qt,
int* unzigPtr) byte* unzigPtr)
{ {
float* s = (float*)block; float* s = (float*)block;
float* d = (float*)dest; float* d = (float*)dest;

48
src/ImageSharp/Formats/Jpeg/Common/ZigZag.cs

@ -1,6 +1,7 @@
// 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;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common namespace SixLabors.ImageSharp.Formats.Jpeg.Common
@ -11,25 +12,52 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
/// unzig[3] is the column and row of the fourth element in zigzag order. The /// unzig[3] is the column and row of the fourth element in zigzag order. The
/// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2). /// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2).
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct ZigZag internal unsafe struct ZigZag
{ {
/// <summary> /// <summary>
/// Copy of <see cref="Unzig"/> in a value type /// Copy of <see cref="Unzig"/> in a value type
/// </summary> /// </summary>
public fixed int Data[64]; public fixed byte Data[64];
/// <summary> /// <summary>
/// Unzig maps from the zigzag ordering to the natural ordering. For example, /// Unzig maps from the zigzag ordering to the natural ordering. For example,
/// unzig[3] is the column and row of the fourth element in zigzag order. The /// unzig[3] is the column and row of the fourth element in zigzag order. The
/// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2). /// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2).
/// </summary> /// </summary>
private static readonly int[] Unzig = private static readonly byte[] Unzig =
{
0,
1, 8,
16, 9, 2,
3, 10, 17, 24,
32, 25, 18, 11, 4,
5, 12, 19, 26, 33, 40,
48, 41, 34, 27, 20, 13, 6,
7, 14, 21, 28, 35, 42, 49, 56,
57, 50, 43, 36, 29, 22, 15,
23, 30, 37, 44, 51, 58,
59, 52, 45, 38, 31,
39, 46, 53, 60,
61, 54, 47,
55, 62,
63
};
/// <summary>
/// Returns the value at the given index
/// </summary>
/// <param name="idx">The index</param>
/// <returns>The <see cref="byte"/></returns>
public byte this[int idx]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{ {
0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, ref byte self = ref Unsafe.As<ZigZag, byte>(ref this);
40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, return Unsafe.Add(ref self, idx);
43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, }
53, 60, 61, 54, 47, 55, 62, 63, }
};
/// <summary> /// <summary>
/// Creates and fills an instance of <see cref="ZigZag"/> with Jpeg unzig indices /// Creates and fills an instance of <see cref="ZigZag"/> with Jpeg unzig indices
@ -37,8 +65,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
/// <returns>The new instance</returns> /// <returns>The new instance</returns>
public static ZigZag CreateUnzigTable() public static ZigZag CreateUnzigTable()
{ {
ZigZag result = default(ZigZag); ZigZag result = default;
int* unzigPtr = result.Data; byte* unzigPtr = result.Data;
Marshal.Copy(Unzig, 0, (IntPtr)unzigPtr, 64); Marshal.Copy(Unzig, 0, (IntPtr)unzigPtr, 64);
return result; return result;
} }
@ -48,7 +76,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
/// </summary> /// </summary>
public static Block8x8F CreateDequantizationTable(ref Block8x8F qt) public static Block8x8F CreateDequantizationTable(ref Block8x8F qt)
{ {
Block8x8F result = default(Block8x8F); Block8x8F result = default;
for (int i = 0; i < 64; i++) for (int i = 0; i < 64; i++)
{ {

4
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.DataPointers.cs

@ -21,9 +21,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
public Block8x8* Block; public Block8x8* Block;
/// <summary> /// <summary>
/// Pointer to <see cref="ComputationData.Unzig"/> as int* /// Pointer to <see cref="ComputationData.Unzig"/> as byte*
/// </summary> /// </summary>
public int* Unzig; public byte* Unzig;
/// <summary> /// <summary>
/// Pointer to <see cref="ComputationData.ScanData"/> as Scan* /// Pointer to <see cref="ComputationData.ScanData"/> as Scan*

2
src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs

@ -489,7 +489,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
Block8x8F* tempDest1, Block8x8F* tempDest1,
Block8x8F* tempDest2, Block8x8F* tempDest2,
Block8x8F* quant, Block8x8F* quant,
int* unzigPtr) byte* unzigPtr)
{ {
FastFloatingPointDCT.TransformFDCT(ref *src, ref *tempDest1, ref *tempDest2); FastFloatingPointDCT.TransformFDCT(ref *src, ref *tempDest1, ref *tempDest2);

34
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs

@ -17,27 +17,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// </summary> /// </summary>
internal struct PdfJsScanDecoder internal struct PdfJsScanDecoder
{ {
/// <summary> private ZigZag dctZigZag;
/// Gets the ZigZag scan table
/// </summary>
private static readonly byte[] DctZigZag =
{
0,
1, 8,
16, 9, 2,
3, 10, 17, 24,
32, 25, 18, 11, 4,
5, 12, 19, 26, 33, 40,
48, 41, 34, 27, 20, 13, 6,
7, 14, 21, 28, 35, 42, 49, 56,
57, 50, 43, 36, 29, 22, 15,
23, 30, 37, 44, 51, 58,
59, 52, 45, 38, 31,
39, 46, 53, 60,
61, 54, 47,
55, 62,
63
};
private byte[] markerBuffer; private byte[] markerBuffer;
@ -98,6 +78,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
int successivePrev, int successivePrev,
int successive) int successive)
{ {
this.dctZigZag = ZigZag.CreateUnzigTable();
this.markerBuffer = new byte[2]; this.markerBuffer = new byte[2];
this.compIndex = componentIndex; this.compIndex = componentIndex;
this.specStart = spectralStart; this.specStart = spectralStart;
@ -195,7 +176,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeScanBaseline( private void DecodeScanBaseline(
PdfJsHuffmanTables dcHuffmanTables, PdfJsHuffmanTables dcHuffmanTables,
PdfJsHuffmanTables acHuffmanTables, PdfJsHuffmanTables acHuffmanTables,
@ -256,7 +236,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeScanProgressive( private void DecodeScanProgressive(
PdfJsHuffmanTables huffmanTables, PdfJsHuffmanTables huffmanTables,
bool isAC, bool isAC,
@ -598,7 +577,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
return n + (-1 << length) + 1; return n + (-1 << length) + 1;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeBaseline(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, Stream stream) private void DecodeBaseline(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, Stream stream)
{ {
short t = this.DecodeHuffman(ref dcHuffmanTable, stream); short t = this.DecodeHuffman(ref dcHuffmanTable, stream);
@ -640,7 +618,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
break; break;
} }
ref byte z = ref DctZigZag[k]; byte z = this.dctZigZag[k];
short re = (short)this.ReceiveAndExtend(s, stream); short re = (short)this.ReceiveAndExtend(s, stream);
Unsafe.Add(ref blockDataRef, offset + z) = re; Unsafe.Add(ref blockDataRef, offset + z) = re;
k++; k++;
@ -672,7 +650,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
Unsafe.Add(ref blockDataRef, offset) |= (short)(bit << this.successiveState); Unsafe.Add(ref blockDataRef, offset) |= (short)(bit << this.successiveState);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeACFirst(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable acHuffmanTable, Stream stream) private void DecodeACFirst(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable acHuffmanTable, Stream stream)
{ {
if (this.eobrun > 0) if (this.eobrun > 0)
@ -708,13 +685,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
k += r; k += r;
ref byte z = ref DctZigZag[k]; byte z = this.dctZigZag[k];
Unsafe.Add(ref blockDataRef, offset + z) = (short)(this.ReceiveAndExtend(s, stream) * (1 << this.successiveState)); Unsafe.Add(ref blockDataRef, offset + z) = (short)(this.ReceiveAndExtend(s, stream) * (1 << this.successiveState));
k++; k++;
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeACSuccessive(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable acHuffmanTable, Stream stream) private void DecodeACSuccessive(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable acHuffmanTable, Stream stream)
{ {
int k = this.specStart; int k = this.specStart;
@ -723,7 +699,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
while (k <= e) while (k <= e)
{ {
int offsetZ = offset + DctZigZag[k]; int offsetZ = offset + this.dctZigZag[k];
ref short blockOffsetZRef = ref Unsafe.Add(ref blockDataRef, offsetZ); ref short blockOffsetZRef = ref Unsafe.Add(ref blockDataRef, offsetZ);
int sign = blockOffsetZRef < 0 ? -1 : 1; int sign = blockOffsetZRef < 0 ? -1 : 1;

6
tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.cs

@ -19,13 +19,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
/// </summary> /// </summary>
internal static partial class ReferenceImplementations internal static partial class ReferenceImplementations
{ {
public static unsafe void DequantizeBlock(Block8x8F* blockPtr, Block8x8F* qtPtr, int* unzigPtr) public static unsafe void DequantizeBlock(Block8x8F* blockPtr, Block8x8F* qtPtr, byte* unzigPtr)
{ {
float* b = (float*)blockPtr; float* b = (float*)blockPtr;
float* qtp = (float*)qtPtr; float* qtp = (float*)qtPtr;
for (int qtIndex = 0; qtIndex < Block8x8F.Size; qtIndex++) for (int qtIndex = 0; qtIndex < Block8x8F.Size; qtIndex++)
{ {
int i = unzigPtr[qtIndex]; byte i = unzigPtr[qtIndex];
float* unzigPos = b + i; float* unzigPos = b + i;
float val = *unzigPos; float val = *unzigPos;
@ -115,7 +115,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
/// <param name="dest">The destination block of integers</param> /// <param name="dest">The destination block of integers</param>
/// <param name="qt">The quantization table</param> /// <param name="qt">The quantization table</param>
/// <param name="unzigPtr">Pointer to <see cref="ZigZag.Data"/> </param> /// <param name="unzigPtr">Pointer to <see cref="ZigZag.Data"/> </param>
public static unsafe void QuantizeRational(Block8x8F* src, int* dest, Block8x8F* qt, int* unzigPtr) public static unsafe void QuantizeRational(Block8x8F* src, int* dest, Block8x8F* qt, byte* unzigPtr)
{ {
float* s = (float*)src; float* s = (float*)src;
float* q = (float*)qt; float* q = (float*)qt;

Loading…
Cancel
Save