home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / pbm / pbmtogem.c < prev    next >
C/C++ Source or Header  |  1994-02-14  |  6KB  |  252 lines

  1. /* pbmtogem.c - read a portable bitmap and produce a GEM .img file
  2. **
  3. ** Author: David Beckemeyer (bdt!david)
  4. **
  5. ** Much of the code for this program was taken from other
  6. ** pbmto* programs.  I just modified the code to produce
  7. ** a .img header and generate .img "Bit Strings".
  8. **
  9. ** Thanks to Diomidis D. Spinellis for the .img header format.
  10. **
  11. ** Copyright (C) 1988 by David Beckemeyer (bdt!david) and Jef Poskanzer.
  12. **
  13. ** Modified by Johann Haider to produce Atari ST compatible files
  14. **
  15. ** Permission to use, copy, modify, and distribute this software and its
  16. ** documentation for any purpose and without fee is hereby granted, provided
  17. ** that the above copyright notice appear in all copies and that both that
  18. ** copyright notice and this permission notice appear in supporting
  19. ** documentation.  This software is provided "as is" without express or
  20. ** implied warranty.
  21. */
  22. /*
  23. *  92/07/11 jh
  24. *
  25. *  Changes made to this program:
  26. *  changed header length to count words to conform with Atari ST documentation
  27. *  removed rounding of the imagewidth to the next word boundary
  28. *  removed arbitrary limit to imagewidth
  29. *  changed pattern length to 1 to simplify locating of compressable parts
  30. *    in real world images
  31. *  add solid run and pattern run compression
  32. *
  33. *  Deficiencies:
  34. *  Compression of repeated scanlines not added
  35. *  
  36. *    Johann Haider (jh@fortec.tuwien.ac.at)
  37. *
  38. * 94/01/31 Andreas Schwab (schwab@ls5.informatik.uni-dortmund.de)
  39. * Changed to remove architecture dependencies
  40. * Added compression of repeated scanlines
  41. */
  42.  
  43. #include <stdio.h>
  44. #include "pbm.h"
  45.  
  46. #define SOLID_0 0
  47. #define SOLID_1 0xff
  48. #define MINRUN 4
  49. #define putsolid(v,c) putc((v&0x80)|c, stdout)
  50. #define putpattern(v,c) putc(0, stdout);putc(c, stdout);putc(v, stdout)
  51.  
  52. static void putinit ARGS ((int rows, int cols));
  53. static void putbit ARGS(( bit b ));
  54. static void putitem ARGS(( void ));
  55. static void putrow ARGS(( void ));
  56. static void flushrow ARGS ((void));
  57. static void putstring ARGS((register char *p, register int n));
  58.  
  59. int
  60. main( argc, argv )
  61.     int argc;
  62.     char* argv[];
  63.     {
  64.     FILE* ifp;
  65.     bit* bitrow;
  66.     register bit* bP;
  67.     int rows, cols, format, row, col;
  68.  
  69.     pbm_init( &argc, argv );
  70.  
  71.     if ( argc > 2 )
  72.     pm_usage( "[pbmfile]" );
  73.  
  74.     if ( argc == 2 )
  75.     ifp = pm_openr( argv[1] );
  76.     else
  77.     ifp = stdin;
  78.  
  79.     pbm_readpbminit( ifp, &cols, &rows, &format );
  80.  
  81.     bitrow = pbm_allocrow( cols );
  82.  
  83.     putinit (rows, cols);
  84.     for ( row = 0; row < rows; ++row )
  85.     {
  86. #ifdef DEBUG
  87.     fprintf (stderr, "row %d\n", row);
  88. #endif
  89.     pbm_readpbmrow( ifp, bitrow, cols, format );
  90.         for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
  91.         putbit( *bP );
  92.         putrow( );
  93.         }
  94.     flushrow ();
  95.  
  96.     pm_close( ifp );
  97.  
  98.  
  99.     exit( 0 );
  100.     }
  101.  
  102. static short item;
  103. static int outcol, outmax;
  104. static short bitsperitem, bitshift;
  105. static short linerepeat;
  106. static unsigned char *outrow, *lastrow;
  107.  
  108. static void
  109. putinit (rows, cols)
  110.      int rows, cols;
  111. {
  112.   if (pm_writebigshort (stdout, (short) 1) == -1 /* Image file version */
  113.       || pm_writebigshort (stdout, (short) 8) == -1 /* Header length */
  114.       || pm_writebigshort (stdout, (short) 1) == -1 /* Number of planes */
  115.       || pm_writebigshort (stdout, (short) 1) == -1 /* Pattern length */
  116.       || pm_writebigshort (stdout, (short) 372) == -1 /* Pixel width */
  117.       || pm_writebigshort (stdout, (short) 372) == -1 /* Pixel height */
  118.       || pm_writebigshort (stdout, (short) cols) == -1
  119.       || pm_writebigshort (stdout, (short) rows) == -1)
  120.     pm_error ("write error");
  121.   item = 0;
  122.   bitsperitem = 0;
  123.   bitshift = 7;
  124.   outcol = 0;
  125.   outmax = (cols + 7) / 8;
  126.   outrow = (unsigned char *) pm_allocrow (outmax, sizeof (unsigned char));
  127.   lastrow = (unsigned char *) pm_allocrow (outmax, sizeof (unsigned char));
  128.   linerepeat = -1;
  129. }
  130.  
  131. #if __STDC__
  132. static void
  133. putbit( bit b )
  134. #else /*__STDC__*/
  135. static void
  136. putbit( b )
  137.     bit b;
  138. #endif /*__STDC__*/
  139.     {
  140.     if ( bitsperitem == 8 )
  141.     putitem( );
  142.     ++bitsperitem;
  143.     if ( b == PBM_BLACK )
  144.     item += 1 << bitshift;
  145.     --bitshift;
  146.     }
  147.  
  148. static void
  149. putitem( )
  150.     {
  151.     outrow[outcol++] = item;
  152.     item = 0;
  153.     bitsperitem = 0;
  154.     bitshift = 7;
  155.     }
  156.  
  157. static void
  158. putstring (p, n)
  159. register char *p;
  160. register int n;
  161. {
  162. #ifdef DEBUG
  163.     fprintf (stderr, "Bitstring, length: %d, pos %d\n", n, outcol);
  164. #endif
  165.     (void) putc(0x80, stdout);        /* a Bit string */
  166.     (void) putc(n, stdout);    /* count */
  167.     fwrite( p, n, 1, stdout );
  168. }
  169.  
  170. static void
  171. putrow( )
  172. {
  173.   if (bitsperitem > 0)
  174.     putitem ();
  175.   outcol = 0;
  176.   if (linerepeat == -1 || linerepeat == 255
  177.       || bcmp (outrow, lastrow, outmax) != 0)
  178.     {
  179.       unsigned char *temp;
  180.       if (linerepeat != -1) /* Unless first line */
  181.     flushrow ();
  182.       /* Swap the pointers */
  183.       temp = outrow; outrow = lastrow; lastrow = temp;
  184.       linerepeat = 1;
  185.     }
  186.   else
  187.     /* Repeated line */
  188.     linerepeat++;
  189. }
  190.  
  191. static void
  192. flushrow( )
  193.     {
  194.     register unsigned char *outp, *p, *q;
  195.     register int count;
  196.     int col = outmax;
  197.  
  198.     if (linerepeat > 1)
  199.       {
  200.     /* Put out line repeat count */
  201.     fwrite ("\0\0\377", 3, 1, stdout);
  202.     putchar (linerepeat);
  203.       }
  204.     for (outp = p = lastrow; col > 0;)
  205.     {
  206.         for (q = p, count=0; (count < col) && (*q == *p); q++,count++);
  207.         if (count > MINRUN)
  208.         {
  209.         if (p > outp)
  210.         {
  211.             putstring (outp, p-outp);
  212.             outp = p;
  213.         }
  214.         col -= count;
  215.         switch (*p)
  216.         {
  217.         case SOLID_0:
  218. #ifdef DEBUG
  219. /*            if (outcol > 0) */
  220.             fprintf (stderr, "Solid run 0, length: %d\n", count);
  221. #endif
  222.             putsolid (SOLID_0, count);
  223.             break;
  224.  
  225.         case SOLID_1:
  226. #ifdef DEBUG
  227.             fprintf (stderr, "Solid run 1, length: %d, pos %d\n", count, outcol);
  228. #endif
  229.             putsolid (SOLID_1, count);
  230.             break;
  231.         default:
  232. #ifdef DEBUG
  233.             fprintf (stderr, "Pattern run, length: %d\n", count);
  234. #endif
  235.             putpattern (*p, count);
  236.             break;
  237.         }
  238.         outp = p = q;
  239.         }
  240.         else
  241.         {
  242.         p++;
  243.         col--;
  244.         }
  245.     }        
  246.     if (p > outp)
  247.          putstring (outp, p-outp);
  248.     if (ferror (stdout))
  249.       pm_error ("write error");
  250. }
  251.  
  252.