1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00
Beef/BeefySysLib/img/BFIData.cpp

873 lines
19 KiB
C++
Raw Normal View History

2019-08-23 11:56:54 -07:00
#include "BFIData.h"
#include "ImageUtils.h"
USING_NS_BF;
#define IS_ZERO(v) ((fabs(v) < 0.000000001))
#include <complex>
#include <iostream>
#include <valarray>
const double PI = 3.141592653589793238460;
typedef std::complex<double> Complex;
typedef std::valarray<Complex> CArray;
// Cooley<65>Tukey FFT (in-place)
void fft(CArray& x)
{
const size_t N = x.size();
if (N <= 1) return;
// divide
CArray even = x[std::slice(0, N/2, 2)];
CArray odd = x[std::slice(1, N/2, 2)];
// conquer
fft(even);
fft(odd);
// combine
for (size_t k = 0; k < N/2; ++k)
{
Complex t = std::polar(1.0, -2 * PI * k / N) * odd[k];
x[k ] = even[k] + t;
x[k+N/2] = even[k] - t;
}
}
void DFTTest()
{
const Complex test[] = { 1.0, 2.0, 3.0, 4.0 };
CArray data(test, sizeof(test) / sizeof(test[0]));
fft(data);
}
/*-------------------------------------------------------------------------
Perform a 2D FFT inplace given a complex 2D array
The direction dir, 1 for forward, -1 for reverse
The size of the array (nx,ny)
Return false if there are memory problems or
the dimensions are not powers of 2
*/
class COMPLEX
{
public:
double real;
double imag;
};
/*-------------------------------------------------------------------------
This computes an in-place complex-to-complex FFT
x and y are the real and imaginary arrays of 2^m points.
dir = 1 gives forward transform
dir = -1 gives reverse transform
Formula: forward
N-1
---
1 \ - j k 2 pi n / N
X(n) = --- > x(k) e = forward transform
N / n=0..N-1
---
k=0
Formula: reverse
N-1
---
\ j k 2 pi n / N
X(n) = > x(k) e = forward transform
/ n=0..N-1
---
k=0
*/
int FFT(int dir,int m,double *x,double *y)
{
long nn,i,i1,j,k,i2,l,l1,l2;
double c1,c2,tx,ty,t1,t2,u1,u2,z;
/* Calculate the number of points */
nn = 1;
for (i=0;i<m;i++)
nn *= 2;
/* Do the bit reversal */
i2 = nn >> 1;
j = 0;
for (i=0;i<nn-1;i++) {
if (i < j) {
tx = x[i];
ty = y[i];
x[i] = x[j];
y[i] = y[j];
x[j] = tx;
y[j] = ty;
}
k = i2;
while (k <= j) {
j -= k;
k >>= 1;
}
j += k;
}
/* Compute the FFT */
c1 = -1.0;
c2 = 0.0;
l2 = 1;
for (l=0;l<m;l++) {
l1 = l2;
l2 <<= 1;
u1 = 1.0;
u2 = 0.0;
for (j=0;j<l1;j++) {
for (i=j;i<nn;i+=l2) {
i1 = i + l1;
t1 = u1 * x[i1] - u2 * y[i1];
t2 = u1 * y[i1] + u2 * x[i1];
x[i1] = x[i] - t1;
y[i1] = y[i] - t2;
x[i] += t1;
y[i] += t2;
}
z = u1 * c1 - u2 * c2;
u2 = u1 * c2 + u2 * c1;
u1 = z;
}
c2 = sqrt((1.0 - c1) / 2.0);
if (dir == 1)
c2 = -c2;
c1 = sqrt((1.0 + c1) / 2.0);
}
/* Scaling for forward transform */
if (dir == 1) {
for (i=0;i<nn;i++) {
x[i] /= (double)nn;
y[i] /= (double)nn;
}
}
return true;
}
class BFComplex
{
public:
double mR;
double mI;
public:
BFComplex(double r = 0, double i = 0)
{
mR = r;
mI = i;
}
BFComplex operator +(const BFComplex& complex) const
{
return BFComplex(mR + complex.mR, mI + complex.mI);
}
BFComplex& operator +=(const BFComplex& complex)
{
*this = BFComplex(mR + complex.mR, mI + complex.mI);
return *this;
}
BFComplex operator *(const BFComplex& complex) const
{
return BFComplex(mR * complex.mR - mI * complex.mI, mR * complex.mI + mI * complex.mR);
}
BFComplex operator *(double scalar) const
{
return BFComplex(mR * scalar, mI * scalar);
}
double Magnitude()
{
return sqrt(mR * mR + mI * mI);
}
double Phase()
{
return atan2(mI, mR);
}
String ToString()
{
if (fabs(mI) < 0.00000001)
{
if (fabs(mR) < 0.00000001)
return StrFormat("%f", 0.0);
return StrFormat("%f", mR);
}
if (mI > 0)
return StrFormat("%f + %fi", mR, mI);
return StrFormat("%f - %fi", mR, -mI);
}
static BFComplex Polar(double scalar, double angle)
{
return BFComplex(scalar * cos(angle), scalar * sin(angle));
}
};
bool Powerof2(int num, int* power, int* twoPM)
{
*power = 0;
*twoPM = 1;
while (*twoPM < num)
{
*twoPM *= 2;
(*power)++;
}
return *twoPM == num;
}
int FFT2D(BFComplex **c,int nx,int ny,int dir)
{
int i,j;
int m,twopm;
double *real,*imag;
/* Transform the rows */
real = (double *)malloc(nx * sizeof(double));
imag = (double *)malloc(nx * sizeof(double));
if (real == NULL || imag == NULL)
return(false);
if (!Powerof2(nx,&m,&twopm) || twopm != nx)
return(false);
for (j=0;j<ny;j++) {
for (i=0;i<nx;i++) {
real[i] = c[i][j].mR;
imag[i] = c[i][j].mI;
}
FFT(dir,m,real,imag);
for (i=0;i<nx;i++) {
c[i][j].mR = real[i];
c[i][j].mI = imag[i];
}
}
free(real);
free(imag);
/* Transform the columns */
real = (double *)malloc(ny * sizeof(double));
imag = (double *)malloc(ny * sizeof(double));
if (real == NULL || imag == NULL)
return(false);
if (!Powerof2(ny,&m,&twopm) || twopm != ny)
return(false);
for (i=0;i<nx;i++) {
for (j=0;j<ny;j++) {
real[j] = c[i][j].mR;
imag[j] = c[i][j].mI;
}
FFT(dir,m,real,imag);
for (j=0;j<ny;j++) {
c[i][j].mR = real[j];
c[i][j].mI = imag[j];
}
}
free(real);
free(imag);
return(true);
}
void DFTTest_2D()
{
BFComplex** test = new BFComplex*[4];
for (int i = 0; i < 4; i++)
{
test[i] = new BFComplex[4];
for (int j = 0; j < 4; j++)
test[i][j].mR = i*4+j+1;
}
/*std::wstring aString;
for (int i = 0; i < 4; i++)
{
aString += L"(";
for (int j = 0; j < 4; j++)
{
if (j != 0)
aString += L", ";
aString += test[i][j].ToString();
}
aString += L")\n";
}
OutputDebugStringW(aString.c_str());*/
/*[][3] =
{{1.0, 2.0, 3.0},
{4.0, 5.0, 6.0},
{7.0, 8.0, 9.0}};*/
FFT2D(test, 4, 4, -1);
String aString;
for (int i = 0; i < 4; i++)
{
aString += "(";
for (int j = 0; j < 4; j++)
{
if (j != 0)
aString += ", ";
aString += test[i][j].ToString();
}
aString += ")\n";
}
BfpOutput_DebugString(aString.c_str());
}
void PrintComplex2D(BFComplex* ptr, int cols, int rows)
{
String aString = "(\n";
for (int i = 0; i < rows; i++)
{
aString += "\t(";
for (int j = 0; j < cols; j++)
{
if (j != 0)
aString += ", ";
aString += ptr[i*cols+j].ToString();
}
aString += ")\n";
}
aString += ")\n";
BfpOutput_DebugString(aString.c_str());
}
void FFD_1D(BFComplex* array, int size, int pitch, int aDir)
{
BFComplex* prev = new BFComplex[size];
for (int i = 0; i < size; i++)
prev[i] = array[i*pitch];
for (int idxOut = 0; idxOut < size; idxOut++)
{
BFComplex val;
for (int idxIn = 0; idxIn < size; idxIn++)
val += prev[idxIn] * BFComplex::Polar(1.0, aDir * 2 * BF_PI_D * idxIn * idxOut / (double) size);
if (aDir == 1)
val = val * BFComplex(1.0/size);
array[idxOut*pitch] = val;
}
}
void DFTTest_Mine()
{
BFComplex test[] =
{ 1.0, 2.0, 3.0, 4.0,
5.0, 6.0, 7.0, 8.0,
9.0, 10.0, 11.0, 12.0,
13.0, 14.0, 15.0, 16.0};
int aCols = 4;
int aRows = 4;
/*std::vector<BFComplex> outR;
for (int row = 0; row < aRows; row++)
{
for (int colOut = 0; colOut < aCols; colOut++)
{
BFComplex val;
for (int colIn = 0; colIn < aCols; colIn++)
val += test[row*aCols+colIn] * BFComplex::Polar(1.0, - 2 * BF_PI_D * colIn * colOut / (double) aCols);
outR.push_back(val);
}
}
PrintComplex2D(&outR.front(), aCols, aRows);
std::vector<BFComplex> outC;
outC.insert(outC.begin(), aCols*aRows, BFComplex());
for (int col = 0; col < aCols; col++)
{
for (int rowOut = 0; rowOut < aRows; rowOut++)
{
BFComplex val;
for (int rowIn = 0; rowIn < aRows; rowIn++)
val += outR[rowIn*aCols+col] * BFComplex::Polar(1.0, - 2 * BF_PI_D * rowIn * rowOut / (double) aRows);
//outC.push_back(val);
outC[rowOut*aCols+col] = val;
}
}*/
for (int col = 0; col < aCols; col++)
FFD_1D(test + col, aRows, aCols, -1);
PrintComplex2D(test, aRows, aCols);
for (int row = 0; row < aRows; row++)
FFD_1D(test + row*aCols, aCols, 1, -1);
PrintComplex2D(test, aRows, aCols);
/*std::vector<BFComplex> outC;
outC.insert(outC.begin(), aRows*aCols, BFComplex());
for (int col = 0; col < aCols; col++)
{
for (int rowOut = 0; rowOut < aRows; rowOut++)
{
BFComplex val;
for (int rowIn = 0; rowIn < aRows; rowIn++)
val += test[rowIn*aCols+col] * BFComplex::Polar(1.0, - 2 * BF_PI_D * rowIn * rowOut / (double) aRows);
outC[rowOut*aCols+col] = val;
}
}
PrintComplex2D(&outC.front(), aRows, aCols);
std::vector<BFComplex> outR;
outR.insert(outR.begin(), aRows*aCols, BFComplex());
for (int row = 0; row < aRows; row++)
{
for (int colOut = 0; colOut < aCols; colOut++)
{
BFComplex val;
for (int colIn = 0; colIn < aCols; colIn++)
val += outC[row*aCols+colIn] * BFComplex::Polar(1.0, - 2 * BF_PI_D * colIn * colOut / (double) aCols);
//outC.push_back(val);
outR[row*aCols+colOut] = val;
}
}
PrintComplex2D(&outR.front(), aRows, aCols);*/
/*int N = sizeof(test) / sizeof(test[0]);
std::vector<BFComplex> out;
std::vector<BFComplex> invOut;
BFComplex _a = BFComplex::Polar(1.0, 0.5f) * BFComplex::Polar(1.0, 2.01f);
for (int k = 0; k < N; k++)
{
BFComplex val;
for (int n = 0; n < N; n++)
val += test[n] * BFComplex::Polar(1.0, - 2 * BF_PI_D * k * n / (double) N);
out.push_back(val);
}
for (int n = 0; n < N; n++)
{
BFComplex val;
for (int k = 0; k < N; k++)
val += out[k] * BFComplex::Polar(1.0, 2 * BF_PI_D * k * n / (double) N);
invOut.push_back(BFComplex(1.0/N) * val);
}*/
}
void FFTShift1D(BFComplex* array, int size, int pitch, int dir)
{
BFComplex* prev = new BFComplex[size];
for (int i = 0; i < size; i++)
prev[i] = array[i * pitch];
while (dir < 0)
dir += size;
for (int i = 0; i < size; i++)
array[i * pitch] = prev[((i + dir) % size)];
delete [] prev;
2019-08-23 11:56:54 -07:00
}
static void FFTShift2D(BFComplex* data, int cols, int rows)
{
for (int col = 0; col < cols; col++)
FFTShift1D(data + col, rows, cols, cols / 2);
for (int row = 0; row < rows; row++)
FFTShift1D(data + row*cols, cols, 1, rows / 2);
}
static void FFTConvert(ImageData* source)
{
int aCols = source->mWidth;
int aRows = source->mHeight;
int count = aCols * aRows;
BFComplex* nums = new BFComplex[count];
for (int i = 0; i < count; i++)
{
PackedColor& color = *((PackedColor*) &source->mBits[i]);
nums[i].mR = PackedColorGetGray()(color);
}
//FFT
for (int col = 0; col < aCols; col++)
FFD_1D(nums + col, aRows, aCols, -1);
for (int row = 0; row < aRows; row++)
FFD_1D(nums + row*aCols, aCols, 1, -1);
//INV FFT
/*for (int col = 0; col < aCols; col++)
FFD_1D(nums + col, aRows, aCols, 1);
for (int row = 0; row < aRows; row++)
FFD_1D(nums + row*aCols, aCols, 1, 1);*/
FFTShift2D(nums, aCols, aRows);
double* fFTLog = new double[count];
double maxLog = 0;
for (int i = 0; i < count; i++)
{
double aLog = log(1 + nums[i].Magnitude());
maxLog = std::max(maxLog, aLog);
fFTLog[i] = aLog;
}
for (int i = 0; i < count; i++)
{
//int val = (int) nums[i].Magnitude() / 1;
int val = (int) (fFTLog[i] * 255 / maxLog);
val = std::min(255, std::max(0, val));
source->mBits[i] = 0xFF000000 | val | (val << 8) | (val << 16);
}
delete [] fFTLog;
2019-08-23 11:56:54 -07:00
delete [] nums;
}
void DCT_1D(double* array, int size, int pitch)
{
double* prev = new double[size];
for (int i = 0; i < size; i++)
prev[i] = array[i*pitch];
for (int idxOut = 0; idxOut < size; idxOut++)
{
double val = 0;
double scale = (idxOut == 0) ? 1/sqrt(2.0) : 1;
for (int idxIn = 0; idxIn < size; idxIn++)
val += prev[idxIn] * cos(idxOut * BF_PI * (2*idxIn + 1)/(2 * size));
array[idxOut*pitch] = 0.5 * scale * val;
}
delete [] prev;
2019-08-23 11:56:54 -07:00
}
void IDCT_1D(double* array, int size, int pitch)
{
double* prev = new double[size];
for (int i = 0; i < size; i++)
prev[i] = array[i*pitch];
for (int idxOut = 0; idxOut < size; idxOut++)
{
double val = 0;
for (int idxIn = 0; idxIn < size; idxIn++)
{
double scale = (idxIn == 0) ? 1/sqrt(2.0) : 1;
val += scale * prev[idxIn] * cos(idxIn * BF_PI * (2*idxOut + 1)/(2 * size));
}
array[idxOut*pitch] = 0.5 * val;
}
delete [] prev;
2019-08-23 11:56:54 -07:00
}
const int DCT_1D_I_TABLE[64] =
{
4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096,
4017, 3405, 2275, 799, -799, -2275, -3405, -4017,
3784, 1567, -1567, -3784, -3784, -1567, 1567, 3784,
3405, -799, -4017, -2275, 2275, 4017, 799, -3405,
2896, -2896, -2896, 2896, 2896, -2896, -2896, 2896,
2275, -4017, 799, 3405, -3405, -799, 4017, -2275,
1567, -3784, 3784, -1567, -1567, 3784, -3784, 1567,
799, -2275, 3405, -4017, 4017, -3405, 2275, -799
};
void DCT_1D_I(int* array, int size, int pitch)
{
int* prev = new int[size];
for (int i = 0; i < size; i++)
prev[i] = array[i*pitch];
int multIdx = 0;
for (int idxOut = 0; idxOut < size; idxOut++)
{
int val = 0;
for (int idxIn = 0; idxIn < size; idxIn++)
val += prev[idxIn] * DCT_1D_I_TABLE[multIdx++];
if (idxOut == 0)
array[idxOut*pitch] = val / 0x2d41;
else
array[idxOut*pitch] = val / 0x2000;
}
delete [] prev;
2019-08-23 11:56:54 -07:00
}
const int IDCT_1D_I_TABLE[64] =
{
2896, 4017, 3784, 3405, 2896, 2275, 1567, 799,
2896, 3405, 1567, -799, -2896, -4017, -3784, -2275,
2896, 2275, -1567, -4017, -2896, 799, 3784, 3405,
2896, 799, -3784, -2275, 2896, 3405, -1567, -4017,
2896, -799, -3784, 2275, 2896, -3405, -1567, 4017,
2896, -2275, -1567, 4017, -2896, -799, 3784, -3405,
2896, -3405, 1567, 799, -2896, 4017, -3784, 2275,
2896, -4017, 3784, -3405, 2896, -2275, 1567, -799
};
void IDCT_1D_I(int* array, int size, int pitch)
{
int prev[64];
for (int i = 0; i < size; i++)
prev[i] = array[i*pitch];
int multIdx = 0;
for (int idxOut = 0; idxOut < size; idxOut++)
{
int val = 0;
for (int idxIn = 0; idxIn < size; idxIn++)
val += prev[idxIn] * IDCT_1D_I_TABLE[multIdx++];
array[idxOut*pitch] = val / 0x2000;
}
}
void BFIData::Compress(ImageData* source)
{
/*DFTTest();
DFTTest_2D();
DFTTest_Mine();*/
//FFTConvert(source);
/*const int rowCount = 3;
const int colCount = 4;
double mat[rowCount][colCount] = {{2, 2, 5, 5}, {4, 4, 10, 11}, {3, 2, 6, 4}};
double rightVals[rowCount] = {1, 2, 3};
int pivotIdx[colCount] = {-1, -1, -1, -1};
int moveIdx = 0;
double pivotVals[colCount] = {0};
for (int pivot = 0; pivot < colCount; pivot++)
{
bool moved = false;
for (int eq = moveIdx; eq < rowCount; eq++)
{
if (!IS_ZERO(mat[eq][pivot]))
{
pivotVals[pivot] = mat[eq][pivot];
for (int swapIdx = 0; swapIdx < colCount; swapIdx++)
std::swap(mat[eq][swapIdx], mat[moveIdx][swapIdx]);
std::swap(rightVals[eq], rightVals[moveIdx]);
pivotIdx[pivot] = moveIdx;
moved = true;
break;
}
}
if (!moved)
continue;
for (int eq = moveIdx + 1; eq < rowCount; eq++)
{
double multFactor = -mat[eq][pivot] / mat[moveIdx][pivot];
bool nonZero = false;
for (int multIdx = pivot; multIdx < colCount; multIdx++)
{
mat[eq][multIdx] += mat[moveIdx][multIdx]*multFactor;
nonZero |= !IS_ZERO(mat[eq][multIdx]);
}
rightVals[eq] += rightVals[moveIdx]*multFactor;
BF_ASSERT(IS_ZERO(rightVals[eq]) || (nonZero));
}
moveIdx++;
}
// Back substitute
double result[colCount];
for (int col = colCount - 1; col >= 0; col--)
{
result[col] = 0;
if (pivotIdx[col] != -1)
{
int eq = pivotIdx[col];
double left = 0;
for (int multCol = col + 1; multCol < colCount; multCol++)
left += mat[eq][multCol] * result[multCol];
double right = rightVals[eq] - left;
right /= mat[eq][col];
result[col] = right;
}
}
///*/
uint8 rawData[64] = {
52, 55, 61, 66, 70, 61, 64, 73,
63, 59, 55, 90,109, 85, 69, 72,
62, 59, 68,113,144,104, 66, 73,
63, 58, 71,122,154,106, 70, 69,
67, 61, 68,104,126, 88, 68, 70,
79, 65, 60, 70, 77, 68, 58, 75,
85, 71, 64, 59, 55, 61, 65, 83,
87, 79, 69, 68, 65, 76, 78, 94};
double dCTIn[64];
for (int i = 0; i < 64; i++)
dCTIn[i] = (int) rawData[i] - 128;
//double dCTOut[64];
/*for (int v = 0; v < 8; v++)
{
for (int u = 0; u < 8; u++)
{
dCTOut[u+v*8] = 0;
for (int y = 0; y < 8; y++)
{
for (int x = 0; x < 8; x++)
{
double au = (u == 0) ? sqrt(1.0/8.0) : sqrt(2.0/8.0);
double av = (v == 0) ? sqrt(1.0/8.0) : sqrt(2.0/8.0);
dCTOut[u+v*8] += au*av*dCTIn[x+y*8]*
cos(BF_PI_D/8 * (x + 0.5)*u) *
cos(BF_PI_D/8 * (y + 0.5)*v);
}
}
}
}*/
double dCT[64];
for (int i = 0; i < 64; i++)
dCT[i] = rawData[i] - 128;
int aCols = 8;
int aRows = 8;
for (int col = 0; col < aCols; col++)
DCT_1D(dCT + col, aRows, aCols);
for (int row = 0; row < aRows; row++)
DCT_1D(dCT + row*aCols, aCols, 1);
for (int col = 0; col < aCols; col++)
IDCT_1D(dCT + col, aRows, aCols);
for (int row = 0; row < aRows; row++)
IDCT_1D(dCT + row*aCols, aCols, 1);
//
int dCT_I[64];
for (int i = 0; i < 64; i++)
dCT_I[i] = (rawData[i] - 128) * 256;
for (int col = 0; col < aCols; col++)
DCT_1D_I(dCT_I + col, aRows, aCols);
for (int row = 0; row < aRows; row++)
DCT_1D_I(dCT_I + row*aCols, aCols, 1);
for (int col = 0; col < aCols; col++)
IDCT_1D_I(dCT_I + col, aRows, aCols);
for (int row = 0; row < aRows; row++)
IDCT_1D_I(dCT_I + row*aCols, aCols, 1);
for (int i = 0; i < 64; i++)
{
int val = dCT_I[i];
if (val < 0)
dCT_I[i] = (val - 128) / 256;
else
dCT_I[i] = (val + 128) / 256;
}
///
int quantTable[] = {16, 11, 11, 16, 23, 27, 31, 30, 11, 12, 12, 15, 20, 23, 23, 30,
11, 12, 13, 16, 23, 26, 35, 47, 16, 15, 16, 23, 26, 37, 47, 64,
23, 20, 23, 26, 39, 51, 64, 64, 27, 23, 26, 37, 51, 64, 64, 64,
31, 23, 35, 47, 64, 64, 64, 64, 30, 30, 47, 64, 64, 64, 64, 64};
int quantDCT[64];
for (int i = 0; i < 64; i++)
quantDCT[i] = (int) BFRound((float) (dCT[i] / quantTable[i]));
int zigZag[64] = {
0, 1, 5, 6, 14, 15, 27, 28,
2, 4, 7, 13, 16, 26, 29, 42,
3, 8, 12, 17, 25, 30, 41, 43,
9, 11, 18, 24, 31, 40, 44, 53,
10, 19, 23, 32, 39, 45, 52, 54,
20, 22, 33, 38, 46, 51, 55, 60,
21, 34, 37, 47, 50, 56, 59, 61,
35, 36, 48, 49, 57, 58, 62, 63
};
int zigZagDCT[64];
for (int i = 0; i < 64; i++)
{
zigZagDCT[i] = quantDCT[zigZag[i]];
}
/*double dCTOutH[64];
double dCTOutV[64];
for (int v = 0; v < 8; v++)
{
for (int u = 0; u < 8; u++)
{
dCTOutV[u+v*8] = 0;
for (int y = 0; y < 8; y++)
{
double av = (v == 0) ? sqrt(1.0/8.0) : sqrt(2.0/8.0);
dCTOutV[u+v*8] += av*dCTIn[u+y*8]*
cos(BF_PI_D/8 * (y + 0.5)*v);
}
}
}
for (int v = 0; v < 8; v++)
{
for (int u = 0; u < 8; u++)
{
dCTOutH[u+v*8] = 0;
for (int x = 0; x < 8; x++)
{
double au = (u == 0) ? sqrt(1.0/8.0) : sqrt(2.0/8.0);
dCTOutH[u+v*8] += au*dCTOutV[x+v*8]*
cos(BF_PI_D/8 * (x + 0.5)*u);
}
//dCTOut[u+v*8] = val;
}
}*/
}