home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / pnm / pnmtops.c < prev    next >
C/C++ Source or Header  |  1994-01-31  |  14KB  |  558 lines

  1. /* pnmtops.c - read a portable anymap and produce a PostScript file
  2. **
  3. ** Copyright (C) 1989 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. **
  12. **
  13. ** -nocenter option added November 1993 by Wolfgang Stuerzlinger,
  14. **  wrzl@gup.uni-linz.ac.at.
  15. **
  16. */
  17.  
  18.  
  19. #include "pnm.h"
  20.  
  21. #define MARGIN 0.95
  22.  
  23. static void putinit ARGS(( char* name, int cols, int rows, int padright, int bps, float scale, int dpi, int pagewid, int pagehgt, int format, int turnflag, int turnokflag, int rleflag, int center ));
  24. static void putitem ARGS(( void ));
  25. static void putxelval ARGS(( xelval xv ));
  26. static void putrest ARGS(( void ));
  27. static void rleputbuffer ARGS(( void ));
  28. static void rleputitem ARGS(( void ));
  29. static void rleputxelval ARGS(( xelval xv ));
  30. static void rleflush ARGS(( void ));
  31. static void rleputrest ARGS(( void ));
  32.  
  33. int
  34. main( argc, argv )
  35.     int argc;
  36.     char* argv[];
  37.     {
  38.     FILE* ifp;
  39.     xel* xelrow;
  40.     register xel* xP;
  41.     int argn, turnflag, turnokflag, rleflag, center;
  42.     int rows, cols, format, bps, padright, row, col;
  43.     xelval maxval, nmaxval;
  44.     float scale, f;
  45.     int dpi, pagewid, pagehgt;
  46.     char name[100];
  47.     char* cp;
  48.     char* usage = "[-scale <x>] [-turn|-noturn] [-rle|-runlength] [-dpi <n>] [-width <n>] [-height <n>] [-rle|-runlength] [-center|-nocenter] [pnmfile]";
  49.  
  50.     pnm_init( &argc, argv );
  51.  
  52.     argn = 1;
  53.     scale = 1.0;
  54.     turnflag = 0;
  55.     center = 1;
  56.     turnokflag = 1;
  57.     rleflag = 0;
  58.     /* LaserWriter defaults. */
  59.     dpi = 300;
  60.     pagewid = 612;
  61.     pagehgt = 762;
  62.  
  63.     /* Check for flags. */
  64.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  65.     {
  66.     if ( pm_keymatch( argv[argn], "-scale", 2 ) )
  67.         {
  68.         ++argn;
  69.         if ( argn == argc || sscanf( argv[argn], "%f", &scale ) != 1 )
  70.         pm_usage( usage );
  71.         }
  72.     else if ( pm_keymatch( argv[argn], "-turn", 2 ) )
  73.         turnflag = 1;
  74.     else if ( pm_keymatch( argv[argn], "-noturn", 4 ) )
  75.         turnokflag = 0;
  76.       else if ( pm_keymatch( argv[argn], "-center", 2 ) )
  77.           center = 1;
  78.       else if ( pm_keymatch( argv[argn], "-nocenter", 4 ) )
  79.           center = 0;
  80.     else if ( pm_keymatch( argv[argn], "-rle", 2 ) ||
  81.               pm_keymatch( argv[argn], "-runlength", 2 ) )
  82.         rleflag = 1;
  83.     else if ( pm_keymatch( argv[argn], "-dpi", 2 ) )
  84.         {
  85.         ++argn;
  86.         if ( argn == argc || sscanf( argv[argn], "%d", &dpi ) != 1 )
  87.         pm_usage( usage );
  88.         }
  89.     else if ( pm_keymatch( argv[argn], "-width", 2 ) )
  90.         {
  91.         ++argn;
  92.         if ( argn == argc || sscanf( argv[argn], "%f", &f ) != 1 )
  93.         pm_usage( usage );
  94.         pagewid = f * 72.0;
  95.         }
  96.     else if ( pm_keymatch( argv[argn], "-height", 2 ) )
  97.         {
  98.         ++argn;
  99.         if ( argn == argc || sscanf( argv[argn], "%f", &f ) != 1 )
  100.         pm_usage( usage );
  101.         pagehgt = f * 72.0;
  102.         }
  103.     else
  104.         pm_usage( usage );
  105.     ++argn;
  106.     }
  107.  
  108.     if ( argn < argc )
  109.     {
  110.     ifp = pm_openr( argv[argn] );
  111.     strcpy( name, argv[argn] );
  112.     if ( strcmp( name, "-" ) == 0 )
  113.         strcpy( name, "noname" );
  114.  
  115.     if ( ( cp = index( name, '.' ) ) != 0 )
  116.         *cp = '\0';
  117.     ++argn;
  118.     }
  119.     else
  120.     {
  121.     ifp = stdin;
  122.     strcpy( name, "noname" );
  123.     }
  124.  
  125.     if ( argn != argc )
  126.     pm_usage( usage );
  127.  
  128.     pnm_readpnminit( ifp, &cols, &rows, &maxval, &format );
  129.     xelrow = pnm_allocrow( cols );
  130.  
  131.     /* Figure out bps. */
  132.     bps = pm_maxvaltobits( (int) maxval );
  133.     if ( bps > 2 && bps < 4 )
  134.     bps = 4;
  135.     else if ( bps > 4 && bps < 8 )
  136.     bps = 8;
  137.     else if ( bps > 8 )
  138.     pm_error( "maxval of %d is too large for PostScript", maxval );
  139.     nmaxval = pm_bitstomaxval( bps );
  140.     
  141.     /* Compute padding to round cols * bps up to the nearest multiple of 8. */
  142.     padright = ( ( ( cols * bps + 7 ) / 8 ) * 8 - cols * bps ) / bps;
  143.  
  144.     putinit(name, cols, rows, padright, bps, scale, dpi, pagewid, pagehgt,
  145.     format, turnflag, turnokflag, rleflag, center );
  146.     for ( row = 0; row < rows; ++row )
  147.     {
  148.     pnm_readpnmrow( ifp, xelrow, cols, maxval, format );
  149.     switch ( PNM_FORMAT_TYPE( format ) )
  150.         {
  151.         case PPM_TYPE:
  152.         /* Color. */
  153.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  154.         if ( maxval != nmaxval )
  155.             PPM_DEPTH( *xP, *xP, maxval, nmaxval );
  156.         /* First red. */
  157.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  158.         if ( rleflag )
  159.             rleputxelval( PPM_GETR( *xP ) );
  160.         else
  161.             putxelval( PPM_GETR( *xP ) );
  162.         for ( col = 0; col < padright; ++col )
  163.         if ( rleflag )
  164.             rleputxelval( 0 );
  165.         else
  166.             putxelval( 0 );
  167.         if ( rleflag )
  168.         rleflush();
  169.         /* Then green. */
  170.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  171.         if ( rleflag )
  172.             rleputxelval( PPM_GETG( *xP ) );
  173.         else
  174.             putxelval( PPM_GETG( *xP ) );
  175.         for ( col = 0; col < padright; ++col )
  176.         if ( rleflag )
  177.             rleputxelval( 0 );
  178.         else
  179.             putxelval( 0 );
  180.         if ( rleflag )
  181.         rleflush();
  182.         /* And blue. */
  183.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  184.         if ( rleflag )
  185.             rleputxelval( PPM_GETB( *xP ) );
  186.         else
  187.             putxelval( PPM_GETB( *xP ) );
  188.         for ( col = 0; col < padright; ++col )
  189.         if ( rleflag )
  190.             rleputxelval( 0 );
  191.         else
  192.             putxelval( 0 );
  193.         if ( rleflag )
  194.         rleflush();
  195.         break;
  196.         default:
  197.         /* Grayscale. */
  198.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  199.         {
  200.         if ( maxval != nmaxval )
  201.             PNM_ASSIGN1( *xP, (int) PNM_GET1(*xP) * nmaxval / maxval );
  202.         if ( rleflag )
  203.             rleputxelval( PNM_GET1( *xP ) );
  204.         else
  205.             putxelval( PNM_GET1( *xP ) );
  206.         }
  207.         for ( col = 0; col < padright; ++col )
  208.         if ( rleflag )
  209.             rleputxelval( 0 );
  210.         else
  211.             putxelval( 0 );
  212.         if ( rleflag )
  213.         rleflush();
  214.         break;
  215.         }
  216.         }
  217.  
  218.     pm_close( ifp );
  219.  
  220.     if ( rleflag )
  221.     rleputrest();
  222.     else
  223.     putrest();
  224.  
  225.     exit( 0 );
  226.     }
  227.  
  228. static int bitspersample, item, bitsperitem, bitshift, itemsperline, items;
  229. static int rleitem, rlebitsperitem, rlebitshift;
  230. static int repeat, itembuf[128], count, repeatitem, repeatcount;
  231.  
  232. #if __STDC__
  233. static void
  234. putinit( char* name, int cols, int rows, int padright, int bps, float scale,
  235.      int dpi, int pagewid, int pagehgt, int format, int turnflag,
  236.      int turnokflag, int rleflag, int center )
  237. #else /*__STDC__*/
  238. static void
  239. putinit( name, cols, rows, padright, bps, scale, dpi, pagewid, pagehgt, format,
  240.          turnflag, turnokflag, rleflag, center )
  241.     char* name;
  242.     int cols, rows, padright, bps;
  243.     float scale;
  244.     int dpi, pagewid, pagehgt, format, turnflag, turnokflag, rleflag, center;
  245. #endif /*__STDC__*/
  246.     {
  247.     int icols, irows, devpix;
  248.     float pixfac, scols, srows, llx, lly;
  249.  
  250.     /* Turn? */
  251.     icols = cols;
  252.     irows = rows;
  253.     if ( turnflag || ( turnokflag && cols > rows ) )
  254.     {
  255.     turnflag = 1;
  256.     cols = irows;
  257.     rows = icols;
  258.     }
  259.  
  260.     /* Figure out size. */
  261.     devpix = dpi / 72.0 + 0.5;        /* device pixels per unit, approx. */
  262.     pixfac = 72.0 / dpi * devpix;    /* 1, approx. */
  263.     scols = scale * cols * pixfac;
  264.     srows = scale * rows * pixfac;
  265.     if ( scols > pagewid * MARGIN || srows > pagehgt * MARGIN )
  266.     {
  267.     if ( scols > pagewid * MARGIN )
  268.         {
  269.         scale *= pagewid / scols * MARGIN;
  270.         scols = scale * cols * pixfac;
  271.         srows = scale * rows * pixfac;
  272.         }
  273.     if ( srows > pagehgt * MARGIN )
  274.         {
  275.         scale *= pagehgt / srows * MARGIN;
  276.         scols = scale * cols * pixfac;
  277.         srows = scale * rows * pixfac;
  278.         }
  279.     pm_message(
  280.         "warning, image too large for page, rescaling to %g", scale );
  281.     }
  282.     llx = (center) ? ( pagewid - scols ) / 2 : 0;
  283.     lly = (center) ? ( pagehgt - srows ) / 2 : 0;
  284.  
  285.     printf( "%%!PS-Adobe-2.0 EPSF-2.0\n" );
  286.     printf( "%%%%Creator: pnmtops\n" );
  287.     printf( "%%%%Title: %s.ps\n", name );
  288.     printf( "%%%%Pages: 1\n" );
  289.     printf(
  290.     "%%%%BoundingBox: %d %d %d %d\n",
  291.     (int) llx, (int) lly,
  292.     (int) ( llx + scols + 0.5 ), (int) ( lly + srows + 0.5 ) );
  293.     printf( "%%%%EndComments\n" );
  294.     if ( rleflag )
  295.     {
  296.     printf( "/rlestr1 1 string def\n" );
  297.     printf( "/readrlestring {\n" );                /* s -- nr */
  298.     printf( "  /rlestr exch def\n" );            /* - */
  299.     printf( "  currentfile rlestr1 readhexstring pop\n" );    /* s1 */
  300.     printf( "  0 get\n" );                    /* c */
  301.     printf( "  dup 127 le {\n" );                /* c */
  302.     printf( "    currentfile rlestr 0\n" );            /* c f s 0 */
  303.     printf( "    4 3 roll\n" );                /* f s 0 c */
  304.     printf( "    1 add  getinterval\n" );            /* f s */
  305.     printf( "    readhexstring pop\n" );            /* s */
  306.     printf( "    length\n" );                /* nr */
  307.     printf( "  } {\n" );                    /* c */
  308.     printf( "    256 exch sub dup\n" );            /* n n */
  309.     printf( "    currentfile rlestr1 readhexstring pop\n" );/* n n s1 */
  310.     printf( "    0 get\n" );                /* n n c */
  311.     printf( "    exch 0 exch 1 exch 1 sub {\n" );        /* n c 0 1 n-1*/
  312.     printf( "      rlestr exch 2 index put\n" );
  313.     printf( "    } for\n" );                /* n c */
  314.     printf( "    pop\n" );                    /* nr */
  315.     printf( "  } ifelse\n" );                /* nr */
  316.     printf( "} bind def\n" );
  317.     printf( "/readstring {\n" );                /* s -- s */
  318.         printf( "  dup length 0 {\n" );                /* s l 0 */
  319.     printf( "    3 copy exch\n" );                /* s l n s n l*/
  320.     printf( "    1 index sub\n" );                /* s l n s n r*/
  321.     printf( "    getinterval\n" );                /* s l n ss */
  322.     printf( "    readrlestring\n" );            /* s l n nr */
  323.     printf( "    add\n" );                    /* s l n */
  324.         printf( "    2 copy le { exit } if\n" );        /* s l n */
  325.         printf( "  } loop\n" );                    /* s l l */
  326.         printf( "  pop pop\n" );                /* s */
  327.     printf( "} bind def\n" );
  328.     }
  329.     else
  330.     {
  331.     printf( "/readstring {\n" );                /* s -- s */
  332.     printf( "  currentfile exch readhexstring pop\n" );
  333.     printf( "} bind def\n" );
  334.     }
  335.     if ( PNM_FORMAT_TYPE( format ) == PPM_TYPE )
  336.     {
  337.     printf( "/rpicstr %d string def\n", ( icols + padright ) * bps / 8 );
  338.     printf( "/gpicstr %d string def\n", ( icols + padright ) * bps / 8 );
  339.     printf( "/bpicstr %d string def\n", ( icols + padright ) * bps / 8 );
  340.     }
  341.     else
  342.     printf( "/picstr %d string def\n", ( icols + padright ) * bps / 8 );
  343.     printf( "%%%%EndProlog\n" );
  344.     printf( "%%%%Page: 1 1\n" );
  345.     printf( "gsave\n" );
  346.     printf( "%g %g translate\n", llx, lly );
  347.     printf( "%g %g scale\n", scols, srows );
  348.     if ( turnflag )
  349.     printf( "0.5 0.5 translate  90 rotate  -0.5 -0.5 translate\n" );
  350.     printf( "%d %d %d\n", icols, irows, bps );
  351.     printf( "[ %d 0 0 -%d 0 %d ]\n", icols, irows, irows );
  352.     if ( PNM_FORMAT_TYPE( format ) == PPM_TYPE )
  353.     {
  354.     printf( "{ rpicstr readstring }\n" );
  355.     printf( "{ gpicstr readstring }\n" );
  356.     printf( "{ bpicstr readstring }\n" );
  357.     printf( "true 3\n" );
  358.     printf( "colorimage\n" );
  359.     pm_message( "writing color PostScript..." );
  360.     }
  361.     else
  362.     {
  363.     printf( "{ picstr readstring }\n" );
  364.     printf( "image\n" );
  365.     }
  366.  
  367.     bitspersample = bps;
  368.     itemsperline = items = 0;
  369.     if ( rleflag )
  370.     {
  371.     rleitem = 0;
  372.     rlebitsperitem = 0;
  373.     rlebitshift = 8 - bitspersample;
  374.     repeat = 1;
  375.     count = 0;
  376.     }
  377.     else
  378.     {
  379.     item = 0;
  380.     bitsperitem = 0;
  381.     bitshift = 8 - bitspersample;
  382.     }
  383.     }
  384.  
  385. static void
  386. putitem()
  387.     {
  388.     char* hexits = "0123456789abcdef";
  389.  
  390.     if ( itemsperline == 30 )
  391.     {
  392.     putchar( '\n' );
  393.     itemsperline = 0;
  394.     }
  395.     putchar( hexits[item >> 4] );
  396.     putchar( hexits[item & 15] );
  397.     ++itemsperline;
  398.     ++items;
  399.     item = 0;
  400.     bitsperitem = 0;
  401.     bitshift = 8 - bitspersample;
  402.     }
  403.  
  404. #if __STDC__
  405. static void putxelval( xelval xv )
  406. #else /*__STDC__*/
  407. static void
  408. putxelval( xv )
  409.     xelval xv;
  410. #endif /*__STDC__*/
  411.     {
  412.     if ( bitsperitem == 8 )
  413.     putitem();
  414.     item += xv << bitshift;
  415.     bitsperitem += bitspersample;
  416.     bitshift -= bitspersample;
  417.     }
  418.  
  419. static void
  420. putrest()
  421.     {
  422.     if ( bitsperitem > 0 )
  423.     putitem();
  424.     printf( "\n" );
  425.     printf( "grestore\n" );
  426.     printf( "showpage\n" );
  427.     printf( "%%%%Trailer\n" );
  428.     }
  429.  
  430. static void
  431. rleputbuffer()
  432.     {
  433.     int i;
  434.  
  435.     if ( repeat )
  436.     {
  437.     item = 256 - count;
  438.     putitem();
  439.     item = repeatitem;
  440.     putitem();
  441.     }
  442.     else
  443.     {
  444.     item = count - 1;
  445.     putitem();
  446.     for ( i = 0; i < count; ++i )
  447.         {
  448.         item = itembuf[i];
  449.         putitem();
  450.         }
  451.     }
  452.     repeat = 1;
  453.     count = 0;
  454.     }
  455.  
  456. static void
  457. rleputitem()
  458.     {
  459.     int i;
  460.  
  461.     if ( count == 128 )
  462.     rleputbuffer();
  463.  
  464.     if ( repeat && count == 0 )
  465.     { /* Still initializing a repeat buf. */
  466.     itembuf[count] = repeatitem = rleitem;
  467.     ++count;
  468.     }
  469.     else if ( repeat )
  470.     { /* Repeating - watch for end of run. */
  471.     if ( rleitem == repeatitem )
  472.         { /* Run continues. */
  473.         itembuf[count] = rleitem;
  474.         ++count;
  475.         }
  476.     else
  477.         { /* Run ended - is it long enough to dump? */
  478.         if ( count > 2 )
  479.         { /* Yes, dump a repeat-mode buffer and start a new one. */
  480.         rleputbuffer();
  481.         itembuf[count] = repeatitem = rleitem;
  482.         ++count;
  483.         }
  484.         else
  485.         { /* Not long enough - convert to non-repeat mode. */
  486.         repeat = 0;
  487.         itembuf[count] = repeatitem = rleitem;
  488.         ++count;
  489.         repeatcount = 1;
  490.         }
  491.         }
  492.     }
  493.     else
  494.     { /* Not repeating - watch for a run worth repeating. */
  495.     if ( rleitem == repeatitem )
  496.         { /* Possible run continues. */
  497.         ++repeatcount;
  498.         if ( repeatcount > 3 )
  499.         { /* Long enough - dump non-repeat part and start repeat. */
  500.         count = count - ( repeatcount - 1 );
  501.         rleputbuffer();
  502.         count = repeatcount;
  503.         for ( i = 0; i < count; ++i )
  504.             itembuf[i] = rleitem;
  505.         }
  506.         else
  507.         { /* Not long enough yet - continue as non-repeat buf. */
  508.         itembuf[count] = rleitem;
  509.         ++count;
  510.         }
  511.         }
  512.     else
  513.         { /* Broken run. */
  514.         itembuf[count] = repeatitem = rleitem;
  515.         ++count;
  516.         repeatcount = 1;
  517.         }
  518.     }
  519.  
  520.     rleitem = 0;
  521.     rlebitsperitem = 0;
  522.     rlebitshift = 8 - bitspersample;
  523.     }
  524.  
  525. #if __STDC__
  526. static void rleputxelval( xelval xv )
  527. #else /*__STDC__*/
  528. static void
  529. rleputxelval( xv )
  530.     xelval xv;
  531. #endif /*__STDC__*/
  532.     {
  533.     if ( rlebitsperitem == 8 )
  534.     rleputitem();
  535.     rleitem += xv << rlebitshift;
  536.     rlebitsperitem += bitspersample;
  537.     rlebitshift -= bitspersample;
  538.     }
  539.  
  540. static void
  541. rleflush()
  542.     {
  543.     if ( rlebitsperitem > 0 )
  544.     rleputitem();
  545.     if ( count > 0 )
  546.     rleputbuffer();
  547.     }
  548.  
  549. static void
  550. rleputrest()
  551.     {
  552.     rleflush();
  553.     printf( "\n" );
  554.     printf( "grestore\n" );
  555.     printf( "showpage\n" );
  556.     printf( "%%%%Trailer\n" );
  557.     }
  558.