/*************************************************************************
* ----------------
* | 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);
}
http://clementine.cnes.fr/software/pcdos/source/clemdcmp.c
(possibly inaccurate URL)
07/1998