View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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 }