home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume9 / pbmplus / part09 / pgm / pgmtops.c < prev    next >
C/C++ Source or Header  |  1989-11-26  |  9KB  |  414 lines

  1. /* pgmtops.c - read a portable graymap 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. #include <stdio.h>
  14. #include "pgm.h"
  15. #ifdef SYSV
  16. #include <string.h>
  17. #define index strchr
  18. #else /*SYSV*/
  19. #include <strings.h>
  20. #endif /*SYSV*/
  21.  
  22. #define max(a,b) ((a) > (b) ? (a) : (b))
  23.  
  24. main( argc, argv )
  25. int argc;
  26. char *argv[];
  27.     {
  28.     FILE *ifd;
  29.     register gray *grayrow, *gP;
  30.     int argn, rleflag, rows, cols, format, bps, padright, row, col;
  31.     gray maxval;
  32.     float scale;
  33.     char name[100], *cp;
  34.     int maxvaltobps();
  35.     char *usage = "[-rle] [-scale <x>] [pgmfile]";
  36.  
  37.     pm_progname = argv[0];
  38.  
  39.     argn = 1;
  40.     rleflag = 0;
  41.     scale = 1.0;
  42.  
  43.     /* Check for flags. */
  44.     while ( argn < argc && argv[argn][0] == '-' )
  45.     {
  46.     if ( strncmp(argv[argn],"-rle",max(strlen(argv[argn]),2)) == 0 ||
  47.          strncmp(argv[argn],"-runlength",max(strlen(argv[argn]),2)) == 0 )
  48.         rleflag = 1;
  49.     else if ( strncmp(argv[argn],"-scale",max(strlen(argv[argn]),2)) == 0 )
  50.         {
  51.         argn++;
  52.         if ( argn == argc || sscanf( argv[argn], "%f", &scale ) != 1 )
  53.         pm_usage( usage );
  54.         }
  55.     else
  56.         pm_usage( usage );
  57.     argn++;
  58.     }
  59.  
  60.     if ( argn < argc )
  61.     {
  62.     ifd = pm_openr( argv[argn] );
  63.     strcpy( name, argv[argn] );
  64.     if ( strcmp( name, "-" ) == 0 )
  65.         strcpy( name, "noname" );
  66.  
  67.     if ( ( cp = index( name, '.' ) ) != 0 )
  68.         *cp = '\0';
  69.     argn++;
  70.     }
  71.     else
  72.     {
  73.     ifd = stdin;
  74.     strcpy( name, "noname" );
  75.     }
  76.  
  77.     if ( argn != argc )
  78.     pm_usage( usage );
  79.  
  80.     pgm_readpgminit( ifd, &cols, &rows, &maxval, &format );
  81.     grayrow = pgm_allocrow( cols );
  82.  
  83.     /* Figure out bps. */
  84.     bps = maxvaltobps( maxval );
  85.     
  86.     /* Compute padding to round cols * bps up to the nearest multiple of 8. */
  87.     padright = ( ( cols * bps + 7 ) / 8 ) * 8 - cols * bps;
  88.  
  89.     if ( rleflag )
  90.     rleputinit( name, cols, rows, bps, scale );
  91.     else
  92.     putinit( name, cols, rows, bps, scale );
  93.     for ( row = 0; row < rows; row++ )
  94.     {
  95.     pgm_readpgmrow( ifd, grayrow, cols, maxval, format );
  96.         for ( col = 0, gP = grayrow; col < cols; col++, gP++ )
  97.         if ( rleflag )
  98.         rleputgray( *gP );
  99.         else
  100.         putgray( *gP );
  101.     for ( col = 0; col < padright; col++ )
  102.         if ( rleflag )
  103.         rleputgray( maxval );
  104.         else
  105.         putgray( maxval );
  106.         }
  107.  
  108.     pm_close( ifd );
  109.  
  110.     if ( rleflag )
  111.     rleputrest( );
  112.     else
  113.     putrest( );
  114.  
  115.     exit( 0 );
  116.     }
  117.  
  118. int
  119. maxvaltobps( maxval )
  120. gray maxval;
  121.     {
  122.     switch ( maxval )
  123.     {
  124.     case 1:
  125.     return 1;
  126.  
  127.     case 3:
  128.     return 2;
  129.  
  130.     case 15:
  131.     return 4;
  132.  
  133.     case 255:
  134.     return 8;
  135.  
  136. #ifdef notdef
  137.     case 7:
  138.     return 3;
  139.  
  140.     case 31:
  141.     return 5;
  142.  
  143.     case 63:
  144.     return 6;
  145.  
  146.     case 127:
  147.     return 7;
  148. #endif /*notdef*/
  149.  
  150.     default:
  151.     pm_error( "maxval of %d is not supported", maxval, 0,0,0,0 );
  152.     /* NOTREACHED */
  153.     }
  154.     }
  155.  
  156.  
  157. int bitspersample, item, bitsperitem, bitshift, itemsperline, items;
  158. int rleitem, rlebitsperitem, rlebitshift;
  159. int repeat, itembuf[128], count, repeatitem, repeatcount;
  160. #define HSBUFSIZ 256
  161.  
  162. putinit( name, cols, rows, bps, scale )
  163. char *name;
  164. int cols, rows, bps;
  165. float scale;
  166.     {
  167.     float scols, srows, llx, lly;
  168.  
  169.     scols = scale * cols * 0.96 + 0.5;    /*   0.96 is the multiple of   */
  170.     srows = scale * rows * 0.96 + 0.5;    /* 72/300 that is closest to 1 */
  171.     llx = ( 612.0 - scols ) / 2;
  172.     lly = ( 792.0 - srows ) / 2;
  173.     if ( llx < 0.0 || lly < 0.0 )
  174.     pm_message( "warning, image too large for page", 0,0,0,0,0 );
  175.  
  176.     printf( "%%!PS-Adobe-2.0 EPSF-2.0\n" );
  177.     printf( "%%%%Creator: pgmtops\n" );
  178.     printf( "%%%%Title: %s.ps\n", name );
  179.     printf( "%%%%Pages: 1\n" );
  180.     printf(
  181.     "%%%%BoundingBox: %d %d %d %d\n",
  182.     (int) llx, (int) lly, (int) ( llx + scols ), (int) ( lly + srows ) );
  183.     printf( "%%%%EndComments\n" );
  184.     printf( "%%%%EndProlog\n" );
  185.     printf( "%%%%Page 1 1\n" );
  186.     printf( "/picstr %d string def\n", HSBUFSIZ );
  187.     printf( "gsave\n" );
  188.     printf( "%g %g translate\n", llx, lly );
  189.     printf( "%g %g scale\n", scols, srows );
  190.     printf( "%d %d %d\n", cols, rows, bps );
  191.     printf( "[ %d 0 0 -%d 0 %d ]\n", cols, rows, rows );
  192.     printf( "{ currentfile picstr readhexstring pop }\n" );
  193.     printf( "image\n" );
  194.  
  195.     bitspersample = bps;
  196.     itemsperline = items = 0;
  197.     item = 0;
  198.     bitsperitem = 0;
  199.     bitshift = 8 - bitspersample;
  200.     }
  201.  
  202. putitem( )
  203.     {
  204.     char *hexits = "0123456789abcdef";
  205.  
  206.     if ( itemsperline == 30 )
  207.     {
  208.     putchar( '\n' );
  209.     itemsperline = 0;
  210.     }
  211.     putchar( hexits[item >> 4] );
  212.     putchar( hexits[item & 15] );
  213.     itemsperline++;
  214.     items++;
  215.     item = 0;
  216.     bitsperitem = 0;
  217.     bitshift = 8 - bitspersample;
  218.     }
  219.  
  220. putgray( g )
  221. gray g;
  222.     {
  223.     if ( bitsperitem == 8 )
  224.     putitem( );
  225.     item += g << bitshift;
  226.     bitsperitem += bitspersample;
  227.     bitshift -= bitspersample;
  228.     }
  229.  
  230. putrest( )
  231.     {
  232.     if ( bitsperitem > 0 )
  233.     putitem( );
  234.     while ( items % HSBUFSIZ != 0 )
  235.     putitem( );
  236.     printf( "\n" );
  237.     printf( "grestore\n" );
  238.     printf( "showpage\n" );
  239.     printf( "%%%%Trailer\n" );
  240.     }
  241.  
  242. rleputinit( name, cols, rows, bps, scale )
  243. char *name;
  244. int cols, rows, bps;
  245. float scale;
  246.     {
  247.     float scols, srows, llx, lly;
  248.  
  249.     scols = scale * cols * 0.96 + 0.5;    /*   0.96 is the multiple of   */
  250.     srows = scale * rows * 0.96 + 0.5;    /* 72/300 that is closest to 1 */
  251.     llx = ( 612.0 - scols ) / 2;
  252.     lly = ( 792.0 - srows ) / 2;
  253.     if ( llx < 0.0 || lly < 0.0 )
  254.     pm_message( "warning, image too large for page", 0,0,0,0,0 );
  255.  
  256.     printf( "%%!PS-Adobe-2.0 EPSF-2.0\n" );
  257.     printf( "%%%%Creator: pgmtops\n" );
  258.     printf( "%%%%Title: %s.ps\n", name );
  259.     printf( "%%%%Pages: 1\n" );
  260.     printf(
  261.     "%%%%BoundingBox: %d %d %d %d\n",
  262.     (int) llx, (int) lly, (int) ( llx + scols ), (int) ( lly + srows ) );
  263.     printf( "%%%%EndComments\n" );
  264.     printf( "%%%%EndProlog\n" );
  265.     printf( "/rlestr1 1 string def\n" );
  266.     printf( "/rlestr 128 string def\n" );
  267.     printf( "/readrlestring {\n" );
  268.     printf( "  currentfile rlestr1 readhexstring pop  0 get\n" );
  269.     printf( "  dup 127 le {\n" );
  270.     printf( "    currentfile rlestr 0  4 3 roll  1 add  getinterval\n" );
  271.     printf( "    readhexstring  pop\n" );
  272.     printf( "  } {\n" );
  273.     printf( "    256 exch sub  dup\n" );
  274.     printf( "    currentfile rlestr1 readhexstring pop  0 get\n" );
  275.     printf( "    exch 0 exch 1 exch 1 sub { rlestr exch 2 index put } for\n" );
  276.     printf( "    pop  rlestr exch 0 exch getinterval\n" );
  277.     printf( "  } ifelse\n" );
  278.     printf( "} bind def\n" );
  279.     printf( "%%%%EndProlog\n" );
  280.     printf( "%%%%Page 1 1\n" );
  281.     printf( "gsave\n" );
  282.     printf( "%g %g translate\n", llx, lly );
  283.     printf( "%g %g scale\n", scols, srows );
  284.     printf( "%d %d %d\n", cols, rows, bps );
  285.     printf( "[ %d 0 0 -%d 0 %d ]\n", cols, rows, rows );
  286.     printf( "{ readrlestring }\n" );
  287.     printf( "image\n" );
  288.  
  289.     bitspersample = bps;
  290.     itemsperline = items = 0;
  291.     rleitem = 0;
  292.     rlebitsperitem = 0;
  293.     rlebitshift = 8 - bitspersample;
  294.     repeat = 1;
  295.     count = 0;
  296.     }
  297.  
  298. rleputbuffer( )
  299.     {
  300.     int i;
  301.  
  302.     if ( repeat )
  303.     {
  304.     item = 256 - count;
  305.     putitem( );
  306.     item = repeatitem;
  307.     putitem( );
  308.     }
  309.     else
  310.     {
  311.     item = count - 1;
  312.     putitem( );
  313.     for ( i = 0; i < count; i++ )
  314.         {
  315.         item = itembuf[i];
  316.         putitem( );
  317.         }
  318.     }
  319.     repeat = 1;
  320.     count = 0;
  321.     }
  322.  
  323. rleputitem( )
  324.     {
  325.     int i;
  326.  
  327.     if ( count == 128 )
  328.     rleputbuffer( );
  329.  
  330.     if ( repeat && count == 0 )
  331.     { /* Still initializing a repeat buf. */
  332.     itembuf[count] = repeatitem = rleitem;
  333.     count++;
  334.     }
  335.     else if ( repeat )
  336.     { /* Repeating - watch for end of run. */
  337.     if ( rleitem == repeatitem )
  338.         { /* Run continues. */
  339.         itembuf[count] = rleitem;
  340.         count++;
  341.         }
  342.     else
  343.         { /* Run ended - is it long enough to dump? */
  344.         if ( count > 2 )
  345.         { /* Yes, dump a repeat-mode buffer and start a new one. */
  346.         rleputbuffer( );
  347.         itembuf[count] = repeatitem = rleitem;
  348.         count++;
  349.         }
  350.         else
  351.         { /* Not long enough - convert to non-repeat mode. */
  352.         repeat = 0;
  353.         itembuf[count] = repeatitem = rleitem;
  354.         count++;
  355.         repeatcount = 1;
  356.         }
  357.         }
  358.     }
  359.     else
  360.     { /* Not repeating - watch for a run worth repeating. */
  361.     if ( rleitem == repeatitem )
  362.         { /* Possible run continues. */
  363.         repeatcount++;
  364.         if ( repeatcount > 3 )
  365.         { /* Long enough - dump non-repeat part and start repeat. */
  366.         count = count - ( repeatcount - 1 );
  367.         rleputbuffer( );
  368.         count = repeatcount;
  369.         for ( i = 0; i < count; i++ )
  370.             itembuf[i] = rleitem;
  371.         }
  372.         else
  373.         { /* Not long enough yet - continue as non-repeat buf. */
  374.         itembuf[count] = rleitem;
  375.         count++;
  376.         }
  377.         }
  378.     else
  379.         { /* Broken run. */
  380.         itembuf[count] = repeatitem = rleitem;
  381.         count++;
  382.         repeatcount = 1;
  383.         }
  384.     }
  385.  
  386.     rleitem = 0;
  387.     rlebitsperitem = 0;
  388.     rlebitshift = 8 - bitsperitem;
  389.     }
  390.  
  391. rleputgray( g )
  392. gray g;
  393.     {
  394.     if ( rlebitsperitem == 8 )
  395.     {
  396.     rleputitem( );
  397.     }
  398.     rleitem += g << rlebitshift;
  399.     rlebitsperitem += bitsperitem;
  400.     rlebitshift -= bitsperitem;
  401.     }
  402.  
  403. rleputrest( )
  404.     {
  405.     if ( rlebitsperitem > 0 )
  406.     rleputitem( );
  407.     if ( count > 0 )
  408.     rleputbuffer( );
  409.     printf( "\n" );
  410.     printf( "grestore\n" );
  411.     printf( "showpage\n" );
  412.     printf( "%%%%Trailer\n" );
  413.     }
  414.