14 #include <Eigen/Dense> 32 static void four1(
float data[],
unsigned long nn,
int isign)
34 unsigned long n, mmax, m, j, i;
35 double wtemp, wr, wpr, wpi, wi,
51 while (m >= 2 && j > m)
62 unsigned long istep = mmax << 1;
63 theta = isign * (6.28318530717959 /
65 wtemp = sin(0.5 * theta);
66 wpr = -2.0 * wtemp * wtemp;
70 for (m = 1; m < mmax; m += 2)
72 for (i = m; i <= n; i += istep)
75 tempr = (float)(wr *
data[j] - wi *
data[j + 1]);
76 tempi = (float)(wr *
data[j + 1] + wi *
data[j]);
82 wr = (wtemp = wr) * wpr - wi * wpi +
84 wi = wi * wpr + wtemp * wpi + wi;
103 unsigned long i, i1, i2, i3, i4, np3;
104 float c1 = 0.5, c2, h1r, h1i, h2r, h2i;
105 double wr, wi, wpr, wpi, wtemp,
107 theta = 3.141592653589793 / (double)(n >> 1);
112 wtemp = sin(0.5 * theta);
113 wpr = -2.0 * wtemp * wtemp;
118 for (i = 2; i <= (n >> 2); i++)
120 i4 = 1 + (i3 = np3 - (i2 = 1 + (i1 = i + i - 1)));
127 (float)(h1r + wr * h2r - wi * h2i);
130 data[i2] = (float)(h1i + wr * h2i + wi * h2r);
131 data[i3] = (float)(h1r - wr * h2r + wi * h2i);
132 data[i4] = (float)(-h1i + wr * h2i + wi * h2r);
133 wr = (wtemp = wr) * wpr - wi * wpi + wr;
134 wi = wi * wpr + wtemp * wpi + wi;
159 int j, j1, j2, j3, k, k1, ks, l, m;
160 FFT_TYPE wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
161 FFT_TYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
167 for (j = 0; j <= l - 2; j += 2)
173 x0i = a[j + 1] + a[j1 + 1];
175 x1i = a[j + 1] - a[j1 + 1];
177 x2i = a[j2 + 1] + a[j3 + 1];
179 x3i = a[j2 + 1] - a[j3 + 1];
181 a[j + 1] = x0i + x2i;
183 a[j2 + 1] = x0i - x2i;
185 a[j1 + 1] = x1i + x3r;
187 a[j3 + 1] = x1i - x3r;
192 for (j = m; j <= l + m - 2; j += 2)
198 x0i = a[j + 1] + a[j1 + 1];
200 x1i = a[j + 1] - a[j1 + 1];
202 x2i = a[j2 + 1] + a[j3 + 1];
204 x3i = a[j2 + 1] - a[j3 + 1];
206 a[j + 1] = x0i + x2i;
208 a[j2 + 1] = x0r - x2r;
211 a[j1] = wk1r * (x0r - x0i);
212 a[j1 + 1] = wk1r * (x0r + x0i);
215 a[j3] = wk1r * (x0i - x0r);
216 a[j3 + 1] = wk1r * (x0i + x0r);
220 for (k = (m << 1); k <= n - m; k += m)
225 wk1i = w[(k1 << 1) + 1];
228 wk3r = wk1r - 2 * wk2i * wk1i;
229 wk3i = 2 * wk2i * wk1r - wk1i;
230 for (j = k; j <= l + k - 2; j += 2)
236 x0i = a[j + 1] + a[j1 + 1];
238 x1i = a[j + 1] - a[j1 + 1];
240 x2i = a[j2 + 1] + a[j3 + 1];
242 x3i = a[j2 + 1] - a[j3 + 1];
244 a[j + 1] = x0i + x2i;
247 a[j2] = wk2r * x0r - wk2i * x0i;
248 a[j2 + 1] = wk2r * x0i + wk2i * x0r;
251 a[j1] = wk1r * x0r - wk1i * x0i;
252 a[j1 + 1] = wk1r * x0i + wk1i * x0r;
255 a[j3] = wk3r * x0r - wk3i * x0i;
256 a[j3 + 1] = wk3r * x0i + wk3i * x0r;
264 for (j = 0; j <= l - 2; j += 2)
268 x0i = a[j + 1] - a[j1 + 1];
270 a[j + 1] += a[j1 + 1];
279 int j, j1, j2, j3, k, k1, ks, l, m;
280 FFT_TYPE wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
281 FFT_TYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
287 for (j = 0; j <= l - 2; j += 2)
293 x0i = a[j + 1] + a[j1 + 1];
295 x1i = a[j + 1] - a[j1 + 1];
297 x2i = a[j2 + 1] + a[j3 + 1];
299 x3i = a[j2 + 1] - a[j3 + 1];
301 a[j + 1] = x0i + x2i;
303 a[j2 + 1] = x0i - x2i;
305 a[j1 + 1] = x1i - x3r;
307 a[j3 + 1] = x1i + x3r;
312 for (j = m; j <= l + m - 2; j += 2)
318 x0i = a[j + 1] + a[j1 + 1];
320 x1i = a[j + 1] - a[j1 + 1];
322 x2i = a[j2 + 1] + a[j3 + 1];
324 x3i = a[j2 + 1] - a[j3 + 1];
326 a[j + 1] = x0i + x2i;
328 a[j2 + 1] = x2r - x0r;
331 a[j1] = wk1r * (x0i + x0r);
332 a[j1 + 1] = wk1r * (x0i - x0r);
335 a[j3] = wk1r * (x0r + x0i);
336 a[j3 + 1] = wk1r * (x0r - x0i);
340 for (k = (m << 1); k <= n - m; k += m)
345 wk1i = w[(k1 << 1) + 1];
348 wk3r = wk1r - 2 * wk2i * wk1i;
349 wk3i = 2 * wk2i * wk1r - wk1i;
350 for (j = k; j <= l + k - 2; j += 2)
356 x0i = a[j + 1] + a[j1 + 1];
358 x1i = a[j + 1] - a[j1 + 1];
360 x2i = a[j2 + 1] + a[j3 + 1];
362 x3i = a[j2 + 1] - a[j3 + 1];
364 a[j + 1] = x0i + x2i;
367 a[j2] = wk2r * x0r + wk2i * x0i;
368 a[j2 + 1] = wk2r * x0i - wk2i * x0r;
371 a[j1] = wk1r * x0r + wk1i * x0i;
372 a[j1 + 1] = wk1r * x0i - wk1i * x0r;
375 a[j3] = wk3r * x0r + wk3i * x0i;
376 a[j3 + 1] = wk3r * x0i - wk3i * x0r;
384 for (j = 0; j <= l - 2; j += 2)
388 x0i = a[j + 1] - a[j1 + 1];
390 a[j + 1] += a[j1 + 1];
408 delta = atan(1.0f) / nwh;
411 w[nwh] = cos(delta * nwh);
413 for (j = 2; j <= nwh - 2; j += 2)
440 delta = atan(1.0f) / nch;
442 c[nch] = 0.5f * cos(delta * nch);
443 for (j = 1; j <= nch - 1; j++)
445 c[j] = 0.5f * cos(delta * j);
446 c[nc - j] = 0.5f * sin(delta * j);
458 int j, j1, k, k1, l, m, m2;
467 for (j = 0; j <= m - 1; j++)
469 ip[m + j] = ip[j] + l;
475 for (k = 1; k <= m - 1; k++)
477 for (j = 0; j <= k - 1; j++)
479 j1 = (j << 1) + ip[k];
480 k1 = (k << 1) + ip[j];
484 a[j1 + 1] = a[k1 + 1];
493 for (k = 1; k <= m - 1; k++)
495 for (j = 0; j <= k - 1; j++)
497 j1 = (j << 1) + ip[k];
498 k1 = (k << 1) + ip[j];
502 a[j1 + 1] = a[k1 + 1];
510 a[j1 + 1] = a[k1 + 1];
525 if (n > (ip[0] << 2))
550 for (k = (n >> 1) - 2; k >= 2; k -= 2)
557 xi = a[k + 1] + a[j + 1];
558 yr = wkr * xr + wki * xi;
559 yi = wkr * xi - wki * xr;
586 a[1] = 0.5f * (a[0] - a[1]);
619 for (k = (n >> 1) - 2; k >= 2; k -= 2)
626 xi = a[k + 1] + a[j + 1];
627 yr = wkr * xr - wki * xi;
628 yi = wkr * xi + wki * xr;
738 int n, nw, nc, n1h, i, j, i2;
761 for (i = 1; i <= n1h - 1; i++)
764 xi = a[i][0] - a[j][0];
767 xi = a[j][1] - a[i][1];
771 for (j = 0; j <= n2 - 2; j += 2)
773 for (i = 0; i <= n1 - 1; i++)
777 t[i2 + 1] = a[i][j + 1];
779 cdft(n1 << 1, isgn, t, ip, w);
780 for (i = 0; i <= n1 - 1; i++)
784 a[i][j + 1] = t[i2 + 1];
787 for (i = 0; i <= n1 - 1; i++)
789 rdft(n2, isgn, a[i], ip, w);
794 for (i = 0; i <= n1 - 1; i++)
796 rdft(n2, isgn, a[i], ip, w);
798 for (j = 0; j <= n2 - 2; j += 2)
800 for (i = 0; i <= n1 - 1; i++)
804 t[i2 + 1] = a[i][j + 1];
806 cdft(n1 << 1, isgn, t, ip, w);
807 for (i = 0; i <= n1 - 1; i++)
811 a[i][j + 1] = t[i2 + 1];
814 for (i = 1; i <= n1h - 1; i++)
817 a[j][0] = 0.5f * (a[i][0] - a[j][0]);
819 a[j][1] = 0.5f * (a[i][1] + a[j][1]);
899 if (n > (ip[0] << 2))
903 for (i = 0; i <= n1 - 1; i++)
905 cdft(n2, isgn, a[i], ip, w);
907 for (j = 0; j <= n2 - 2; j += 2)
909 for (i = 0; i <= n1 - 1; i++)
913 t[i2 + 1] = a[i][j + 1];
915 cdft(n1 << 1, isgn, t, ip, w);
916 for (i = 0; i <= n1 - 1; i++)
920 a[i][j + 1] = t[i2 + 1];
933 auto n = (
unsigned long)in_realData.
size();
939 memcpy(&auxVect[1], &in_realData[0], n *
sizeof(auxVect[0]));
943 unsigned int n_2 = 1 + (n / 2);
949 for (
unsigned int i = 0; i < n_2; i++)
952 out_FFT_Re[i] = auxVect[2];
954 out_FFT_Re[i] = auxVect[1 + i * 2];
956 if (i == 0 || i == (n_2 - 1))
959 out_FFT_Im[i] = auxVect[1 + i * 2 + 1];
962 std::sqrt(
square(out_FFT_Re[i]) +
square(out_FFT_Im[i]));
977 size_t dim1 = in_data.
rows();
978 size_t dim2 = in_data.
cols();
989 a =
new float_ptr[dim1];
990 for (i = 0; i < dim1; i++)
993 for (j = 0; j < dim2; j++) a[i][j] = in_data(i, j);
997 ip =
new int[(int)ceil(20 + 2 + sqrt((
FFT_TYPE)max(dim1, dim2 / 2)))];
999 w =
new FFT_TYPE[max(dim1 / 2, dim2 / 4) + dim2 / 4 + 20];
1003 rdft2d((
int)dim1, (
int)dim2, 1, a, t, ip, w);
1013 for (i = 1; i < dim1; i++)
1014 for (j = 1; j < dim2 / 2; j++)
1016 out_real(i, j) = (float)a[i][j * 2];
1017 out_real(dim1 - i, dim2 - j) = (float)a[i][j * 2];
1018 out_imag(i, j) = (float)-a[i][j * 2 + 1];
1019 out_imag(dim1 - i, dim2 - j) = (float)a[i][j * 2 + 1];
1024 for (j = 1; j < dim2 / 2; j++)
1026 out_real(0, j) = (float)a[0][j * 2];
1027 out_real(0, dim2 - j) = (float)a[0][j * 2];
1028 out_imag(0, j) = (float)-a[0][j * 2 + 1];
1029 out_imag(0, dim2 - j) = (float)a[0][j * 2 + 1];
1037 for (i = 1; i < dim1 / 2; i++)
1039 out_real(i, 0) = (float)a[i][0];
1040 out_real(dim1 - i, 0) = (float)a[i][0];
1041 out_imag(i, 0) = (float)-a[i][1];
1042 out_imag(dim1 - i, 0) = (float)a[i][1];
1043 out_real(i, dim2 / 2) = (float)a[dim1 - i][1];
1044 out_real(dim1 - i, dim2 / 2) = (float)a[dim1 - i][1];
1045 out_imag(i, dim2 / 2) = (float)a[dim1 - i][0];
1046 out_imag(dim1 - i, dim2 / 2) = (float)-a[dim1 - i][0];
1053 out_real(0, 0) = (float)a[0][0];
1054 out_real(0, dim2 / 2) = (float)a[0][1];
1055 out_real(dim1 / 2, 0) = (float)a[dim1 / 2][0];
1056 out_real(dim1 / 2, dim2 / 2) = (float)a[dim1 / 2][1];
1059 for (i = 0; i < dim1; i++)
delete[] a[i];
1081 size_t dim1 = in_real.
rows();
1082 size_t dim2 = in_real.
cols();
1096 a =
new float_ptr[dim1];
1097 for (i = 0; i < dim1; i++) a[i] =
new FFT_TYPE[dim2];
1102 for (i = 1; i < dim1; i++)
1103 for (j = 1; j < dim2 / 2; j++)
1105 a[i][2 * j] = in_real(i, j);
1106 a[i][2 * j + 1] = -in_imag(i, j);
1112 for (j = 1; j < dim2 / 2; j++)
1114 a[0][2 * j] = in_real(0, j);
1115 a[0][2 * j + 1] = -in_imag(0, j);
1123 for (i = 1; i < dim1 / 2; i++)
1125 a[i][0] = in_real(i, 0);
1126 a[i][1] = -in_imag(i, 0);
1127 a[dim1 - i][1] = in_real(i, dim2 / 2);
1128 a[dim1 - i][0] = in_imag(i, dim2 / 2);
1135 a[0][0] = in_real(0, 0);
1136 a[0][1] = in_real(0, dim2 / 2);
1137 a[dim1 / 2][0] = in_real(dim1 / 2, 0);
1138 a[dim1 / 2][1] = in_real(dim1 / 2, dim2 / 2);
1141 ip =
new int[(int)ceil(20 + 2 + sqrt((
FFT_TYPE)max(dim1, dim2 / 2)))];
1143 w =
new FFT_TYPE[max(dim1 / 2, dim2 / 4) + dim2 / 4 + 20];
1147 rdft2d((
int)dim1, (
int)dim2, -1, a, t, ip, w);
1153 FFT_TYPE scale = 2.0f / (dim1 * dim2);
1155 for (i = 0; i < dim1; i++)
1156 for (j = 0; j < dim2; j++) out_data(i, j) = (float)(a[i][j] * scale);
1159 for (i = 0; i < dim1; i++)
delete[] a[i];
1181 size_t dim1 = in_real.
rows();
1182 size_t dim2 = in_real.
cols();
1184 size_t k1, k2, n1, n2;
1186 auto ang1 = (float)(
sign *
M_2PI / dim1);
1187 auto ang2 = (float)(
sign *
M_2PI / dim2);
1190 float scale =
sign == 1 ? (1.0f / (dim1 * dim2)) : 1;
1195 for (k1 = 0; k1 < dim1; k1++)
1197 for (k2 = 0; k2 < dim2; k2++)
1201 for (n1 = 0; n1 < dim1; n1++)
1203 phase = ang1 * n1 * k1;
1204 for (n2 = 0; n2 < dim2; n2++)
1209 R += w_r * in_real(n1, n2) - w_i * in_imag(n1, n2);
1210 I += w_i * in_real(n1, n2) + w_r * in_imag(n1, n2);
1217 out_real(k1, k2) =
R * scale;
1218 out_imag(k1, k2) = I * scale;
1237 size_t dim1 = in_real.
rows();
1238 size_t dim2 = in_real.
cols();
1245 if (dim1IsPower2 && dim2IsPower2)
1256 static int* ip =
nullptr;
1261 static int alreadyInitSize1 = -1, alreadyInitSize2 = -1;
1263 if (alreadyInitSize1 != (
int)dim1 || alreadyInitSize2 != (int)dim2)
1268 for (i = 0; i < dim1; i++)
delete[] a[i];
1271 if (ip)
delete[] ip;
1275 alreadyInitSize1 = (int)dim1;
1276 alreadyInitSize2 = (int)dim2;
1278 a =
new float_ptr[dim1];
1279 for (i = 0; i < dim1; i++) a[i] =
new FFT_TYPE[2 * dim2];
1282 ip =
new int[(int)ceil(
1283 20 + 2 + sqrt((
FFT_TYPE)max(dim1, dim2 / 2)))];
1285 w =
new FFT_TYPE[max(dim1 / 2, dim2 / 4) + dim2 / 4 + 20];
1290 for (i = 0; i < dim1; i++)
1291 for (j = 0; j < dim2; j++)
1293 a[i][2 * j + 0] = in_real(i, j);
1294 a[i][2 * j + 1] = in_imag(i, j);
1299 cdft2d((
int)dim1, (
int)(2 * dim2), 1, a, t, ip, w);
1309 for (i = 0; i < dim1; i++)
1310 for (j = 0; j < dim2; j++)
1312 out_real(i, j) = (float)a[i][j * 2 + 0];
1313 out_imag(i, j) = (float)a[i][j * 2 + 1];
1322 printf(
"Using general DFT...\n");
1323 myGeneralDFT(-1, in_real, in_imag, out_real, out_imag);
1342 size_t dim1 = in_real.
rows();
1343 size_t dim2 = in_real.
cols();
1350 if (dim1IsPower2 && dim2IsPower2)
1361 static int* ip =
nullptr;
1369 static int alreadyInitSize1 = -1, alreadyInitSize2 = -1;
1371 if (alreadyInitSize1 != (
int)dim1 || alreadyInitSize2 != (int)dim2)
1376 for (i = 0; i < dim1; i++)
delete[] a[i];
1379 if (ip)
delete[] ip;
1383 alreadyInitSize1 = (int)dim1;
1384 alreadyInitSize2 = (int)dim2;
1386 a =
new float_ptr[dim1];
1387 for (i = 0; i < dim1; i++) a[i] =
new FFT_TYPE[2 * dim2];
1389 ip =
new int[(int)ceil(
1390 20 + 2 + sqrt((
FFT_TYPE)max(dim1, dim2 / 2)))];
1392 w =
new FFT_TYPE[max(dim1 / 2, dim2 / 4) + dim2 / 4 + 20];
1397 for (i = 0; i < dim1; i++)
1398 for (j = 0; j < dim2; j++)
1400 a[i][2 * j + 0] = in_real(i, j);
1401 a[i][2 * j + 1] = in_imag(i, j);
1406 cdft2d((
int)dim1, (
int)(2 * dim2), -1, a, t, ip, w);
1413 FFT_TYPE scale = 1.0f / (dim1 * dim2);
1418 for (i = 0; i < dim1; i++)
1419 for (j = 0; j < dim2; j++)
1423 out_real(i, j) = (float)(a[i][j * 2 + 0]);
1424 out_imag(i, j) = (float)(a[i][j * 2 + 1]);
1439 printf(
"Using general DFT...\n");
1458 const size_t lx =
A.cols();
1459 const size_t ly =
A.rows();
1470 for (y = 0; y < ly; y++)
1471 for (x = 0; x < lx; x++)
1473 float r1 = I1_R(y, x);
1474 float r2 = I2_R(y, x);
1476 float ii1 = I1_I(y, x);
1477 float ii2 = I2_I(y, x);
1480 I2_R(y, x) = (r1 * r2 + ii1 * ii2) / den;
1481 I2_I(y, x) = (ii2 * r1 - r2 * ii1) / den;
1489 for (y = 0; y < ly; y++)
1490 for (x = 0; x < lx; x++)
1491 out_corr(y, x) = sqrt(
square(res_R(y, x)) +
square(res_I(y, x)));
static void four1(float data[], unsigned long nn, int isign)
Template for column vectors of dynamic size, compatible with Eigen.
#define THROW_EXCEPTION(msg)
void dft2_real(const CMatrixFloat &in_data, CMatrixFloat &out_real, CMatrixFloat &out_imag)
Compute the 2D Discrete Fourier Transform (DFT) of a real matrix, returning the real and imaginary pa...
void fft_real(CVectorFloat &in_realData, CVectorFloat &out_FFT_Re, CVectorFloat &out_FFT_Im, CVectorFloat &out_FFT_Mag)
Computes the FFT of a 2^N-size vector of real numbers, and returns the Re+Im+Magnitude parts...
size_type size() const
Get a 2-vector with [NROWS NCOLS] (as in MATLAB command size(x))
static void rftfsub(int n, FFT_TYPE *a, int nc, FFT_TYPE *c)
static void myGeneralDFT(int sign, const CMatrixFloat &in_real, const CMatrixFloat &in_imag, CMatrixFloat &out_real, CMatrixFloat &out_imag)
#define ASSERT_(f)
Defines an assertion mechanism.
static void cdft2d(int n1, int n2, int isgn, FFT_TYPE **a, FFT_TYPE *t, int *ip, FFT_TYPE *w)
Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
static void rftbsub(int n, FFT_TYPE *a, int nc, FFT_TYPE *c)
This base provides a set of functions for maths stuff.
static void cftbsub(int n, FFT_TYPE *a, FFT_TYPE *w)
void cross_correlation_FFT(const CMatrixFloat &A, const CMatrixFloat &B, CMatrixFloat &out_corr)
Correlation of two matrixes using 2D FFT.
static void cftfsub(int n, FFT_TYPE *a, FFT_TYPE *w)
int sign(T x)
Returns the sign of X as "1" or "-1".
static void bitrv2(int n, int *ip, FFT_TYPE *a)
Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
T round2up(T val)
Round up to the nearest power of two of a given number.
float FFT_TYPE
Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
size_type rows() const
Number of rows in the matrix.
size_type cols() const
Number of columns in the matrix.
void idft2_complex(const CMatrixFloat &in_real, const CMatrixFloat &in_imag, CMatrixFloat &out_real, CMatrixFloat &out_imag)
Compute the 2D inverse Discrete Fourier Transform (DFT).
static void rdft(int n, int isgn, FFT_TYPE *a, int *ip, FFT_TYPE *w)
return_t square(const num_t x)
Inline function for the square of a number.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void idft2_real(const CMatrixFloat &in_real, const CMatrixFloat &in_imag, CMatrixFloat &out_data)
Compute the 2D inverse Discrete Fourier Transform (DFT)
static void makewt(int nw, int *ip, FFT_TYPE *w)
void setSize(size_t row, size_t col, bool zeroNewElements=false)
Changes the size of matrix, maintaining the previous contents.
static void rdft2d(int n1, int n2, int isgn, FFT_TYPE **a, FFT_TYPE *t, int *ip, FFT_TYPE *w)
Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
static void realft(float data[], unsigned long n)
static void makect(int nc, int *ip, FFT_TYPE *c)
Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
void resize(std::size_t N, bool zeroNewElements=false)
void dft2_complex(const CMatrixFloat &in_real, const CMatrixFloat &in_imag, CMatrixFloat &out_real, CMatrixFloat &out_imag)
Compute the 2D Discrete Fourier Transform (DFT) of a complex matrix, returning the real and imaginary...
EIGEN_MAP asEigen()
Get as an Eigen-compatible Eigen::Map object.
This template class provides the basic functionality for a general 2D any-size, resizable container o...
static void cdft(int n, int isgn, FFT_TYPE *a, int *ip, FFT_TYPE *w)
Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
static struct FontData data