fedilab-Android-App/app/src/main/java/app/fedilab/android/watermark/androidwm/utils/FastDctFft.java

98 lines
2.8 KiB
Java

/*
* Copyright 2018 Yizheng Huang
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package app.fedilab.android.watermark.androidwm.utils;
import java.util.Arrays;
import java.util.Objects;
public final class FastDctFft {
/**
* Computes the unscaled DCT type II on the specified array in place.
* The array length must be a power of 2 or zero.
*
* @param vector the vector of numbers to transform
* @throws NullPointerException if the array is {@code null}
*/
public static void transform(double[] vector) {
Objects.requireNonNull(vector);
int len = vector.length;
int halfLen = len / 2;
double[] real = new double[len];
for (int i = 0; i < halfLen; i++) {
real[i] = vector[i * 2];
real[len - 1 - i] = vector[i * 2 + 1];
}
if (len % 2 == 1) {
real[halfLen] = vector[len - 1];
}
Arrays.fill(vector, 0.0);
Fft.transform(real, vector);
for (int i = 0; i < len; i++) {
double temp = i * Math.PI / (len * 2);
vector[i] = real[i] * Math.cos(temp) + vector[i] * Math.sin(temp);
}
}
/**
* Computes the unscaled DCT type III on the specified array in place.
* The array length must be a power of 2 or zero.
*
* @param vector the vector of numbers to transform
* @throws NullPointerException if the array is {@code null}
*/
public static void inverseTransform(double[] vector) {
Objects.requireNonNull(vector);
int len = vector.length;
if (len > 0) {
vector[0] = vector[0] / 2;
}
double[] real = new double[len];
for (int i = 0; i < len; i++) {
double temp = i * Math.PI / (len * 2);
real[i] = vector[i] * Math.cos(temp);
vector[i] *= -Math.sin(temp);
}
Fft.transform(real, vector);
int halfLen = len / 2;
for (int i = 0; i < halfLen; i++) {
vector[i * 2] = real[i];
vector[i * 2 + 1] = real[len - 1 - i];
}
if (len % 2 == 1) {
vector[len - 1] = real[halfLen];
}
double scale = (double) len / 2;
for (int i = 0; i < len; i++) {
vector[i] = (int) Math.round(vector[i] / scale);
}
}
}