Browse Source

Fused transpose with zig-zag ordering

pull/1847/head
Dmitry Pentin 5 years ago
parent
commit
2294693446
  1. 10
      src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs
  2. 16
      src/ImageSharp/Formats/Jpeg/Components/ZigZag.cs
  3. 3
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  4. 14
      tests/ImageSharp.Tests/Formats/Jpg/ZigZagTests.cs

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

@ -501,7 +501,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
i += r;
s = buffer.Receive(s);
Unsafe.Add(ref blockDataRef, ZigZag.ZigZagOrder[i++]) = (short)s;
Unsafe.Add(ref blockDataRef, ZigZag.TransposingOrder[i++]) = (short)s;
}
else
{
@ -570,7 +570,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
if (s != 0)
{
s = buffer.Receive(s);
Unsafe.Add(ref blockDataRef, ZigZag.ZigZagOrder[i]) = (short)(s << low);
Unsafe.Add(ref blockDataRef, ZigZag.TransposingOrder[i]) = (short)(s << low);
}
else
{
@ -646,7 +646,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
do
{
ref short coef = ref Unsafe.Add(ref blockDataRef, ZigZag.ZigZagOrder[k]);
ref short coef = ref Unsafe.Add(ref blockDataRef, ZigZag.TransposingOrder[k]);
if (coef != 0)
{
buffer.CheckBits();
@ -672,7 +672,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
if ((s != 0) && (k < 64))
{
Unsafe.Add(ref blockDataRef, ZigZag.ZigZagOrder[k]) = (short)s;
Unsafe.Add(ref blockDataRef, ZigZag.TransposingOrder[k]) = (short)s;
}
}
}
@ -681,7 +681,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
for (; k <= end; k++)
{
ref short coef = ref Unsafe.Add(ref blockDataRef, ZigZag.ZigZagOrder[k]);
ref short coef = ref Unsafe.Add(ref blockDataRef, ZigZag.TransposingOrder[k]);
if (coef != 0)
{

16
src/ImageSharp/Formats/Jpeg/Components/ZigZag.cs

@ -35,5 +35,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63
};
public static ReadOnlySpan<byte> TransposingOrder => new byte[]
{
0, 8, 1, 2, 9, 16, 24, 17,
10, 3, 4, 11, 18, 25, 32, 40,
33, 26, 19, 12, 5, 6, 13, 20,
27, 34, 41, 48, 56, 49, 42, 35,
28, 21, 14, 7, 15, 22, 29, 36,
43, 50, 57, 58, 51, 44, 37, 30,
23, 31, 38, 45, 52, 59, 60, 53,
46, 39, 47, 54, 61, 62, 55, 63,
// Extra entries for safety in decoder
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63
};
}
}

3
src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

@ -942,6 +942,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
break;
}
}
// Adjusting table for IDCT step during decompression
FastFloatingPointDCT.AdjustToIDCT(ref table);
}
}

14
tests/ImageSharp.Tests/Formats/Jpg/ZigZagTests.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Formats.Jpeg.Components;
using Xunit;
@ -9,8 +10,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Trait("Format", "Jpg")]
public class ZigZagTests
{
[Fact]
public void ZigZagCanHandleAllPossibleCoefficients()
private static void CanHandleAllPossibleCoefficients(ReadOnlySpan<byte> order)
{
// Mimic the behaviour of the huffman scan decoder using all possible byte values
short[] block = new short[64];
@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
if (s != 0)
{
i += r;
block[ZigZag.ZigZagOrder[i++]] = (short)s;
block[order[i++]] = (short)s;
}
else
{
@ -40,5 +40,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
}
}
[Fact]
public static void ZigZagCanHandleAllPossibleCoefficients() =>
CanHandleAllPossibleCoefficients(ZigZag.ZigZagOrder);
[Fact]
public static void TrasposingZigZagCanHandleAllPossibleCoefficients() =>
CanHandleAllPossibleCoefficients(ZigZag.TransposingOrder);
}
}

Loading…
Cancel
Save