home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 309.lha / PBM_PLUS / pgm / pgmtops.c < prev    next >
C/C++ Source or Header  |  1980-12-04  |  9KB  |  407 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. #ifdef    SYSV
  15. #include <string.h>
  16. #define index strchr
  17. #else    SYSV
  18. #include <strings.h>
  19. #endif    SYSV
  20. #include "pgm.h"
  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.     int scols, srows, llx, lly;
  168.  
  169.     scols = cols * 0.96 + 0.5;    /*   0.96 is the multiple of   */
  170.     srows = rows * 0.96 + 0.5;    /* 72/300 that is closest to 1 */
  171.     llx = 300 - ( scols / 2 );
  172.     lly = 400 - ( srows / 2 );
  173.  
  174.     printf( "%%!PS-Adobe-2.0 EPSF-2.0\n" );
  175.     printf( "%%%%Creator: pgmtops\n" );
  176.     printf( "%%%%Title: %s.ps\n", name );
  177.     printf( "%%%%Pages: 1\n" );
  178.     printf(
  179.     "%%%%BoundingBox: %d %d %d %d\n", llx, lly, llx + scols, lly + srows );
  180.     printf( "%%%%EndComments\n" );
  181.     printf( "%%%%EndProlog\n" );
  182.     printf( "%%%%Page 1 1\n" );
  183.     printf( "/picstr %d string def\n", HSBUFSIZ );
  184.     printf( "gsave\n" );
  185.     printf( "%d %d translate\n", llx, lly );
  186.     printf( "%g %g scale\n", scale, scale );
  187.     printf( "%d %d scale\n", scols, srows );
  188.     printf( "%d %d %d\n", cols, rows, bps );
  189.     printf( "[ %d 0 0 -%d 0 %d ]\n", cols, rows, rows );
  190.     printf( "{ currentfile picstr readhexstring pop }\n" );
  191.     printf( "image\n" );
  192.  
  193.     bitspersample = bps;
  194.     itemsperline = items = 0;
  195.     item = 0;
  196.     bitsperitem = 0;
  197.     bitshift = 8 - bitspersample;
  198.     }
  199.  
  200. putitem( )
  201.     {
  202.     if ( itemsperline == 30 )
  203.     {
  204.     putchar( '\n' );
  205.     itemsperline = 0;
  206.     }
  207.     printf( "%02x", item );
  208.     itemsperline++;
  209.     items++;
  210.     item = 0;
  211.     bitsperitem = 0;
  212.     bitshift = 8 - bitspersample;
  213.     }
  214.  
  215. putgray( g )
  216. gray g;
  217.     {
  218.     if ( bitsperitem == 8 )
  219.     putitem( );
  220.     item += g << bitshift;
  221.     bitsperitem += bitspersample;
  222.     bitshift -= bitspersample;
  223.     }
  224.  
  225. putrest( )
  226.     {
  227.     if ( bitsperitem > 0 )
  228.     putitem( );
  229.     while ( items % HSBUFSIZ != 0 )
  230.     putitem( );
  231.     printf( "\n" );
  232.     printf( "grestore\n" );
  233.     printf( "showpage\n" );
  234.     printf( "%%%%Trailer\n" );
  235.     }
  236.  
  237. rleputinit( name, cols, rows, bps, scale )
  238. char *name;
  239. int cols, rows, bps;
  240. float scale;
  241.     {
  242.     int scols, srows, llx, lly;
  243.  
  244.     scols = cols * 0.96 + 0.5;    /*   0.96 is the multiple of   */
  245.     srows = rows * 0.96 + 0.5;    /* 72/300 that is closest to 1 */
  246.     llx = 300 - ( scols / 2 );
  247.     lly = 400 - ( srows / 2 );
  248.  
  249.     printf( "%%!PS-Adobe-2.0 EPSF-2.0\n" );
  250.     printf( "%%%%Creator: pgmtops\n" );
  251.     printf( "%%%%Title: %s.ps\n", name );
  252.     printf( "%%%%Pages: 1\n" );
  253.     printf(
  254.     "%%%%BoundingBox: %d %d %d %d\n", llx, lly, llx + scols, lly + srows );
  255.     printf( "%%%%EndComments\n" );
  256.     printf( "%%%%EndProlog\n" );
  257.     printf( "/rlestr1 1 string def\n" );
  258.     printf( "/rlestr 128 string def\n" );
  259.     printf( "/readrlestring {\n" );
  260.     printf( "  currentfile rlestr1 readhexstring pop  0 get\n" );
  261.     printf( "  dup 127 le {\n" );
  262.     printf( "    currentfile rlestr 0  4 3 roll  1 add  getinterval\n" );
  263.     printf( "    readhexstring  pop\n" );
  264.     printf( "  } {\n" );
  265.     printf( "    256 exch sub  dup\n" );
  266.     printf( "    currentfile rlestr1 readhexstring pop  0 get\n" );
  267.     printf( "    exch 0 exch 1 exch 1 sub { rlestr exch 2 index put } for\n" );
  268.     printf( "    pop  rlestr exch 0 exch getinterval\n" );
  269.     printf( "  } ifelse\n" );
  270.     printf( "} bind def\n" );
  271.     printf( "%%%%EndProlog\n" );
  272.     printf( "%%%%Page 1 1\n" );
  273.     printf( "gsave\n" );
  274.     printf( "%d %d translate\n", llx, lly );
  275.     printf( "%g %g scale\n", scale, scale );
  276.     printf( "%d %d scale\n", scols, srows );
  277.     printf( "%d %d %d\n", cols, rows, bps );
  278.     printf( "[ %d 0 0 -%d 0 %d ]\n", cols, rows, rows );
  279.     printf( "{ readrlestring }\n" );
  280.     printf( "image\n" );
  281.  
  282.     bitspersample = bps;
  283.     itemsperline = items = 0;
  284.     rleitem = 0;
  285.     rlebitsperitem = 0;
  286.     rlebitshift = 8 - bitspersample;
  287.     repeat = 1;
  288.     count = 0;
  289.     }
  290.  
  291. rleputbuffer( )
  292.     {
  293.     int i;
  294.  
  295.     if ( repeat )
  296.     {
  297.     item = 256 - count;
  298.     putitem( );
  299.     item = repeatitem;
  300.     putitem( );
  301.     }
  302.     else
  303.     {
  304.     item = count - 1;
  305.     putitem( );
  306.     for ( i = 0; i < count; i++ )
  307.         {
  308.         item = itembuf[i];
  309.         putitem( );
  310.         }
  311.     }
  312.     repeat = 1;
  313.     count = 0;
  314.     }
  315.  
  316. rleputitem( )
  317.     {
  318.     int i;
  319.  
  320.     if ( count == 128 )
  321.     rleputbuffer( );
  322.  
  323.     if ( repeat && count == 0 )
  324.     { /* Still initializing a repeat buf. */
  325.     itembuf[count] = repeatitem = rleitem;
  326.     count++;
  327.     }
  328.     else if ( repeat )
  329.     { /* Repeating - watch for end of run. */
  330.     if ( rleitem == repeatitem )
  331.         { /* Run continues. */
  332.         itembuf[count] = rleitem;
  333.         count++;
  334.         }
  335.     else
  336.         { /* Run ended - is it long enough to dump? */
  337.         if ( count > 2 )
  338.         { /* Yes, dump a repeat-mode buffer and start a new one. */
  339.         rleputbuffer( );
  340.         itembuf[count] = repeatitem = rleitem;
  341.         count++;
  342.         }
  343.         else
  344.         { /* Not long enough - convert to non-repeat mode. */
  345.         repeat = 0;
  346.         itembuf[count] = repeatitem = rleitem;
  347.         count++;
  348.         repeatcount = 1;
  349.         }
  350.         }
  351.     }
  352.     else
  353.     { /* Not repeating - watch for a run worth repeating. */
  354.     if ( rleitem == repeatitem )
  355.         { /* Possible run continues. */
  356.         repeatcount++;
  357.         if ( repeatcount > 3 )
  358.         { /* Long enough - dump non-repeat part and start repeat. */
  359.         count = count - ( repeatcount - 1 );
  360.         rleputbuffer( );
  361.         count = repeatcount;
  362.         for ( i = 0; i < count; i++ )
  363.             itembuf[i] = rleitem;
  364.         }
  365.         else
  366.         { /* Not long enough yet - continue as non-repeat buf. */
  367.         itembuf[count] = rleitem;
  368.         count++;
  369.         }
  370.         }
  371.     else
  372.         { /* Broken run. */
  373.         itembuf[count] = repeatitem = rleitem;
  374.         count++;
  375.         repeatcount = 1;
  376.         }
  377.     }
  378.  
  379.     rleitem = 0;
  380.     rlebitsperitem = 0;
  381.     rlebitshift = 8 - bitsperitem;
  382.     }
  383.  
  384. rleputgray( g )
  385. gray g;
  386.     {
  387.     if ( rlebitsperitem == 8 )
  388.     {
  389.     rleputitem( );
  390.     }
  391.     rleitem += g << rlebitshift;
  392.     rlebitsperitem += bitsperitem;
  393.     rlebitshift -= bitsperitem;
  394.     }
  395.  
  396. rleputrest( )
  397.     {
  398.     if ( rlebitsperitem > 0 )
  399.     rleputitem( );
  400.     if ( count > 0 )
  401.     rleputbuffer( );
  402.     printf( "\n" );
  403.     printf( "grestore\n" );
  404.     printf( "showpage\n" );
  405.     printf( "%%%%Trailer\n" );
  406.     }
  407.