home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3322 < prev    next >
Encoding:
Internet Message Format  |  1991-05-12  |  10.8 KB

  1. From: rpvinci@leland.Stanford.EDU (Richard Vinci)
  2. Newsgroups: alt.sources,alt.graphics.pixutils,comp.graphics
  3. Subject: ppmtosixel converter and man page
  4. Message-ID: <1991May11.185202.7354@leland.Stanford.EDU>
  5. Date: 11 May 91 18:52:02 GMT
  6.  
  7. This is a no-frills converter from ppm format to color sixel format (i.e. for a
  8. DEC LJ250 color inkjet printer). It requires code from Jef Poskanzer's PBMPlus
  9. utilities to compile. This software is provided "as is" without express or
  10. implied warranty. If you find a bug or have an improvement (and boy, is there
  11. room for that!) please let me know (rpvinci@leland.stanford.edu).
  12.  
  13. -------- CUT HERE FOR README --------
  14. This is a no-frills converter from ppm format to color sixel format (i.e. for a
  15. DEC LJ250 color inkjet printer). It requires code from Jef Poskanzer's PBMPlus
  16. utilities to compile. This software is provided "as is" without express or
  17. implied warranty. If you find a bug or have an improvement (and boy, is there
  18. room for that!) please let me know (rpvinci@leland.stanford.edu).
  19.  
  20. There are three segments of this posting that must be separated into individual
  21. files: (1) this README, (2) ppmtosix.1, the man page for the converter, and 
  22. (3) ppmtosix.c itself.
  23.  
  24. Compile ppmtosix.c by moving it to the pbmplus/ppm source directory and enter
  25. the appropriately altered line from the ppm Makefile. On my DECstation 3100, 
  26. I use: 
  27.  
  28. gcc -fcombine-regs -fpcc-struct-return -O -s -DRGB_DB=\"/usr/lib/X11/rgb.txt\"
  29.  -o ppmtosix ppmtosix.c -lm libppm.a ../pgm/libpgm.a ../pbm/libpbm.a -I../pgm
  30.  -I../pbm
  31.  
  32. This is set up so that ppmtosix can be easily bundled as part of the ppm
  33. utilities.
  34.  
  35. Copy ppmtosix.1 to the appropriate man directory (e.g. /usr/man/man1).
  36.  
  37. The man page is fairly explicit about the operation and limitations of ppmtosix
  38. and I won't repeat it here. I will point out, however, that my LJ250 printer
  39. does not really match my screen colors very well, even with the same RGB
  40. values. I guess I could make up my own color map, but you'd think that
  41. following the DEC recommended color map would do the trick.... 
  42. Suggestions are welcome.
  43.  
  44. -------- CUT HERE FOR PPMTOSIX.1 --------
  45. .TH ppmtosix 1 "26 April 1991"
  46. .SH NAME
  47. ppmtosix - convert a portable pixmap into a sixel format
  48. .SH SYNOPSIS
  49. .B ppmtosix
  50. .RB [ -raw ] [-margin]
  51. .RI [ ppmfile ]
  52. .SH DESCRIPTION
  53. Reads a portable pixmap as input. Produces sixel commands (SIX) as output. The output is formatted for color printing (i.e. for a DEC LJ250 color inkjet printer). 
  54. .PP
  55. If RGB values from the PPM file do not have maxval=100, the RGB values are rescaled. A printer control header and a color assignment table begin the SIX file. Image data is written in a compressed format by default. A printer control footer ends the image file.
  56. .SH OPTIONS
  57. .TP
  58. .B -raw
  59. If specified, each pixel will be explicitly described in the image file.  If
  60. .RB -raw
  61. is not specified, output will default to compressed format in which identical adjacent pixels are replaced by "repeat pixel" commands. A raw file is often an order of magnitude larger than a compressed file and prints much slower. Abbreviation as
  62. .RB -r
  63. is allowed.
  64. .TP
  65. .B -margin
  66. If
  67. .RB -margin
  68. is not specified, the image will be start at the left margin (of the window, paper, or whatever). If
  69. .RB -margin
  70. is specified, a 1.5 inch left margin will offset the image. Abbreviation as
  71. .RB -m
  72. is allowed.
  73. .SH EXAMPLE
  74. To convert the file "dot.xwd" from xwd to a sixel file called "dot.six", one could specify
  75. .IP
  76. xwdtopnm dot.xwd | ppmtosix > dot.six
  77. .SH PRINTING
  78. Generally, sixel files must reach the printer unfiltered. Use the lpr -x option or cat filename > /dev/tty0?.
  79. .SH BUGS
  80. Upon rescaling, truncation of the least significant bits of RGB values may result in
  81. poor color conversion.  If the original PPM maxval was greater than 100, rescaling also reduces the image depth. While the actual RGB values from the ppm file are more or less retained, the color palette of the LJ250 may not match the colors on your screen. This seems to be a printer limitation.
  82. .SH "SEE ALSO"
  83. ppm(5)
  84. .SH AUTHOR
  85. Copyright (C) 1991 by Rick Vinci.
  86. Uses code from Jef Poskanzer's PBMPlus utilities.
  87. .\" Permission to use, copy, modify, and distribute this software and its
  88. .\" documentation for any purpose and without fee is hereby granted, provided
  89. .\" that the above copyright notice appear in all copies and that both that
  90. .\" copyright notice and this permission notice appear in supporting
  91. .\" documentation.  This software is provided "as is" without express or
  92. .\" implied warranty.
  93.  
  94. -------- CUT HERE FOR PPMTOSIX.C --------
  95. /* ppmtosix.c - read a portable pixmap and produce a color sixel file
  96. **
  97. ** Copyright (C) 1991 by Rick Vinci.
  98. **
  99. ** Uses code from Jef Poskanzer's PBMPlus utilities.
  100. **
  101. ** Permission to use, copy, modify, and distribute this software and its
  102. ** documentation for any purpose and without fee is hereby granted, provided
  103. ** that the above copyright notice appear in all copies and that both that
  104. ** copyright notice and this permission notice appear in supporting
  105. ** documentation.  This software is provided "as is" without express or
  106. ** implied warranty.
  107. **
  108. */
  109.  
  110. #include "ppm.h"
  111. #include "ppmcmap.h"
  112.  
  113. #define MAXCOLORS 256
  114. #define DCS '\x90'   /* Device Control String */
  115. #define ST '\x9c'   /* String Terminator */
  116. #define CSI '\x9b'   /* Control String Introducer */
  117. #define ESC '\x1b'   /* Escape character */
  118.  
  119. static pixel** pixels;   /* stored ppm pixmap input */
  120. static colorhash_table cht;
  121. int margin;
  122.  
  123. /***** main function *****/
  124. void main( argc, argv )
  125.     int argc;
  126.     char* argv[];
  127. {
  128.     FILE* ifp;   /* file name */
  129.     int argn, rows, cols, colors;   /* from ppmfile header */
  130.     int Red, Grn, Blue, rownum, colnum;
  131.     int raw;   /* -raw option flag */
  132.     pixval maxval;
  133.     colorhist_vector chv;
  134.     char* usage = "[-raw] [-margin] [ppmfile]"; /* usage error output */
  135.  
  136.     ppm_init( &argc, argv );
  137.  
  138.     argn = 1;   /* command line argument to start with */
  139.     raw = 0;   /* -raw option not chosen (default) */
  140.     margin = 0;   /* -margin argument not chosen (default) */
  141.     
  142.     /* check to see if -option is selected and, if so, is it -raw */
  143.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  144.     {
  145.         if ( pm_keymatch( argv[argn], "-raw", 2 ) )
  146.             raw =1;
  147.         else
  148.             if ( pm_keymatch( argv[argn], "-margin", 2 ) )
  149.                   margin = 1;
  150.             else
  151.                pm_usage( usage );
  152.         ++argn;
  153.     }
  154.  
  155.     if ( argn < argc ) /* if a ppmfile name is provided, open it */
  156.     {
  157.         ifp = pm_openr( argv[argn] );
  158.        ++argn;
  159.     }
  160.     else
  161.        ifp = stdin;
  162.  
  163.     if ( argn != argc ) /* wrong number of arguments */
  164.        pm_usage( usage );
  165.  
  166.     /* read in the ppmfile, storing in pixels, then close ppmfile */
  167.     pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
  168.     pm_close( ifp );
  169.  
  170.     /* Now change the ppm colormap into a RGB percentage scale. */
  171.     if ( maxval != 100 )
  172.     {
  173.     pm_message( 
  174.       "automatically rescaling colors...", 0,0,0,0,0 );
  175.     for (rownum = 0; rownum < rows; ++rownum )
  176.       for (colnum = 0; colnum < cols; ++colnum)
  177.       {
  178.         Red = (int) (PPM_GETR( pixels[rownum][colnum]) * 100 / maxval)+1;
  179.         Grn = (int) (PPM_GETG( pixels[rownum][colnum] ) * 100 / maxval)+1;
  180.         Blue = (int) (PPM_GETB( pixels[rownum][colnum] ) * 100 / maxval)+1;
  181.         if ( Red > 100 ) Red = 100;
  182.         if ( Grn > 100 ) Grn = 100;
  183.         if ( Blue > 100 ) Blue = 100;
  184.         PPM_ASSIGN( pixels[rownum][colnum], Red, Grn, Blue );
  185.       }
  186.      }
  187.        
  188.     /* Figure out the colormap. */
  189.     pm_message( "computing colormap...", 0,0,0,0,0 );
  190.     chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors );
  191.     if ( chv == (colorhist_vector) 0 )
  192.        pm_error( "too many colors - try doing a 'ppmquant %d'", 
  193.                            MAXCOLORS, 0,0,0,0 );
  194.     pm_message( "%d colors found", colors, 0,0,0,0 );
  195.  
  196.     /* Make a hash table for fast color lookup. */
  197.     cht = ppm_colorhisttocolorhash( chv, colors );
  198.  
  199.     pm_message( "delivering sixel image...", 0,0,0,0,0 );
  200.     WriteHeader();
  201.     WriteColorMap( chv, colors );
  202.     if ( raw == 1 )
  203.        WriteRawImage( cht, rows, cols );
  204.    else
  205.         WritePackedImage( cht, rows, cols ); 
  206.     WriteEnd();
  207.  
  208.     exit( 0 );
  209.  
  210. } /***** end main *****/
  211.  
  212.  
  213. int WriteHeader ( )
  214. {
  215.    if ( margin == 1 )
  216.        printf( "%c%d;%ds", CSI, 14, 72 );
  217.    printf( "%c", DCS );   /* start with Device Control String */
  218.    printf( "0;0;8q" );   /* Horizontal Grid Size at 1/90" and graphics On */
  219.    printf( "\"1;1\n" );   /* set aspect ratio 1:1 */
  220. }
  221.  
  222. int WriteColorMap( chv, colors )
  223. colorhist_vector chv;
  224. int colors;
  225. {
  226.    register int colornum;
  227.    
  228.    for ( colornum = 0; colornum < colors ; ++colornum )
  229.      printf( "#%d;2;%d;%d;%d", colornum, 
  230.            (int) PPM_GETR(chv[colornum].color),
  231.            (int) PPM_GETG(chv[colornum].color),
  232.            (int) PPM_GETB(chv[colornum].color) );
  233.    printf( "\n" );
  234. }
  235.  
  236. int WriteRawImage( cht, rows, cols )
  237. colorhash_table cht;
  238. int rows, cols;
  239. {
  240.    int rownum, colnum, bit;
  241.    char sixel[] = "@ACGO_";
  242.    register pixel* pP;
  243.    
  244.    for ( rownum = 0; rownum < rows; ++rownum )
  245.    {     
  246.      bit = rownum % 6;
  247.      for ( colnum = 0, pP = pixels[rownum]; colnum < cols; ++colnum, ++pP )
  248.      {
  249.        printf( "#%d%c", ppm_lookupcolor(cht, pP), sixel[bit] );
  250.      }
  251.      printf( "$\n" );   /* Carriage Return */
  252.      if ( bit == 5 )
  253.        printf( "-\n" );   /* Line Feed (one sixel height) */
  254.    }
  255. }
  256.  
  257. int WritePackedImage( cht, rows, cols )
  258. colorhash_table cht;
  259. int rows, cols;
  260. {   int rownum, colnum, bit, repeat, thiscolor, nextcolor;
  261.    char sixel[] = "@ACGO_";
  262.    register pixel* pP;
  263.    
  264.    for ( rownum = 0; rownum < rows; ++rownum )
  265.    {     
  266.      bit = rownum % 6;
  267.      repeat = 1;
  268.      for ( colnum = 0, pP = pixels[rownum]; colnum < cols; ++colnum, ++pP )
  269.      {
  270.        thiscolor = ppm_lookupcolor(cht, pP);
  271.        if ( colnum == cols -1 )   /* last pixel in row */
  272.            if ( repeat == 1 )
  273.                printf( "#%d%c", thiscolor, sixel[bit] );
  274.            else
  275.                printf( "#%d!%d%c", thiscolor, repeat, sixel[bit] );
  276.        else   /* not last pixel in row */
  277.         {
  278.            nextcolor =  ppm_lookupcolor(cht, pP+1);
  279.            if ( thiscolor == nextcolor )
  280.                repeat++;
  281.            else
  282.                if ( repeat == 1 )
  283.                    printf( "#%d%c", thiscolor, sixel[bit] );
  284.                else
  285.                {
  286.                    printf( "#%d!%d%c", thiscolor, repeat, sixel[bit] );
  287.                    repeat = 1;
  288.                 }
  289.          }
  290.      }   /* end colnum loop */
  291.      printf( "$\n" );   /* Carriage Return */
  292.      if ( bit == 5 )
  293.        printf( "-\n" );   /* Line Feed (one sixel height) */
  294.    }
  295. }
  296.  
  297. int WriteEnd ()
  298. {
  299.    if ( margin == 1 )
  300.        printf ( "%c%d;%ds", CSI, 1, 80 );
  301.    printf( "%c\n", ST );
  302. }
  303.  
  304. /* end ppmtosix.c */
  305. -- 
  306. Rick Vinci                  Department of Materials Science and Engineering
  307. rpvinci@portia.stanford.edu    Stanford University, Stanford, CA 94305
  308. ---------------------------
  309.