home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / pgm / spottopgm.c < prev   
C/C++ Source or Header  |  1994-01-31  |  8KB  |  240 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. /* prototypes */
  12. int get_image ARGS((long length));
  13. int get_imghdr ARGS((int length));
  14. int usage ARGS((void));
  15. /* Global variables */
  16.  
  17. FILE *spotfile;            /* The input file */
  18. #if defined (atarist) && defined (__MBASE__)
  19. char *linebuf;
  20. #else
  21. char linebuf[12000];        /* The line buffer */
  22. #endif
  23.  
  24. long Firstline = 0,        /* The rectangle the user wants */
  25.      Lastline = 3000,    /* cut out of the image */
  26.      Firstcol = 0,
  27.      Lastcol = 0;
  28. long Diff = 0;            /* Firstcol - Lastcol */
  29. char *Bufptr;            /* Pointer into the input image */
  30. int Color = 1;            /* Either 1, 2 or 3 */
  31. int Colbool = 0;        /* 1 if colour */
  32.  
  33.  
  34. /* Get_image extracts the pixel data from one line
  35.  * (i.e one record) in the SPOT input file. A SPOT image
  36.  * record has a header, data and trailer. The data lengths
  37.  * are fixed at 3960, 5400, 8640 or 10980 bytes.
  38.  *
  39.  * When we arrive here we have read in 12 bytes of the record.
  40.  * We then read in the rest of the record. We find the trailer
  41.  * and from that determine the number of pixels on the line.
  42.  *
  43.  * If the image is really color i.e interleaved 3 colors, we
  44.  * convert a line if its spectral sequence is the same as the one
  45.  * requested by the user (i.e 1, 2 or 3). I could create a ppm file
  46.  * but I couldn't be bothered with the rearranging of the data.
  47.  */
  48. int 
  49. get_image(length)
  50.   long length;
  51. {
  52.   int cnt;
  53.   struct Linehdr        /* Each line begins with the 12 bytes */
  54.   {                /* we have already, plus these 20 bytes */
  55.     long linenum;        /* The line number of the record */
  56.     short recseq;        /* The record sequence number */
  57.     short spectseq;        /* The spectral number of the line */
  58.     long linetime;        /* Time it was recorded (in ms). */
  59.     long leftpixmar;        /* The pixel number of the 1st pixel */
  60.     long rightpixmar;        /* The pixel number of the last pixel */
  61.   } linehdr;
  62.   long numpixels;        /* Number of pixels on the line */
  63.  
  64.                 /* Get the details of this line */
  65.   if (pm_readbiglong (spotfile, &linehdr.linenum) == -1
  66.       || pm_readbigshort (spotfile, &linehdr.recseq) == -1
  67.       || pm_readbigshort (spotfile, &linehdr.spectseq) == -1
  68.       || pm_readbiglong (spotfile, &linehdr.linetime) == -1
  69.       || pm_readbiglong (spotfile, &linehdr.leftpixmar) == -1
  70.       | pm_readbiglong (spotfile, &linehdr.rightpixmar) == -1)
  71.     pm_error ("EOF / read error reading line header");
  72.  
  73.                 /* Now read in the line data */
  74.   cnt = length - 20 - 88;
  75.   cnt = fread(linebuf, 1, cnt, spotfile);
  76.  
  77.   if (!Diff)
  78.   {
  79.     cnt += 28;
  80.     if (fseek (spotfile, 24, 1) == EOF)
  81.       pm_error ("seek error");
  82.     if (pm_readbiglong (spotfile, &numpixels) == -1)
  83.       pm_error ("EOF / read error reading line ender");
  84.     
  85.     /* Determine the picture size */
  86.     Bufptr = &linebuf[Firstcol];
  87.     if (Lastcol == 0 || Lastcol > numpixels)
  88.       Lastcol = numpixels;
  89.     Diff = Lastcol - Firstcol;
  90.                 /* Print out the header */
  91.     printf("P5\n%d %d\n255\n", Diff, Lastline - Firstline);
  92.                 /* Inform about the image size */
  93.     if (Colbool) fprintf(stderr, "Color image, ");
  94.     fprintf(stderr, "%d pixels wide\n", numpixels);
  95.   }
  96.  
  97.                 /* Output the line */
  98.   if (linehdr.linenum >= Firstline && linehdr.linenum <= Lastline
  99.     && linehdr.spectseq == Color)
  100.     fwrite(Bufptr, 1, Diff, stdout);
  101.   if (linehdr.linenum > Lastline) exit(0);
  102.  
  103. #ifdef DEBUG
  104.   fprintf(stderr,
  105.     "Line %4d, %3d, %3d, time %4d, l/r pixmar %4d %4d len %d pixnum %d\n",
  106.       linehdr.linenum, linehdr.recseq, linehdr.spectseq, linehdr.linetime,
  107.       linehdr.leftpixmar, linehdr.rightpixmar, length, numpixels);
  108. #endif
  109.             /* And return the amount to seek */
  110.   return (length - 20 - cnt);
  111. }
  112.  
  113. /* The image header tells us if the image is in monochrome or color, and
  114.  * if the latter, if the input colors are interleaved. If interleaved
  115.  * color, lines are interleaved R, G, B, R, G, B etc. Technically, some
  116.  * interleaving of infra-red, visible and ultra-violet.
  117.  *
  118.  * In the description field below,
  119.  *    element 0 == P --> monochrome
  120.  *    element 0 == X --> color
  121.  *    element 9 == S --> sequential (i.e only one color here)
  122.  *    element 9 == I --> interleaved (1 or more colors)
  123.  */
  124. int 
  125. get_imghdr(length)
  126.   int length;
  127. {
  128.   struct Imghdr
  129.   {
  130.     long linewidth;
  131.     char dummy1[36];
  132.     char description[16];    /* Type of image */
  133.   } header;
  134.  
  135.   if (pm_readbiglong (spotfile, &header.linewidth) == -1)
  136.     pm_error ("EOF / read error reading header");
  137. #ifdef DEBUG
  138.   if (fread (header.dummy1, 1, 36, spotfile) != 36)
  139.     pm_error ("EOF / read error reading header");
  140. #else
  141.   if (fseek (spotfile, 36, 1) == EOF)
  142.     pm_error ("seek error");
  143. #endif
  144.   if (fread (header.description, 1, 16, spotfile) != 16)
  145.     pm_error ("EOF / read error reading header");
  146.  
  147.                 /* Determine mono or colour */
  148.   if (header.description[0] == 'X' && header.description[9] == 'S')
  149.     Colbool = 1;
  150.   else Colbool = 0;
  151.  
  152. #ifdef DEBUG
  153.   fprintf(stderr, "Dummy str is >%s<\n", header.dummy1);
  154.   fprintf(stderr, "Imghdr str is >%s<, col %d\n", header.description, Colbool);
  155. #endif
  156.                 /* Return the amount to fseek */
  157.   return (length - 56);
  158. }
  159.  
  160. usage()
  161. {
  162.   fprintf(stderr,
  163. "Usage: spottopgm [-1|2|3] [Firstcol Firstline Lastcol Lastline] input_file\n");
  164.   exit(1);
  165. }
  166.  
  167. int
  168. main(argc, argv)
  169.   int argc;
  170.   char *argv[];
  171.  
  172. {
  173.   struct Record                /* A SPOT image is broken up into */
  174.   {                    /* records with the following fields */
  175.     long record;            /* The record number (1, 2, 3...) */
  176.     unsigned char sub1;            /* Record sub type 1 */
  177.     unsigned char type;            /* The record type */
  178.     unsigned char sub2;            /* Record sub type 2 */
  179.     unsigned char sub3;            /* Record sub type 3 */
  180.     long length;            /* Record length in bytes */
  181.   } arecord;
  182.  
  183.   pgm_init( &argc, argv );
  184.    
  185.   switch (argc)
  186.   {
  187.     case 7:
  188.       Color= -(atoi(argv[1]));        /* Get the color to extract */
  189.       argv++;
  190.     case 6:
  191.       Firstcol = atoi(argv[1]);        /* Get the rectangle to extract */
  192.       Firstline = atoi(argv[2]);
  193.       Lastcol = atoi(argv[3]);
  194.       Lastline = atoi(argv[4]);
  195.       argv += 4;
  196.       goto openfile;            /* Yuk, a goto! */
  197.     case 3:
  198.       Color= -(atoi(argv[1]));        /* Get the color to extract */
  199.       argv++;
  200.     case 2:
  201. openfile:
  202.       spotfile = fopen(argv[1], "r");    /* Open the input file */
  203.       if (spotfile == NULL) { perror("fopen"); exit(1); }
  204.       break;
  205.     default:
  206.       usage();
  207.   }
  208.  
  209. #if defined (atarist) && defined (__MBASE__)
  210.   linebuf = (char *) pm_allocrow (12000, sizeof (char));
  211. #endif
  212.  
  213.   while (1)                /* Get a record */
  214.   {
  215.     if (pm_readbiglong (spotfile, &arecord.record) == -1)
  216.       break;
  217.     arecord.sub1 = fgetc (spotfile);
  218.     arecord.type = fgetc (spotfile);
  219.     arecord.sub2 = fgetc (spotfile);
  220.     arecord.sub3 = fgetc (spotfile);
  221.     if (pm_readbiglong (spotfile, &arecord.length) == -1)
  222.       pm_error ("EOF / read error reading a record");
  223.  
  224.     arecord.length -= 12;    /* Subtract header size as well */
  225.     if (arecord.type == 0355 && arecord.sub1 == 0355)
  226.       arecord.length = get_image(arecord.length);
  227.     else if (arecord.type == 0300 && arecord.sub1 == 077)
  228.       arecord.length = get_imghdr(arecord.length);
  229. #ifdef DEBUG
  230.     else
  231.       fprintf(stderr, "Rcrd %3d, type %03o, stype %03o %03o %03o, length %d\n",
  232.           arecord.record, arecord.type, arecord.sub1, arecord.sub2,
  233.           (int) arecord.sub3 & 0xff, arecord.length);
  234. #endif
  235.                 /* Seek to next record */
  236.     fseek(spotfile, arecord.length, 1);
  237.   }
  238.   exit (0);
  239. }
  240.