1 /*******************************************************************************
2 
3 License:
4 This software was developed at the National Institute of Standards and
5 Technology (NIST) by employees of the Federal Government in the course
6 of their official duties. Pursuant to title 17 Section 105 of the
7 United States Code, this software is not subject to copyright protection
8 and is in the public domain. NIST assumes no responsibility  whatsoever for
9 its use by other parties, and makes no guarantees, expressed or implied,
10 about its quality, reliability, or any other characteristic.
11 
12 Disclaimer:
13 This software was developed to promote biometric standards and biometric
14 technology testing for the Federal Government in accordance with the USA
15 PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
16 Specific hardware and software products identified in this software were used
17 in order to perform the software development.  In no case does such
18 identification imply recommendation or endorsement by the National Institute
19 of Standards and Technology, nor does it imply that the products and equipment
20 identified are necessarily the best available for the purpose.
21 
22 *******************************************************************************/
23 
24 /***********************************************************************
25       LIBRARY: LFS - NIST Latent Fingerprint System
26 
27       FILE:    INIT.C
28       AUTHOR:  Michael D. Garris
29       DATE:    03/16/1999
30       UPDATED: 10/04/1999 Version 2 by MDG
31       UPDATED: 03/16/2005 by MDG
32 
33       Contains routines responsible for allocation and/or initialization
34       of memories required by the NIST Latent Fingerprint System.
35 
36 ***********************************************************************
37                ROUTINES:
38                         init_dir2rad()
39                         init_dftwaves()
40                         get_max_padding_V2()
41                         init_rotgrids()
42                         alloc_dir_powers()
43                         alloc_power_stats()
44 ***********************************************************************/
45 
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <lfs.h>
49 
50 /*************************************************************************
51 **************************************************************************
52 #cat: init_dir2rad - Allocates and initializes a lookup table containing
53 #cat:                cosine and sine values needed to convert integer IMAP
54 #cat:                directions to angles in radians.
55 
56    Input:
57       ndirs - the number of integer directions to be defined in a
58               semicircle
59    Output:
60       optr  - points to the allocated/initialized DIR2RAD structure
61    Return Code:
62       Zero     - successful completion
63       Negative - system error
64 **************************************************************************/
init_dir2rad(DIR2RAD ** optr,const int ndirs)65 int init_dir2rad(DIR2RAD **optr, const int ndirs)
66 {
67    DIR2RAD *dir2rad;
68    int i;
69    double theta, pi_factor;
70    double cs, sn;
71 
72    /* Allocate structure */
73    dir2rad = (DIR2RAD *)malloc(sizeof(DIR2RAD));
74    if(dir2rad == (DIR2RAD *)NULL){
75       fprintf(stderr, "ERROR : init_dir2rad : malloc : dir2rad\n");
76       return(-10);
77    }
78 
79    /* Assign number of directions */
80    dir2rad->ndirs = ndirs;
81 
82    /* Allocate cosine vector */
83    dir2rad->cos = (double *)malloc(ndirs * sizeof(double));
84    if(dir2rad->cos == (double *)NULL){
85       /* Free memory allocated to this point. */
86       free(dir2rad);
87       fprintf(stderr, "ERROR : init_dir2rad : malloc : dir2rad->cos\n");
88       return(-11);
89    }
90 
91    /* Allocate sine vector */
92    dir2rad->sin = (double *)malloc(ndirs * sizeof(double));
93    if(dir2rad->sin == (double *)NULL){
94       /* Free memory allocated to this point. */
95       free(dir2rad->cos);
96       free(dir2rad);
97       fprintf(stderr, "ERROR : init_dir2rad : malloc : dir2rad->sin\n");
98       return(-12);
99    }
100 
101    /* Pi_factor sets the period of the trig functions to NDIRS units in x. */
102    /* For example, if NDIRS==16, then pi_factor = 2(PI/16) = .3926...      */
103    pi_factor = 2.0*M_PI/(double)ndirs;
104 
105    /* Now compute cos and sin values for each direction.    */
106    for (i = 0; i < ndirs; ++i) {
107       theta = (double)(i * pi_factor);
108       cs = cos(theta);
109       sn = sin(theta);
110       /* Need to truncate precision so that answers are consistent */
111       /* on different computer architectures. */
112       cs = trunc_dbl_precision(cs, TRUNC_SCALE);
113       sn = trunc_dbl_precision(sn, TRUNC_SCALE);
114       dir2rad->cos[i] = cs;
115       dir2rad->sin[i] = sn;
116    }
117 
118    *optr = dir2rad;
119    return(0);
120 }
121 
122 /*************************************************************************
123 **************************************************************************
124 #cat: init_dftwaves - Allocates and initializes a set of wave forms needed
125 #cat:                 to conduct DFT analysis on blocks of the input image
126 
127    Input:
128       dft_coefs - array of multipliers used to define the frequency for
129                   each wave form to be computed
130       nwaves    - number of wave forms to be computed
131       blocksize - the width and height of each block of image data to
132                   be DFT analyzed
133    Output:
134       optr     - points to the allocated/initialized DFTWAVES structure
135    Return Code:
136       Zero     - successful completion
137       Negative - system error
138 **************************************************************************/
init_dftwaves(DFTWAVES ** optr,const double * dft_coefs,const int nwaves,const int blocksize)139 int init_dftwaves(DFTWAVES **optr, const double *dft_coefs,
140                   const int nwaves, const int blocksize)
141 {
142    DFTWAVES *dftwaves;
143    int i, j;
144    double pi_factor, freq, x;
145    double *cptr, *sptr;
146 
147    /* Allocate structure */
148    dftwaves = (DFTWAVES *)malloc(sizeof(DFTWAVES));
149    if(dftwaves == (DFTWAVES *)NULL){
150       fprintf(stderr, "ERROR : init_dftwaves : malloc : dftwaves\n");
151       return(-20);
152    }
153 
154    /* Set number of DFT waves */
155    dftwaves->nwaves = nwaves;
156    /* Set wave length of the DFT waves (they all must be the same length) */
157    dftwaves->wavelen = blocksize;
158 
159    /* Allocate list of wave pointers */
160    dftwaves->waves = (DFTWAVE **)malloc(nwaves * sizeof(DFTWAVE *));
161    if(dftwaves == (DFTWAVES *)NULL){
162       /* Free memory allocated to this point. */
163       free(dftwaves);
164       fprintf(stderr, "ERROR : init_dftwaves : malloc : dftwaves->waves\n");
165       return(-21);
166    }
167 
168    /* Pi_factor sets the period of the trig functions to BLOCKSIZE units */
169    /* in x.  For example, if BLOCKSIZE==24, then                         */
170    /*                         pi_factor = 2(PI/24) = .26179...           */
171    pi_factor = 2.0*M_PI/(double)blocksize;
172 
173    /* Foreach of 4 DFT frequency coef ... */
174    for (i = 0; i < nwaves; ++i) {
175       /* Allocate wave structure */
176       dftwaves->waves[i] = (DFTWAVE *)malloc(sizeof(DFTWAVE));
177       if(dftwaves->waves[i] == (DFTWAVE *)NULL){
178          /* Free memory allocated to this point. */
179          { int _j; for(_j = 0; _j < i; _j++){
180             free(dftwaves->waves[_j]->cos);
181             free(dftwaves->waves[_j]->sin);
182             free(dftwaves->waves[_j]);
183          }}
184          free(dftwaves->waves);
185          free(dftwaves);
186          fprintf(stderr,
187                  "ERROR : init_dftwaves : malloc : dftwaves->waves[i]\n");
188          return(-22);
189       }
190       /* Allocate cosine vector */
191       dftwaves->waves[i]->cos = (double *)malloc(blocksize * sizeof(double));
192       if(dftwaves->waves[i]->cos == (double *)NULL){
193          /* Free memory allocated to this point. */
194          { int _j; for(_j = 0; _j < i; _j++){
195             free(dftwaves->waves[_j]->cos);
196             free(dftwaves->waves[_j]->sin);
197             free(dftwaves->waves[_j]);
198          }}
199          free(dftwaves->waves[i]);
200          free(dftwaves->waves);
201          free(dftwaves);
202          fprintf(stderr,
203                  "ERROR : init_dftwaves : malloc : dftwaves->waves[i]->cos\n");
204          return(-23);
205       }
206       /* Allocate sine vector */
207       dftwaves->waves[i]->sin = (double *)malloc(blocksize * sizeof(double));
208       if(dftwaves->waves[i]->sin == (double *)NULL){
209          /* Free memory allocated to this point. */
210          { int _j; for(_j = 0; _j < i; _j++){
211             free(dftwaves->waves[_j]->cos);
212             free(dftwaves->waves[_j]->sin);
213             free(dftwaves->waves[_j]);
214          }}
215          free(dftwaves->waves[i]->cos);
216          free(dftwaves->waves[i]);
217          free(dftwaves->waves);
218          free(dftwaves);
219          fprintf(stderr,
220                  "ERROR : init_dftwaves : malloc : dftwaves->waves[i]->sin\n");
221          return(-24);
222       }
223 
224       /* Assign pointer nicknames */
225       cptr = dftwaves->waves[i]->cos;
226       sptr = dftwaves->waves[i]->sin;
227 
228       /* Compute actual frequency */
229       freq = pi_factor * dft_coefs[i];
230 
231       /* Used as a 1D DFT on a 24 long vector of pixel sums */
232       for (j = 0; j < blocksize; ++j) {
233          /* Compute sample points from frequency */
234          x = freq * (double)j;
235          /* Store cos and sin components of sample point */
236          *cptr++ = cos(x);
237          *sptr++ = sin(x);
238       }
239    }
240 
241    *optr = dftwaves;
242    return(0);
243 }
244 
245 /*************************************************************************
246 **************************************************************************
247 #cat: get_max_padding_V2 - Deterines the maximum amount of image pixel padding
248 #cat:         required by all LFS (Version 2) processes.  Padding is currently
249 #cat:         required by the rotated grids used in DFT analyses and in
250 #cat:         directional binarization.  The NIST generalized code enables
251 #cat:         the parameters governing these processes to be redefined, so a
252 #cat:         check at runtime is required to determine which process
253 #cat:         requires the most padding.  By using the maximum as the padding
254 #cat:         factor, all processes will run safely with a single padding of
255 #cat:         the input image avoiding the need to repad for further processes.
256 
257    Input:
258       map_windowsize  - the size (in pixels) of each window centered about
259                         each block in the image used in DFT analyses
260       map_windowoffset - the offset (in pixels) from the orgin of the
261                         surrounding window to the origin of the block
262       dirbin_grid_w   - the width (in pixels) of the rotated grids used in
263                         directional binarization
264       dirbin_grid_h   - the height (in pixels) of the rotated grids used in
265                         directional binarization
266    Return Code:
267       Non-negative - the maximum padding required for all processes
268 **************************************************************************/
get_max_padding_V2(const int map_windowsize,const int map_windowoffset,const int dirbin_grid_w,const int dirbin_grid_h)269 int get_max_padding_V2(const int map_windowsize, const int map_windowoffset,
270                        const int dirbin_grid_w, const int dirbin_grid_h)
271 {
272    int dft_pad, dirbin_pad, max_pad;
273    double diag;
274    double pad;
275 
276 
277    /* 1. Compute pad required for rotated windows used in DFT analyses. */
278 
279    /* Explanation of DFT padding:
280 
281                     B---------------------
282                     |      window        |
283                     |                    |
284                     |                    |
285                     |      A.......______|__________
286                     |      :      :      |
287                     |<-C-->: block:      |
288                  <--|--D-->:      :      | image
289                     |      ........      |
290                     |      |             |
291                     |      |             |
292                     |      |             |
293                     ----------------------
294                            |
295                            |
296                            |
297 
298          Pixel A = Origin of entire fingerprint image
299                  = Also origin of first block in image. Each pixel in
300                    this block gets the same DFT results computed from
301                    the surrounding window.  Note that in general
302                    blocks are adjacent and non-overlapping.
303 
304          Pixel B = Origin of surrounding window in which DFT
305                    analysis is conducted.  Note that this window is not
306                    completely contained in the image but extends to the
307                    top and to the right.
308 
309          Distance C = Number of pixels in which the window extends
310                    beyond the image (map_windowoffset).
311 
312          Distance D = Amount of padding required to hold the entire
313                    rotated window in memory.
314 
315    */
316 
317    /* Compute pad as difference between the MAP windowsize           */
318    /* and the diagonal distance of the window.                       */
319    /* (DFT grids are computed with pixel offsets RELATIVE2ORIGIN.)   */
320    diag = sqrt((double)(2.0 * map_windowsize * map_windowsize));
321    pad = (diag-map_windowsize)/(double)2.0;
322    /* Need to truncate precision so that answers are consistent  */
323    /* on different computer architectures when rounding doubles. */
324    pad = trunc_dbl_precision(pad, TRUNC_SCALE);
325    /* Must add the window offset to the rotational padding. */
326    dft_pad = sround(pad) + map_windowoffset;
327 
328    /* 2. Compute pad required for rotated blocks used in directional  */
329    /*    binarization.  Binarization blocks are applied to each pixel */
330    /*    in the input image.                                          */
331    diag = sqrt((double)((dirbin_grid_w*dirbin_grid_w)+
332                         (dirbin_grid_h*dirbin_grid_h)));
333    /* Assumption: all grid centers reside in valid/allocated memory. */
334    /* (Dirbin grids are computed with pixel offsets RELATIVE2CENTER.) */
335    pad = (diag-1)/(double)2.0;
336    /* Need to truncate precision so that answers are consistent */
337    /* on different computer architectures when rounding doubles. */
338    pad = trunc_dbl_precision(pad, TRUNC_SCALE);
339    dirbin_pad = sround(pad);
340 
341    max_pad = max(dft_pad, dirbin_pad);
342 
343    /* Return the maximum of the two required paddings.  This padding will */
344    /* be sufficiently large for all purposes, so that padding of the      */
345    /* input image will only be required once.                             */
346    return(max_pad);
347 }
348 
349 /*************************************************************************
350 **************************************************************************
351 #cat: init_rotgrids - Allocates and initializes a set of offsets that address
352 #cat:                 individual rotated pixels within a grid.
353 #cat:                 These rotated grids are used to conduct DFT analyses
354 #cat:                 on blocks of input image data, and they are used
355 #cat:                 in isotropic binarization.
356 
357    Input:
358       iw        - width (in pixels) of the input image
359       ih        - height (in pixels) of the input image
360       pad       - designates the number of pixels to be padded to the perimeter
361                   of the input image.  May be passed as UNDEFINED, in which
362                   case the specific padding required by the rotated grids
363                   will be computed and returned in ROTGRIDS.
364       start_dir_angle - angle from which rotations are to start
365       ndirs     - number of rotations to compute (within a semicircle)
366       grid_w    - width of the grid in pixels to be rotated
367       grid_h    - height of the grid in pixels to be rotated
368       relative2 - designates whether pixel offsets whould be computed
369                   relative to the ORIGIN or the CENTER of the grid
370    Output:
371       optr      - points to the allcated/initialized ROTGRIDS structure
372    Return Code:
373       Zero     - successful completion
374       Negative - system error
375 **************************************************************************/
init_rotgrids(ROTGRIDS ** optr,const int iw,const int ih,const int ipad,const double start_dir_angle,const int ndirs,const int grid_w,const int grid_h,const int relative2)376 int init_rotgrids(ROTGRIDS **optr, const int iw, const int ih, const int ipad,
377                   const double start_dir_angle, const int ndirs,
378                   const int grid_w, const int grid_h, const int relative2)
379 {
380    ROTGRIDS *rotgrids;
381    double pi_offset, pi_incr;
382    int dir, ix, iy, grid_size, pw, grid_pad, min_dim;
383    int *grid;
384    double diag, theta, cs, sn, cx, cy;
385    double fxm, fym, fx, fy;
386    int ixt, iyt;
387    double pad;
388 
389    /* Allocate structure */
390    rotgrids = (ROTGRIDS *)malloc(sizeof(ROTGRIDS));
391    if(rotgrids == (ROTGRIDS *)NULL){
392       fprintf(stderr, "ERROR : init_rotgrids : malloc : rotgrids\n");
393       return(-30);
394    }
395 
396    /* Set rotgrid attributes */
397    rotgrids->ngrids = ndirs;
398    rotgrids->grid_w = grid_w;
399    rotgrids->grid_h = grid_h;
400    rotgrids->start_angle = start_dir_angle;
401    rotgrids->relative2 = relative2;
402 
403    /* Compute pad based on diagonal of the grid */
404    diag = sqrt((double)((grid_w*grid_w)+(grid_h*grid_h)));
405    switch(relative2){
406       case RELATIVE2CENTER:
407          /* Assumption: all grid centers reside in valid/allocated memory. */
408          pad = (diag-1)/(double)2.0;
409          /* Need to truncate precision so that answers are consistent */
410          /* on different computer architectures when rounding doubles. */
411          pad = trunc_dbl_precision(pad, TRUNC_SCALE);
412          grid_pad = sround(pad);
413          break;
414       case RELATIVE2ORIGIN:
415          /* Assumption: all grid origins reside in valid/allocated memory. */
416          min_dim = min(grid_w, grid_h);
417          /* Compute pad as difference between the smallest grid dimension */
418          /* and the diagonal distance of the grid. */
419          pad = (diag-min_dim)/(double)2.0;
420          /* Need to truncate precision so that answers are consistent */
421          /* on different computer architectures when rounding doubles. */
422          pad = trunc_dbl_precision(pad, TRUNC_SCALE);
423          grid_pad = sround(pad);
424          break;
425       default:
426          fprintf(stderr,
427                  "ERROR : init_rotgrids : Illegal relative flag : %d\n",
428                  relative2);
429          free(rotgrids);
430          return(-31);
431    }
432 
433    /* If input padding is UNDEFINED ... */
434    if(ipad == UNDEFINED)
435       /* Use the padding specifically required by the rotated grids herein. */
436       rotgrids->pad = grid_pad;
437    else{
438       /* Otherwise, input pad was specified, so check to make sure it is */
439       /* sufficiently large to handle the rotated grids herein.          */
440       if(ipad < grid_pad){
441          /* If input pad is NOT large enough, then ERROR. */
442          fprintf(stderr, "ERROR : init_rotgrids : Pad passed is too small\n");
443          free(rotgrids);
444          return(-32);
445       }
446       /* Otherwise, use the specified input pad in computing grid offsets. */
447       rotgrids->pad = ipad;
448    }
449 
450    /* Total number of points in grid */
451    grid_size = grid_w * grid_h;
452 
453    /* Compute width of "padded" image */
454    pw = iw + (rotgrids->pad<<1);
455 
456    /* Center coord of grid (0-oriented). */
457    cx = (grid_w-1)/(double)2.0;
458    cy = (grid_h-1)/(double)2.0;
459 
460    /* Allocate list of rotgrid pointers */
461    rotgrids->grids = (int **)malloc(ndirs * sizeof(int *));
462    if(rotgrids->grids == (int **)NULL){
463       /* Free memory allocated to this point. */
464       free(rotgrids);
465       fprintf(stderr, "ERROR : init_rotgrids : malloc : rotgrids->grids\n");
466       return(-33);
467    }
468 
469    /* Pi_offset is the offset in radians from which angles are to begin. */
470    pi_offset = start_dir_angle;
471    pi_incr = M_PI/(double)ndirs;  /* if ndirs == 16, incr = 11.25 degrees */
472 
473    /* For each direction to rotate a grid ... */
474    for (dir = 0, theta = pi_offset;
475         dir < ndirs; dir++, theta += pi_incr) {
476 
477       /* Allocate a rotgrid */
478       rotgrids->grids[dir] = (int *)malloc(grid_size * sizeof(int));
479       if(rotgrids->grids[dir] == (int *)NULL){
480          /* Free memory allocated to this point. */
481          { int _j; for(_j = 0; _j < dir; _j++){
482             free(rotgrids->grids[_j]);
483          }}
484          free(rotgrids);
485          fprintf(stderr,
486                  "ERROR : init_rotgrids : malloc : rotgrids->grids[dir]\n");
487          return(-34);
488       }
489 
490       /* Set pointer to current grid */
491       grid = rotgrids->grids[dir];
492 
493       /* Compute cos and sin of current angle */
494       cs = cos(theta);
495       sn = sin(theta);
496 
497       /* This next section of nested FOR loops precomputes a         */
498       /* rotated grid.  The rotation is set up to rotate a GRID_W X  */
499       /* GRID_H grid on its center point at C=(Cx,Cy). The current   */
500       /* pixel being rotated is P=(Ix,Iy).  Therefore, we have a     */
501       /* rotation transformation of point P about pivot point C.     */
502       /* The rotation transformation about a pivot point in matrix   */
503       /* form is:                                                    */
504       /*
505             +-                                                       -+
506             |             cos(T)                   sin(T)           0 |
507   [Ix Iy 1] |            -sin(T)                   cos(T)           0 |
508             | (1-cos(T))*Cx + Cy*sin(T)  (1-cos(T))*Cy - Cx*sin(T)  1 |
509             +-                                                       -+
510       */
511       /* Multiplying the 2 matrices and combining terms yeilds the */
512       /* equations for rotated coordinates (Rx, Ry):               */
513       /*        Rx = Cx + (Ix - Cx)*cos(T) - (Iy - Cy)*sin(T)      */
514       /*        Ry = Cy + (Ix - Cx)*sin(T) + (Iy - Cy)*cos(T)      */
515       /*                                                           */
516       /* Care has been taken to ensure that (for example) when     */
517       /* BLOCKSIZE==24 the rotated indices stay within a centered  */
518       /* 34X34 area.                                               */
519       /* This is important for computing an accurate padding of    */
520       /* the input image.  The rotation occurs "in-place" so that  */
521       /* outer pixels in the grid are mapped at times from         */
522       /* adjoining blocks.  As a result, to keep from accessing    */
523       /* "unknown" memory or pixels wrapped from the other side of */
524       /* the image, the input image should first be padded by      */
525       /* PAD=round((DIAG - BLOCKSIZE)/2.0) where DIAG is the       */
526       /* diagonal distance of the grid.                            */
527       /* For example, when BLOCKSIZE==24, Dx=34, so PAD=5.         */
528 
529       /* Foreach each y coord in block ... */
530       for (iy = 0; iy < grid_h; ++iy) {
531          /* Compute rotation factors dependent on Iy (include constant) */
532          fxm = -1.0 * ((iy - cy) * sn);
533          fym = ((iy - cy) * cs);
534 
535          /* If offsets are to be relative to the grids origin, then */
536          /* we need to subtract CX and CY.                          */
537          if(relative2 == RELATIVE2ORIGIN){
538             fxm += cx;
539             fym += cy;
540          }
541 
542          /* foreach each x coord in block ... */
543          for (ix = 0; ix < grid_w; ++ix) {
544 
545              /* Now combine factors dependent on Iy with those of Ix */
546              fx = fxm + ((ix - cx) * cs);
547              fy = fym + ((ix - cx) * sn);
548              /* Need to truncate precision so that answers are consistent */
549              /* on different computer architectures when rounding doubles. */
550              fx = trunc_dbl_precision(fx, TRUNC_SCALE);
551              fy = trunc_dbl_precision(fy, TRUNC_SCALE);
552              ixt = sround(fx);
553              iyt = sround(fy);
554 
555              /* Store the current pixels relative   */
556              /* rotated offset.  Make sure to       */
557              /* multiply the y-component of the     */
558              /* offset by the "padded" image width! */
559              *grid++ = ixt + (iyt * pw);
560          }/* ix */
561       }/* iy */
562    }/* dir */
563 
564    *optr = rotgrids;
565    return(0);
566 }
567 
568 /*************************************************************************
569 **************************************************************************
570 #cat: alloc_dir_powers - Allocates the memory associated with DFT power
571 #cat:           vectors.  The DFT analysis is conducted block by block in the
572 #cat:           input image, and within each block, N wave forms are applied
573 #cat:           at M different directions.
574 
575    Input:
576       nwaves - number of DFT wave forms
577       ndirs  - number of orientations (directions) used in DFT analysis
578    Output:
579       opowers - pointer to the allcated power vectors
580    Return Code:
581       Zero     - successful completion
582       Negative - system error
583 **************************************************************************/
alloc_dir_powers(double *** opowers,const int nwaves,const int ndirs)584 int alloc_dir_powers(double ***opowers, const int nwaves, const int ndirs)
585 {
586    int w;
587    double **powers;
588 
589    /* Allocate list of double pointers to hold power vectors */
590    powers = (double **)malloc(nwaves * sizeof(double*));
591    if(powers == (double **)NULL){
592       fprintf(stderr, "ERROR : alloc_dir_powers : malloc : powers\n");
593       return(-40);
594    }
595    /* Foreach DFT wave ... */
596    for(w = 0; w < nwaves; w++){
597       /* Allocate power vector for all directions */
598       powers[w] = (double *)malloc(ndirs * sizeof(double));
599       if(powers[w] == (double *)NULL){
600          /* Free memory allocated to this point. */
601          { int _j; for(_j = 0; _j < w; _j++){
602             free(powers[_j]);
603          }}
604          free(powers);
605          fprintf(stderr, "ERROR : alloc_dir_powers : malloc : powers[w]\n");
606          return(-41);
607       }
608    }
609 
610    *opowers = powers;
611    return(0);
612 }
613 
614 /*************************************************************************
615 **************************************************************************
616 #cat: alloc_power_stats - Allocates memory associated with set of statistics
617 #cat:             derived from DFT power vectors computed in a block of the
618 #cat:             input image.  Statistics are not computed for the lowest DFT
619 #cat:             wave form, so the length of the statistics arrays is 1 less
620 #cat:             than the number of DFT wave forms used.  The staistics
621 #cat:             include the Maximum power for each wave form, the direction
622 #cat:             at which the maximum power occured, and a normalized value
623 #cat:             for the maximum power.  In addition, the statistics are
624 #cat:             ranked in descending order based on normalized squared
625 #cat:             maximum power.
626 
627    Input:
628       nstats - the number of waves forms from which statistics are to be
629                derived (N Waves - 1)
630    Output:
631       owis      - points to an array to hold the ranked wave form indicies
632                   of the corresponding statistics
633       opowmaxs  - points to an array to hold the maximum DFT power for each
634                   wave form
635       opowmax_dirs - points to an array to hold the direction corresponding to
636                   each maximum power value
637       opownorms - points to an array to hold the normalized maximum power
638    Return Code:
639       Zero     - successful completion
640       Negative - system error
641 **************************************************************************/
alloc_power_stats(int ** owis,double ** opowmaxs,int ** opowmax_dirs,double ** opownorms,const int nstats)642 int alloc_power_stats(int **owis, double **opowmaxs, int **opowmax_dirs,
643                       double **opownorms, const int nstats)
644 {
645    int *wis, *powmax_dirs;
646    double *powmaxs, *pownorms;
647 
648    /* Allocate DFT wave index vector */
649    wis = (int *)malloc(nstats * sizeof(int));
650    if(wis == (int *)NULL){
651       fprintf(stderr, "ERROR : alloc_power_stats : malloc : wis\n");
652       return(-50);
653    }
654 
655    /* Allocate max power vector */
656    powmaxs = (double *)malloc(nstats * sizeof(double));
657    if(powmaxs == (double *)NULL){
658       /* Free memory allocated to this point. */
659       free(wis);
660       fprintf(stderr, "ERROR : alloc_power_stats : malloc : powmaxs\n");
661       return(-51);
662    }
663 
664    /* Allocate max power direction vector */
665    powmax_dirs = (int *)malloc(nstats * sizeof(int));
666    if(powmax_dirs == (int *)NULL){
667       /* Free memory allocated to this point. */
668       free(wis);
669       free(powmaxs);
670       fprintf(stderr, "ERROR : alloc_power_stats : malloc : powmax_dirs\n");
671       return(-52);
672    }
673 
674    /* Allocate normalized power vector */
675    pownorms = (double *)malloc(nstats * sizeof(double));
676    if(pownorms == (double *)NULL){
677       /* Free memory allocated to this point. */
678       free(wis);
679       free(powmaxs);
680       free(pownorms);
681       fprintf(stderr, "ERROR : alloc_power_stats : malloc : pownorms\n");
682       return(-53);
683    }
684 
685    *owis = wis;
686    *opowmaxs = powmaxs;
687    *opowmax_dirs = powmax_dirs;
688    *opownorms = pownorms;
689    return(0);
690 }
691 
692 
693 
694