/********************************************************************/ /* Program FractDim1.c */ /********************************************************************/ /* C program for HSI Box Counting Program */ /* Derived from program BoxCount4.cpp */ /********************************************************************/ /* Program written by: Ronald G. Resmini, Ph.D. The National Geospatial-Intelligence Agency (NGA) Reston, VA 20191 June 8, 2005 (BoxCount4.cpp) Revised: May 11, 2008 (FractDim1.cpp) */ /********************************************************************/ /* Identical to boxcount3.c except allows for variable intervals */ /* and tallies bad pixel occurrences. */ /********************************************************************/ /* Special directions/notes: Convert HSI/MSI cube to BIP Convert pixel values to floats Contiguity not currently implemented */ /********************************************************************/ /* Definitions: */ #pragma hdrstop #pragma argsused #include #include #include #include #include #define SAMPLES 300 #define LINES 250 #define BANDS 180 /********************************************************************/ /* List of Variables: address_array(BANDS) { short, 8-bit integers...for space-saving, speed } stackptr { dynamically-created linked-list of nodes containing: 1) address_array(BANDS); 2) tally (32-bit integer); 3) number (32-bit integer); and 4) contiguity (dynamically-created linked list of 16-bit integers) } global_tally {32-bit integer } { tally of total number of boxes } image(SAMPLES, LINES) { 32-bit integer, to contain box numbers } */ /********************************************************************/ struct contiguity { short neighbor; struct contiguity *nextptr; }; struct stacknode { short address_array[BANDS]; unsigned int tally; unsigned int number; struct contiguity *contiguity; struct stacknode *nextptr; }; typedef struct stacknode STACKNODE; typedef STACKNODE *STACKNODEPTR; typedef struct contiguity CONTIGUITY; typedef CONTIGUITY *CONTIGUITYPTR; /********************************************************************/ /* List of Procedures, Subroutines, and Functions: */ /********************************************************************/ void Clear_Initialize(short address_array[BANDS]); void GetBoxAddress(float spectrum[BANDS], short address_array[BANDS], short m, float minValue, float maxValue, unsigned int *badpixtally); void Add_New_Node(short address_array[BANDS], unsigned int global_tally, STACKNODEPTR *); void Search_Add(short address_array[BANDS], unsigned int *global_tally, unsigned int *imageij, STACKNODEPTR *); int same(STACKNODEPTR *, short address_array2[BANDS]); int isempty(STACKNODEPTR); long PixelTally(STACKNODEPTR); /********************************************************************/ /* Begin main() program processing */ int main() { /* Variables: */ FILE *infile, *outfile2; char infile_name[65], outfile_name2[65]; STACKNODEPTR stackptr = NULL; /* Points to the top of the stack */ short i, j, k, m, stintervals, endintervals; unsigned int image[SAMPLES][LINES]={0}, global_tally, badpixtally; long pixel_count; short address_array[BANDS]={0}; float minValue, maxValue, spectrum[BANDS]; struct time t; clrscr(); printf( "%s\n\n", "Beginning of program FractDim1.c"); /* Poll user for input information; e.g., file names, etc.: */ printf("%s", "Input cube MUST be in BIP format, floats! "); printf("\n\n\n"); printf("%s", "Enter the input BIP HSI cube name: "); scanf("%s", infile_name); printf("\n\n"); printf("%s", "Enter the output box count tally file name: "); scanf("%s", outfile_name2); printf("\n\n"); printf("%s", "Enter the minimum refl. value: "); scanf("%f", &minValue); printf("\n\n"); printf("%s", "Enter the maximum refl. value: "); scanf("%f", &maxValue); printf("\n\n"); printf("%s", "Interval increment will be by one (1)... "); printf("\n\n"); printf("%s", "Enter the starting number of intervals: "); scanf("%hd", &stintervals); printf("\n\n"); printf("%s", "Enter the ending number of intervals: "); scanf("%hd", &endintervals); printf("\n\n"); gettime(&t); printf("The start time is: %2d:%02d:%02d.%02d\n", t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund); /* Some housekeeping activities; open the input and output files: */ outfile2 = fopen(outfile_name2, "w"); for (m=stintervals; m<=endintervals; m++) { /* Variable initialization/file opening: */ infile = fopen(infile_name, "rb"); Clear_Initialize(address_array); stackptr = NULL; global_tally = 0; badpixtally = 0; /* Main logic and processing... */ for (i=0; i<=SAMPLES-1; i++) { for (j=0; j<=LINES-1; j++) { /* Read in one spectrum at a time; BIP cube */ for (k=0; k<=BANDS-1; k++) { fread(&spectrum[k], sizeof(float), 1, infile); } /* End of for k */ /* Get box 'address' of spectrum */ GetBoxAddress(spectrum, address_array, m, minValue, maxValue, &badpixtally); if ((i == 0) && (j == 0)) { global_tally = 1; Add_New_Node(address_array, global_tally, &stackptr); image[i][j] = 1; } else { Search_Add(address_array, &global_tally, &image[i][j], &stackptr); } Clear_Initialize(address_array); gotoxy(1,28); printf("%s%d%s%d%s", "Sample: ", i, " Line: ", j, " processed"); /* Process next spectrum */ } /* End of for j */ } /* End of for i */ /* Print global_tally: */ printf("\n\n\n%s%d\n", "Total number of boxes: ", global_tally); /* Print pixel count: */ pixel_count = PixelTally(stackptr); printf("\n\n%s%ld\n", "Total number of pixels: ", pixel_count); printf("\n\n%s%d\n", "Total number of bad pixels: ", badpixtally); fprintf(outfile2, "%d%s%d%s%d\n", m, " , ", global_tally, " , ", badpixtally); fclose(infile); free(stackptr); } /* End of for m */ /* Some additional housekeeping activities: */ fclose(outfile2); printf("\n\n"); gettime(&t); printf("The program-end time is: %2d:%02d:%02d.%02d\n", t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund); printf("\n\n%s\n\n", "End of program FractDim1.c"); // End of program message and acknowledgment: printf("%s", "Type x to Finish... "); scanf("%f", &i); return 0; } /* End of Main Processing */ /********************************************************************/ /* Code for Procedures and Subroutines */ /********************************************************************/ void Search_Add(short address_array[BANDS], unsigned int *global_tally, unsigned int *imageij, STACKNODEPTR *topptr) { char add_new_box; STACKNODEPTR workptr = NULL; /* Find a node that has the same address as that stored in address_array; */ /* now pointing to first node in list: */ add_new_box = 'Y'; /* Establish a pointer to traverse the stack: */ workptr = *topptr; while (workptr != NULL) { if (same(&workptr, address_array) == 1) { add_new_box = 'N'; workptr->tally += 1; (*imageij)=workptr->number; /* ...to tag the pixel as belonging to a box... */ } /* End if */ workptr = workptr->nextptr; } /* End while */ /* Entire stack has now been traversed; should a new node be pushed?... */ /* If add_new_box flag is not flipped to 'N' then, add... */ if (add_new_box == 'Y') { *global_tally += 1; /* increment of global_tally also becomes box number */ Add_New_Node(address_array, *global_tally, &(*topptr)); (*imageij)=*global_tally; } } /* End of Search_Add() */ /********************************************************************/ void Add_New_Node(short address_array[BANDS], unsigned int global_tally, STACKNODEPTR *topptr) { /* Add a node to the stack; use a push operation. */ STACKNODEPTR newptr; short i; /* Allocate memory to build a new node: */ newptr = (STACKNODEPTR) malloc(sizeof(STACKNODE)); if (newptr) { /* Initialize node elements/variables: */ for (i = 0; i<=(BANDS-1); i++) { newptr->address_array[i] = address_array[i]; } /* End of for i */ newptr->tally = 1; newptr->number = global_tally; newptr->nextptr = *topptr; newptr->contiguity = NULL; *topptr = newptr; } else printf("%s\n", "Node not inserted. Error. No memory available. \n"); } /* End of Add_New_Node() */ /********************************************************************/ void GetBoxAddress(float spectrum[BANDS], short address_array[BANDS], short intervals, float MinValue, float MaxValue, unsigned int *badpixtally) { short i, k; char BinFlag; float width; width = ((MaxValue-MinValue)/intervals); for (k=0; k<=BANDS-1; k++) { BinFlag = 'N'; i = 1; while (i <= intervals-1) { if ((spectrum[k] >= (MinValue+(width*(i-1)))) && (spectrum[k] < MinValue+(width*i))) { address_array[k]=i; BinFlag = 'Y'; } /* End if */ i += 1; } /* End While */ /* Special handling for the last box; for the highest DN value in the cube: */ if ((spectrum[k] >= (MinValue+(width*(i-1)))) && (spectrum[k] <= MinValue+(width*i))) { address_array[k]=i; BinFlag = 'Y'; } /* End if */ if (BinFlag == 'N') { *badpixtally +=1; /* printf("\n%s\n", "...Error...Stop...End...Channel Not Assigned..."); */ } /* End if */ } /* End of for k */ } /* End of GetBoxAddress() */ /*******************************************************************/ void Clear_Initialize(short address_array[BANDS]) { short i; for (i = 0; i<=(BANDS-1); i++) address_array[i] = 0; } /* End of Clear_Initialize() */ /********************************************************************/ int same(STACKNODEPTR *topptr, short address_array2[BANDS]) { short i; int same; same = 1; for (i=0; i<=BANDS-1; i++) { if ((*topptr)->address_array[i] != address_array2[i]) { same = 0; break; } } /* End of for i */ return same; } /* End of Function same() */ /********************************************************************/ int isempty(STACKNODEPTR topptr) { return !topptr; } /* End of isempty() */ /********************************************************************/ long PixelTally(STACKNODEPTR currentptr) { long PixelTally; PixelTally = 0; while (currentptr) { PixelTally += currentptr->tally; currentptr= currentptr->nextptr; } /* End while */ return PixelTally; } /* End of TallyPixels() */ /********************************************************************/