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.Assert.assertEquals;
21  
22  import org.junit.Test;
23  
24  public class DctTest {
25  
26      @Test
27      public void testVectors() throws Exception {
28          final float[] originalData = new float[8];
29          for (int i = 0; i < 8; i++) {
30              originalData[i] = i;
31          }
32  
33          final float[] transformed = REFERENCE_forwardDCT(originalData);
34          final float[] reversed = REFERENCE_inverseDCT(transformed);
35          for (int i = 0; i < 8; i++) {
36              assertEquals("Reference transforms broken, at x=" + i,
37                      originalData[i], reversed[i], 0.001);
38          }
39  
40          final float[] data = originalData.clone();
41          Dct.forwardDCT8(data);
42          Dct.scaleQuantizationVector(data);
43          for (int i = 0; i < 8; i++) {
44              assertEquals("Forward transform broken, at x=" + i, data[i],
45                      transformed[i], 0.001);
46          }
47  
48          Dct.scaleDequantizationVector(data);
49          Dct.inverseDCT8(data);
50          for (int i = 0; i < 8; i++) {
51              assertEquals("Inverse transform broken, at x=" + i, data[i],
52                      originalData[i], 0.001);
53          }
54      }
55  
56      @Test
57      public void testMatrices() throws Exception {
58          final float[] originalData = new float[8 * 8];
59          final float[][] originalData8x8 = new float[8][8];
60          for (int y = 0; y < 8; y++) {
61              for (int x = 0; x < 8; x++) {
62                  final float value = 8 * y + x;
63                  originalData8x8[y][x] = value;
64                  originalData[8 * y + x] = value;
65              }
66          }
67  
68          final float[][] transformed8x8 = REFERENCE_forwardDCT(originalData8x8);
69          final float[][] reversed8x8 = REFERENCE_inverseDCT(transformed8x8);
70          for (int y = 0; y < 8; y++) {
71              for (int x = 0; x < 8; x++) {
72                  assertEquals("Reference transforms broken, at x=" + x + ",y="
73                          + y, originalData8x8[y][x], reversed8x8[y][x], 0.001);
74              }
75          }
76  
77          final float[] data = originalData.clone();
78          Dct.forwardDCT8x8(data);
79          Dct.scaleQuantizationMatrix(data);
80          for (int y = 0; y < 8; y++) {
81              for (int x = 0; x < 8; x++) {
82                  assertEquals("Forward transform broken, at x=" + x + ",y=" + y,
83                          transformed8x8[y][x], data[8 * y + x], 0.001);
84              }
85          }
86  
87          Dct.scaleDequantizationMatrix(data);
88          Dct.inverseDCT8x8(data);
89          for (int y = 0; y < 8; y++) {
90              for (int x = 0; x < 8; x++) {
91                  assertEquals("Inverse transform broken, at x=" + x + ",y=" + y,
92                          originalData8x8[y][x], data[8 * y + x], 0.001);
93              }
94          }
95      }
96  
97      private static float[][] REFERENCE_inverseDCT(final float[][] matrix) {
98          final float[][] ret = new float[8][8];
99          for (int y = 0; y < 8; y++) {
100             for (int x = 0; x < 8; x++) {
101                 float sum = 0;
102                 for (int u = 0; u < 8; u++) {
103                     for (int v = 0; v < 8; v++) {
104                         final float cu = (u == 0) ? ((float) (1.0 / Math.sqrt(2)))
105                                 : 1;
106                         final float cv = (v == 0) ? ((float) (1.0 / Math.sqrt(2)))
107                                 : 1;
108                         sum += cu * cv * matrix[v][u]
109                                 * Math.cos((2 * x + 1) * u * Math.PI / 16)
110                                 * Math.cos((2 * y + 1) * v * Math.PI / 16);
111                     }
112                 }
113                 ret[y][x] = 0.25f * sum;
114             }
115         }
116         return ret;
117     }
118 
119     private static float[] REFERENCE_inverseDCT(final float[] vector) {
120         final float[] ret = new float[8];
121         for (int x = 0; x < 8; x++) {
122             float sum = 0;
123             for (int u = 0; u < 8; u++) {
124                 final float cu = (u == 0) ? ((float) (1.0 / Math.sqrt(2))) : 1;
125                 sum += cu * vector[u]
126                         * Math.cos((2 * x + 1) * u * Math.PI / 16);
127             }
128             ret[x] = 0.5f * sum;
129         }
130         return ret;
131     }
132 
133     private static float[][] REFERENCE_forwardDCT(final float[][] matrix) {
134         final float[][] ret = new float[8][8];
135         for (int u = 0; u < 8; u++) {
136             for (int v = 0; v < 8; v++) {
137                 float sum = 0;
138                 final float cu = (u == 0) ? ((float) (1.0 / Math.sqrt(2))) : 1;
139                 final float cv = (v == 0) ? ((float) (1.0 / Math.sqrt(2))) : 1;
140                 for (int x = 0; x < 8; x++) {
141                     for (int y = 0; y < 8; y++) {
142                         sum += matrix[y][x]
143                                 * Math.cos((2 * x + 1) * u * Math.PI / 16)
144                                 * Math.cos((2 * y + 1) * v * Math.PI / 16);
145                     }
146                 }
147                 ret[v][u] = 0.25f * cu * cv * sum;
148             }
149         }
150         return ret;
151     }
152 
153     private static float[] REFERENCE_forwardDCT(final float[] vector) {
154         final float[] ret = new float[8];
155         for (int u = 0; u < 8; u++) {
156             float sum = 0;
157             final float cu = (u == 0) ? ((float) (1.0 / Math.sqrt(2))) : 1;
158             for (int x = 0; x < 8; x++) {
159                 sum += vector[x] * Math.cos((2 * x + 1) * u * Math.PI / 16);
160             }
161             ret[u] = 0.5f * cu * sum;
162         }
163         return ret;
164     }
165 }