diff --git a/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs b/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs
index 0a15c37f01..c24bab9b84 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs
@@ -60,6 +60,58 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
return !left.Equals(right);
}
+ public static Block8x8 operator *(Block8x8 block, int value)
+ {
+ Block8x8 result = block;
+ for (int i = 0; i < Size; i++)
+ {
+ int val = result[i];
+ val *= value;
+ result[i] = (short)val;
+ }
+
+ return result;
+ }
+
+ public static Block8x8 operator /(Block8x8 block, int value)
+ {
+ Block8x8 result = block;
+ for (int i = 0; i < Size; i++)
+ {
+ int val = result[i];
+ val /= value;
+ result[i] = (short)val;
+ }
+
+ return result;
+ }
+
+ public static Block8x8 operator +(Block8x8 block, int value)
+ {
+ Block8x8 result = block;
+ for (int i = 0; i < Size; i++)
+ {
+ int val = result[i];
+ val += value;
+ result[i] = (short)val;
+ }
+
+ return result;
+ }
+
+ public static Block8x8 operator -(Block8x8 block, int value)
+ {
+ Block8x8 result = block;
+ for (int i = 0; i < Size; i++)
+ {
+ int val = result[i];
+ val -= value;
+ result[i] = (short)val;
+ }
+
+ return result;
+ }
+
///
/// Pointer-based "Indexer" (getter part)
///
@@ -195,5 +247,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
return result;
}
+
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
index 9a1acecfa2..233cc0580b 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
@@ -89,6 +89,58 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
set => this[(y * 8) + x] = value;
}
+ public static Block8x8F operator *(Block8x8F block, float value)
+ {
+ Block8x8F result = block;
+ for (int i = 0; i < Size; i++)
+ {
+ float val = result[i];
+ val *= value;
+ result[i] = val;
+ }
+
+ return result;
+ }
+
+ public static Block8x8F operator /(Block8x8F block, float value)
+ {
+ Block8x8F result = block;
+ for (int i = 0; i < Size; i++)
+ {
+ float val = result[i];
+ val /= value;
+ result[i] = (float)val;
+ }
+
+ return result;
+ }
+
+ public static Block8x8F operator +(Block8x8F block, float value)
+ {
+ Block8x8F result = block;
+ for (int i = 0; i < Size; i++)
+ {
+ float val = result[i];
+ val += value;
+ result[i] = (float)val;
+ }
+
+ return result;
+ }
+
+ public static Block8x8F operator -(Block8x8F block, float value)
+ {
+ Block8x8F result = block;
+ for (int i = 0; i < Size; i++)
+ {
+ float val = result[i];
+ val -= value;
+ result[i] = (float)val;
+ }
+
+ return result;
+ }
+
///
/// Pointer-based "Indexer" (getter part)
///
@@ -119,18 +171,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
fp[idx] = value;
}
- //public Block8x8 AsInt16Block()
- //{
- // // TODO: Optimize this
- // var result = default(Block8x8);
- // for (int i = 0; i < Size; i++)
- // {
- // result[i] = (short)this[i];
- // }
-
- // return result;
- //}
-
///
/// Fill the block with defaults (zeroes)
///
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs
index 05fe178cb3..66d9e8d0c9 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs
@@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.CompareBlocks(data.ConvertAllToFloat(), src, 2f);
}
- [Theory]
+ [Theory(Skip = "Sandboxing only! (Incorrect reference implementation)")]
[InlineData(42)]
[InlineData(1)]
[InlineData(2)]
@@ -82,12 +82,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
int[] intData = JpegUtilityTestFixture.Create8x8RandomIntData(-1000, 1000, seed);
float[] floatSrc = intData.ConvertAllToFloat();
- ReferenceImplementations.StandardIntegerDCT.TransformFDCTInplace(intData);
+ ReferenceImplementations.StandardIntegerDCT.Subtract128_TransformFDCT_Upscale8_Inplace(intData);
float[] dest = new float[64];
float[] temp = new float[64];
- ReferenceImplementations.FastFloatingPointDCT.fDCT2D_llm(floatSrc, dest, temp, offsetSourceByNeg128: true);
+ ReferenceImplementations.FastFloatingPointDCT.fDCT2D_llm(floatSrc, dest, temp, subtract128FromSource: true);
this.CompareBlocks(intData.ConvertAllToFloat(), dest, 2f);
}
@@ -104,7 +104,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
source.LoadFrom(floatData);
Block8x8F expected = ReferenceImplementations.AccurateDCT.TransformFDCT(ref source);
- Block8x8F actual = ReferenceImplementations.FastFloatingPointDCT.TransformFDCT(ref source);
+ Block8x8F actual = ReferenceImplementations.FastFloatingPointDCT.TransformFDCT_UpscaleBy8(ref source);
+ actual /= 8;
this.CompareBlocks(expected, actual, 1f);
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.StandardIntegerDCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.StandardIntegerDCT.cs
index 4fdfd62f33..1ea9609bb4 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.StandardIntegerDCT.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.StandardIntegerDCT.cs
@@ -1,3 +1,4 @@
+// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{
using System;
@@ -10,16 +11,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public partial class ReferenceImplementationsTests
{
- public class StandardIntegerDCT
+ public class StandardIntegerDCT : JpegUtilityTestFixture
{
public StandardIntegerDCT(ITestOutputHelper output)
+ : base(output)
{
- this.Output = output;
}
- private ITestOutputHelper Output { get; }
-
- [Theory]
+ [Theory(Skip = "Sandboxing only! (Incorrect reference implementation)")]
[InlineData(42)]
[InlineData(1)]
[InlineData(2)]
@@ -54,18 +53,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{
int[] data = Create8x8RandomIntData(-1000, 1000, seed);
- Block8x8 source = default(Block8x8);
+ Block8x8F source = default(Block8x8F);
source.LoadFrom(data);
- Block8x8 expected = ReferenceImplementations.AccurateDCT.TransformFDCT(ref source);
- Block8x8 actual = ReferenceImplementations.StandardIntegerDCT.TransformFDCT(ref source);
-
- long diff = Block8x8.TotalDifference(ref expected, ref actual);
- this.Output.WriteLine(expected.ToString());
- this.Output.WriteLine(actual.ToString());
- this.Output.WriteLine("DIFFERENCE: " + diff);
+ Block8x8F expected = ReferenceImplementations.AccurateDCT.TransformFDCT(ref source);
- Assert.True(diff < 4);
+ source += 128;
+ Block8x8 temp = source.RoundAsInt16Block();
+ Block8x8 actual8 = ReferenceImplementations.StandardIntegerDCT.Subtract128_TransformFDCT_Upscale8(ref temp);
+ Block8x8F actual = actual8.AsFloatBlock();
+ actual /= 8;
+
+ this.CompareBlocks(expected, actual, 1f);
}
@@ -79,7 +78,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Span block = original.AddScalarToAllValues(128);
- ReferenceImplementations.StandardIntegerDCT.TransformFDCTInplace(block);
+ ReferenceImplementations.StandardIntegerDCT.Subtract128_TransformFDCT_Upscale8_Inplace(block);
for (int i = 0; i < 64; i++)
{
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.AccurateDCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.AccurateDCT.cs
index 7f80b4f980..f46155ac42 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.AccurateDCT.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.AccurateDCT.cs
@@ -7,7 +7,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
internal static partial class ReferenceImplementations
{
///
- /// Reference implementations based on:
+ /// True accurate FDCT/IDCT implementations. We should test everything against them!
+ /// Based on:
/// https://github.com/keithw/mympeg2enc/blob/master/idct.c#L222
/// Claiming:
/// /* reference idct taken from "ieeetest.c"
@@ -18,8 +19,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
internal static class AccurateDCT
{
private static double[,] CosLut = InitCosLut();
-
-
+
public static Block8x8 TransformIDCT(ref Block8x8 block)
{
Block8x8F temp = block.AsFloatBlock();
@@ -50,27 +50,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
result.CopyTo(span);
}
-
-
- private static double[,] InitCosLut()
- {
- double[,] coslu = new double[8,8];
- int a, b;
- double tmp;
-
- for (a = 0; a < 8; a++)
- for (b = 0; b < 8; b++)
- {
- tmp = Math.Cos((double)((a + a + 1) * b) * (3.14159265358979323846 / 16.0));
- if (b == 0)
- {
- tmp /= Math.Sqrt(2.0);
- }
- coslu[a, b] = tmp * 0.5;
- }
- return coslu;
- }
-
public static Block8x8F TransformIDCT(ref Block8x8F block)
{
int x, y, u, v;
@@ -92,8 +71,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
}
return res;
}
-
-
+
public static Block8x8F TransformFDCT(ref Block8x8F block)
{
int x, y, u, v;
@@ -119,7 +97,26 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
}
return res;
- }
+ }
+
+ private static double[,] InitCosLut()
+ {
+ double[,] coslu = new double[8, 8];
+ int a, b;
+ double tmp;
+
+ for (a = 0; a < 8; a++)
+ for (b = 0; b < 8; b++)
+ {
+ tmp = Math.Cos((double)((a + a + 1) * b) * (3.14159265358979323846 / 16.0));
+ if (b == 0)
+ {
+ tmp /= Math.Sqrt(2.0);
+ }
+ coslu[a, b] = tmp * 0.5;
+ }
+ return coslu;
+ }
}
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.FastFloatingPointDCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.FastFloatingPointDCT.cs
index 6aea87330f..c4157f6947 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.FastFloatingPointDCT.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.FastFloatingPointDCT.cs
@@ -1,3 +1,4 @@
+// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
{
using System;
@@ -24,7 +25,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
return result;
}
- public static Block8x8F TransformFDCT(ref Block8x8F source)
+ public static Block8x8F TransformFDCT_UpscaleBy8(ref Block8x8F source)
{
float[] s = new float[64];
source.CopyTo(s);
@@ -480,15 +481,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
y[1] = c0 + c3;
y[7] = c0 - c3;
}
-
+
internal static void fDCT2D_llm(
Span s,
Span d,
Span temp,
bool downscaleBy8 = false,
- bool offsetSourceByNeg128 = false)
+ bool subtract128FromSource = false)
{
- Span sWorker = offsetSourceByNeg128 ? s.AddScalarToAllValues(-128f) : s;
+ Span sWorker = subtract128FromSource ? s.AddScalarToAllValues(-128f) : s;
for (int j = 0; j < 8; j++)
{
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.StandardIntegerDCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.StandardIntegerDCT.cs
index a1f70bcdd6..4d2a1e44ff 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.StandardIntegerDCT.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.StandardIntegerDCT.cs
@@ -1,3 +1,4 @@
+// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
{
using System;
@@ -65,11 +66,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
///
private const int CenterJSample = 128;
- public static Block8x8 TransformFDCT(ref Block8x8 block)
+ public static Block8x8 Subtract128_TransformFDCT_Upscale8(ref Block8x8 block)
{
int[] temp = new int[Block8x8.Size];
block.CopyTo(temp);
- TransformFDCTInplace(temp);
+ Subtract128_TransformFDCT_Upscale8_Inplace(temp);
var result = default(Block8x8);
result.LoadFrom(temp);
return result;
@@ -91,7 +92,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
/// Leave results scaled up by an overall factor of 8.
///
/// The block of coefficients.
- public static void TransformFDCTInplace(Span block)
+ public static void Subtract128_TransformFDCT_Upscale8_Inplace(Span block)
{
// Pass 1: process rows.
for (int y = 0; y < 8; y++)