Mercurial > hg > wm
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fotopoulos-dir/common.c Fri Dec 20 13:08:59 2024 +0100 @@ -0,0 +1,571 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <float.h> +#include "netpbm/pgm.h" +#include "common.h" + +#define IA 16807 +#define IM 2147483647 +#define AM (1.0/IM) +#define IQ 127773 +#define IR 2836 +#define MASK 123459876 + +static int NN = 0; +static int m = 0; +static double two_over_N = 0; +static double root2_over_rootN = 0; +static double *C = NULL; + +static gray maxval; +static int format; + +void open_image(FILE *in, int *width, int *height) +{ + + pgm_readpgminit(in, width, height, &maxval, &format); +} + +void load_image(int **im, FILE *in, int width, int height) +{ + int col, row; + gray *rowbuf; + + rowbuf = malloc(sizeof(gray) * width); + + for (row = 0; row < height; row++) { + pgm_readpgmrow(in, rowbuf, width, maxval, format); + for (col = 0; col < width; col++) + im[row][col] = rowbuf[col]; + } + + free(rowbuf); +} + +void save_image(int **im, FILE *out, int width, int height) +{ + int col, row; + gray *rowbuf; + + pgm_writepgminit(out, width, height, 255, 0); + + rowbuf = malloc(sizeof(gray) * width); + + for (row = 0; row < height; row++) { + for (col = 0; col < width; col++) + rowbuf[col] = im[row][col]; + pgm_writepgmrow(out, rowbuf, width, 255, 0); + } + + free(rowbuf); +} + +int ** imatrix(int nrows, int ncols) +{ + int **m; + int i, j; + m = (int **) malloc (nrows * sizeof(int *)); + for (i = 0; i < nrows; i++) { + m[i] = (int *) malloc (ncols * sizeof(int)); + if (!m[i]) fprintf(stderr, "\nIt's not working"); + } + for (i = 0; i < nrows; i++) + for (j = 0; j < ncols; j++) + m[i][j] = 0; + return m; +} + +void freematrix(int **I, int rows) +{ + int k; + for (k = 0; k < rows; k++) + free (I[k]); +} + +float ran0(long int *idum) +{ + long int k; + float ans; + *idum ^= MASK; + k = (*idum) / IQ; + *idum = IA * (*idum - k * IQ) - IR * k; + if (*idum < 0) *idum += IM; + ans = AM * (*idum); + *idum ^= MASK; + return ans; +} + +float gasdev(long int *idum) +{ + + float v1; + v1 = (float) sqrt( -2.0 * log(ran0(idum))) * cos(2 * PI * ran0(idum)); + return v1; +} + + +void put_image_from_int_2_double(int **i, double *f, int N) +{ + int l, j, k; + k = 0; + for (l = 0; l < N; l++) + for (j = 0; j < N; j++) + f[k++] = (double) i[l][j]; +} + +void put_image_from_double_2_int(double *f, int **i, int N) +{ + int l, j, k; + k = 0; + for (l = 0; l < N; l++) + for (j = 0; j < N; j++) + i[l][j] = (int) f[k++]; +} + + +void bitrev(double *f, int len) +{ + int i, j, m, halflen; + double temp; + + if (len <= 2) return ; /* No action necessary if n=1 or n=2 */ + halflen = len >> 1; + j = 1; + for (i = 1; i <= len; i++) { + if (i < j) { + temp = f[j - 1]; + f[j - 1] = f[i - 1]; + f[i - 1] = temp; + } + m = halflen; + while (j > m) { + j = j - m; + m = (m + 1) >> 1; + } + j = j + m; + } +} + +void inv_sums(double *f) +{ + int stepsize, stage, curptr, nthreads, thread, step, nsteps; + + for (stage = 1; stage <= m - 1; stage++) { + nthreads = 1 << (stage - 1); + stepsize = nthreads << 1; + nsteps = (1 << (m - stage)) - 1; + for (thread = 1; thread <= nthreads; thread++) { + curptr = NN - thread; + for (step = 1; step <= nsteps; step++) { + f[curptr] += f[curptr - stepsize]; + curptr -= stepsize; + } + } + } +} + +//-------------------------------------------------------- +//Foreign code - FCT from Bath Univerity +//-------------------------------------------------------- +void rarrwrt(double f[], int n) +{ + int i; + + for (i = 0; i <= n - 1; i++) { + fprintf(stderr, "%4d : %f\n", i, f[i]); + } +} + +/* fast DCT based on IEEE signal proc, 1992 #8, yugoslavian authors. */ + +void fwd_sums(double *f) +{ + int stepsize, stage, curptr, nthreads, thread, step, nsteps; + + for (stage = m - 1; stage >= 1; stage--) { + nthreads = 1 << (stage - 1); + stepsize = nthreads << 1; + nsteps = (1 << (m - stage)) - 1; + for (thread = 1; thread <= nthreads; thread++) { + curptr = nthreads + thread - 1; + for (step = 1; step <= nsteps; step++) { + f[curptr] += f[curptr + stepsize]; + curptr += stepsize; + } + } + } +} + +void scramble(double *f, int len) +{ + double temp; + int i, ii1, ii2, halflen, qtrlen; + + halflen = len >> 1; + qtrlen = halflen >> 1; + bitrev(f, len); + bitrev(&f[0], halflen); + bitrev(&f[halflen], halflen); + ii1 = len - 1; + ii2 = halflen; + for (i = 0; i <= qtrlen - 1; i++) { + temp = f[ii1]; + f[ii1] = f[ii2]; + f[ii2] = temp; + ii1--; + ii2++; + } +} + +void unscramble(double *f, int len) +{ + double temp; + int i, ii1, ii2, halflen, qtrlen; + + halflen = len >> 1; + qtrlen = halflen >> 1; + ii1 = len - 1; + ii2 = halflen; + for (i = 0; i <= qtrlen - 1; i++) { + temp = f[ii1]; + f[ii1] = f[ii2]; + f[ii2] = temp; + ii1--; + ii2++; + } + bitrev(&f[0], halflen); + bitrev(&f[halflen], halflen); + bitrev(f, len); +} + +void initcosarray(int length) +{ + int i, group, base, item, nitems, halfN; + double factor; + + m = -1; + do { + m++; + NN = 1 << m; + if (NN > length) { + fprintf(stderr, "ERROR in FCT-- length %d not a power of 2\n", length); + exit(1); + } + } while (NN < length); + if (C != NULL) free(C); + C = (double *)calloc(NN, sizeof(double)); + if (C == NULL) { + fprintf(stderr, "Unable to allocate C array\n"); + exit(1); + } + halfN = NN / 2; + two_over_N = 2.0 / (double)NN; + root2_over_rootN = sqrt(2.0 / (double)NN); + for (i = 0; i <= halfN - 1; i++) C[halfN + i] = 4 * i + 1; + for (group = 1; group <= m - 1; group++) { + base = 1 << (group - 1); + nitems = base; + factor = 1.0 * (1 << (m - group)); + for (item = 1; item <= nitems; item++) C[base + item - 1] = factor * C[halfN + item - 1]; + } + + //printf("before taking cos, C array =\n"); rarrwrt(C,N); + for (i = 1; i <= NN - 1; i++) C[i] = 1.0 / (2.0 * cos(C[i] * PI / (2.0 * NN))); + //printf("After taking cos, Carray = \n"); rarrwrt(C,N); +} + + +void inv_butterflies(double *f) +{ + int stage, ii1, ii2, butterfly, ngroups, group, wingspan, increment, baseptr; + double Cfac, T; + + for (stage = 1; stage <= m; stage++) { + ngroups = 1 << (m - stage); + wingspan = 1 << (stage - 1); + increment = wingspan << 1; + for (butterfly = 1; butterfly <= wingspan; butterfly++) { + Cfac = C[wingspan + butterfly - 1]; + baseptr = 0; + for (group = 1; group <= ngroups; group++) { + ii1 = baseptr + butterfly - 1; + ii2 = ii1 + wingspan; + T = Cfac * f[ii2]; + f[ii2] = f[ii1]-T; + f[ii1] = f[ii1] + T; + baseptr += increment; + } + } + } +} + +void fwd_butterflies(double *f) +{ + int stage, ii1, ii2, butterfly, ngroups, group, wingspan, increment, baseptr; + double Cfac, T; + + for (stage = m; stage >= 1; stage--) { + ngroups = 1 << (m - stage); + wingspan = 1 << (stage - 1); + increment = wingspan << 1; + for (butterfly = 1; butterfly <= wingspan; butterfly++) { + Cfac = C[wingspan + butterfly - 1]; + baseptr = 0; + for (group = 1; group <= ngroups; group++) { + ii1 = baseptr + butterfly - 1; + ii2 = ii1 + wingspan; + T = f[ii2]; + f[ii2] = Cfac * (f[ii1]-T); + f[ii1] = f[ii1] + T; + baseptr += increment; + } + } + } +} + +void ifct_noscale(double *f, int length) +{ + if (length != NN) initcosarray(length); + f[0] *= INVROOT2; + inv_sums(f); + bitrev(f, NN); + inv_butterflies(f); + unscramble(f, NN); +} + +void fct_noscale(double *f, int length) +{ + if (length != NN) initcosarray(length); + scramble(f, NN); + fwd_butterflies(f); + bitrev(f, NN); + fwd_sums(f); + f[0] *= INVROOT2; +} + +void ifct_defn_scaling(double *f, int length) +{ + ifct_noscale(f, length); +} + +void fct_defn_scaling(double *f, int length) +{ + int i; + + fct_noscale(f, length); + for (i = 0; i <= NN - 1; i++) f[i] *= two_over_N; +} + +void ifct(double *f, int length) +{ + /* CALL THIS FOR INVERSE 1D DCT DON-MONRO PREFERRED SCALING */ + int i; + + if (length != NN) initcosarray(length); /* BGS patch June 1997 */ + for (i = 0; i <= NN - 1; i++) f[i] *= root2_over_rootN; + ifct_noscale(f, length); +} + +void fct(double *f, int length) +{ + /* CALL THIS FOR FORWARD 1D DCT DON-MONRO PREFERRED SCALING */ + int i; + + fct_noscale(f, length); + for (i = 0; i <= NN - 1; i++) f[i] *= root2_over_rootN; +} + +/**************************************************************** + 2D FAST DCT SECTION +****************************************************************/ + +static double *g = NULL; +static double two_over_sqrtncolsnrows = 0.0; +static int ncolsvalue = 0; +static int nrowsvalue = 0; + +void initfct2d(int nrows, int ncols) +{ + if ((nrows <= 0) || (ncols < 0)) { + fprintf(stderr, "FCT2D -- ncols=%d or nrows=%d is <=0\n", nrows, ncols); + exit(1); + } + if (g != NULL) free(g); + g = (double *)calloc(nrows, sizeof(double)); + if (g == NULL) { + fprintf(stderr, "FCT2D -- Unable to allocate g array\n"); + exit(1); + } + ncolsvalue = ncols; + nrowsvalue = nrows; + two_over_sqrtncolsnrows = 2.0 / sqrt(ncols * 1.0 * nrows); +} + +void fct2d(double f[], int nrows, int ncols) +/* CALL THIS FOR FORWARD 2d DCT DON-MONRO PREFERRED SCALING */ +{ + int u, v; + + if ((ncols != ncolsvalue) || (nrows != nrowsvalue)){ + initfct2d(nrows, ncols); + } + for (u = 0; u <= nrows - 1; u++){ + fct_noscale(&f[u*ncols], ncols); + } + for (v = 0; v <= ncols - 1; v++){ + for (u = 0; u <= nrows - 1; u++) { + g[u] = f[u * ncols + v]; + } + fct_noscale(g, nrows); + for (u = 0; u <= nrows - 1; u++) { + f[u*ncols + v] = g[u] * two_over_sqrtncolsnrows; + } + } +} + +void ifct2d(double f[], int nrows, int ncols) +/* CALL THIS FOR INVERSE 2d DCT DON-MONRO PREFERRED SCALING */ +{ + int u, v; + + if ((ncols != ncolsvalue) || (nrows != nrowsvalue)){ + initfct2d(nrows, ncols); + } + for (u = 0; u <= nrows - 1; u++){ + ifct_noscale(&f[u*ncols], ncols); + } + for (v = 0; v <= ncols - 1; v++){ + for (u = 0; u <= nrows - 1; u++) { + g[u] = f[u * ncols + v]; + } + ifct_noscale(g, nrows); + for (u = 0; u <= nrows - 1; u++) { + f[u*ncols + v] = g[u] * two_over_sqrtncolsnrows; + } + } +} + +void matmul(double **a, double **b, double **r, int N) +{ + int i, j, k; + + for (i = 0; i < N; i++) + for (j = 0; j < N; j++) { + r[i][j] = 0.0; + for (k = 0; k < N; k++) + r[i][j] += a[i][k] * b[k][j]; + } +} + +void hartley(double **in, double **out, int N) +{ + int k, n; + double **h; + + h = dmatrix(N, N); + //Building up the transformation matrix + for (k = 0; k < N; k++) + for (n = 0; n < N; n++) + h[k][n] = (cos(2 * PI * k * n / N) + sin(2 * PI * k * n / N)) / sqrt(N); + + // Now we have to multiply the input with the transformation matrix + matmul(h, in, out, N); + freematrix_d(h, N); + return ; +} + +double ** dmatrix(int nrows, int ncols) +{ + double **m; + int i, j; + m = (double **) malloc (nrows * sizeof(double *)); + for (i = 0; i < nrows; i++) { + m[i] = (double *) malloc (ncols * sizeof(double)); + if (!m[i]) printf("\nIt's not working"); + } + for (i = 0; i < nrows; i++) + for (j = 0; j < ncols; j++) + m[i][j] = 0.0; + return m; +} + +void freematrix_d(double **I, int rows) +{ + int k; + for (k = 0; k < rows; k++) + free (I[k]); +} + +void matrix_i2d(int **i, double **d, int N) +{ + int x, y; + for (x = 0; x < N; x++) + for (y = 0; y < N; y++) + d[y][x] = i[y][x]; +} + +void matrix_d2i(double **d, int **i, int N) +{ + int x, y; + for (x = 0; x < N; x++) + for (y = 0; y < N; y++) + i[y][x] = d[y][x]; +} + +double * dvector(long int N) +{ + double *m; + m = (double *) malloc (N * sizeof(double)); + if (!m) printf("\nIt's not working"); + return m; +} + +void put_matrix_2_vector(double **i, double *f, int N) +{ + int l, j, k; + k = 0; + for (l = 0; l < N; l++) + for (j = 0; j < N; j++) + f[k++] = i[l][j]; +} + +void put_vector_2_matrix(double *f, double **i, int N) +{ + int l, j, k; + k = 0; + for (l = 0; l < N; l++) + for (j = 0; j < N; j++) + i[l][j] = f[k++]; +} + +void set_in_binary() { +#if defined(EMX) + _fsetmode(in, "b"); +#elif defined(MINGW) + setmode(STDIN_FILENO, O_BINARY); +#endif +} + +void set_out_binary() { +#if defined(EMX) + _fsetmode(out, "b"); +#elif defined(MINGW) + setmode(STDOUT_FILENO, O_BINARY); +#endif +} + +void wm_init2() { + set_out_binary(); +} + +void wm_init1() { + set_in_binary(); +} + +void wm_init() { + set_in_binary(); + set_out_binary(); +} +