Mercurial > hg > wm
comparison Fotopoulos-dir/common.c @ 24:9f20bce6184e v0.7
move directories, support netpbm 11
| author | Peter Meerwald-Stadler <pmeerw@pmeerw.net> |
|---|---|
| date | Fri, 20 Dec 2024 13:08:59 +0100 |
| parents | Fotopoulos/common.c@cbecc570129d |
| children |
comparison
equal
deleted
inserted
replaced
| 23:71dd4b96221b | 24:9f20bce6184e |
|---|---|
| 1 #include <stdio.h> | |
| 2 #include <stdlib.h> | |
| 3 #include <string.h> | |
| 4 #include <math.h> | |
| 5 #include <float.h> | |
| 6 #include "netpbm/pgm.h" | |
| 7 #include "common.h" | |
| 8 | |
| 9 #define IA 16807 | |
| 10 #define IM 2147483647 | |
| 11 #define AM (1.0/IM) | |
| 12 #define IQ 127773 | |
| 13 #define IR 2836 | |
| 14 #define MASK 123459876 | |
| 15 | |
| 16 static int NN = 0; | |
| 17 static int m = 0; | |
| 18 static double two_over_N = 0; | |
| 19 static double root2_over_rootN = 0; | |
| 20 static double *C = NULL; | |
| 21 | |
| 22 static gray maxval; | |
| 23 static int format; | |
| 24 | |
| 25 void open_image(FILE *in, int *width, int *height) | |
| 26 { | |
| 27 | |
| 28 pgm_readpgminit(in, width, height, &maxval, &format); | |
| 29 } | |
| 30 | |
| 31 void load_image(int **im, FILE *in, int width, int height) | |
| 32 { | |
| 33 int col, row; | |
| 34 gray *rowbuf; | |
| 35 | |
| 36 rowbuf = malloc(sizeof(gray) * width); | |
| 37 | |
| 38 for (row = 0; row < height; row++) { | |
| 39 pgm_readpgmrow(in, rowbuf, width, maxval, format); | |
| 40 for (col = 0; col < width; col++) | |
| 41 im[row][col] = rowbuf[col]; | |
| 42 } | |
| 43 | |
| 44 free(rowbuf); | |
| 45 } | |
| 46 | |
| 47 void save_image(int **im, FILE *out, int width, int height) | |
| 48 { | |
| 49 int col, row; | |
| 50 gray *rowbuf; | |
| 51 | |
| 52 pgm_writepgminit(out, width, height, 255, 0); | |
| 53 | |
| 54 rowbuf = malloc(sizeof(gray) * width); | |
| 55 | |
| 56 for (row = 0; row < height; row++) { | |
| 57 for (col = 0; col < width; col++) | |
| 58 rowbuf[col] = im[row][col]; | |
| 59 pgm_writepgmrow(out, rowbuf, width, 255, 0); | |
| 60 } | |
| 61 | |
| 62 free(rowbuf); | |
| 63 } | |
| 64 | |
| 65 int ** imatrix(int nrows, int ncols) | |
| 66 { | |
| 67 int **m; | |
| 68 int i, j; | |
| 69 m = (int **) malloc (nrows * sizeof(int *)); | |
| 70 for (i = 0; i < nrows; i++) { | |
| 71 m[i] = (int *) malloc (ncols * sizeof(int)); | |
| 72 if (!m[i]) fprintf(stderr, "\nIt's not working"); | |
| 73 } | |
| 74 for (i = 0; i < nrows; i++) | |
| 75 for (j = 0; j < ncols; j++) | |
| 76 m[i][j] = 0; | |
| 77 return m; | |
| 78 } | |
| 79 | |
| 80 void freematrix(int **I, int rows) | |
| 81 { | |
| 82 int k; | |
| 83 for (k = 0; k < rows; k++) | |
| 84 free (I[k]); | |
| 85 } | |
| 86 | |
| 87 float ran0(long int *idum) | |
| 88 { | |
| 89 long int k; | |
| 90 float ans; | |
| 91 *idum ^= MASK; | |
| 92 k = (*idum) / IQ; | |
| 93 *idum = IA * (*idum - k * IQ) - IR * k; | |
| 94 if (*idum < 0) *idum += IM; | |
| 95 ans = AM * (*idum); | |
| 96 *idum ^= MASK; | |
| 97 return ans; | |
| 98 } | |
| 99 | |
| 100 float gasdev(long int *idum) | |
| 101 { | |
| 102 | |
| 103 float v1; | |
| 104 v1 = (float) sqrt( -2.0 * log(ran0(idum))) * cos(2 * PI * ran0(idum)); | |
| 105 return v1; | |
| 106 } | |
| 107 | |
| 108 | |
| 109 void put_image_from_int_2_double(int **i, double *f, int N) | |
| 110 { | |
| 111 int l, j, k; | |
| 112 k = 0; | |
| 113 for (l = 0; l < N; l++) | |
| 114 for (j = 0; j < N; j++) | |
| 115 f[k++] = (double) i[l][j]; | |
| 116 } | |
| 117 | |
| 118 void put_image_from_double_2_int(double *f, int **i, int N) | |
| 119 { | |
| 120 int l, j, k; | |
| 121 k = 0; | |
| 122 for (l = 0; l < N; l++) | |
| 123 for (j = 0; j < N; j++) | |
| 124 i[l][j] = (int) f[k++]; | |
| 125 } | |
| 126 | |
| 127 | |
| 128 void bitrev(double *f, int len) | |
| 129 { | |
| 130 int i, j, m, halflen; | |
| 131 double temp; | |
| 132 | |
| 133 if (len <= 2) return ; /* No action necessary if n=1 or n=2 */ | |
| 134 halflen = len >> 1; | |
| 135 j = 1; | |
| 136 for (i = 1; i <= len; i++) { | |
| 137 if (i < j) { | |
| 138 temp = f[j - 1]; | |
| 139 f[j - 1] = f[i - 1]; | |
| 140 f[i - 1] = temp; | |
| 141 } | |
| 142 m = halflen; | |
| 143 while (j > m) { | |
| 144 j = j - m; | |
| 145 m = (m + 1) >> 1; | |
| 146 } | |
| 147 j = j + m; | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 void inv_sums(double *f) | |
| 152 { | |
| 153 int stepsize, stage, curptr, nthreads, thread, step, nsteps; | |
| 154 | |
| 155 for (stage = 1; stage <= m - 1; stage++) { | |
| 156 nthreads = 1 << (stage - 1); | |
| 157 stepsize = nthreads << 1; | |
| 158 nsteps = (1 << (m - stage)) - 1; | |
| 159 for (thread = 1; thread <= nthreads; thread++) { | |
| 160 curptr = NN - thread; | |
| 161 for (step = 1; step <= nsteps; step++) { | |
| 162 f[curptr] += f[curptr - stepsize]; | |
| 163 curptr -= stepsize; | |
| 164 } | |
| 165 } | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 //-------------------------------------------------------- | |
| 170 //Foreign code - FCT from Bath Univerity | |
| 171 //-------------------------------------------------------- | |
| 172 void rarrwrt(double f[], int n) | |
| 173 { | |
| 174 int i; | |
| 175 | |
| 176 for (i = 0; i <= n - 1; i++) { | |
| 177 fprintf(stderr, "%4d : %f\n", i, f[i]); | |
| 178 } | |
| 179 } | |
| 180 | |
| 181 /* fast DCT based on IEEE signal proc, 1992 #8, yugoslavian authors. */ | |
| 182 | |
| 183 void fwd_sums(double *f) | |
| 184 { | |
| 185 int stepsize, stage, curptr, nthreads, thread, step, nsteps; | |
| 186 | |
| 187 for (stage = m - 1; stage >= 1; stage--) { | |
| 188 nthreads = 1 << (stage - 1); | |
| 189 stepsize = nthreads << 1; | |
| 190 nsteps = (1 << (m - stage)) - 1; | |
| 191 for (thread = 1; thread <= nthreads; thread++) { | |
| 192 curptr = nthreads + thread - 1; | |
| 193 for (step = 1; step <= nsteps; step++) { | |
| 194 f[curptr] += f[curptr + stepsize]; | |
| 195 curptr += stepsize; | |
| 196 } | |
| 197 } | |
| 198 } | |
| 199 } | |
| 200 | |
| 201 void scramble(double *f, int len) | |
| 202 { | |
| 203 double temp; | |
| 204 int i, ii1, ii2, halflen, qtrlen; | |
| 205 | |
| 206 halflen = len >> 1; | |
| 207 qtrlen = halflen >> 1; | |
| 208 bitrev(f, len); | |
| 209 bitrev(&f[0], halflen); | |
| 210 bitrev(&f[halflen], halflen); | |
| 211 ii1 = len - 1; | |
| 212 ii2 = halflen; | |
| 213 for (i = 0; i <= qtrlen - 1; i++) { | |
| 214 temp = f[ii1]; | |
| 215 f[ii1] = f[ii2]; | |
| 216 f[ii2] = temp; | |
| 217 ii1--; | |
| 218 ii2++; | |
| 219 } | |
| 220 } | |
| 221 | |
| 222 void unscramble(double *f, int len) | |
| 223 { | |
| 224 double temp; | |
| 225 int i, ii1, ii2, halflen, qtrlen; | |
| 226 | |
| 227 halflen = len >> 1; | |
| 228 qtrlen = halflen >> 1; | |
| 229 ii1 = len - 1; | |
| 230 ii2 = halflen; | |
| 231 for (i = 0; i <= qtrlen - 1; i++) { | |
| 232 temp = f[ii1]; | |
| 233 f[ii1] = f[ii2]; | |
| 234 f[ii2] = temp; | |
| 235 ii1--; | |
| 236 ii2++; | |
| 237 } | |
| 238 bitrev(&f[0], halflen); | |
| 239 bitrev(&f[halflen], halflen); | |
| 240 bitrev(f, len); | |
| 241 } | |
| 242 | |
| 243 void initcosarray(int length) | |
| 244 { | |
| 245 int i, group, base, item, nitems, halfN; | |
| 246 double factor; | |
| 247 | |
| 248 m = -1; | |
| 249 do { | |
| 250 m++; | |
| 251 NN = 1 << m; | |
| 252 if (NN > length) { | |
| 253 fprintf(stderr, "ERROR in FCT-- length %d not a power of 2\n", length); | |
| 254 exit(1); | |
| 255 } | |
| 256 } while (NN < length); | |
| 257 if (C != NULL) free(C); | |
| 258 C = (double *)calloc(NN, sizeof(double)); | |
| 259 if (C == NULL) { | |
| 260 fprintf(stderr, "Unable to allocate C array\n"); | |
| 261 exit(1); | |
| 262 } | |
| 263 halfN = NN / 2; | |
| 264 two_over_N = 2.0 / (double)NN; | |
| 265 root2_over_rootN = sqrt(2.0 / (double)NN); | |
| 266 for (i = 0; i <= halfN - 1; i++) C[halfN + i] = 4 * i + 1; | |
| 267 for (group = 1; group <= m - 1; group++) { | |
| 268 base = 1 << (group - 1); | |
| 269 nitems = base; | |
| 270 factor = 1.0 * (1 << (m - group)); | |
| 271 for (item = 1; item <= nitems; item++) C[base + item - 1] = factor * C[halfN + item - 1]; | |
| 272 } | |
| 273 | |
| 274 //printf("before taking cos, C array =\n"); rarrwrt(C,N); | |
| 275 for (i = 1; i <= NN - 1; i++) C[i] = 1.0 / (2.0 * cos(C[i] * PI / (2.0 * NN))); | |
| 276 //printf("After taking cos, Carray = \n"); rarrwrt(C,N); | |
| 277 } | |
| 278 | |
| 279 | |
| 280 void inv_butterflies(double *f) | |
| 281 { | |
| 282 int stage, ii1, ii2, butterfly, ngroups, group, wingspan, increment, baseptr; | |
| 283 double Cfac, T; | |
| 284 | |
| 285 for (stage = 1; stage <= m; stage++) { | |
| 286 ngroups = 1 << (m - stage); | |
| 287 wingspan = 1 << (stage - 1); | |
| 288 increment = wingspan << 1; | |
| 289 for (butterfly = 1; butterfly <= wingspan; butterfly++) { | |
| 290 Cfac = C[wingspan + butterfly - 1]; | |
| 291 baseptr = 0; | |
| 292 for (group = 1; group <= ngroups; group++) { | |
| 293 ii1 = baseptr + butterfly - 1; | |
| 294 ii2 = ii1 + wingspan; | |
| 295 T = Cfac * f[ii2]; | |
| 296 f[ii2] = f[ii1]-T; | |
| 297 f[ii1] = f[ii1] + T; | |
| 298 baseptr += increment; | |
| 299 } | |
| 300 } | |
| 301 } | |
| 302 } | |
| 303 | |
| 304 void fwd_butterflies(double *f) | |
| 305 { | |
| 306 int stage, ii1, ii2, butterfly, ngroups, group, wingspan, increment, baseptr; | |
| 307 double Cfac, T; | |
| 308 | |
| 309 for (stage = m; stage >= 1; stage--) { | |
| 310 ngroups = 1 << (m - stage); | |
| 311 wingspan = 1 << (stage - 1); | |
| 312 increment = wingspan << 1; | |
| 313 for (butterfly = 1; butterfly <= wingspan; butterfly++) { | |
| 314 Cfac = C[wingspan + butterfly - 1]; | |
| 315 baseptr = 0; | |
| 316 for (group = 1; group <= ngroups; group++) { | |
| 317 ii1 = baseptr + butterfly - 1; | |
| 318 ii2 = ii1 + wingspan; | |
| 319 T = f[ii2]; | |
| 320 f[ii2] = Cfac * (f[ii1]-T); | |
| 321 f[ii1] = f[ii1] + T; | |
| 322 baseptr += increment; | |
| 323 } | |
| 324 } | |
| 325 } | |
| 326 } | |
| 327 | |
| 328 void ifct_noscale(double *f, int length) | |
| 329 { | |
| 330 if (length != NN) initcosarray(length); | |
| 331 f[0] *= INVROOT2; | |
| 332 inv_sums(f); | |
| 333 bitrev(f, NN); | |
| 334 inv_butterflies(f); | |
| 335 unscramble(f, NN); | |
| 336 } | |
| 337 | |
| 338 void fct_noscale(double *f, int length) | |
| 339 { | |
| 340 if (length != NN) initcosarray(length); | |
| 341 scramble(f, NN); | |
| 342 fwd_butterflies(f); | |
| 343 bitrev(f, NN); | |
| 344 fwd_sums(f); | |
| 345 f[0] *= INVROOT2; | |
| 346 } | |
| 347 | |
| 348 void ifct_defn_scaling(double *f, int length) | |
| 349 { | |
| 350 ifct_noscale(f, length); | |
| 351 } | |
| 352 | |
| 353 void fct_defn_scaling(double *f, int length) | |
| 354 { | |
| 355 int i; | |
| 356 | |
| 357 fct_noscale(f, length); | |
| 358 for (i = 0; i <= NN - 1; i++) f[i] *= two_over_N; | |
| 359 } | |
| 360 | |
| 361 void ifct(double *f, int length) | |
| 362 { | |
| 363 /* CALL THIS FOR INVERSE 1D DCT DON-MONRO PREFERRED SCALING */ | |
| 364 int i; | |
| 365 | |
| 366 if (length != NN) initcosarray(length); /* BGS patch June 1997 */ | |
| 367 for (i = 0; i <= NN - 1; i++) f[i] *= root2_over_rootN; | |
| 368 ifct_noscale(f, length); | |
| 369 } | |
| 370 | |
| 371 void fct(double *f, int length) | |
| 372 { | |
| 373 /* CALL THIS FOR FORWARD 1D DCT DON-MONRO PREFERRED SCALING */ | |
| 374 int i; | |
| 375 | |
| 376 fct_noscale(f, length); | |
| 377 for (i = 0; i <= NN - 1; i++) f[i] *= root2_over_rootN; | |
| 378 } | |
| 379 | |
| 380 /**************************************************************** | |
| 381 2D FAST DCT SECTION | |
| 382 ****************************************************************/ | |
| 383 | |
| 384 static double *g = NULL; | |
| 385 static double two_over_sqrtncolsnrows = 0.0; | |
| 386 static int ncolsvalue = 0; | |
| 387 static int nrowsvalue = 0; | |
| 388 | |
| 389 void initfct2d(int nrows, int ncols) | |
| 390 { | |
| 391 if ((nrows <= 0) || (ncols < 0)) { | |
| 392 fprintf(stderr, "FCT2D -- ncols=%d or nrows=%d is <=0\n", nrows, ncols); | |
| 393 exit(1); | |
| 394 } | |
| 395 if (g != NULL) free(g); | |
| 396 g = (double *)calloc(nrows, sizeof(double)); | |
| 397 if (g == NULL) { | |
| 398 fprintf(stderr, "FCT2D -- Unable to allocate g array\n"); | |
| 399 exit(1); | |
| 400 } | |
| 401 ncolsvalue = ncols; | |
| 402 nrowsvalue = nrows; | |
| 403 two_over_sqrtncolsnrows = 2.0 / sqrt(ncols * 1.0 * nrows); | |
| 404 } | |
| 405 | |
| 406 void fct2d(double f[], int nrows, int ncols) | |
| 407 /* CALL THIS FOR FORWARD 2d DCT DON-MONRO PREFERRED SCALING */ | |
| 408 { | |
| 409 int u, v; | |
| 410 | |
| 411 if ((ncols != ncolsvalue) || (nrows != nrowsvalue)){ | |
| 412 initfct2d(nrows, ncols); | |
| 413 } | |
| 414 for (u = 0; u <= nrows - 1; u++){ | |
| 415 fct_noscale(&f[u*ncols], ncols); | |
| 416 } | |
| 417 for (v = 0; v <= ncols - 1; v++){ | |
| 418 for (u = 0; u <= nrows - 1; u++) { | |
| 419 g[u] = f[u * ncols + v]; | |
| 420 } | |
| 421 fct_noscale(g, nrows); | |
| 422 for (u = 0; u <= nrows - 1; u++) { | |
| 423 f[u*ncols + v] = g[u] * two_over_sqrtncolsnrows; | |
| 424 } | |
| 425 } | |
| 426 } | |
| 427 | |
| 428 void ifct2d(double f[], int nrows, int ncols) | |
| 429 /* CALL THIS FOR INVERSE 2d DCT DON-MONRO PREFERRED SCALING */ | |
| 430 { | |
| 431 int u, v; | |
| 432 | |
| 433 if ((ncols != ncolsvalue) || (nrows != nrowsvalue)){ | |
| 434 initfct2d(nrows, ncols); | |
| 435 } | |
| 436 for (u = 0; u <= nrows - 1; u++){ | |
| 437 ifct_noscale(&f[u*ncols], ncols); | |
| 438 } | |
| 439 for (v = 0; v <= ncols - 1; v++){ | |
| 440 for (u = 0; u <= nrows - 1; u++) { | |
| 441 g[u] = f[u * ncols + v]; | |
| 442 } | |
| 443 ifct_noscale(g, nrows); | |
| 444 for (u = 0; u <= nrows - 1; u++) { | |
| 445 f[u*ncols + v] = g[u] * two_over_sqrtncolsnrows; | |
| 446 } | |
| 447 } | |
| 448 } | |
| 449 | |
| 450 void matmul(double **a, double **b, double **r, int N) | |
| 451 { | |
| 452 int i, j, k; | |
| 453 | |
| 454 for (i = 0; i < N; i++) | |
| 455 for (j = 0; j < N; j++) { | |
| 456 r[i][j] = 0.0; | |
| 457 for (k = 0; k < N; k++) | |
| 458 r[i][j] += a[i][k] * b[k][j]; | |
| 459 } | |
| 460 } | |
| 461 | |
| 462 void hartley(double **in, double **out, int N) | |
| 463 { | |
| 464 int k, n; | |
| 465 double **h; | |
| 466 | |
| 467 h = dmatrix(N, N); | |
| 468 //Building up the transformation matrix | |
| 469 for (k = 0; k < N; k++) | |
| 470 for (n = 0; n < N; n++) | |
| 471 h[k][n] = (cos(2 * PI * k * n / N) + sin(2 * PI * k * n / N)) / sqrt(N); | |
| 472 | |
| 473 // Now we have to multiply the input with the transformation matrix | |
| 474 matmul(h, in, out, N); | |
| 475 freematrix_d(h, N); | |
| 476 return ; | |
| 477 } | |
| 478 | |
| 479 double ** dmatrix(int nrows, int ncols) | |
| 480 { | |
| 481 double **m; | |
| 482 int i, j; | |
| 483 m = (double **) malloc (nrows * sizeof(double *)); | |
| 484 for (i = 0; i < nrows; i++) { | |
| 485 m[i] = (double *) malloc (ncols * sizeof(double)); | |
| 486 if (!m[i]) printf("\nIt's not working"); | |
| 487 } | |
| 488 for (i = 0; i < nrows; i++) | |
| 489 for (j = 0; j < ncols; j++) | |
| 490 m[i][j] = 0.0; | |
| 491 return m; | |
| 492 } | |
| 493 | |
| 494 void freematrix_d(double **I, int rows) | |
| 495 { | |
| 496 int k; | |
| 497 for (k = 0; k < rows; k++) | |
| 498 free (I[k]); | |
| 499 } | |
| 500 | |
| 501 void matrix_i2d(int **i, double **d, int N) | |
| 502 { | |
| 503 int x, y; | |
| 504 for (x = 0; x < N; x++) | |
| 505 for (y = 0; y < N; y++) | |
| 506 d[y][x] = i[y][x]; | |
| 507 } | |
| 508 | |
| 509 void matrix_d2i(double **d, int **i, int N) | |
| 510 { | |
| 511 int x, y; | |
| 512 for (x = 0; x < N; x++) | |
| 513 for (y = 0; y < N; y++) | |
| 514 i[y][x] = d[y][x]; | |
| 515 } | |
| 516 | |
| 517 double * dvector(long int N) | |
| 518 { | |
| 519 double *m; | |
| 520 m = (double *) malloc (N * sizeof(double)); | |
| 521 if (!m) printf("\nIt's not working"); | |
| 522 return m; | |
| 523 } | |
| 524 | |
| 525 void put_matrix_2_vector(double **i, double *f, int N) | |
| 526 { | |
| 527 int l, j, k; | |
| 528 k = 0; | |
| 529 for (l = 0; l < N; l++) | |
| 530 for (j = 0; j < N; j++) | |
| 531 f[k++] = i[l][j]; | |
| 532 } | |
| 533 | |
| 534 void put_vector_2_matrix(double *f, double **i, int N) | |
| 535 { | |
| 536 int l, j, k; | |
| 537 k = 0; | |
| 538 for (l = 0; l < N; l++) | |
| 539 for (j = 0; j < N; j++) | |
| 540 i[l][j] = f[k++]; | |
| 541 } | |
| 542 | |
| 543 void set_in_binary() { | |
| 544 #if defined(EMX) | |
| 545 _fsetmode(in, "b"); | |
| 546 #elif defined(MINGW) | |
| 547 setmode(STDIN_FILENO, O_BINARY); | |
| 548 #endif | |
| 549 } | |
| 550 | |
| 551 void set_out_binary() { | |
| 552 #if defined(EMX) | |
| 553 _fsetmode(out, "b"); | |
| 554 #elif defined(MINGW) | |
| 555 setmode(STDOUT_FILENO, O_BINARY); | |
| 556 #endif | |
| 557 } | |
| 558 | |
| 559 void wm_init2() { | |
| 560 set_out_binary(); | |
| 561 } | |
| 562 | |
| 563 void wm_init1() { | |
| 564 set_in_binary(); | |
| 565 } | |
| 566 | |
| 567 void wm_init() { | |
| 568 set_in_binary(); | |
| 569 set_out_binary(); | |
| 570 } | |
| 571 |
