|
Isis 3.0 Application Source Code Reference |
Home |
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 }