home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / pbm / pbmtogo.c < prev    next >
C/C++ Source or Header  |  1993-10-04  |  8KB  |  304 lines

  1. /* pbmtogo.c - read a portable bitmap and produce a GraphOn terminal raster file
  2. **    
  3. **    Rev 1.1 was based on pbmtolj.c
  4. **
  5. **    Bo Thide', Swedish Institute of Space Physics, bt@irfu.se
  6. **                   
  7. **
  8. ** $Log:    pbmtogo.c,v $
  9.  * Revision 1.5  89/11/25  00:24:12  00:24:12  root (Bo Thide)
  10.  * Bug found: The byte after 64 repeated bytes sometimes lost. Fixed.
  11.  * 
  12.  * Revision 1.4  89/11/24  14:56:04  14:56:04  root (Bo Thide)
  13.  * Fixed the command line parsing since pbmtogo now always uses 2D
  14.  * compression.  Added a few comments to the source.
  15.  * 
  16.  * Revision 1.3  89/11/24  13:43:43  13:43:43  root (Bo Thide)
  17.  * Added support for > 63 repeated bytes and > 62 repeated lines in
  18.  * the 2D compression scheme.
  19.  * 
  20.  * Revision 1.2  89/11/15  01:04:47  01:04:47  root (Bo Thide)
  21.  * First version that works reasonably well with GraphOn 2D runlength
  22.  * encoding/compression.
  23.  * 
  24.  * Revision 1.1  89/11/02  23:25:25  23:25:25  root (Bo Thide)
  25.  * Initial revision
  26.  * 
  27. **
  28. ** Copyright (C) 1988, 1989 by Jef Poskanzer, Michael Haberler, and Bo Thide'.
  29. **
  30. ** Permission to use, copy, modify, and distribute this software and its
  31. ** documentation for any purpose and without fee is hereby granted, provided
  32. ** that the above copyright notice appear in all copies and that both that
  33. ** copyright notice and this permission notice appear in supporting
  34. ** documentation.  This software is provided "as is" without express or
  35. ** implied warranty.
  36. */
  37.  
  38. #include <stdio.h>
  39. #include "pbm.h"
  40.  
  41. #define TRUE 1
  42. #define BUFSIZE 132    /* GraphOn has 132 byte/1056 bit wide raster lines */
  43. #define REPEAT_CURRENT_LINE_MASK    0x00 
  44. #define SKIP_AND_PLOT_MASK        0x40 
  45. #define REPEAT_PLOT_MASK        0x80 
  46. #define PLOT_ARBITRARY_DATA_MASK    0xc0 
  47. #define MAX_REPEAT 64
  48.  
  49. static unsigned char *scanlineptr;        /* Pointer to current scan line byte */
  50.  
  51. static void putinit ARGS(( void ));
  52. static void putbit ARGS(( bit b ));
  53. static void putrest ARGS(( void ));
  54. static void putitem ARGS(( void ));
  55.  
  56. int
  57. main( argc, argv )
  58.     int argc;
  59.     char* argv[];
  60.     {
  61.     FILE* ifp;
  62.     bit* bitrow;
  63.     register bit* bP;
  64.     int argn, rows, cols, format, rucols, padright, row, col;
  65.     int nbyte, bytesperrow, ecount, ucount, nout, i, linerepeat;
  66.     int    olditem;
  67.     unsigned char oldscanline[BUFSIZE];
  68.     unsigned char newscanline[BUFSIZE];
  69.     unsigned char diff[BUFSIZE];
  70.     unsigned char buffer[BUFSIZE];
  71.     unsigned char outbuffer[2*(BUFSIZE+1)];    /* Worst case.  Should malloc */
  72.     char* usage = "[-c] [pbmfile]";
  73.  
  74.  
  75.     pbm_init( &argc, argv );
  76.  
  77.     argn = 2;
  78.  
  79.     /* Check for flags. */
  80.     if (argc > argn + 1)
  81.     pm_usage(usage);
  82.  
  83.     if (argc == argn)
  84.     ifp = pm_openr( argv[argn-1] );
  85.     else
  86.     ifp = stdin;
  87.  
  88.     pbm_readpbminit(ifp, &cols, &rows, &format);
  89.     bitrow = pbm_allocrow(cols);
  90.  
  91.     /* Round cols up to the nearest multiple of 8. */
  92.     rucols = ( cols + 7 ) / 8;
  93.     bytesperrow = rucols;            /* GraphOn uses bytes */
  94.     rucols = rucols * 8;
  95.     padright = rucols - cols;
  96.  
  97.     for (i = 0; i < BUFSIZE; ++i )
  98.     buffer[i] = 0;
  99.     putinit();
  100.  
  101.     /* Start donwloading screen raster */
  102.     printf("\033P0;1;0;4;1;%d;%d;1!R1/", rows, rucols);
  103.  
  104.     linerepeat = 63;            /*  63 means "Start new picture" */
  105.     for (row = 0; row < rows; row++)
  106.     {
  107.       /* Store scan line data in the new scan line vector */
  108.       scanlineptr = newscanline;
  109.       pbm_readpbmrow(ifp, bitrow, cols, format);
  110.       /* Transfer raster graphics */
  111.       for (col = 0, bP = bitrow; col < cols; col++, bP++)
  112.     putbit(*bP);
  113.       for (col = 0; col < padright; col++)
  114.     putbit(0);
  115.       
  116.       /* XOR data from the new scan line with data from the old scan line */
  117.       for (i = 0; i < bytesperrow; i++)
  118.     diff[i] = oldscanline[i]^newscanline[i];
  119.  
  120.       /*
  121.       ** If the difference map is different from the current internal buffer,
  122.       ** encode the difference and put it in the output buffer. 
  123.       ** Else, increase the counter for the current buffer by one.
  124.       */
  125.  
  126.       if ((bcmp(buffer, diff, bytesperrow) != 0) || (row == 0))
  127.       {
  128.     /*
  129.     ** Since the data in the buffer has changed, send the scan line
  130.     ** repeat count to cause the old line(s) to be plotted on the screen,
  131.     ** copy the new data into the internal buffer, and reset the counters.
  132.     */
  133.     putchar(linerepeat);
  134.     for (i = 0; i < bytesperrow; ++i)
  135.         buffer[i] = diff[i];
  136.     nbyte = 0;            /* Internal buffer byte counter */
  137.     nout = 0;            /* Output buffer byte counter */
  138.  
  139.     /* Run length encode the new internal buffer (= difference map) */
  140.     while (TRUE)
  141.     {
  142.       ucount = 0;            /* Unique items counter */
  143.       do                /* Find unique patterns */
  144.       {
  145.         olditem = buffer[nbyte++];
  146.         ucount++;
  147.       } while ((olditem != buffer[nbyte])
  148.         && (ucount < min(bytesperrow, MAX_REPEAT)));
  149.  
  150.       if ((ucount != MAX_REPEAT) && (nbyte != bytesperrow))
  151.       {
  152.         /* Back up to the last truly unique pattern */
  153.         ucount--;
  154.         nbyte--;
  155.       }
  156.  
  157.       if (ucount > 0)        /* Output the unique patterns */
  158.       {
  159.         outbuffer[nout++] = (ucount-1) | PLOT_ARBITRARY_DATA_MASK;
  160.         for (i = nbyte-ucount; i < nbyte; i++)
  161.           outbuffer[nout++] = buffer[i];
  162.       }
  163.  
  164.       /*
  165.       ** If we already are at the end of the current scan line, skip the
  166.       ** rest of the encoding and start with a new scan line.
  167.       */
  168.       if (nbyte >= bytesperrow)
  169.         goto nextrow;
  170.  
  171.       ecount = 0;            /* Equal items counter */
  172.       do                /* Find equal patterns */
  173.       {
  174.         olditem = buffer[nbyte++];
  175.         ecount++;
  176.       } while ((olditem == buffer[nbyte])
  177.         && (ecount < min(bytesperrow, MAX_REPEAT)));
  178.  
  179.       if (ecount > 1)            /* More than 1 equal pattern */
  180.       {
  181.         if (olditem == '\0')        /* White patterns */
  182.         {
  183.           if (nbyte >= bytesperrow-1)    /* No more valid data ahead */
  184.           {
  185.         outbuffer[nout++] = (ecount-2) | SKIP_AND_PLOT_MASK;
  186.         outbuffer[nout++] = buffer[nbyte-1];
  187.           } 
  188.           else                /* More valid data ahead */
  189.           {
  190.         outbuffer[nout++] = (ecount-1) | SKIP_AND_PLOT_MASK;
  191.         outbuffer[nout++] = buffer[nbyte++];
  192.           } 
  193.         }
  194.         else                /* Non-white patterns */
  195.         {
  196.           outbuffer[nout++] = (ecount-1) | REPEAT_PLOT_MASK;
  197.           outbuffer[nout++] = olditem;
  198.         } /* if (olditem == '\0') */
  199.       } /* if (ecount > 1) */
  200.       else
  201.         nbyte--;                /* No equal items found */
  202.  
  203.       if (nbyte >= bytesperrow)
  204.         goto nextrow;
  205.     } /* while (TRUE) */
  206.  
  207. nextrow: printf("%d/", nout+1);        /* Total bytes to transfer = nout+1 */
  208.         fflush(stdout);
  209.  
  210.     /* Output the plot data */
  211.     write(1, outbuffer, nout);
  212.  
  213.     /* Reset the counters */
  214.     linerepeat = 0;
  215.     }
  216.     else
  217.     {
  218.       linerepeat++;
  219.       if (linerepeat == 62)        /* 62 lines max, then restart */
  220.       {
  221.     putchar(linerepeat);
  222.     printf("%d/", nout+1);
  223.     fflush(stdout);
  224.     write(1, outbuffer, nout);
  225.     linerepeat = 0;
  226.       }
  227.     }
  228.  
  229.     /* Now we are ready for a new scan line */
  230.     for (i = 0; i < bytesperrow; ++i)
  231.     oldscanline[i] = newscanline[i];
  232.   }
  233.   putchar(linerepeat);            /* For the last line(s) to be plotted */
  234.   pm_close(ifp);
  235.   putrest();
  236.   exit(0);
  237. }
  238.  
  239. static int item, bitsperitem, bitshift;
  240.  
  241. static void
  242. putinit()
  243. {
  244.   /* Enter graphics window */
  245.   printf("\0331");
  246.  
  247.   /* Erase graphics window */
  248.   printf("\033\014");
  249.  
  250.   /* Set graphics window in raster mode */
  251.   printf("\033r");
  252.  
  253.   /* Select standard Tek coding **/
  254.   printf("\033[=11l");
  255.  
  256.   bitsperitem = 1;
  257.   item = 0;
  258.   bitshift = 7;
  259. }
  260.  
  261. #if __STDC__
  262. static void
  263. putbit(bit b)
  264. #else /*__STDC__*/
  265. static void
  266. putbit(b)
  267. bit b;
  268. #endif /*__STDC__*/
  269. {
  270.   if (b == PBM_BLACK)
  271.     item += 1 << bitshift;
  272.   bitshift--;
  273.   if (bitsperitem == 8)
  274.   {
  275.     putitem();
  276.     bitshift = 7;
  277.   }
  278.   bitsperitem++;
  279. }
  280.  
  281. static void
  282. putrest()
  283. {
  284.   if (bitsperitem > 1)
  285.       putitem();
  286.  
  287.   /* end raster downloading */
  288.   printf("\033\134");
  289.  
  290.   /* Exit raster mode */
  291.   printf("\033t");
  292.  
  293.   /* Exit graphics window
  294.   printf("\0332"); */
  295. }
  296.  
  297. static void
  298. putitem()
  299.   {
  300.   *scanlineptr++ = item;
  301.   bitsperitem = 0;
  302.   item = 0;
  303.   }
  304.