#include #include #include /* compile this file with cc -o osc2pgm osc2pgm.c -lm */ #define TRUE 1 #define FALSE 0 typedef union { float real; unsigned char string[4]; unsigned int integer; } FOURBYTES; /* function prototypes */ FOURBYTES fix_float(FOURBYTES wrong_order); /* global notifier of frame byte=order */ int swap_bytes = FALSE; /* frame handling routines */ FILE *GetFrame(char *filename, char *header); unsigned char header[2048]; main(int argv, char** argc) { /* exit status */ int return_code = 0; /* utility variables */ int i; char *filename; FILE *frame = NULL; unsigned long int **image; /* frame information variables */ int record_size; int num_records; int pixels_per_line; int image_width; int image_height; float eight = 8; /* output image variables */ int xsize; int ysize; /* indicies */ int x, z; int in_x, in_z; int overloads = 0; /* limits */ int high = 0; int low = 0xFFFF; double sum = 0; double sigma = 0; int stat_pixels = 0; double scale = 0; double zoom = 1; int negate = 0; int start_x = 0; int start_y = 0; int stop_x = 0; int stop_y = 0; int box_offset_x = 0; int box_offset_y = 0; /* storage */ unsigned short int *record; unsigned short int *swapped; unsigned short int *temp; /* output PGM stuff */ unsigned char *PGMdata; FILE *pgmout = NULL; char outfilename[256] = ""; /* begin progam here */ printf("OSC2PGM 1.0\t\tby James Holton 2-1-01\n\n"); /* check argument list */ for(i=1; i= (i+1))) { scale = atof(argc[i+1]); } if(strstr(argc[i], "-zoom") && (argv >= (i+1))) { zoom = atof(argc[i+1]); } if(strstr(argc[i], "-box") && (argv >= (i+4))) { start_y = atol(argc[i+1]); start_x = atol(argc[i+2]); stop_y = atol(argc[i+3]); stop_x = atol(argc[i+4]); } } } if(frame != NULL) { /* Print intentions * printf("converting %s to %s\n", filename, outfilename); printf("scaling size by %g\n", zoom); /* */ if(scale == 0) { printf("autoscaling intensity \n"); } else { printf("intensity scale set to %g\n", scale); } printf("\n"); /* Filename */ printf("reading %s ", filename); /* read file sizes from header */ memcpy(&record_size, &header[784], 4); memcpy(&num_records, &header[788], 4); memcpy(&pixels_per_line, &header[768], 4); memcpy(&eight, &header[800], 4); /* most probable record sizes * record_size = 4096; num_records = 1900; pixels_per_line = 1900; eight = 8; /* */ /* handle weird box definitions */ if(stop_x < start_x) {i = start_x; start_x = stop_x; stop_x = i;} if(stop_y < start_y) {i = start_y; start_y = stop_y; stop_y = i;} /* default to whole image */ if(stop_x == 0) stop_x = pixels_per_line; if(stop_y == 0) stop_y = num_records; /* preserve output image size (for later) */ xsize = (int) (zoom* (double) (stop_x - start_x)); ysize = (int) (zoom* (double) (stop_y - start_y)); box_offset_x = start_x; box_offset_y = start_y; /* clip edges (for reading only) */ printf("box from (%d,%d) to (%d,%d)\n", start_x, start_y, stop_x, stop_y); if(stop_x > pixels_per_line) stop_x = pixels_per_line; if(stop_y > num_records) stop_y = num_records; if(start_x < 0) start_x = 0; if(start_y < 0) start_y = 0; image_width = stop_x - start_x; image_height = stop_y - start_y; box_offset_x -= start_x; box_offset_y -= start_y; /* allocate space for memeory-resident image */ image = (unsigned long int **) calloc(sizeof(unsigned long int *), image_height); record = calloc(2, image_width); /* need a little extra memory for swapping bytes */ if(swap_bytes == TRUE) { swapped = calloc(1, image_width*2); printf("swapping bytes...\n"); } /* load appropriate records (line) into memory */ for(z = 0; z < image_height; ++z) { /* allocate space for this line */ image[z] = calloc(4, image_width); /* position file at beginning of the desired scan line */ fseek(frame, ((z+start_y+1)*record_size)+(start_x*2), SEEK_SET); /* read the record into memory */ fread(record, 2, image_width, frame); /* Account for byte swapping */ if(swap_bytes == TRUE) { /* preserve location of read-in pixels */ temp = record; /* swab() can only COPY swapped bytes */ swab((char*)record, (char*)swapped, image_width*2); record = swapped; /* exchange buffers for next time */ swapped = temp; } /* enter this record into the image */ /* promote pixel words to actual values and */ /* do statistics on pixel values */ for(x = 0; x < image_width; ++x) { /* initialize from words in file */ if(record[x] == 0xFFFF) { ++overloads; /* simulate burn-thru effect? */ record[x] = 0; } if(record[x] >= 0) { image[z][x] = (unsigned long) record[x]; } if(record[x] < -1) { image[z][x] = (unsigned long int) eight*(0x7fff & record[x]); /* this should never happen * if(record[x] < -28672) printf("oddball pixel!: (%4d, %4d) = %4d\n", x, z-1, record[x]); */ } /* debug * printf("reading (%d,%d) = ", z, x); printf("%d \n", image[z][x]); /* */ /* now collect statistics */ if((record[x] != 0)&&(record[x] != 0xFFFF)) { sigma += ( (double) image[z][x]) * ((double) image[z][x]); ++stat_pixels; } } } /* image has now been completely read into memory */ fclose(frame); /* finish statistics */ if(stat_pixels == 0) { /* no data read? */ stat_pixels=1; sigma=1; } sigma /= (double) stat_pixels; sigma = sqrt(sigma); /* autoscale output image to 5-sigma cuttoff */ if(scale == 0) { scale = 256.0/(5*sigma); printf("intensity scale set to %g\n", scale); } /* convert and copy all image data into new PGM file */ PGMdata = (unsigned char *) calloc(xsize, ysize); printf("transforming data ...\n"); for(z = 0; z < ysize; ++z) { for(x = 0; x < xsize; ++x) { /* transform output coordinates to input image frame (pixel units) */ in_x = (int) (x/zoom) + box_offset_x; in_z = (int) (z/zoom) + box_offset_y; /* check for out-of-bounds data */ if((in_x<0)||(in_z<0)||(in_x>=image_width)||(in_z>=image_height)) { /* slam non-image output to zero */ sum = 0.0; } else { /* transform frame image */ sum = scale*image[in_z][in_x]; } /* clip output intensity */ if(sum > 255) sum = 255; /* optional negative image */ if(negate) sum = 255-sum; PGMdata[(z*xsize)+x] = (unsigned char) sum; } } /* write out the PGM image */ pgmout = fopen(outfilename, "wb"); if(pgmout != NULL) { printf("writing %s\n", outfilename); fprintf(pgmout, "P2\n%d %d\n255\n", ysize, xsize); fprintf(pgmout, "# (%d,%d) to (%d,%d) on %s\n", start_x, start_y, stop_x, stop_y, filename); fprintf(pgmout, "# pixels scaled by %f and zoomed in %fX\n", scale, zoom); /* print out bytes as text integers */ i=0; for(x = xsize-1; x >= 0; --x) { for(z = 0; z < ysize; ++z) { fprintf(pgmout, "%3d ", PGMdata[(z*xsize)+x]); /* wrap long lines as per PGM definition */ ++i; if((i%20==0)||((i%xsize) == (xsize-1))) fprintf(pgmout, "\n"); } } fclose(pgmout); } else { printf("ERROR: could not open %s\n", outfilename); } } else { printf("usage: %s framefile.osc [outfile.pgm] [-zoom factor] [-box x1 y1 x2 y2] [-negate]\n", argc[0]); printf("\n\t framefile.osc - the RAXIS II/IV image file you want to convert\n"); printf( "\t outfile.pgm - name of output PGM (portable graymap) file.\n"); printf( "\t factor - zoom in by this factor.\n"); printf( "\t x1 y1 x2 y2 - corners of box to convert (original image pixel coordinates).\n"); printf( "\t -negate - black spots on white background\n"); printf("\n"); printf( "NOTE:\t denzo/mosflm (X,Y) detector coordinates are (Y,X) here."); printf("\n"); /* report unhappy ending */ return_code = 2; } return return_code; } FILE *GetFrame(char *filename, char *header) { FILE *frame; unsigned char *string; unsigned char *byte_order; unsigned long int test; typedef union { unsigned char string[2]; unsigned short integer; } TWOBYTES; TWOBYTES twobytes; FOURBYTES fourbytes; twobytes.integer = 24954; frame = fopen(filename, "rb"); if(frame != NULL) { fread(header, 1, 2048, frame); /* What kind of file is this? */ string = header; if(0!=strncmp(string, "R-AXIS", 6)) { /* probably not an OSC frame */ /* inform the user */ printf("ERROR: %s does not look like an Raxis II frame!\n", filename); /* skip this file */ fclose(frame); frame = NULL; } else { /* determine byte order on this machine */ if(0==strncmp(twobytes.string, "az", 2)) { byte_order = "big_endian"; } else { byte_order = "little_endian"; } /* see if we will need to swap bytes */ memcpy(&fourbytes, &header[784], 4); if(fourbytes.integer < 10000) { swap_bytes = FALSE; } else { swap_bytes = TRUE; /* byte-swap the header */ printf("swapping header\n"); string = (char*) calloc(1, 2048); swab((char*)header, (char*)string, 2048); memcpy(&header, &string, 2048); free(string); } } } else { /* fopen() failed */ perror("osc2pgm"); } return frame; }