home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / utilities / utilsm / netpbmsca / pgm / c / spottopgm < prev   
Encoding:
Text File  |  1993-10-04  |  8.4 KB  |  299 lines

  1. /* Spottopgm: Convert a SPOT satellite image to Portable Greymap format.
  2.  *
  3.  * Usage: spottopgm [-1|2|3] [Firstcol Firstline Lastcol Lastline] inputfile
  4.  *
  5.  * Author: Warren Toomey, 1992.
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include "pgm.h"
  10.  
  11. /* You may have to redefine these for your compiler.
  12.  */
  13. typedef unsigned int uint32_t;
  14. typedef unsigned short uint16_t;
  15. typedef unsigned char uint8_t;
  16.  
  17. /* Define one of the following as appropriate
  18.  * to your architecture.
  19.  */
  20. #undef BIG_ENDIAN
  21. #define LITTLE_ENDIAN
  22.  
  23. /* prototypes */
  24. #ifdef LITTLE_ENDIAN
  25. uint16_t ntohs ARGS((uint16_t x));
  26. uint32_t ntohl ARGS((uint32_t x));
  27. #endif
  28. int get_image ARGS((uint32_t length));
  29. int get_imghdr ARGS((int length));
  30. int usage ARGS((void));
  31. /* Global variables */
  32.  
  33. FILE *spotfile;            /* The input file */
  34. uint8_t linebuf[12000];        /* The line buffer */
  35.  
  36. uint32_t Firstline = 0,        /* The rectangle the user wants */
  37.      Lastline = 3000,    /* cut out of the image */
  38.      Firstcol = 0,
  39.      Lastcol = 0;
  40. uint32_t Diff = 0;        /* Firstcol - Lastcol */
  41. uint8_t *Bufptr;        /* Pointer into the input image */
  42. int Color = 1;            /* Either 1, 2 or 3 */
  43. int Colbool = 0;        /* 1 if colour */
  44.  
  45.  
  46. /* Architecture-dependent functions */
  47.  
  48. #ifdef BIG_ENDIAN
  49. # define ntohs(x) (x)        /* Convert big endian to little endian */
  50. # define ntohl(x) (x)        /* for both 16- and 32- bit values */
  51. #endif
  52.  
  53. #ifdef LITTLE_ENDIAN
  54. uint16_t 
  55. ntohs(x)
  56.   uint16_t x;
  57. {
  58.   uint16_t y;
  59.   char *a, *b;
  60.  
  61.   a = (char *) &x; b = (char *) &y;
  62.   b[0] = a[1]; b[1] = a[0];
  63.   return y;
  64. }
  65.  
  66. uint32_t 
  67. ntohl(x)
  68.   uint32_t x;
  69. {
  70.   uint32_t y;
  71.   char *a, *b;
  72.  
  73.   a = (char *) &x; b = (char *) &y;
  74.   b[0] = a[3]; b[3] = a[0];
  75.   b[1] = a[2]; b[2] = a[1];
  76.   return y;
  77. }
  78. #endif
  79.  
  80.  
  81. /* Get_image extracts the pixel data from one line
  82.  * (i.e one record) in the SPOT input file. A SPOT image
  83.  * record has a header, data and trailer. The data lengths
  84.  * are fixed at 3960, 5400, 8640 or 10980 bytes.
  85.  *
  86.  * When we arrive here we have read in 12 bytes of the record.
  87.  * We then read in the rest of the record. We find the trailer
  88.  * and from that determine the number of pixels on the line.
  89.  *
  90.  * If the image is really color i.e interleaved 3 colors, we
  91.  * convert a line if its spectral sequence is the same as the one
  92.  * requested by the user (i.e 1, 2 or 3). I could create a ppm file
  93.  * but I couldn't be bothered with the rearranging of the data.
  94.  */
  95. int 
  96. get_image(length)
  97.   uint32_t length;
  98. {
  99.   int cnt;
  100.   struct Linehdr        /* Each line begins with the 12 bytes */
  101.   {                /* we have already, plus these 20 bytes */
  102.     uint32_t linenum;        /* The line number of the record */
  103.     uint16_t recseq;        /* The record sequence number */
  104.     uint16_t spectseq;        /* The spectral number of the line */
  105.     uint32_t linetime;        /* Time it was recorded (in ms). */
  106.     uint32_t leftpixmar;    /* The pixel number of the 1st pixel */
  107.     uint32_t rightpixmar;    /* The pixel number of the last pixel */
  108.   } linehdr;
  109.   struct Lineend
  110.   {                /* And after the fixed size */
  111.     uint8_t lossflg;        /* data, we have this */
  112.     uint8_t oorflag;
  113.     uint8_t reserved1[22];
  114.     uint32_t numpixels;        /* Number of pixels on the line */
  115.   } *lineend;
  116.  
  117.                 /* Get the details of this line */
  118.   cnt = fread(&linehdr, sizeof(linehdr), 1, spotfile);
  119.   if (cnt == 0) exit(1);
  120.                 /* Convert to little-endian */
  121. #ifdef LITTLE_ENDIAN
  122.   linehdr.linenum = ntohl(linehdr.linenum);
  123.   linehdr.spectseq = ntohs(linehdr.spectseq);
  124. # ifdef DEBUG
  125.   linehdr.leftpixmar = ntohl(linehdr.leftpixmar);
  126.   linehdr.rightpixmar = ntohl(linehdr.rightpixmar);
  127.   linehdr.recseq = ntohs(linehdr.recseq);
  128.   linehdr.linetime = ntohl(linehdr.linetime);
  129. # endif
  130. #endif
  131.  
  132.                 /* Now read in the line data */
  133.   cnt = length - 20;
  134.   cnt = fread(linebuf, 1, cnt, spotfile);
  135.  
  136.   if (!Diff)
  137.   {  switch (length)        /* Try and find the trailer */
  138.     {
  139.       case 3948: lineend = (struct Lineend *) &linebuf[3860]; break;
  140.       case 5388: lineend = (struct Lineend *) &linebuf[5300]; break;
  141.       case 8628: lineend = (struct Lineend *) &linebuf[8540]; break;
  142.       case 10968: lineend = (struct Lineend *) &linebuf[10880]; break;
  143.       default: fprintf(stderr, "Bad image line record size\n"); exit(1);
  144.     }
  145.  
  146. #ifdef LITTLE_ENDIAN
  147.                 /* Work out the number of pixels */
  148.     lineend->numpixels = ntohl(lineend->numpixels);
  149. #endif
  150.  
  151.                 /* Determine the picture size */
  152.     Bufptr = &linebuf[Firstcol];
  153.     if (Lastcol == 0 || Lastcol > lineend->numpixels)
  154.        Lastcol = lineend->numpixels;
  155.     Diff = Lastcol - Firstcol;
  156.                 /* Print out the header */
  157.     printf("P5\n%d %d\n255\n", Diff, Lastline - Firstline);
  158.                 /* Inform about the image size */
  159.     if (Colbool) fprintf(stderr, "Color image, ");
  160.     fprintf(stderr, "%d pixels wide\n", lineend->numpixels);
  161.   }
  162.  
  163.                 /* Output the line */
  164.   if (linehdr.linenum >= Firstline && linehdr.linenum <= Lastline
  165.     && linehdr.spectseq == Color)
  166.     fwrite(Bufptr, 1, Diff, stdout);
  167.   if (linehdr.linenum > Lastline) exit(0);
  168.  
  169. #ifdef DEBUG
  170.   fprintf(stderr,
  171.     "Line %4d, %3d, %3d, time %4d, l/r pixmar %4d %4d len %d pixnum %d\n",
  172.       linehdr.linenum, linehdr.recseq, linehdr.spectseq, linehdr.linetime,
  173.       linehdr.leftpixmar, linehdr.rightpixmar, length, lineend->numpixels);
  174. #endif
  175.             /* And return the amount to seek - should be 0 */
  176.   return (length - 20 - cnt);
  177. }
  178.  
  179. /* The image header tells us if the image is in monochrome or color, and
  180.  * if the latter, if the input colors are interleaved. If interleaved
  181.  * color, lines are interleaved R, G, B, R, G, B etc. Technically, some
  182.  * interleaving of infra-red, visible and ultra-violet.
  183.  *
  184.  * In the description field below,
  185.  *    element 0 == P --> monochrome
  186.  *    element 0 == X --> color
  187.  *    element 9 == S --> sequential (i.e only one color here)
  188.  *    element 9 == I --> interleaved (1 or more colors)
  189.  */
  190. int 
  191. get_imghdr(length)
  192.   int length;
  193. {
  194.   int cnt;
  195.   struct Imghdr
  196.   {
  197.     uint32_t linewidth;
  198.     uint8_t dummy1[36];
  199.     char description[16];    /* Type of image */
  200.   } header;
  201.  
  202.   cnt = fread(&header, sizeof(header), 1, spotfile);
  203.   if (cnt == 0) exit(1);
  204.  
  205.                 /* Determine mono or colour */
  206.   if (header.description[0] == 'X' && header.description[9] == 'S')
  207.     Colbool = 1;
  208.   else Colbool = 0;
  209.  
  210. #ifdef DEBUG
  211.   fprintf(stderr, "Dummy str is >%s<\n", header.dummy1);
  212.   fprintf(stderr, "Imghdr str is >%s<, col %d\n", header.description, Colbool);
  213. #endif
  214.                 /* Return the amount to fseek */
  215.   return (length - sizeof(header));
  216. }
  217.  
  218. usage()
  219. {
  220.   fprintf(stderr,
  221. "Usage: spottopgm [-1|2|3] [Firstcol Firstline Lastcol Lastline] input_file\n");
  222.   exit(1);
  223. }
  224.  
  225. int
  226. main(argc, argv)
  227.   int argc;
  228.   char *argv[];
  229.  
  230. {
  231.   struct Record                /* A SPOT image is broken up into */
  232.   {                    /* records with the following fields */
  233.     uint32_t record;            /* The record number (1, 2, 3...) */
  234.     uint8_t sub1;            /* Record sub type 1 */
  235.     uint8_t type;            /* The record type */
  236.     uint8_t sub2;            /* Record sub type 2 */
  237.     uint8_t sub3;            /* Record sub type 3 */
  238.     uint32_t length;            /* Record length in bytes */
  239.   } arecord;
  240.   int cnt;
  241.  
  242.   pgm_init( &argc, argv );
  243.  
  244.   if (sizeof(uint32_t)!=4 || sizeof(uint16_t)!=2 || sizeof(uint8_t)!=1)
  245.    { fprintf(stderr, "Typedefs in spottopgm wrong size -- recompile!\n");
  246.      exit(1);
  247.    }
  248.    
  249.   switch (argc)
  250.   {
  251.     case 7:
  252.       Color= -(atoi(argv[1]));        /* Get the color to extract */
  253.       argv++;
  254.     case 6:
  255.       Firstcol = atoi(argv[1]);        /* Get the rectangle to extract */
  256.       Firstline = atoi(argv[2]);
  257.       Lastcol = atoi(argv[3]);
  258.       Lastline = atoi(argv[4]);
  259.       argv += 4;
  260.       goto openfile;            /* Yuk, a goto! */
  261.     case 3:
  262.       Color= -(atoi(argv[1]));        /* Get the color to extract */
  263.       argv++;
  264.     case 2:
  265. openfile:
  266.       spotfile = fopen(argv[1], "r");    /* Open the input file */
  267.       if (spotfile == NULL) { perror("fopen"); exit(1); }
  268.       break;
  269.     default:
  270.       usage();
  271.   }
  272.  
  273.   while (1)                /* Get a record */
  274.   { cnt = fread(&arecord, sizeof(arecord), 1, spotfile);
  275.     if (cnt == 0) break;
  276. #ifdef LITTLE_ENDIAN
  277.     arecord.length = ntohl(arecord.length);
  278. # ifdef DEBUG
  279.     arecord.record = ntohl(arecord.record);
  280. # endif
  281. #endif
  282.  
  283.  
  284.     arecord.length -= 12;    /* Subtract header size as well */
  285.     if (arecord.type == 0355 && arecord.sub1 == 0355)
  286.       arecord.length = get_image(arecord.length);
  287.     else if (arecord.type == 0300 && arecord.sub1 == 077)
  288.       arecord.length = get_imghdr(arecord.length);
  289. #ifdef DEBUG
  290.     else
  291.       fprintf(stderr, "Rcrd %3d, type %03o, stype %03o %03o %03o, length %d\n",
  292.           arecord.record, arecord.type, arecord.sub1, arecord.sub2,
  293.           (int) arecord.sub3 & 0xff, arecord.length);
  294. #endif
  295.                 /* Seek to next record */
  296.     fseek(spotfile, arecord.length, 1);
  297.   }
  298. }
  299.