about summary refs log tree commit diff
path: root/converter/pbm/pbmtogo.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/pbm/pbmtogo.c')
-rw-r--r--converter/pbm/pbmtogo.c309
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;
+  }