#include #include #include /* compile this file with: cc -o osc2sgi osc2sgi.c -lm */ #define TRUE 1 #define FALSE 0 /* Note: denzo's convention of X and Y is reversed from the one used here in denzo, the slow axis (up and down) is X and the fast axis (side to side) is Y If you want to zoom in on a spot at a denzo (X,Y) of (800,900) (in the .x file) use -box 880 780 920 820 -zoom 10 */ /* the following used to be in swapper.h */ typedef union { float real; unsigned char string[4]; unsigned int integer; } FOURBYTES; /* function prototypes */ FOURBYTES fix_int(FOURBYTES wrong_order); FOURBYTES fix_float(FOURBYTES wrong_order); void fix_int_list(FOURBYTES *wrong_order, int howmany); void fix_float_list(FOURBYTES *wrong_order, int howmany); void nospaces(char *string); /* the following used to be in rgbgen.h */ typedef struct _SGIHeader { short Magic; /* Identification number (474) */ char storage; /* Compression flag */ char bpc; /* Bytes per pixel */ unsigned short int dimension; /* Number of image dimensions */ unsigned short int xsize; /* Width of image in pixels */ unsigned short int ysize; /* Height of image in pixels */ unsigned short int zsize; /* Number of bit planes */ long pixmin; /* Smallest pixel value */ long pixmax; /* Largest pixel value */ char dummy1[4]; /* Not used */ char name[80]; /* Name of image */ long colormap; /* Format of pixel data */ char dummy2[404]; /* Not used */ } SGIHEAD; /* Raxis frame data structures */ typedef enum {UNIX, VMS, UNKNOWN} byte_order; byte_order file_type = UNKNOWN; unsigned char header[4096]; /* Raxis frame handling routines */ FILE *GetFrame(char *filename); char *GetString(char *buffer, int position, int length); float GetFloat(int position); int GetInt(int position); 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; float eight; /* indicies */ int x, z; int overloads = 0; /* limits */ int high = 0; int low = 0xFFFF; double sum = 0; double sigma = 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; /* storage */ short *record; short *swapped; short *temp; /* output RGB stuff */ SGIHEAD SGIhead; unsigned char *SGIdata; FILE *rgbout = NULL; char outfilename[256] = "new.rgb"; /* begin progam here */ printf("OSC2SGI 1.0.1\t\tby James Holton 3-4-99\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_x = atol(argc[i+1]); start_y = atol(argc[i+2]); stop_x = atol(argc[i+3]); stop_y = atol(argc[i+4]); } } } /* now process the given file */ if((file_type != UNKNOWN)&&(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); record_size = GetInt(784); num_records = GetInt(788); pixels_per_line = GetInt(768); eight = GetFloat(800); if(stop_x == 0) stop_x = pixels_per_line; if(stop_y == 0) stop_y = num_records; 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;} printf("box from (%d,%d) to (%d,%d)\n", start_x, start_y, stop_x, stop_y); record = calloc(1, record_size); /* allocate space for memeory-resident image */ image = (unsigned long int **) calloc(sizeof(unsigned long int *), stop_y - start_y); /* need a little extra memory for swapping bytes */ if(file_type == VMS) { swapped = calloc(1, record_size); printf("swapping bytes...\n"); } /* load appropriate records (line) into memory */ for(z = 0; z < (stop_y - start_y); ++z) { /* position file at beginning of this DATA record */ fseek(frame, (z+start_y+1)*record_size, SEEK_SET); /* read the record into memory */ fread(record, 1, record_size, frame); /* Account for byte swapping */ if(file_type == VMS) { /* preserve location of read-in pixels */ temp = record; /* swab() can only COPY swapped bytes */ swab((char*)record, (char*)swapped, record_size); record = swapped; /* exchange buffers for next time */ swapped = temp; } /* allocate space for real pixel values */ image[z] = (unsigned long int *) calloc(sizeof(unsigned long int), stop_x - start_x); /* promote pixel words to actual values */ for(x = 0; x < (stop_x - start_x); ++x) { i = start_x + x; /* initialize from words in file */ if(record[i] == -1) { ++overloads; image[z][x] = 262144; } if(record[i] >= 0) { image[z][x] = record[i]; } if(record[i] < -1) { image[z][x] = (unsigned long int) eight*(0x8000+(record[i])); /* this should never happen */ if(record[i] < -28672) printf("oddball pixel!: (%4d, %4d) = %4d\n", x, z-1, record[i]); } /* debug * printf("reading (%d,%d) = ", z, x); printf("%d \n", image[z][x]); /* */ /* now collect statistics */ sigma += ( (double) image[z][x]) * ((double) image[z][x]); } } /* image has now been completely read into memory */ fclose(frame); /* do some statistics */ sigma /= (double) ((stop_x - start_x) * (stop_y - start_y)); sigma = sqrt(sigma); /* scale output image to 5-sigma cuttoff */ if(scale == 0) { scale = 256.0/(5*sigma); printf("intensity scale set to %g\n", scale); } /* construct RGB image header */ SGIhead.Magic = 474; /* always 474 for RGB */ SGIhead.storage = 0; /* uncompressed */ SGIhead.bpc = 1; /* one byte per pixel (channel) */ SGIhead.dimension = 2; /* 2D image */ SGIhead.xsize = (stop_x - start_x)*zoom; /* */ SGIhead.ysize = (stop_y - start_y)*zoom; /* */ SGIhead.zsize = 1; /* one z-pixel (* channels) */ SGIdata = (unsigned char *) calloc(SGIhead.xsize*SGIhead.ysize*SGIhead.zsize, SGIhead.bpc); strncpy(SGIhead.dummy1, SGIdata, 4); strncpy(SGIhead.dummy2, SGIdata, 404); SGIhead.pixmin = 0; /* minimum pixel value */ SGIhead.pixmax = 255; /* maximum pixel value */ strcpy(SGIhead.name, "no name"); /* set to origional image name */ SGIhead.colormap = 0; /* grayscale/RGB */ /* convert and copy all image data into new RGB file */ printf("transforming data ...\n"); for(z = 0; z < SGIhead.ysize; ++z) { for(x = 0; x < SGIhead.xsize; ++x) { /* debug * printf("xform (%d,%d) -> (%d,%d) = ", (int)(z/zoom), (int)(x/zoom), z, x); printf("%d\n", image[(int)(z/zoom)][(int)(x/zoom)]); /* */ /* transform frame image */ sum = scale*image[(int)(z/zoom)][(int)(x/zoom)]; if(sum > 255) sum = 255; if(negate) sum = 255-sum; SGIdata[(z*SGIhead.xsize)+x] = (unsigned char) sum; } } /* write out the RGB image */ rgbout = fopen(outfilename, "wb"); if(rgbout != NULL) { printf("writing %s\n", outfilename); fwrite(&SGIhead, 512, 1, rgbout); fwrite(SGIdata, SGIhead.bpc, SGIhead.xsize*SGIhead.ysize*SGIhead.zsize, rgbout); fclose(rgbout); } else { printf("ERROR: could not open %s\n", outfilename); } } else /* user needs help */ { printf("usage: %s framefile.osc [outfile.rgb] [-zoom factor] [-box x1 y1 x2 y2] [-negate]\n", argc[0]); printf("\n\t framefile.osc - the Raxis-IIc file you want to convert\n"); printf( "\t outfile.rgb - name of output SGI RGB 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's (X,Y) detector coordinate in *.x files is (Y,X) here."); printf("\n"); /* report unhappy ending */ file_type = UNKNOWN; return_code = 1; } /* return appropriate exit status */ return return_code; } FILE *GetFrame(char *filename) { FILE *frame; unsigned char string[1024]; frame = fopen(filename, "rb"); if(frame != NULL) { fread(header, 1, 2048, frame); /* What kind of file is this? */ GetString(string, 0, 6); if(0!=strcmp(string, "R-AXIS")) { /* probably not an R-AXIS frame */ file_type = UNKNOWN; /* inform the user */ printf("ERROR: %s does not look like an R-AXIS frame!\n", filename); /* skip this file */ fclose(frame); frame = NULL; } else { GetString(string, 812, 4); if(0==strcmp(string, "IRIS")) { /* this is a "new" Raxis file */ file_type = UNIX; } else { /* probably from "old" Raxis */ file_type = VMS; } } } else { /* fopen() failed */ perror("osc2sgi"); file_type = UNKNOWN; } return frame; } char *GetString(char *buffer, int position, int length) { memcpy(buffer, &header[position], length); buffer[length] = 0; nospaces(buffer); return buffer; } float GetFloat(position) { FOURBYTES datum; memcpy(&datum, &header[position], 4); if(file_type == VMS) datum = fix_float(datum); return datum.real; } int GetInt(position) { FOURBYTES datum; memcpy(&datum, &header[position], 4); if(file_type == VMS) datum = fix_int(datum); return datum.integer; } /* the following stuff used to be in swapper.c */ FOURBYTES fix_int(FOURBYTES wrong_order) { FOURBYTES right_order; /* reorganize byte order */ right_order.string[0] = wrong_order.string[3]; right_order.string[1] = wrong_order.string[2]; right_order.string[2] = wrong_order.string[1]; right_order.string[3] = wrong_order.string[0]; return right_order; } FOURBYTES fix_float(FOURBYTES wrong_float) { FOURBYTES right_float; right_float.string[0] = wrong_float.string[1]; right_float.string[1] = wrong_float.string[0]; right_float.string[2] = wrong_float.string[3]; right_float.string[3] = wrong_float.string[2]; if(right_float.string[0] != 0) right_float.string[0] -= 1; return right_float; } void fix_int_list(FOURBYTES *wrong_order, int howfar) { int i; for (i=0; i< howfar; ++i) { /* reorganize byte order */ wrong_order[i]=fix_int(wrong_order[i]); } return; } void fix_float_list(FOURBYTES *wrong_order, int howfar) { int i; for (i=0; i< howfar; ++i) { /* reorganize byte order */ wrong_order[i]=fix_float(wrong_order[i]); } return; } void nospaces(char *string) { /* start at the end of the string */ int index = strlen(string)-1; /* look for the first non-space */ while(string[index] == ' ') { --index; } /* truncate the string */ string[index+1] = 0; return; }