Skip to content

Commit e11f318

Browse files
Merge pull request #1847 from br3aker/jpeg-idct-zigzag-optimization
Jpeg new IDCT & fused zigzag/transpose steps
2 parents 05c3f2b + da82761 commit e11f318

File tree

16 files changed

+612
-566
lines changed

16 files changed

+612
-566
lines changed

src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,64 @@ public nint GetLastNonZeroIndex()
337337
}
338338
}
339339

340+
/// <summary>
341+
/// Transpose the block inplace.
342+
/// </summary>
343+
[MethodImpl(InliningOptions.ShortMethod)]
344+
public void TransposeInplace()
345+
{
346+
ref short elemRef = ref Unsafe.As<Block8x8, short>(ref this);
347+
348+
// row #0
349+
Swap(ref Unsafe.Add(ref elemRef, 1), ref Unsafe.Add(ref elemRef, 8));
350+
Swap(ref Unsafe.Add(ref elemRef, 2), ref Unsafe.Add(ref elemRef, 16));
351+
Swap(ref Unsafe.Add(ref elemRef, 3), ref Unsafe.Add(ref elemRef, 24));
352+
Swap(ref Unsafe.Add(ref elemRef, 4), ref Unsafe.Add(ref elemRef, 32));
353+
Swap(ref Unsafe.Add(ref elemRef, 5), ref Unsafe.Add(ref elemRef, 40));
354+
Swap(ref Unsafe.Add(ref elemRef, 6), ref Unsafe.Add(ref elemRef, 48));
355+
Swap(ref Unsafe.Add(ref elemRef, 7), ref Unsafe.Add(ref elemRef, 56));
356+
357+
// row #1
358+
Swap(ref Unsafe.Add(ref elemRef, 10), ref Unsafe.Add(ref elemRef, 17));
359+
Swap(ref Unsafe.Add(ref elemRef, 11), ref Unsafe.Add(ref elemRef, 25));
360+
Swap(ref Unsafe.Add(ref elemRef, 12), ref Unsafe.Add(ref elemRef, 33));
361+
Swap(ref Unsafe.Add(ref elemRef, 13), ref Unsafe.Add(ref elemRef, 41));
362+
Swap(ref Unsafe.Add(ref elemRef, 14), ref Unsafe.Add(ref elemRef, 49));
363+
Swap(ref Unsafe.Add(ref elemRef, 15), ref Unsafe.Add(ref elemRef, 57));
364+
365+
// row #2
366+
Swap(ref Unsafe.Add(ref elemRef, 19), ref Unsafe.Add(ref elemRef, 26));
367+
Swap(ref Unsafe.Add(ref elemRef, 20), ref Unsafe.Add(ref elemRef, 34));
368+
Swap(ref Unsafe.Add(ref elemRef, 21), ref Unsafe.Add(ref elemRef, 42));
369+
Swap(ref Unsafe.Add(ref elemRef, 22), ref Unsafe.Add(ref elemRef, 50));
370+
Swap(ref Unsafe.Add(ref elemRef, 23), ref Unsafe.Add(ref elemRef, 58));
371+
372+
// row #3
373+
Swap(ref Unsafe.Add(ref elemRef, 28), ref Unsafe.Add(ref elemRef, 35));
374+
Swap(ref Unsafe.Add(ref elemRef, 29), ref Unsafe.Add(ref elemRef, 43));
375+
Swap(ref Unsafe.Add(ref elemRef, 30), ref Unsafe.Add(ref elemRef, 51));
376+
Swap(ref Unsafe.Add(ref elemRef, 31), ref Unsafe.Add(ref elemRef, 59));
377+
378+
// row #4
379+
Swap(ref Unsafe.Add(ref elemRef, 37), ref Unsafe.Add(ref elemRef, 44));
380+
Swap(ref Unsafe.Add(ref elemRef, 38), ref Unsafe.Add(ref elemRef, 52));
381+
Swap(ref Unsafe.Add(ref elemRef, 39), ref Unsafe.Add(ref elemRef, 60));
382+
383+
// row #5
384+
Swap(ref Unsafe.Add(ref elemRef, 46), ref Unsafe.Add(ref elemRef, 53));
385+
Swap(ref Unsafe.Add(ref elemRef, 47), ref Unsafe.Add(ref elemRef, 61));
386+
387+
// row #6
388+
Swap(ref Unsafe.Add(ref elemRef, 55), ref Unsafe.Add(ref elemRef, 62));
389+
390+
static void Swap(ref short a, ref short b)
391+
{
392+
short tmp = a;
393+
a = b;
394+
b = tmp;
395+
}
396+
}
397+
340398
/// <summary>
341399
/// Calculate the total sum of absolute differences of elements in 'a' and 'b'.
342400
/// </summary>

