BFIData.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. #include "BFIData.h"
  2. #include "ImageUtils.h"
  3. USING_NS_BF;
  4. #define IS_ZERO(v) ((fabs(v) < 0.000000001))
  5. #include <complex>
  6. #include <iostream>
  7. #include <valarray>
  8. const double PI = 3.141592653589793238460;
  9. typedef std::complex<double> Complex;
  10. typedef std::valarray<Complex> CArray;
  11. // Cooley�Tukey FFT (in-place)
  12. void fft(CArray& x)
  13. {
  14. const size_t N = x.size();
  15. if (N <= 1) return;
  16. // divide
  17. CArray even = x[std::slice(0, N/2, 2)];
  18. CArray odd = x[std::slice(1, N/2, 2)];
  19. // conquer
  20. fft(even);
  21. fft(odd);
  22. // combine
  23. for (size_t k = 0; k < N/2; ++k)
  24. {
  25. Complex t = std::polar(1.0, -2 * PI * k / N) * odd[k];
  26. x[k ] = even[k] + t;
  27. x[k+N/2] = even[k] - t;
  28. }
  29. }
  30. void DFTTest()
  31. {
  32. const Complex test[] = { 1.0, 2.0, 3.0, 4.0 };
  33. CArray data(test, sizeof(test) / sizeof(test[0]));
  34. fft(data);
  35. }
  36. /*-------------------------------------------------------------------------
  37. Perform a 2D FFT inplace given a complex 2D array
  38. The direction dir, 1 for forward, -1 for reverse
  39. The size of the array (nx,ny)
  40. Return false if there are memory problems or
  41. the dimensions are not powers of 2
  42. */
  43. class COMPLEX
  44. {
  45. public:
  46. double real;
  47. double imag;
  48. };
  49. /*-------------------------------------------------------------------------
  50. This computes an in-place complex-to-complex FFT
  51. x and y are the real and imaginary arrays of 2^m points.
  52. dir = 1 gives forward transform
  53. dir = -1 gives reverse transform
  54. Formula: forward
  55. N-1
  56. ---
  57. 1 \ - j k 2 pi n / N
  58. X(n) = --- > x(k) e = forward transform
  59. N / n=0..N-1
  60. ---
  61. k=0
  62. Formula: reverse
  63. N-1
  64. ---
  65. \ j k 2 pi n / N
  66. X(n) = > x(k) e = forward transform
  67. / n=0..N-1
  68. ---
  69. k=0
  70. */
  71. int FFT(int dir,int m,double *x,double *y)
  72. {
  73. long nn,i,i1,j,k,i2,l,l1,l2;
  74. double c1,c2,tx,ty,t1,t2,u1,u2,z;
  75. /* Calculate the number of points */
  76. nn = 1;
  77. for (i=0;i<m;i++)
  78. nn *= 2;
  79. /* Do the bit reversal */
  80. i2 = nn >> 1;
  81. j = 0;
  82. for (i=0;i<nn-1;i++) {
  83. if (i < j) {
  84. tx = x[i];
  85. ty = y[i];
  86. x[i] = x[j];
  87. y[i] = y[j];
  88. x[j] = tx;
  89. y[j] = ty;
  90. }
  91. k = i2;
  92. while (k <= j) {
  93. j -= k;
  94. k >>= 1;
  95. }
  96. j += k;
  97. }
  98. /* Compute the FFT */
  99. c1 = -1.0;
  100. c2 = 0.0;
  101. l2 = 1;
  102. for (l=0;l<m;l++) {
  103. l1 = l2;
  104. l2 <<= 1;
  105. u1 = 1.0;
  106. u2 = 0.0;
  107. for (j=0;j<l1;j++) {
  108. for (i=j;i<nn;i+=l2) {
  109. i1 = i + l1;
  110. t1 = u1 * x[i1] - u2 * y[i1];
  111. t2 = u1 * y[i1] + u2 * x[i1];
  112. x[i1] = x[i] - t1;
  113. y[i1] = y[i] - t2;
  114. x[i] += t1;
  115. y[i] += t2;
  116. }
  117. z = u1 * c1 - u2 * c2;
  118. u2 = u1 * c2 + u2 * c1;
  119. u1 = z;
  120. }
  121. c2 = sqrt((1.0 - c1) / 2.0);
  122. if (dir == 1)
  123. c2 = -c2;
  124. c1 = sqrt((1.0 + c1) / 2.0);
  125. }
  126. /* Scaling for forward transform */
  127. if (dir == 1) {
  128. for (i=0;i<nn;i++) {
  129. x[i] /= (double)nn;
  130. y[i] /= (double)nn;
  131. }
  132. }
  133. return true;
  134. }
  135. class BFComplex
  136. {
  137. public:
  138. double mR;
  139. double mI;
  140. public:
  141. BFComplex(double r = 0, double i = 0)
  142. {
  143. mR = r;
  144. mI = i;
  145. }
  146. BFComplex operator +(const BFComplex& complex) const
  147. {
  148. return BFComplex(mR + complex.mR, mI + complex.mI);
  149. }
  150. BFComplex& operator +=(const BFComplex& complex)
  151. {
  152. *this = BFComplex(mR + complex.mR, mI + complex.mI);
  153. return *this;
  154. }
  155. BFComplex operator *(const BFComplex& complex) const
  156. {
  157. return BFComplex(mR * complex.mR - mI * complex.mI, mR * complex.mI + mI * complex.mR);
  158. }
  159. BFComplex operator *(double scalar) const
  160. {
  161. return BFComplex(mR * scalar, mI * scalar);
  162. }
  163. double Magnitude()
  164. {
  165. return sqrt(mR * mR + mI * mI);
  166. }
  167. double Phase()
  168. {
  169. return atan2(mI, mR);
  170. }
  171. String ToString()
  172. {
  173. if (fabs(mI) < 0.00000001)
  174. {
  175. if (fabs(mR) < 0.00000001)
  176. return StrFormat("%f", 0.0);
  177. return StrFormat("%f", mR);
  178. }
  179. if (mI > 0)
  180. return StrFormat("%f + %fi", mR, mI);
  181. return StrFormat("%f - %fi", mR, -mI);
  182. }
  183. static BFComplex Polar(double scalar, double angle)
  184. {
  185. return BFComplex(scalar * cos(angle), scalar * sin(angle));
  186. }
  187. };
  188. bool Powerof2(int num, int* power, int* twoPM)
  189. {
  190. *power = 0;
  191. *twoPM = 1;
  192. while (*twoPM < num)
  193. {
  194. *twoPM *= 2;
  195. (*power)++;
  196. }
  197. return *twoPM == num;
  198. }
  199. int FFT2D(BFComplex **c,int nx,int ny,int dir)
  200. {
  201. int i,j;
  202. int m,twopm;
  203. double *real,*imag;
  204. /* Transform the rows */
  205. real = (double *)malloc(nx * sizeof(double));
  206. imag = (double *)malloc(nx * sizeof(double));
  207. if (real == NULL || imag == NULL)
  208. return(false);
  209. if (!Powerof2(nx,&m,&twopm) || twopm != nx)
  210. return(false);
  211. for (j=0;j<ny;j++) {
  212. for (i=0;i<nx;i++) {
  213. real[i] = c[i][j].mR;
  214. imag[i] = c[i][j].mI;
  215. }
  216. FFT(dir,m,real,imag);
  217. for (i=0;i<nx;i++) {
  218. c[i][j].mR = real[i];
  219. c[i][j].mI = imag[i];
  220. }
  221. }
  222. free(real);
  223. free(imag);
  224. /* Transform the columns */
  225. real = (double *)malloc(ny * sizeof(double));
  226. imag = (double *)malloc(ny * sizeof(double));
  227. if (real == NULL || imag == NULL)
  228. return(false);
  229. if (!Powerof2(ny,&m,&twopm) || twopm != ny)
  230. return(false);
  231. for (i=0;i<nx;i++) {
  232. for (j=0;j<ny;j++) {
  233. real[j] = c[i][j].mR;
  234. imag[j] = c[i][j].mI;
  235. }
  236. FFT(dir,m,real,imag);
  237. for (j=0;j<ny;j++) {
  238. c[i][j].mR = real[j];
  239. c[i][j].mI = imag[j];
  240. }
  241. }
  242. free(real);
  243. free(imag);
  244. return(true);
  245. }
  246. void DFTTest_2D()
  247. {
  248. BFComplex** test = new BFComplex*[4];
  249. for (int i = 0; i < 4; i++)
  250. {
  251. test[i] = new BFComplex[4];
  252. for (int j = 0; j < 4; j++)
  253. test[i][j].mR = i*4+j+1;
  254. }
  255. /*std::wstring aString;
  256. for (int i = 0; i < 4; i++)
  257. {
  258. aString += L"(";
  259. for (int j = 0; j < 4; j++)
  260. {
  261. if (j != 0)
  262. aString += L", ";
  263. aString += test[i][j].ToString();
  264. }
  265. aString += L")\n";
  266. }
  267. OutputDebugStringW(aString.c_str());*/
  268. /*[][3] =
  269. {{1.0, 2.0, 3.0},
  270. {4.0, 5.0, 6.0},
  271. {7.0, 8.0, 9.0}};*/
  272. FFT2D(test, 4, 4, -1);
  273. String aString;
  274. for (int i = 0; i < 4; i++)
  275. {
  276. aString += "(";
  277. for (int j = 0; j < 4; j++)
  278. {
  279. if (j != 0)
  280. aString += ", ";
  281. aString += test[i][j].ToString();
  282. }
  283. aString += ")\n";
  284. }
  285. BfpOutput_DebugString(aString.c_str());
  286. }
  287. void PrintComplex2D(BFComplex* ptr, int cols, int rows)
  288. {
  289. String aString = "(\n";
  290. for (int i = 0; i < rows; i++)
  291. {
  292. aString += "\t(";
  293. for (int j = 0; j < cols; j++)
  294. {
  295. if (j != 0)
  296. aString += ", ";
  297. aString += ptr[i*cols+j].ToString();
  298. }
  299. aString += ")\n";
  300. }
  301. aString += ")\n";
  302. BfpOutput_DebugString(aString.c_str());
  303. }
  304. void FFD_1D(BFComplex* array, int size, int pitch, int aDir)
  305. {
  306. BFComplex* prev = new BFComplex[size];
  307. for (int i = 0; i < size; i++)
  308. prev[i] = array[i*pitch];
  309. for (int idxOut = 0; idxOut < size; idxOut++)
  310. {
  311. BFComplex val;
  312. for (int idxIn = 0; idxIn < size; idxIn++)
  313. val += prev[idxIn] * BFComplex::Polar(1.0, aDir * 2 * BF_PI_D * idxIn * idxOut / (double) size);
  314. if (aDir == 1)
  315. val = val * BFComplex(1.0/size);
  316. array[idxOut*pitch] = val;
  317. }
  318. }
  319. void DFTTest_Mine()
  320. {
  321. BFComplex test[] =
  322. { 1.0, 2.0, 3.0, 4.0,
  323. 5.0, 6.0, 7.0, 8.0,
  324. 9.0, 10.0, 11.0, 12.0,
  325. 13.0, 14.0, 15.0, 16.0};
  326. int aCols = 4;
  327. int aRows = 4;
  328. /*std::vector<BFComplex> outR;
  329. for (int row = 0; row < aRows; row++)
  330. {
  331. for (int colOut = 0; colOut < aCols; colOut++)
  332. {
  333. BFComplex val;
  334. for (int colIn = 0; colIn < aCols; colIn++)
  335. val += test[row*aCols+colIn] * BFComplex::Polar(1.0, - 2 * BF_PI_D * colIn * colOut / (double) aCols);
  336. outR.push_back(val);
  337. }
  338. }
  339. PrintComplex2D(&outR.front(), aCols, aRows);
  340. std::vector<BFComplex> outC;
  341. outC.insert(outC.begin(), aCols*aRows, BFComplex());
  342. for (int col = 0; col < aCols; col++)
  343. {
  344. for (int rowOut = 0; rowOut < aRows; rowOut++)
  345. {
  346. BFComplex val;
  347. for (int rowIn = 0; rowIn < aRows; rowIn++)
  348. val += outR[rowIn*aCols+col] * BFComplex::Polar(1.0, - 2 * BF_PI_D * rowIn * rowOut / (double) aRows);
  349. //outC.push_back(val);
  350. outC[rowOut*aCols+col] = val;
  351. }
  352. }*/
  353. for (int col = 0; col < aCols; col++)
  354. FFD_1D(test + col, aRows, aCols, -1);
  355. PrintComplex2D(test, aRows, aCols);
  356. for (int row = 0; row < aRows; row++)
  357. FFD_1D(test + row*aCols, aCols, 1, -1);
  358. PrintComplex2D(test, aRows, aCols);
  359. /*std::vector<BFComplex> outC;
  360. outC.insert(outC.begin(), aRows*aCols, BFComplex());
  361. for (int col = 0; col < aCols; col++)
  362. {
  363. for (int rowOut = 0; rowOut < aRows; rowOut++)
  364. {
  365. BFComplex val;
  366. for (int rowIn = 0; rowIn < aRows; rowIn++)
  367. val += test[rowIn*aCols+col] * BFComplex::Polar(1.0, - 2 * BF_PI_D * rowIn * rowOut / (double) aRows);
  368. outC[rowOut*aCols+col] = val;
  369. }
  370. }
  371. PrintComplex2D(&outC.front(), aRows, aCols);
  372. std::vector<BFComplex> outR;
  373. outR.insert(outR.begin(), aRows*aCols, BFComplex());
  374. for (int row = 0; row < aRows; row++)
  375. {
  376. for (int colOut = 0; colOut < aCols; colOut++)
  377. {
  378. BFComplex val;
  379. for (int colIn = 0; colIn < aCols; colIn++)
  380. val += outC[row*aCols+colIn] * BFComplex::Polar(1.0, - 2 * BF_PI_D * colIn * colOut / (double) aCols);
  381. //outC.push_back(val);
  382. outR[row*aCols+colOut] = val;
  383. }
  384. }
  385. PrintComplex2D(&outR.front(), aRows, aCols);*/
  386. /*int N = sizeof(test) / sizeof(test[0]);
  387. std::vector<BFComplex> out;
  388. std::vector<BFComplex> invOut;
  389. BFComplex _a = BFComplex::Polar(1.0, 0.5f) * BFComplex::Polar(1.0, 2.01f);
  390. for (int k = 0; k < N; k++)
  391. {
  392. BFComplex val;
  393. for (int n = 0; n < N; n++)
  394. val += test[n] * BFComplex::Polar(1.0, - 2 * BF_PI_D * k * n / (double) N);
  395. out.push_back(val);
  396. }
  397. for (int n = 0; n < N; n++)
  398. {
  399. BFComplex val;
  400. for (int k = 0; k < N; k++)
  401. val += out[k] * BFComplex::Polar(1.0, 2 * BF_PI_D * k * n / (double) N);
  402. invOut.push_back(BFComplex(1.0/N) * val);
  403. }*/
  404. }
  405. void FFTShift1D(BFComplex* array, int size, int pitch, int dir)
  406. {
  407. BFComplex* prev = new BFComplex[size];
  408. for (int i = 0; i < size; i++)
  409. prev[i] = array[i * pitch];
  410. while (dir < 0)
  411. dir += size;
  412. for (int i = 0; i < size; i++)
  413. array[i * pitch] = prev[((i + dir) % size)];
  414. delete [] prev;
  415. }
  416. static void FFTShift2D(BFComplex* data, int cols, int rows)
  417. {
  418. for (int col = 0; col < cols; col++)
  419. FFTShift1D(data + col, rows, cols, cols / 2);
  420. for (int row = 0; row < rows; row++)
  421. FFTShift1D(data + row*cols, cols, 1, rows / 2);
  422. }
  423. static void FFTConvert(ImageData* source)
  424. {
  425. int aCols = source->mWidth;
  426. int aRows = source->mHeight;
  427. int count = aCols * aRows;
  428. BFComplex* nums = new BFComplex[count];
  429. for (int i = 0; i < count; i++)
  430. {
  431. PackedColor& color = *((PackedColor*) &source->mBits[i]);
  432. nums[i].mR = PackedColorGetGray()(color);
  433. }
  434. //FFT
  435. for (int col = 0; col < aCols; col++)
  436. FFD_1D(nums + col, aRows, aCols, -1);
  437. for (int row = 0; row < aRows; row++)
  438. FFD_1D(nums + row*aCols, aCols, 1, -1);
  439. //INV FFT
  440. /*for (int col = 0; col < aCols; col++)
  441. FFD_1D(nums + col, aRows, aCols, 1);
  442. for (int row = 0; row < aRows; row++)
  443. FFD_1D(nums + row*aCols, aCols, 1, 1);*/
  444. FFTShift2D(nums, aCols, aRows);
  445. double* fFTLog = new double[count];
  446. double maxLog = 0;
  447. for (int i = 0; i < count; i++)
  448. {
  449. double aLog = log(1 + nums[i].Magnitude());
  450. maxLog = std::max(maxLog, aLog);
  451. fFTLog[i] = aLog;
  452. }
  453. for (int i = 0; i < count; i++)
  454. {
  455. //int val = (int) nums[i].Magnitude() / 1;
  456. int val = (int) (fFTLog[i] * 255 / maxLog);
  457. val = std::min(255, std::max(0, val));
  458. source->mBits[i] = 0xFF000000 | val | (val << 8) | (val << 16);
  459. }
  460. delete [] fFTLog;
  461. delete [] nums;
  462. }
  463. void DCT_1D(double* array, int size, int pitch)
  464. {
  465. double* prev = new double[size];
  466. for (int i = 0; i < size; i++)
  467. prev[i] = array[i*pitch];
  468. for (int idxOut = 0; idxOut < size; idxOut++)
  469. {
  470. double val = 0;
  471. double scale = (idxOut == 0) ? 1/sqrt(2.0) : 1;
  472. for (int idxIn = 0; idxIn < size; idxIn++)
  473. val += prev[idxIn] * cos(idxOut * BF_PI * (2*idxIn + 1)/(2 * size));
  474. array[idxOut*pitch] = 0.5 * scale * val;
  475. }
  476. delete [] prev;
  477. }
  478. void IDCT_1D(double* array, int size, int pitch)
  479. {
  480. double* prev = new double[size];
  481. for (int i = 0; i < size; i++)
  482. prev[i] = array[i*pitch];
  483. for (int idxOut = 0; idxOut < size; idxOut++)
  484. {
  485. double val = 0;
  486. for (int idxIn = 0; idxIn < size; idxIn++)
  487. {
  488. double scale = (idxIn == 0) ? 1/sqrt(2.0) : 1;
  489. val += scale * prev[idxIn] * cos(idxIn * BF_PI * (2*idxOut + 1)/(2 * size));
  490. }
  491. array[idxOut*pitch] = 0.5 * val;
  492. }
  493. delete [] prev;
  494. }
  495. const int DCT_1D_I_TABLE[64] =
  496. {
  497. 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096,
  498. 4017, 3405, 2275, 799, -799, -2275, -3405, -4017,
  499. 3784, 1567, -1567, -3784, -3784, -1567, 1567, 3784,
  500. 3405, -799, -4017, -2275, 2275, 4017, 799, -3405,
  501. 2896, -2896, -2896, 2896, 2896, -2896, -2896, 2896,
  502. 2275, -4017, 799, 3405, -3405, -799, 4017, -2275,
  503. 1567, -3784, 3784, -1567, -1567, 3784, -3784, 1567,
  504. 799, -2275, 3405, -4017, 4017, -3405, 2275, -799
  505. };
  506. void DCT_1D_I(int* array, int size, int pitch)
  507. {
  508. int* prev = new int[size];
  509. for (int i = 0; i < size; i++)
  510. prev[i] = array[i*pitch];
  511. int multIdx = 0;
  512. for (int idxOut = 0; idxOut < size; idxOut++)
  513. {
  514. int val = 0;
  515. for (int idxIn = 0; idxIn < size; idxIn++)
  516. val += prev[idxIn] * DCT_1D_I_TABLE[multIdx++];
  517. if (idxOut == 0)
  518. array[idxOut*pitch] = val / 0x2d41;
  519. else
  520. array[idxOut*pitch] = val / 0x2000;
  521. }
  522. delete [] prev;
  523. }
  524. const int IDCT_1D_I_TABLE[64] =
  525. {
  526. 2896, 4017, 3784, 3405, 2896, 2275, 1567, 799,
  527. 2896, 3405, 1567, -799, -2896, -4017, -3784, -2275,
  528. 2896, 2275, -1567, -4017, -2896, 799, 3784, 3405,
  529. 2896, 799, -3784, -2275, 2896, 3405, -1567, -4017,
  530. 2896, -799, -3784, 2275, 2896, -3405, -1567, 4017,
  531. 2896, -2275, -1567, 4017, -2896, -799, 3784, -3405,
  532. 2896, -3405, 1567, 799, -2896, 4017, -3784, 2275,
  533. 2896, -4017, 3784, -3405, 2896, -2275, 1567, -799
  534. };
  535. void IDCT_1D_I(int* array, int size, int pitch)
  536. {
  537. int prev[64];
  538. for (int i = 0; i < size; i++)
  539. prev[i] = array[i*pitch];
  540. int multIdx = 0;
  541. for (int idxOut = 0; idxOut < size; idxOut++)
  542. {
  543. int val = 0;
  544. for (int idxIn = 0; idxIn < size; idxIn++)
  545. val += prev[idxIn] * IDCT_1D_I_TABLE[multIdx++];
  546. array[idxOut*pitch] = val / 0x2000;
  547. }
  548. }
  549. void BFIData::Compress(ImageData* source)
  550. {
  551. /*DFTTest();
  552. DFTTest_2D();
  553. DFTTest_Mine();*/
  554. //FFTConvert(source);
  555. /*const int rowCount = 3;
  556. const int colCount = 4;
  557. double mat[rowCount][colCount] = {{2, 2, 5, 5}, {4, 4, 10, 11}, {3, 2, 6, 4}};
  558. double rightVals[rowCount] = {1, 2, 3};
  559. int pivotIdx[colCount] = {-1, -1, -1, -1};
  560. int moveIdx = 0;
  561. double pivotVals[colCount] = {0};
  562. for (int pivot = 0; pivot < colCount; pivot++)
  563. {
  564. bool moved = false;
  565. for (int eq = moveIdx; eq < rowCount; eq++)
  566. {
  567. if (!IS_ZERO(mat[eq][pivot]))
  568. {
  569. pivotVals[pivot] = mat[eq][pivot];
  570. for (int swapIdx = 0; swapIdx < colCount; swapIdx++)
  571. std::swap(mat[eq][swapIdx], mat[moveIdx][swapIdx]);
  572. std::swap(rightVals[eq], rightVals[moveIdx]);
  573. pivotIdx[pivot] = moveIdx;
  574. moved = true;
  575. break;
  576. }
  577. }
  578. if (!moved)
  579. continue;
  580. for (int eq = moveIdx + 1; eq < rowCount; eq++)
  581. {
  582. double multFactor = -mat[eq][pivot] / mat[moveIdx][pivot];
  583. bool nonZero = false;
  584. for (int multIdx = pivot; multIdx < colCount; multIdx++)
  585. {
  586. mat[eq][multIdx] += mat[moveIdx][multIdx]*multFactor;
  587. nonZero |= !IS_ZERO(mat[eq][multIdx]);
  588. }
  589. rightVals[eq] += rightVals[moveIdx]*multFactor;
  590. BF_ASSERT(IS_ZERO(rightVals[eq]) || (nonZero));
  591. }
  592. moveIdx++;
  593. }
  594. // Back substitute
  595. double result[colCount];
  596. for (int col = colCount - 1; col >= 0; col--)
  597. {
  598. result[col] = 0;
  599. if (pivotIdx[col] != -1)
  600. {
  601. int eq = pivotIdx[col];
  602. double left = 0;
  603. for (int multCol = col + 1; multCol < colCount; multCol++)
  604. left += mat[eq][multCol] * result[multCol];
  605. double right = rightVals[eq] - left;
  606. right /= mat[eq][col];
  607. result[col] = right;
  608. }
  609. }
  610. ///*/
  611. uint8 rawData[64] = {
  612. 52, 55, 61, 66, 70, 61, 64, 73,
  613. 63, 59, 55, 90,109, 85, 69, 72,
  614. 62, 59, 68,113,144,104, 66, 73,
  615. 63, 58, 71,122,154,106, 70, 69,
  616. 67, 61, 68,104,126, 88, 68, 70,
  617. 79, 65, 60, 70, 77, 68, 58, 75,
  618. 85, 71, 64, 59, 55, 61, 65, 83,
  619. 87, 79, 69, 68, 65, 76, 78, 94};
  620. double dCTIn[64];
  621. for (int i = 0; i < 64; i++)
  622. dCTIn[i] = (int) rawData[i] - 128;
  623. //double dCTOut[64];
  624. /*for (int v = 0; v < 8; v++)
  625. {
  626. for (int u = 0; u < 8; u++)
  627. {
  628. dCTOut[u+v*8] = 0;
  629. for (int y = 0; y < 8; y++)
  630. {
  631. for (int x = 0; x < 8; x++)
  632. {
  633. double au = (u == 0) ? sqrt(1.0/8.0) : sqrt(2.0/8.0);
  634. double av = (v == 0) ? sqrt(1.0/8.0) : sqrt(2.0/8.0);
  635. dCTOut[u+v*8] += au*av*dCTIn[x+y*8]*
  636. cos(BF_PI_D/8 * (x + 0.5)*u) *
  637. cos(BF_PI_D/8 * (y + 0.5)*v);
  638. }
  639. }
  640. }
  641. }*/
  642. double dCT[64];
  643. for (int i = 0; i < 64; i++)
  644. dCT[i] = rawData[i] - 128;
  645. int aCols = 8;
  646. int aRows = 8;
  647. for (int col = 0; col < aCols; col++)
  648. DCT_1D(dCT + col, aRows, aCols);
  649. for (int row = 0; row < aRows; row++)
  650. DCT_1D(dCT + row*aCols, aCols, 1);
  651. for (int col = 0; col < aCols; col++)
  652. IDCT_1D(dCT + col, aRows, aCols);
  653. for (int row = 0; row < aRows; row++)
  654. IDCT_1D(dCT + row*aCols, aCols, 1);
  655. //
  656. int dCT_I[64];
  657. for (int i = 0; i < 64; i++)
  658. dCT_I[i] = (rawData[i] - 128) * 256;
  659. for (int col = 0; col < aCols; col++)
  660. DCT_1D_I(dCT_I + col, aRows, aCols);
  661. for (int row = 0; row < aRows; row++)
  662. DCT_1D_I(dCT_I + row*aCols, aCols, 1);
  663. for (int col = 0; col < aCols; col++)
  664. IDCT_1D_I(dCT_I + col, aRows, aCols);
  665. for (int row = 0; row < aRows; row++)
  666. IDCT_1D_I(dCT_I + row*aCols, aCols, 1);
  667. for (int i = 0; i < 64; i++)
  668. {
  669. int val = dCT_I[i];
  670. if (val < 0)
  671. dCT_I[i] = (val - 128) / 256;
  672. else
  673. dCT_I[i] = (val + 128) / 256;
  674. }
  675. ///
  676. int quantTable[] = {16, 11, 11, 16, 23, 27, 31, 30, 11, 12, 12, 15, 20, 23, 23, 30,
  677. 11, 12, 13, 16, 23, 26, 35, 47, 16, 15, 16, 23, 26, 37, 47, 64,
  678. 23, 20, 23, 26, 39, 51, 64, 64, 27, 23, 26, 37, 51, 64, 64, 64,
  679. 31, 23, 35, 47, 64, 64, 64, 64, 30, 30, 47, 64, 64, 64, 64, 64};
  680. int quantDCT[64];
  681. for (int i = 0; i < 64; i++)
  682. quantDCT[i] = (int) BFRound((float) (dCT[i] / quantTable[i]));
  683. int zigZag[64] = {
  684. 0, 1, 5, 6, 14, 15, 27, 28,
  685. 2, 4, 7, 13, 16, 26, 29, 42,
  686. 3, 8, 12, 17, 25, 30, 41, 43,
  687. 9, 11, 18, 24, 31, 40, 44, 53,
  688. 10, 19, 23, 32, 39, 45, 52, 54,
  689. 20, 22, 33, 38, 46, 51, 55, 60,
  690. 21, 34, 37, 47, 50, 56, 59, 61,
  691. 35, 36, 48, 49, 57, 58, 62, 63
  692. };
  693. int zigZagDCT[64];
  694. for (int i = 0; i < 64; i++)
  695. {
  696. zigZagDCT[i] = quantDCT[zigZag[i]];
  697. }
  698. /*double dCTOutH[64];
  699. double dCTOutV[64];
  700. for (int v = 0; v < 8; v++)
  701. {
  702. for (int u = 0; u < 8; u++)
  703. {
  704. dCTOutV[u+v*8] = 0;
  705. for (int y = 0; y < 8; y++)
  706. {
  707. double av = (v == 0) ? sqrt(1.0/8.0) : sqrt(2.0/8.0);
  708. dCTOutV[u+v*8] += av*dCTIn[u+y*8]*
  709. cos(BF_PI_D/8 * (y + 0.5)*v);
  710. }
  711. }
  712. }
  713. for (int v = 0; v < 8; v++)
  714. {
  715. for (int u = 0; u < 8; u++)
  716. {
  717. dCTOutH[u+v*8] = 0;
  718. for (int x = 0; x < 8; x++)
  719. {
  720. double au = (u == 0) ? sqrt(1.0/8.0) : sqrt(2.0/8.0);
  721. dCTOutH[u+v*8] += au*dCTOutV[x+v*8]*
  722. cos(BF_PI_D/8 * (x + 0.5)*u);
  723. }
  724. //dCTOut[u+v*8] = val;
  725. }
  726. }*/
  727. }