USGS

Isis 3.0 Application Source Code Reference

Home

readmocisis.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 ==================================================
00004 2003-APR-17 Glenn Bennett - US Geological Survey
00005 
00006 Due to a conflict with XV - by John Bradley
00007 - XV program also uses a version of this 'readmoc'
00008 program ISIS system has renamed this file
00009 
00010   from: readmoc
00011   to:   readmocisis
00012 
00013 an accompanying program has also been renamed:
00014 
00015   from: readmocdrv
00016   to:   readmocdrvisis
00017 
00018 This will prevent problems encountered where two
00019 packages have the same named underlying programs.
00020 ==================================================
00021 ==================================================
00022 2003-OCT-15 Stuart Sides - US Geological Survey
00023 
00024 Converted calls to "gets" to "fgets" to satisfy
00025 of compiler warning about "gets" being unsafe. These
00026 calls were used to get the input and output filenames.
00027 Changing from "gets" to "fgets" also required a check
00028 to make sure there was no '\n' at the end of the input
00029 string.
00030 ==================================================
00031 
00032 
00033 NOTICE
00034 
00035 The software accompanying this notice (the "Software") is provided to you
00036 free of charge to facilitate your use of the data collected by the Mars
00037 Orbiter Camera (the "MOC Data").  Malin Space Science Systems ("MSSS")
00038 grants to you (either as an individual or entity) a personal,
00039 non-transferable, and non-exclusive right (i) to use and reproduce the
00040 Software solely for the purpose of accessing the MOC Data; (ii) to modify
00041 the source code of the Software as necessary to maintain or adapt the
00042 Software to run on alternate computer platforms; and (iii) to compile, use
00043 and reproduce the modified versions of the Software solely for the purpose
00044 of accessing the MOC Data.  In addition, you may distribute the Software,
00045 including any modifications thereof, solely for use with the MOC Data,
00046 provided that (i) you must include this notice with all copies of the
00047 Software to be distributed; (ii) you may not remove or alter any
00048 proprietary notices contained in the Software; (iii) you may not charge any
00049 third party for the Software; and (iv) you will not export the Software
00050 without the appropriate United States and foreign government licenses.
00051 
00052 You acknowledge that no title to the intellectual property in the Software
00053 is transferred to you.  You further acknowledge that title and full
00054 ownership rights to the Software will remain the exclusive property of MSSS
00055 or its suppliers, and you will not acquire any rights to the Software
00056 except as expressly set forth above.  The Software is provided to you AS
00057 IS.  MSSS MAKES NO WARRANTY, EXPRESS OR IMPLIED, WITH RESPECT TO THE
00058 SOFTWARE, AND SPECIFICALLY DISCLAIMS THE IMPLIED WARRANTIES OF
00059 NON-INFRINGEMENT OF THIRD PARTY RIGHTS, MERCHANTABILITY AND FITNESS FOR A
00060 PARTICULAR PURPOSE.  SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR
00061 LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO SUCH LIMITATIONS OR
00062 EXCLUSIONS MAY NOT APPLY TO YOU.
00063 
00064 Your use or reproduction of the Software constitutes your agreement to the
00065 terms of this Notice.  If you do not agree with the terms of this notice,
00066 promptly return or destroy all copies of the Software in your possession.
00067 
00068 Copyright (C) 1999 Malin Space Science Systems.  All Rights Reserved.
00069 */
00070 //static char *sccsid = "@(#)readmocisis.c  1.2 04/10/00";
00071 
00072 /*
00073     SDP interpretation program
00074     Mike Caplinger, MOC GDS Design Scientist
00075     SCCS @(#)readmocisis.c  1.2 04/10/00
00076 
00077     Reads and decompresses MOC SDP files to create PDS images.
00078     Derived from the GDS readmsdp program.
00079 */
00080 
00081 #include <stdlib.h>
00082 #include <stdio.h>
00083 #include <string.h>
00084 #include <memory.h>
00085 #include "image_io.h"
00086 #include "array.h"
00087 #include "msdp.h"
00088 #include "fs.h"
00089 
00090 extern FILE *write_header(int width, int height,
00091                           FILE *infile, char *outfname);
00092 static FILE *out;
00093 static FILE *infile;
00094 int errors;
00095 static int test_pred;
00096 static int rawencode = 0;
00097 
00098 static int verbose = 0;
00099 
00100 static int frag_offset[128];
00101 
00102 static char infname[256], outfname[256];
00103 static int mbr = 0;
00104 
00105 byte *decode(struct msdp_header h, byte *data, int datlen, int *len, int mbr);
00106 void init_output(struct msdp_header h);
00107 extern unsigned int CS8EACC2(register unsigned char *dat, unsigned int len);
00108 
00109 #define FRAGSIZE (256*1024)
00110 
00111 static char decode_file[128];
00112 
00113 static unsigned int sync;
00114 
00115 static char label[1024];
00116 
00117 static int status;
00118 #define STAT_SHORT 2
00119 #define STAT_BADSEQ 4
00120 #define STAT_BADCS 8
00121 
00122 enum MocCompressEnum {
00123   RAW = 0, PRED, XFORM
00124 } MocCompress = RAW;
00125 
00126 int main(int argc, char **argv)
00127 {
00128   int height = 0, width = 0;
00129   pixel *frag;
00130   int actual_height;
00131   int total_image = 0;
00132   int total = 0;
00133   int cs_check = 1;
00134   int pad_cs = 0;
00135   int multi = 0;
00136   int sequence = -1, processor = 0, n_processors = 1;
00137   int last_frag = -1;
00138 
00139   sync = 0xf0ca;
00140 
00141   if(argc < 3) {
00142     printf("\nEnter name of file to be decompressed: ");
00143     if(!fgets(infname, 256, stdin)) {
00144       fprintf(stderr, "Encountered error while tring to read name of "
00145               "file to be decompressed\n");
00146     }
00147     int inLen = strlen(infname) - 1;
00148     if(inLen == '\n') infname[inLen] = '\0';
00149     printf("\nEnter name of uncompressed output file: ");
00150     int outLen = strlen(outfname) - 1;
00151     if(outLen == '\n') outfname[outLen] = '\0';
00152     if(!fgets(outfname, 256, stdin)) {
00153       fprintf(stderr, "Encountered error while tring to read name of "
00154               "uncompressed output file\n");
00155     }
00156   }
00157   else {
00158     strcpy(infname, argv[1]);
00159     strcpy(outfname, argv[2]);
00160   }
00161 
00162   infile = fopen(infname, "r");
00163   if(infile == 0) {
00164     fprintf(stderr, "Can't open %s\n", argv[1]);
00165   }
00166 
00167   while(1) {
00168     int count;
00169     int len;
00170     static int first = 1;
00171     struct msdp_header h, lasth;
00172     int datlen;
00173     byte *indat = 0, *chunk = 0;
00174 
00175     lasth = h;
00176     fseek(infile, total + 2048, 0);
00177     count = fread(&h, sizeof(h), 1, infile);
00178     MAKELONG(h.len);
00179     if(count && MAKELONG(h.len) == 0) {
00180       // simulate the EOF even though there's padding
00181       count = 0;
00182       h = lasth;
00183     }
00184     if(count == 0 && MocCompress == PRED && (h.status & 2) == 0) {
00185       // image was short -- last flag missing
00186       h.status = 2;
00187       frag = decode(h, indat, 0, &len, mbr);
00188       fwrite(frag, 1, len, out);
00189       total_image += len;
00190     }
00191     if(count == 0) break;
00192     if(MAKELONG(h.len) == 0) break;
00193     sequence += 1;
00194 
00195     if(first && !multi) {
00196       width = h.edit_length * 16;
00197       init_output(h);
00198       first = 0;
00199       height = MAKESHORT(h.down_total) * 16;
00200     }
00201     h.edit_length = width / 16;
00202     if(mbr) width = 512;
00203 
00204     datlen = MAKELONG(h.len);
00205 
00206     if(sequence % n_processors != processor) {
00207       total += sizeof(struct msdp_header) + datlen + 1;
00208       continue;
00209     }
00210 
00211     if(!multi && MAKESHORT(h.fragment) != last_frag + 1) {
00212       int n_pad = MAKESHORT(h.fragment) - last_frag - 1;
00213       char *frag = (char *) malloc(240 * 1024);
00214       // don't pad predictively-compressed data
00215       if(!(h.compression[0] & 3) && n_pad > 0) {
00216         errors += 1;
00217         status |= STAT_BADSEQ;
00218         bzero(frag, 240 * 1024);
00219         total_image += n_pad * 240 * 1024;
00220         if(verbose) fprintf(stderr, "padding %d frags\n", n_pad);
00221         while(n_pad--) fwrite(frag, 1, 240 * 1024, out);
00222       }
00223       free(frag);
00224     }
00225     last_frag = MAKESHORT(h.fragment);
00226 
00227     if(verbose) fprintf(stderr, "id %d/%d, len %d\n", MAKESHORT(h.id),
00228                           MAKESHORT(h.fragment), MAKELONG(h.len));
00229     chunk = (byte *) malloc(datlen + sizeof(struct msdp_header) + 1);
00230     indat = chunk + sizeof(struct msdp_header);
00231     count = fread(indat, 1, datlen, infile);
00232     if(count != datlen) {
00233       if(verbose) fprintf(stderr,
00234                             "Error: short read (%d) of data part of fragment\n",
00235                             count);
00236       errors += 1;
00237       break;
00238     }
00239 
00240     // check MSDP checksum
00241     if(cs_check) {
00242       memmove(chunk, &h, sizeof(h));
00243       if(fread(chunk + datlen + sizeof(h), 1, 1, infile) != 1
00244          && ferror(infile) && verbose) {
00245         fprintf(stderr, "Encountered error while tring to read MSDP "
00246                 "checksum\n");
00247       }
00248       
00249       if(!CS8EACC2(chunk, datlen + sizeof(h) + 1)) {
00250         if(verbose) fprintf(stderr, "Error: bad MSDP checksum\n");
00251         status |= STAT_BADCS;
00252         errors += 1;
00253         if(pad_cs) {
00254           char *frag = (char *) malloc(240 * 1024);
00255           bzero(frag, 240 * 1024);
00256           total_image += 240 * 1024;
00257           total += sizeof(struct msdp_header) + datlen + 1;
00258           if(verbose) fprintf(stderr, "trashing bad frag\n");
00259           fwrite(frag, 1, 240 * 1024, out);
00260           free(frag);
00261           continue;
00262         }
00263       }
00264     }
00265 
00266     frag = decode(h, indat, datlen, &len, mbr);
00267     total_image += len;
00268     if(verbose) fprintf(stderr, "fragment len %d => %d\n", datlen, len);
00269     total += sizeof(struct msdp_header) + datlen + 1;
00270     fwrite(frag, 1, len, out);
00271     if(0) free(frag);
00272     free(chunk);
00273     if(h.status & 2) break;
00274   }
00275   fclose(out);
00276 
00277   actual_height = total_image / width;
00278   if(!multi && actual_height != height) {
00279     if(verbose) fprintf(stderr,
00280                           "Error: total MSDP height (%d) != actual height (%d)\n",
00281                           height, actual_height);
00282     (void) write_header(width, actual_height, infile, outfname);
00283     errors += 1;
00284     status |= STAT_SHORT;
00285   }
00286 
00287   if(status && verbose) fprintf(stderr, "error status %c%c%c%c\n",
00288                                   MocCompress == RAW ? 'r' : (MocCompress == PRED ? 'p' : 't'),
00289                                   status & STAT_BADCS ? 'c' : '-',
00290                                   status & STAT_BADSEQ ? 'n' : '-',
00291                                   status & STAT_SHORT ? 's' : '-'
00292                                  );
00293   if(errors) exit((MocCompress << 4) | status | (errors ? 1 : 0));
00294   else exit(0);
00295 }
00296 
00297 byte *decode(struct msdp_header h, byte *data, int datlen, int *len, int mbr)
00298 {
00299   int height, width;
00300   unsigned int xcomp, pcomp, spacing = 0, levels = 0;
00301   uint8 *transform_decomp_main(uint8 *data, int len, int height, int width, uint32 transform, uint32 spacing, uint32 numLevels);
00302   uint8 *predictive_decomp_main(uint8 *data, int len, int height, int width,
00303                               uint8 doSync, uint16 sync, int xpred, int ypred, int *got_height);
00304   byte *image = 0;
00305   static Array *tbuf;
00306   static int init_decode;
00307   int huffman_table = 0;
00308 
00309   if(mbr) {
00310     width = 512;
00311     height = 480;
00312     xcomp = 0;
00313     pcomp = 0;
00314   }
00315   else {
00316     width = h.edit_length * 16;
00317     height = MAKESHORT(h.down_length) * 16;
00318     xcomp = (h.compression[0] >> 2) & 3;
00319     pcomp = (h.compression[0] & 3);
00320     spacing = h.compression[4] | (h.compression[5] << 8);
00321     levels = (h.compression[1] >> 5) + 1;
00322     huffman_table = h.compression[1] & 0xf;
00323   }
00324 
00325   *len = width * height;
00326 
00327   if(pcomp && xcomp) {
00328     fprintf(stderr, "error: both pcomp and xcomp set\n");
00329     exit(1);
00330   }
00331   if(pcomp) MocCompress = PRED;
00332   if(xcomp) MocCompress = XFORM;
00333 
00334   if(!rawencode && pcomp == 0 && xcomp == 0) {
00335     // raw image
00336     image = data;
00337     if(datlen > *len) {
00338       if(verbose) fprintf(stderr, "Warning: MSDP line count (%d) < implied (%d), using latter\n", height, datlen / width);
00339       *len = datlen;
00340       height = datlen / width;
00341     }
00342     if(verbose) fprintf(stderr, "%d wide by %d high ", width, height);
00343     if(verbose) fprintf(stderr, "raw fragment%s\n", mbr ? " (MBR)" : "");
00344   }
00345   else if(verbose) fprintf(stderr, "%d wide by %d high ", width, height);
00346 
00347   if(xcomp > 0) {
00348     // transform compressed; 2 = DCT, 1 = WHT
00349     if(verbose) fprintf(stderr, "%s transformed fragment (%d groups, %.2f requant)\n",
00350                           xcomp == 2 ? "dct" : "wht", levels, spacing / 16.0);
00351     image = transform_decomp_main(data, datlen, height, width,
00352                                   xcomp - 1, spacing, levels);
00353   }
00354 
00355   if(rawencode || pcomp > 0) {
00356     // predictively compressed
00357     if(rawencode) {
00358       if(verbose) fprintf(stderr, "raw encoded fragment\n");
00359       else if(verbose) fprintf(stderr, "%s%s predictive fragment, table %d\n",
00360                                  pcomp & 1 ? "x" : "", (pcomp & 2) >> 1 ? "y" : "",
00361                                  huffman_table);
00362     }
00363 
00364     // set up decode arrays
00365     extern void decodeLoad(char *);
00366     extern void decodeInit(int);
00367     if(!init_decode) {
00368       if(*decode_file) decodeLoad(decode_file);
00369       else decodeInit(huffman_table);
00370     }
00371 
00372     if(test_pred) {
00373       int dummy;
00374 
00375       image = predictive_decomp_main(data, datlen, height, width,
00376                                      (sync != 0), sync,
00377                                      pcomp & 1, (pcomp & 2) >> 1,
00378                                      &dummy);
00379     }
00380     else {
00381       // squirrel data away
00382       if(!tbuf) tbuf = array_new(datlen * 8);
00383       if(datlen && !array_append(tbuf, (char*)data, datlen)) {
00384         // FIXED 2008/10/29, "datalen" was part of the print statement and no arguments
00385         // were provided for the %d. - Steven Lambright, pointed out by "novas0x2a" (Support Forum Member)
00386         fprintf(stderr, "can't allocate temp space (%d bytes)\n", datlen);
00387         exit(1);
00388       }
00389       image = 0;
00390       *len = 0;
00391       if(h.status & 2) {
00392         int got_height;
00393         extern int pred_past_eof;
00394         int want_h = MAKESHORT(h.down_total) * 16;;
00395         if(verbose) fprintf(stderr, "decompressing %d wide by %d high image\n",
00396                               width, want_h);
00397         image =
00398           predictive_decomp_main((uint8*)array_data(tbuf),
00399                                  array_len(tbuf),
00400                                  want_h, width,
00401                                  (sync != 0), sync,
00402                                  (pcomp & 1), ((pcomp & 2) >> 1),
00403                                  &got_height);
00404         /* This is tricky.  We can get bad sync even without
00405            checksum errors if anomaly 8 occurs.  We want to
00406            distinguish between this case and the case where
00407            we just ran out of fragments during the NA image.
00408            So if we run into a sync error and haven't run off
00409            the end of the image, we force BADCS on. */
00410         if(got_height != want_h && !pred_past_eof)
00411           status |= STAT_BADCS;
00412         *len = got_height * width;
00413       }
00414     }
00415   }
00416 
00417   return image;
00418 }
00419 
00420 int worklist_init() {
00421   struct msdp_header h;
00422   int count;
00423   int frag = 0;
00424   int height, width, xcomp;
00425   int datlen;
00426 
00427   while(1) {
00428     count = fread(&h, sizeof(h), 1, infile);
00429     if(count == 0) break;
00430     xcomp = (h.compression[0] >> 2) & 3;
00431     if(!xcomp) return 0;
00432     height = MAKESHORT(h.down_length) * 16;
00433     width = h.edit_length * 16;
00434     datlen = MAKELONG(h.len);
00435     init_output(h);
00436     frag_offset[frag+1] = frag_offset[frag] + height * width;
00437     frag += 1;
00438     fseek(infile, datlen + 1, 1);
00439   }
00440   return 1;
00441 }
00442 
00443 void init_output(struct msdp_header h)
00444 {
00445   int height, width;
00446   char s[8];
00447   int i;
00448   char buf[1024];
00449 
00450   height = MAKESHORT(h.down_total) * 16;
00451   width = h.edit_length * 16;
00452   sprintf(label, "decompressed-from %s\nid %d time %u:%d\ngain 0x%x \
00453 offset %d\nstart %d cross %d down %d\ncmd ", infname,
00454           MAKESHORT(h.id),
00455           MAKELONG(h.time + 1), h.time[0],
00456           h.gain, h.offset,
00457           h.edit_start * 16,
00458           h.edit_length * 16,
00459           MAKESHORT(h.down_total) * 16);
00460   switch(h.cmd[0]) {
00461     case 1:
00462     case 2:
00463       strcat(label, "na ");
00464       break;
00465     case 3:
00466     case 4:
00467       strcat(label, "wa ");
00468       break;
00469     case 5:
00470     case 6:
00471       strcat(label, "global-map ");
00472       break;
00473     case 0x15:
00474     case 0x16:
00475       strcat(label, "mbr ");
00476       mbr = 1;
00477       width = 512;
00478       height = 512;
00479       break;
00480     case 0xd:
00481       strcat(label, "read-memory ");
00482       break;
00483     default:
00484       strcat(label, "unknown ");
00485       break;
00486   }
00487   for(i = 0; i < 17; i++) {
00488     sprintf(s, "%02x", h.cmd[i]);
00489     strcat(label, s);
00490   }
00491 
00492   sprintf(buf, "\nsensor %d clocking %d system-id 0x%x",
00493           MAKESHORT(h.sensors),
00494           MAKESHORT(h.other + 1),
00495           h.other[3]);
00496   strcat(label, buf);
00497 
00498   out = (FILE *) write_header(width, height, infile, outfname);
00499 }