/************************************************************************* * ---------------- * | CLEMDCMP | * ---------------- * *_TITLE CLEMDCMP Decompress clementine image into various formats * *_DESC CLEMDCMP will decompress a clementine image and format it into * one of three possible formats: * 1) decompressed pds image file, with pds labels, the historgram * object, and an image object, either the browse image or * the full image * 2) decompressed image file, no labels * 3) decompressed gif image * 4) decompressed tiff image * * CLEMDCMP has four command-line arguments. The first argument * indicates the output format of the decompressed image and * the following are the options: * -p = decompressed pds image file * -n = decompressed unlabeled file * -t = decompressed tiff file * -g = decompressed gif file * The second argument indicates which image object to output: * -i = full resolution image * -b = browse image * The third argument is the filename of the input compressed clementine * data file. * The fourth argument is the filename of the output decompressed * clementine image. * *_HIST Aug 27 1994 Tracie Sucharski, USGS, Flagstaff Original Version * **************************************************************************/ #include #include #include #include "pds.h" #define MM_TYPE 0x4D4D #define II_TYPE 0x4949 #define BLKSIZE 32768L main(int argc, char *argv[]) { int c; /* character for command-line arguments */ char format; /* Output file format */ char img; /* Output image or browse image */ char infile[128]; /* Input file name */ char outfile[128]; /* Output file name */ long lines; /* Number of lines and sample of image */ long samps; int i; FILE *fpi, *fpo; /* Input and output file pointers */ int ret; /* Return code */ char b[2]; short int *j; char bitord; unsigned int k, nblocks, rem; PDSINFO *p; int labmod(char *text, char img, char bitord); int writetif(FILE *fp, long nl, long ns, CHARH *buf, char bitord); for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { argv[i][1] = tolower(argv[i][1]); switch (argv[i][1]) { case 'p': case 'n': case 'g': case 't': format = argv[i][1]; break; case 'i': case 'b': img = argv[i][1]; break; default: printf("ERROR:CLEMDCMP-Illegal option chosen %c\n", c); exit(1); } } else break; } if (argc-i != 2) { printf("ERROR:CLEMDCMP-You must specify an input and output file\n"); exit(1); } /************************************************************************* * Default is to output the full image in pds format *************************************************************************/ if (format == '\0') format = 'p'; if (img == '\0') img = 'i'; strcpy(infile, argv[i]); strcpy(outfile, argv[i+1]); /************************************************************************ * Determine the bit order ************************************************************************/ j = (short int *) b; b[0] = 1; b[1] = 0; if (*j == 1) bitord = 'l'; else bitord = 'm'; /**************************************************************************** * The following call will open the compressed Clementine image and create * a structure containing the file objects. ****************************************************************************/ p = PDSR(infile, &lines, &samps); /**************************************************************************** * If user chooses to output the browse image, make sure it exists. ****************************************************************************/ if (img == 'b' && !(p->brw_imag)) { printf("ERROR:CLEMDCMP-This file does not contain a browse image"); exit(1); } /****************************************************************************** * Open output file ******************************************************************************/ fpo = fopen(outfile, "wb"); /***************************************************************************** * For the pds formatted option, the labels will need to be modified before * writing out. The uncompressed output file will either be the image or * the browse image, so the pointer to the browse image will be deleted, * and the image pointer will be modified to point to the start of the data. * The pointer to the histogram will also need to be modified. The * ENCODING_COMPRESSION_RATIO will no longer be applicable, so the value is * changed to "N/A". ******************************************************************************/ if (format == 'p') { printf("Writing PDS labeled file.\n"); if (labmod(p->text, img, bitord) < 0) { printf("ERROR:CLEMDCMP-Error reformatting labels"); exit(1); } fwrite(p->text, strlen(p->text), 1, fpo); } /***************************************************************************** * If the output is a pds file write the histogram data followed by the image * data, either the browse image or the full image. If the output is an * unlabeled image file, write only the image data out. *****************************************************************************/ if (format == 'p') fwrite(p->hist, sizeof(long), 256, fpo); if (format=='p' || format=='n') { if (format=='n') printf("Writing raw unlabeled file.\n"); if (img == 'i') { #ifdef __TURBOC__ nblocks = (lines*samps) / BLKSIZE; rem = (lines*samps) % BLKSIZE; for (k=0; kimage+=BLKSIZE) fwrite(p->image,1,BLKSIZE,fpo); if ( rem > 0 ) fwrite(p->image,1,rem,fpo); #else fwrite(p->image, lines*samps, 1, fpo); #endif if (format=='p')printf("PDS labeled file was successfully written.\n"); if (format=='n') { printf("Raw unlabeled file was successfully written.\n"); printf("\nThe size of the raw image created is %ld lines " "by %ld samples with no\n header or label data.\n\n", lines, samps); } } if (img == 'b') { fwrite(p->brw_imag, p->browse_nrows*p->browse_ncols, 1, fpo); if (format=='p')printf("PDS labeled file was successfully written.\n"); if (format=='n') { printf("Raw unlabeled file was successfully written..\n"); printf("\n\nThe size of the raw image created is %ld lines " "by %ld samples with no\n header or label data.\n\n", p->browse_nrows, p->browse_ncols); } } } if (format == 't') { /* TIFF format */ printf("Writing TIF file.\n"); if (img == 'i') { if (writetif(fpo, lines, samps, p->image, bitord) < 0) { printf("ERROR:CLEMDCMP-Error writing full image in tiff format"); exit(1); } } if (img == 'b') { /* Write browse image */ if (writetif(fpo, p->browse_nrows, p->browse_ncols, p->brw_imag, bitord) < 0) { printf("ERROR:CLEMDCMP-Error writing browse image in tiff format"); exit(1); } } printf("TIF file was successfully written.\n"); } if (format == 'g') { /* GIF format */ if (img == 'i') { if (writegif(fpo, lines, samps, p->image) < 0) { printf("ERROR:CLEMDCMP-Error writing full image in gif format"); exit(1); } } if (img == 'b') { if (writegif(fpo, p->browse_nrows, p->browse_ncols, p->brw_imag) < 0) { printf("ERROR:CLEMDCMP-Error writing browse image in gif format"); exit(1); } } } fclose(fpo); exit(0); } int labmod(char *text, char img, char bitord) /***************************************************************************** * *_TITLE LABMOD - modify the clementine label to reflect the decompression * *_ARGS Type Variable I/O Description *_PARM char *text; I Pointer to clementine label *_PARM char img I Image Type (Full image or browse image) *_PARM char bitord I Bit order of current machine *_PARM int *ret O Return code * 0 - OK * *_DESC LABMOD will modify the clementine label to reflect the decompression, * and the possible rearranging of the browse image and image object. * *_HIST Apr 13 1994 Tracie Sucharski, USGS, Flagstaff Original Version * Jun 27 1994 Tracie Sucharski, Fixed bug when writing out the * browse image. * Jul 14 1994 Tracie Sucharski, Changed output value of ENCODING_ * TYPE keyword. * Aug 23 1994 Tracie Sucharski, Added NOTE to image object if the * output image is the browse image, also correct * the DATA_TYPE keyword in the histogram object * to indicate the correct byte order. * ****************************************************************************/ { int lbllen; /* Length of incoming label */ int nlbllen; /* Length of outgoing label */ char *start, *end; /* Index pointers */ char sdummy[17]; int nc; /* Number of characters */ char byte[4]; /* Starting bytes of objects */ int hbyte; /* Starting byte of Image Historgram */ int ibyte; /* Starting byte of Image */ int bbyte; /* Starting byte of Browse Image */ int diff; /* Difference in bytes between input */ /* label and output label */ char *labels; /* Temporary buffer to hold labels */ lbllen = strlen(text); labels = (char *)malloc(lbllen); start = strstr(text, "^IMAGE_HISTOGRAM "); sscanf(start, "%s = %d", sdummy, &hbyte); start = strstr(text, "^IMAGE "); sscanf(start, "%s = %d", sdummy, &ibyte); start = strstr(text, "^BROWSE_IMAGE "); sscanf(start, "%s = %d", sdummy, &bbyte); /**************************************************************************** * Get rid of pointer to browse image. ****************************************************************************/ end = strchr(start,'\n'); strcpy(start, end+1); /*************************************************************************** * If browse image is being written, get rid of IMAGE object, rename * BROWSE_IMAGE object to IMAGE and add a note to indicate the output * image is the browse image. ***************************************************************************/ if (img == 'b') { start = strstr(text, "OBJECT = IMAGE\n"); end = strstr(start, "END_OBJECT"); strcpy(start, end+11); start = strstr(text, " BROWSE_IMAGE"); end = strchr(start, '\n'); strncpy(labels, text, (start-text)+1); *(labels+(start-text+1)) = '\0'; strcat(labels, "IMAGE"); strcat(labels, end); strcpy(text, labels); end = strstr(start, "END_OBJECT"); strncpy(labels, text, (end-text)+1); *(labels+(end-text)) = '\0'; strcat(labels, " NOTE = \"Averaged subsampled EDR image\"\n"); strcat(labels, end); strcpy(text, labels); } if (img == 'i') { /************************************************************************** * Get rid of the BROWSE_IMAGE object. ***************************************************************************/ start = strstr(text, "OBJECT = BROWSE_IMAGE"); end = strstr(start, "END_OBJECT"); strcpy(start, end+11); /*************************************************************************** * If writing IMAGE object change ENCODING_COMPRESSION_RATIO and * ENCODING_TYPE keyvalues to "N/A", since the output file is uncompressed. ***************************************************************************/ start = strstr(text, "ENCODING_TYPE "); end = strchr(start, '\n'); strncpy(labels, text, (end-text)-1); *(labels+(end-text-1)) = '\0'; strcat(labels, " DECOMPRESSED\""); strcat(labels, end); strcpy(text, labels); start = strstr(text, "ENCODING_COMPRESSION_RATIO "); end = strchr(start, '\n'); strncpy(labels, text, (start-text)+29); *(labels+(start-text+29)) = '\0'; strcat(labels, "\"N/A\""); strcat(labels, end); strcpy(text, labels); } /**************************************************************************** * If the bitorder is MSB which is different from that in the label(LSB), * change the label. ****************************************************************************/ if (bitord == 'm') { start = strstr(text, "LSB_INTEGER"); *start = 'M'; } /**************************************************************************** * Adjust the object pointers. ****************************************************************************/ nlbllen = strlen(text); hbyte = nlbllen + 1; ibyte = hbyte + 1024; /***************************************************************************** * Now that there are new pointer values, write them out to the labels. *****************************************************************************/ sprintf(byte, "%d", hbyte); nc = strlen(byte); start = strstr(text, "^IMAGE_HISTOGRAM "); strncpy(start+19, byte, nc); sprintf(byte, "%d", ibyte); nc = strlen(byte); start = strstr(text, "^IMAGE "); strncpy(start+19, byte, nc); free(labels); return(0); } /************************************************************************* * ------------ * | WRITETIF | * ------------ * *_TITLE WRITETIF Writes decompressed Clementine data into TIF format * *_DESC WRITETIF takes decompressed Clementine data and writes an * uncompressed TIF formatted image. * *_HIST May 04 1994 Tracie Sucharski, USGS, Flagstaff Original Version * *************************************************************************/ int writetif(FILE *fp, long nl, long ns, CHARH *buf, char bitord) { unsigned int j, nblocks, rem; /* Added by Luis Perez 06/29/94 */ int fputword(FILE *fp, short int n); int fputlong(FILE *fp, long n); /******************************************************************** * Write out the TIF header ********************************************************************/ if (bitord == 'm') fputword(fp, MM_TYPE); if (bitord == 'l') fputword(fp, II_TYPE); fputword(fp,42); fputlong(fp,8L); /******************************************************************** * Construct the Image File Directory (IFD) ********************************************************************/ fputword(fp, 8); /* Eight Tags */ fputword(fp, 254); /* NewSubfileType */ fputword(fp, 4); /* Long */ fputlong(fp, 1L); fputlong(fp, 0L); fputword(fp, 256); /* ImageWidth */ fputword(fp, 3); /* Short */ fputlong(fp, 1L); if (bitord == 'm') fputlong(fp, ns*65536); /* Shift value into the two high order bytes */ if (bitord == 'l') fputlong(fp, ns); fputword(fp, 257); /* ImageLength */ fputword(fp, 3); /* Short */ fputlong(fp, 1L); if (bitord == 'm') fputlong(fp, nl*65536); /* Shift value into the two high order bytes */ if (bitord == 'l') fputlong(fp, nl); fputword(fp, 258); /* BitsPerSample */ fputword(fp, 3); /* Short */ fputlong(fp, 1L); if (bitord == 'm') fputlong(fp, 524288L); /* 8 Shifted into the two high order bytes */ if (bitord == 'l') fputlong(fp, 8L); fputword(fp, 259); /* Compression */ fputword(fp, 3); /* Short */ fputlong(fp, 1L); if (bitord == 'm') fputlong(fp, 65536L); /* No compression */ if (bitord == 'l') fputlong(fp, 1L); fputword(fp, 262); /* PhotometricInterpretation */ fputword(fp, 3); /* Short */ fputlong(fp, 1L); if (bitord == 'm') fputlong(fp, 65536L); /* 1 Shifted into the two high order bytes */ if (bitord == 'l') fputlong(fp, 1L); fputword(fp, 273); /* StripOffsets - Start of image data */ fputword(fp, 4); /* Long */ fputlong(fp, 1L); fputlong(fp, 110L); fputword(fp, 277); /* SamplesPerPixel */ fputword(fp, 3); /* Short */ fputlong(fp, 1L); if (bitord == 'm') fputlong(fp, 65536L); if (bitord == 'l') fputlong(fp, 1L); fputlong(fp, 0L); /*********************************************************************** * Write image data ***********************************************************************/ /*!!!!!! BE CAREFUL HERE !!!!!!*/ /* The third argument in fwrite is of type size_t, which under Turbo C becomes an unsigned short int (16 bit integer). This means you have to write the image data out in blocks of 64K bytes or less (32K is a good number). Added by Luis Perez 06/29/94. */ #ifdef __TURBOC__ nblocks = (nl*ns) / BLKSIZE; rem = (nl*ns) % BLKSIZE; for (j=0; j 0 ) fwrite(buf,1,rem,fp); #else fwrite(buf, 1, nl*ns, fp); #endif return(0); } int fputword(FILE *fp, short int n) { fwrite(&n, 2, 1,fp); } int fputlong(FILE *fp, long n) { fwrite(&n, 4, 1, fp); }