diff options
Diffstat (limited to 'converter/pbm/pbmtogo.c')
-rw-r--r-- | converter/pbm/pbmtogo.c | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/converter/pbm/pbmtogo.c b/converter/pbm/pbmtogo.c new file mode 100644 index 00000000..b7c12373 --- /dev/null +++ b/converter/pbm/pbmtogo.c @@ -0,0 +1,309 @@ +/* pbmtogo.c - read a PBM image and produce a GraphOn terminal raster file +** +** Rev 1.1 was based on pbmtolj.c +** +** Bo Thide', Swedish Institute of Space Physics, bt@irfu.se +** +** +** $Log: pbmtogo.c,v $ + * Revision 1.5 89/11/25 00:24:12 00:24:12 root (Bo Thide) + * Bug found: The byte after 64 repeated bytes sometimes lost. Fixed. + * + * Revision 1.4 89/11/24 14:56:04 14:56:04 root (Bo Thide) + * Fixed the command line parsing since pbmtogo now always uses 2D + * compression. Added a few comments to the source. + * + * Revision 1.3 89/11/24 13:43:43 13:43:43 root (Bo Thide) + * Added capability for > 63 repeated bytes and > 62 repeated lines in + * the 2D compression scheme. + * + * Revision 1.2 89/11/15 01:04:47 01:04:47 root (Bo Thide) + * First version that works reasonably well with GraphOn 2D runlength + * encoding/compression. + * + * Revision 1.1 89/11/02 23:25:25 23:25:25 root (Bo Thide) + * Initial revision + * +** +** Copyright (C) 1988, 1989 by Jef Poskanzer, Michael Haberler, and Bo Thide'. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + +#include <stdio.h> +#include <string.h> + +#include "pm_c_util.h" +#include "pbm.h" + +#define BUFSIZE 132 /* GraphOn has 132 byte/1056 bit wide raster lines */ +#define REPEAT_CURRENT_LINE_MASK 0x00 +#define SKIP_AND_PLOT_MASK 0x40 +#define REPEAT_PLOT_MASK 0x80 +#define PLOT_ARBITRARY_DATA_MASK 0xc0 +#define MAX_REPEAT 64 + +static unsigned char *scanlineptr; /* Pointer to current scan line byte */ + +static void putinit ARGS(( void )); +static void putbit ARGS(( bit b )); +static void putrest ARGS(( void )); +static void putitem ARGS(( void )); + +int +main( argc, argv ) + int argc; + char* argv[]; +{ + FILE* ifp; + bit* bitrow; + register bit* bP; + int argn, rows, cols, format, rucols, padright, row, col; + int nbyte, bytesperrow, ecount, ucount, nout, i, linerepeat; + int olditem; + unsigned char oldscanline[BUFSIZE]; + unsigned char newscanline[BUFSIZE]; + unsigned char diff[BUFSIZE]; + unsigned char buffer[BUFSIZE]; + unsigned char outbuffer[2*(BUFSIZE+1)]; /* Worst case. Should malloc */ + const char* usage = "[-c] [pbmfile]"; + + + pbm_init( &argc, argv ); + + argn = 2; + + /* Check for flags. */ + if (argc > argn + 1) + pm_usage(usage); + + if (argc == argn) + ifp = pm_openr( argv[argn-1] ); + else + ifp = stdin; + + pbm_readpbminit(ifp, &cols, &rows, &format); + bitrow = pbm_allocrow(cols); + + /* Round cols up to the nearest multiple of 8. */ + rucols = ( cols + 7 ) / 8; + bytesperrow = rucols; /* GraphOn uses bytes */ + rucols = rucols * 8; + padright = rucols - cols; + + for (i = 0; i < BUFSIZE; ++i ) + buffer[i] = 0; + putinit(); + + /* Start donwloading screen raster */ + printf("\033P0;1;0;4;1;%d;%d;1!R1/", rows, rucols); + + linerepeat = 63; /* 63 means "Start new picture" */ + nout = 0; /* To prevent compiler warning */ + for (row = 0; row < rows; row++) { + /* Store scan line data in the new scan line vector */ + scanlineptr = newscanline; + pbm_readpbmrow(ifp, bitrow, cols, format); + /* Transfer raster graphics */ + for (col = 0, bP = bitrow; col < cols; col++, bP++) + putbit(*bP); + for (col = 0; col < padright; col++) + putbit(0); + + /* XOR data from the new scan line with data from old scan line */ + for (i = 0; i < bytesperrow; i++) + diff[i] = oldscanline[i]^newscanline[i]; + + /* + ** If the difference map is different from current internal buffer, + ** encode the difference and put it in the output buffer. + ** Else, increase the counter for the current buffer by one. + */ + + if ((memcmp(buffer, diff, bytesperrow) != 0) || (row == 0)) { + /* + **Since the data in the buffer has changed, send the + **scan line repeat count to cause the old line(s) to + **be plotted on the screen, copy the new data into + **the internal buffer, and reset the counters. + */ + + putchar(linerepeat); + for (i = 0; i < bytesperrow; ++i) + buffer[i] = diff[i]; + nbyte = 0; /* Internal buffer byte counter */ + nout = 0; /* Output buffer byte counter */ + + /* Run length encode the new internal buffr (= difference map) */ + while (TRUE) { + ucount = 0; /* Unique items counter */ + do /* Find unique patterns */ + { + olditem = buffer[nbyte++]; + ucount++; + } while ((olditem != buffer[nbyte]) + && (ucount < MIN(bytesperrow, MAX_REPEAT))); + + if ((ucount != MAX_REPEAT) && (nbyte != bytesperrow)) { + /* Back up to the last truly unique pattern */ + ucount--; + nbyte--; + } + + if (ucount > 0) { + /* Output the unique patterns */ + outbuffer[nout++] = + (ucount-1) | PLOT_ARBITRARY_DATA_MASK; + for (i = nbyte-ucount; i < nbyte; i++) + outbuffer[nout++] = buffer[i]; + } + + /* + ** If we already are at the end of the current scan + ** line, skip the rest of the encoding and start + ** with a new scan line. + */ + + if (nbyte >= bytesperrow) + goto nextrow; + + ecount = 0; /* Equal items counter */ + do /* Find equal patterns */ + { + olditem = buffer[nbyte++]; + ecount++; + } while ((olditem == buffer[nbyte]) + && (ecount < MIN(bytesperrow, MAX_REPEAT))); + + if (ecount > 1) { + /* More than 1 equal pattern */ + if (olditem == '\0') { + /* White patterns */ + if (nbyte >= bytesperrow-1) { + /* No more valid data ahead */ + outbuffer[nout++] = + (ecount-2) | SKIP_AND_PLOT_MASK; + outbuffer[nout++] = buffer[nbyte-1]; + } + else { + /* More valid data ahead */ + outbuffer[nout++] = + (ecount-1) | SKIP_AND_PLOT_MASK; + outbuffer[nout++] = buffer[nbyte++]; + } + } + else { + /* Non-white patterns */ + outbuffer[nout++] = (ecount-1) | REPEAT_PLOT_MASK; + outbuffer[nout++] = olditem; + } /* if (olditem == '\0') */ + } /* if (ecount > 1) */ + else + nbyte--; /* No equal items found */ + + if (nbyte >= bytesperrow) + goto nextrow; + } /* while (TRUE) */ + + nextrow: printf("%d/", nout+1); /* Total bytes to xfer = nout+1 */ + fflush(stdout); + + /* Output the plot data */ + write(1, outbuffer, nout); + + /* Reset the counters */ + linerepeat = 0; + } else { + linerepeat++; + if (linerepeat == 62) /* 62 lines max, then restart */ + { + putchar(linerepeat); + printf("%d/", nout+1); + fflush(stdout); + write(1, outbuffer, nout); + linerepeat = 0; + } + } + + /* Now we are ready for a new scan line */ + for (i = 0; i < bytesperrow; ++i) + oldscanline[i] = newscanline[i]; + } + putchar(linerepeat); /* For the last line(s) to be plotted */ + pm_close(ifp); + putrest(); + exit(0); +} + + + +static int item, bitsperitem, bitshift; + +static void +putinit() +{ + /* Enter graphics window */ + printf("\0331"); + + /* Erase graphics window */ + printf("\033\014"); + + /* Set graphics window in raster mode */ + printf("\033r"); + + /* Select standard Tek coding **/ + printf("\033[=11l"); + + bitsperitem = 1; + item = 0; + bitshift = 7; +} + +#if __STDC__ +static void +putbit(bit b) +#else /*__STDC__*/ +static void +putbit(b) +bit b; +#endif /*__STDC__*/ +{ + if (b == PBM_BLACK) + item += 1 << bitshift; + bitshift--; + if (bitsperitem == 8) + { + putitem(); + bitshift = 7; + } + bitsperitem++; +} + +static void +putrest() +{ + if (bitsperitem > 1) + putitem(); + + /* end raster downloading */ + printf("\033\134"); + + /* Exit raster mode */ + printf("\033t"); + + /* Exit graphics window + printf("\0332"); */ +} + +static void +putitem() + { + *scanlineptr++ = item; + bitsperitem = 0; + item = 0; + } |