about summary refs log tree commit diff
path: root/converter/pbm/pbmtogem.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/pbm/pbmtogem.c')
-rw-r--r--converter/pbm/pbmtogem.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/converter/pbm/pbmtogem.c b/converter/pbm/pbmtogem.c
new file mode 100644
index 00000000..59f2b9cf
--- /dev/null
+++ b/converter/pbm/pbmtogem.c
@@ -0,0 +1,252 @@
+/* pbmtogem.c - read a portable bitmap and produce a GEM .img file
+**
+** Author: David Beckemeyer (bdt!david)
+**
+** Much of the code for this program was taken from other
+** pbmto* programs.  I just modified the code to produce
+** a .img header and generate .img "Bit Strings".
+**
+** Thanks to Diomidis D. Spinellis for the .img header format.
+**
+** Copyright (C) 1988 by David Beckemeyer (bdt!david) and Jef Poskanzer.
+**
+** Modified by Johann Haider to produce Atari ST compatible files
+**
+** 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.
+*/
+/*
+*  92/07/11 jh
+*
+*  Changes made to this program:
+*  changed header length to count words to conform with Atari ST documentation
+*  removed rounding of the imagewidth to the next word boundary
+*  removed arbitrary limit to imagewidth
+*  changed pattern length to 1 to simplify locating of compressable parts
+*	in real world images
+*  add solid run and pattern run compression
+*
+*  Deficiencies:
+*  Compression of repeated scanlines not added
+*  
+*	Johann Haider (jh@fortec.tuwien.ac.at)
+*
+* 94/01/31 Andreas Schwab (schwab@ls5.informatik.uni-dortmund.de)
+* Changed to remove architecture dependencies
+* Added compression of repeated scanlines
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include "pbm.h"
+
+#define SOLID_0 0
+#define SOLID_1 0xff
+#define MINRUN 4
+#define putsolid(v,c) putc((v&0x80)|c, stdout)
+#define putpattern(v,c) putc(0, stdout);putc(c, stdout);putc(v, stdout)
+
+static void putinit ARGS ((int rows, int cols));
+static void putbit ARGS(( bit b ));
+static void putitem ARGS(( void ));
+static void putrow ARGS(( void ));
+static void flushrow ARGS ((void));
+static void putstring ARGS((register unsigned char *p, register int n));
+
+int
+main( argc, argv )
+    int argc;
+    char* argv[];
+    {
+    FILE* ifp;
+    bit* bitrow;
+    register bit* bP;
+    int rows, cols, format, row, col;
+
+    pbm_init( &argc, argv );
+
+    if ( argc > 2 )
+	pm_usage( "[pbmfile]" );
+
+    if ( argc == 2 )
+	ifp = pm_openr( argv[1] );
+    else
+	ifp = stdin;
+
+    pbm_readpbminit( ifp, &cols, &rows, &format );
+
+    bitrow = pbm_allocrow( cols );
+
+    putinit (rows, cols);
+    for ( row = 0; row < rows; ++row )
+	{
+#ifdef DEBUG
+	fprintf (stderr, "row %d\n", row);
+#endif
+	pbm_readpbmrow( ifp, bitrow, cols, format );
+        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
+	    putbit( *bP );
+        putrow( );
+        }
+    flushrow ();
+
+    pm_close( ifp );
+
+
+    exit( 0 );
+    }
+
+static short item;
+static int outcol, outmax;
+static short bitsperitem, bitshift;
+static short linerepeat;
+static unsigned char *outrow, *lastrow;
+
+static void
+putinit (rows, cols)
+     int rows, cols;
+{
+  if (pm_writebigshort (stdout, (short) 1) == -1 /* Image file version */
+      || pm_writebigshort (stdout, (short) 8) == -1 /* Header length */
+      || pm_writebigshort (stdout, (short) 1) == -1 /* Number of planes */
+      || pm_writebigshort (stdout, (short) 1) == -1 /* Pattern length */
+      || pm_writebigshort (stdout, (short) 372) == -1 /* Pixel width */
+      || pm_writebigshort (stdout, (short) 372) == -1 /* Pixel height */
+      || pm_writebigshort (stdout, (short) cols) == -1
+      || pm_writebigshort (stdout, (short) rows) == -1)
+    pm_error ("write error");
+  item = 0;
+  bitsperitem = 0;
+  bitshift = 7;
+  outcol = 0;
+  outmax = (cols + 7) / 8;
+  outrow = (unsigned char *) pm_allocrow (outmax, sizeof (unsigned char));
+  lastrow = (unsigned char *) pm_allocrow (outmax, sizeof (unsigned char));
+  linerepeat = -1;
+}
+
+#if __STDC__
+static void
+putbit( bit b )
+#else /*__STDC__*/
+static void
+putbit( b )
+    bit b;
+#endif /*__STDC__*/
+    {
+    if ( bitsperitem == 8 )
+	putitem( );
+    ++bitsperitem;
+    if ( b == PBM_BLACK )
+	item += 1 << bitshift;
+    --bitshift;
+    }
+
+static void
+putitem( )
+    {
+    outrow[outcol++] = item;
+    item = 0;
+    bitsperitem = 0;
+    bitshift = 7;
+    }
+
+static void
+putstring (p, n)
+register unsigned char *p;
+register int n;
+{
+#ifdef DEBUG
+    fprintf (stderr, "Bitstring, length: %d, pos %d\n", n, outcol);
+#endif
+    (void) putc((char) 0x80, stdout);     /* a Bit string */
+    (void) putc(n, stdout);	/* count */
+    fwrite( p, n, 1, stdout );
+}
+
+static void
+putrow( )
+{
+  if (bitsperitem > 0)
+    putitem ();
+  outcol = 0;
+  if (linerepeat == -1 || linerepeat == 255
+      || memcmp (outrow, lastrow, outmax) != 0)
+    {
+      unsigned char *temp;
+      if (linerepeat != -1) /* Unless first line */
+	flushrow ();
+      /* Swap the pointers */
+      temp = outrow; outrow = lastrow; lastrow = temp;
+      linerepeat = 1;
+    }
+  else
+    /* Repeated line */
+    linerepeat++;
+}
+
+static void
+flushrow( )
+    {
+    register unsigned char *outp, *p, *q;
+    register int count;
+    int col = outmax;
+
+    if (linerepeat > 1)
+      {
+	/* Put out line repeat count */
+	fwrite ("\0\0\377", 3, 1, stdout);
+	putchar (linerepeat);
+      }
+    for (outp = p = lastrow; col > 0;)
+    {
+	    for (q = p, count=0; (count < col) && (*q == *p); q++,count++);
+	    if (count > MINRUN)
+	    {
+		if (p > outp)
+		{
+		    putstring (outp, p-outp);
+		    outp = p;
+		}
+		col -= count;
+		switch (*p)
+		{
+		case SOLID_0:
+#ifdef DEBUG
+/*			if (outcol > 0) */
+			fprintf (stderr, "Solid run 0, length: %d\n", count);
+#endif
+			putsolid (SOLID_0, count);
+			break;
+
+		case SOLID_1:
+#ifdef DEBUG
+			fprintf (stderr, "Solid run 1, length: %d, pos %d\n", count, outcol);
+#endif
+			putsolid (SOLID_1, count);
+			break;
+		default:
+#ifdef DEBUG
+			fprintf (stderr, "Pattern run, length: %d\n", count);
+#endif
+			putpattern (*p, count);
+			break;
+		}
+		outp = p = q;
+	    }
+	    else
+	    {
+		p++;
+		col--;
+	    }
+    }		
+    if (p > outp)
+         putstring (outp, p-outp);
+    if (ferror (stdout))
+      pm_error ("write error");
+}
+