src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ private void DecodeBlockBaseline(
502502
{
503503
i += r;
504504
s = buffer.Receive(s);
505-
Unsafe.Add(ref blockDataRef, ZigZag.ZigZagOrder[i++]) = (short)s;
505+
Unsafe.Add(ref blockDataRef, ZigZag.TransposingOrder[i++]) = (short)s;
506506
}
507507
else
508508
{
@@ -571,7 +571,7 @@ private void DecodeBlockProgressiveAC(ref Block8x8 block, ref HuffmanTable acTab
571571
if (s != 0)
572572
{
573573
s = buffer.Receive(s);
574-
Unsafe.Add(ref blockDataRef, ZigZag.ZigZagOrder[i]) = (short)(s << low);
574+
Unsafe.Add(ref blockDataRef, ZigZag.TransposingOrder[i]) = (short)(s << low);
575575
}
576576
else
577577
{
@@ -647,7 +647,7 @@ private void DecodeBlockProgressiveACRefined(ref short blockDataRef, ref Huffman
647647

648648
do
649649
{
650-
ref short coef = ref Unsafe.Add(ref blockDataRef, ZigZag.ZigZagOrder[k]);
650+
ref short coef = ref Unsafe.Add(ref blockDataRef, ZigZag.TransposingOrder[k]);
651651
if (coef != 0)
652652
{
653653
buffer.CheckBits();
@@ -673,7 +673,7 @@ private void DecodeBlockProgressiveACRefined(ref short blockDataRef, ref Huffman
673673

674674
if ((s != 0) && (k < 64))
675675
{
676-
Unsafe.Add(ref blockDataRef, ZigZag.ZigZagOrder[k]) = (short)s;
676+
Unsafe.Add(ref blockDataRef, ZigZag.TransposingOrder[k]) = (short)s;
677677
}
678678
}
679679
}
@@ -682,7 +682,7 @@ private void DecodeBlockProgressiveACRefined(ref short blockDataRef, ref Huffman
682682
{
683683
for (; k <= end; k++)
684684
{
685-
ref short coef = ref Unsafe.Add(ref blockDataRef, ZigZag.ZigZagOrder[k]);
685+
ref short coef = ref Unsafe.Add(ref blockDataRef, ZigZag.TransposingOrder[k]);
686686

687687
if (coef != 0)
688688
{

src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ internal struct JpegBlockPostProcessor
1818
/// </summary>
1919
public Block8x8F SourceBlock;
2020

21-
/// <summary>
22-
/// Temporal block to store intermediate computation results.
23-
/// </summary>
24-
public Block8x8F WorkspaceBlock;
25-
2621
/// <summary>
2722
/// The quantization table as <see cref="Block8x8F"/>.
2823
/// </summary>
@@ -45,7 +40,6 @@ public JpegBlockPostProcessor(IRawJpegData decoder, IJpegComponent component)
4540
this.subSamplingDivisors = component.SubSamplingDivisors;
4641

4742
this.SourceBlock = default;
48-
this.WorkspaceBlock = default;
4943
}
5044

5145
/// <summary>
@@ -71,7 +65,7 @@ public void ProcessBlockColorsInto(
7165
// Dequantize:
7266
block.MultiplyInPlace(ref this.DequantiazationTable);
7367

74-
FastFloatingPointDCT.TransformIDCT(ref block, ref this.WorkspaceBlock);
68+
FastFloatingPointDCT.TransformIDCT(ref block);
7569

7670
// To conform better to libjpeg we actually NEED TO loose precision here.
7771
// This is because they store blocks as Int16 between all the operations.

0 commit comments

Comments
 (0)