1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.imaging.formats.jpeg.decoder;
19
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21
22 import org.junit.jupiter.api.Test;
23
24 public class DctTest {
25
26 private static double[] REFERENCE_forwardDCT(final float[] vector) {
27 final double[] ret = new double[8];
28 for (int u = 0; u < 8; u++) {
29 double sum = 0;
30 final float cu = u == 0 ? (float) (1.0 / Math.sqrt(2)) : 1;
31 for (int x = 0; x < 8; x++) {
32 sum += vector[x] * Math.cos((2 * x + 1) * u * Math.PI / 16);
33 }
34 ret[u] = 0.5f * cu * sum;
35 }
36 return ret;
37 }
38
39 private static double[][] REFERENCE_forwardDCT(final float[][] matrix) {
40 final double[][] ret = new double[8][8];
41 for (int u = 0; u < 8; u++) {
42 for (int v = 0; v < 8; v++) {
43 double sum = 0;
44 final float cu = u == 0 ? (float) (1.0 / Math.sqrt(2)) : 1;
45 final float cv = v == 0 ? (float) (1.0 / Math.sqrt(2)) : 1;
46 for (int x = 0; x < 8; x++) {
47 for (int y = 0; y < 8; y++) {
48 sum += matrix[y][x] * Math.cos((2 * x + 1) * u * Math.PI / 16) * Math.cos((2 * y + 1) * v * Math.PI / 16);
49 }
50 }
51 ret[v][u] = 0.25f * cu * cv * sum;
52 }
53 }
54 return ret;
55 }
56
57 private static double[] REFERENCE_inverseDCT(final double[] vector) {
58 final double[] ret = new double[8];
59 for (int x = 0; x < 8; x++) {
60 double sum = 0;
61 for (int u = 0; u < 8; u++) {
62 final float cu = u == 0 ? (float) (1.0 / Math.sqrt(2)) : 1;
63 sum += cu * vector[u] * Math.cos((2 * x + 1) * u * Math.PI / 16);
64 }
65 ret[x] = 0.5f * sum;
66 }
67 return ret;
68 }
69
70 private static double[][] REFERENCE_inverseDCT(final double[][] matrix) {
71 final double[][] ret = new double[8][8];
72 for (int y = 0; y < 8; y++) {
73 for (int x = 0; x < 8; x++) {
74 double sum = 0;
75 for (int u = 0; u < 8; u++) {
76 for (int v = 0; v < 8; v++) {
77 final float cu = u == 0 ? (float) (1.0 / Math.sqrt(2)) : 1;
78 final float cv = v == 0 ? (float) (1.0 / Math.sqrt(2)) : 1;
79 sum += cu * cv * matrix[v][u] * Math.cos((2 * x + 1) * u * Math.PI / 16) * Math.cos((2 * y + 1) * v * Math.PI / 16);
80 }
81 }
82 ret[y][x] = 0.25f * sum;
83 }
84 }
85 return ret;
86 }
87
88 @Test
89 public void testMatrices() {
90 final float[] originalData = new float[8 * 8];
91 final float[][] originalData8x8 = new float[8][8];
92 for (int y = 0; y < 8; y++) {
93 for (int x = 0; x < 8; x++) {
94 final float value = 8 * y + x;
95 originalData8x8[y][x] = value;
96 originalData[8 * y + x] = value;
97 }
98 }
99
100 final double[][] transformed8x8 = REFERENCE_forwardDCT(originalData8x8);
101 final double[][] reversed8x8 = REFERENCE_inverseDCT(transformed8x8);
102 for (int y = 0; y < 8; y++) {
103 for (int x = 0; x < 8; x++) {
104 assertEquals(originalData8x8[y][x], reversed8x8[y][x], 0.001);
105 }
106 }
107
108 final float[] data = originalData.clone();
109 Dct.forwardDct8x8(data);
110 Dct.scaleQuantizationMatrix(data);
111 for (int y = 0; y < 8; y++) {
112 for (int x = 0; x < 8; x++) {
113 assertEquals(transformed8x8[y][x], data[8 * y + x], 0.001);
114 }
115 }
116
117 Dct.scaleDequantizationMatrix(data);
118 Dct.inverseDct8x8(data);
119 for (int y = 0; y < 8; y++) {
120 for (int x = 0; x < 8; x++) {
121 assertEquals(originalData8x8[y][x], data[8 * y + x], 0.001);
122 }
123 }
124 }
125
126 @Test
127 public void testVectors() {
128 final float[] originalData = new float[8];
129 for (int i = 0; i < 8; i++) {
130 originalData[i] = i;
131 }
132
133 final double[] transformed = REFERENCE_forwardDCT(originalData);
134 final double[] reversed = REFERENCE_inverseDCT(transformed);
135 for (int i = 0; i < 8; i++) {
136 assertEquals(originalData[i], reversed[i], 0.001);
137 }
138
139 final float[] data = originalData.clone();
140 Dct.forwardDct8(data);
141 Dct.scaleQuantizationVector(data);
142 for (int i = 0; i < 8; i++) {
143 assertEquals(data[i], transformed[i], 0.001);
144 }
145
146 Dct.scaleDequantizationVector(data);
147 Dct.inverseDct8(data);
148 for (int i = 0; i < 8; i++) {
149 assertEquals(data[i], originalData[i], 0.001);
150 }
151 }
152 }