home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3311 / ppmtopcl.c < prev   
Encoding:
C/C++ Source or Header  |  1991-05-10  |  11.8 KB  |  415 lines

  1. /* ppmtopcl.c - convert portable pixmap into PCL language for HP PaintJet and
  2.  *              PaintJet XL colour printers
  3.  * AJCD 12/3/91
  4.  * 
  5.  * usage:
  6.  *       ppmtopcl [-nopack] [-gamma <n>] [-presentation] [-dark]
  7.  *          [-diffuse] [-cluster] [-dither]
  8.  *          [-xshift <s>] [-yshift <s>]
  9.  *          [-xshift <s>] [-yshift <s>]
  10.  *          [-xsize|-width|-xscale <s>] [-ysize|-height|-yscale <s>]
  11.  *          [ppmfile]
  12.  *
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include <ppm.h>
  17. #include <ppmcmap.h>
  18.  
  19. #define MAXCOLORS 1024
  20.  
  21. extern double atof();
  22. extern int atoi();
  23.  
  24. char *usage="[-nopack] [-gamma <n>] [-presentation] [-dark]\n\
  25.             [-diffuse] [-cluster] [-dither]\n\
  26.             [-xshift <s>] [-yshift <s>]\n\
  27.             [-xshift <s>] [-yshift <s>]\n\
  28.             [-xsize|-width|-xscale <s>] [-ysize|-height|-yscale <s>]\n\
  29.             [ppmfile]";
  30.  
  31. #define PCL_MAXWIDTH 2048
  32. #define PCL_MAXHEIGHT 32767
  33. #define PCL_MAXVAL 255
  34.  
  35. static int nopack = 0;
  36. static int dark = 0;
  37. static int diffuse = 0;
  38. static int dither = 0;
  39. static int cluster = 0;
  40. static int xsize = 0;
  41. static int ysize = 0;
  42. static int xshift = 0;
  43. static int yshift = 0;
  44. static int quality = 0;
  45. static double xscale = 0.0;
  46. static double yscale = 0.0;
  47. static double gamma = 0.0;
  48.  
  49. /* argument types */
  50. #define DIM 0
  51. #define REAL 1
  52. #define BOOL 2
  53. static struct options {
  54.    char *name;
  55.    int type;
  56.    char *value;
  57. } options[] = {
  58.    {"gamma",        REAL, (char *)&gamma },
  59.    {"presentation", BOOL, (char *)&quality },
  60.    {"width",        DIM,  (char *)&xsize },
  61.    {"xsize",        DIM,  (char *)&xsize },
  62.    {"height",       DIM,  (char *)&ysize },
  63.    {"ysize",        DIM,  (char *)&ysize },
  64.    {"xscale",       REAL, (char *)&xscale },
  65.    {"yscale",       REAL, (char *)&yscale },
  66.    {"xshift",       DIM,  (char *)&xshift },
  67.    {"yshift",       DIM,  (char *)&yshift },
  68.    {"dark",         BOOL, (char *)&dark },
  69.    {"diffuse",      BOOL, (char *)&diffuse },
  70.    {"dither",       BOOL, (char *)&dither },
  71.    {"cluster",      BOOL, (char *)&cluster },
  72.    {"nopack",       BOOL, (char *)&nopack },
  73. };
  74.  
  75. #define putword(w) (putchar(((w)>>8) & 255), putchar((w) & 255))
  76.  
  77. int bitsperpixel(v)
  78.      int v;
  79. {
  80.    int bpp = 0;
  81.    while (v > 0) {  /* calculate # bits for value */
  82.       ++bpp;
  83.       v>>=1;
  84.    }
  85.    return (bpp);
  86. }
  87.  
  88. static char *inrow = NULL;
  89. static char *outrow = NULL;
  90. static /*signed*/ char *runcnt = NULL;
  91.  
  92. putbits(b, n) /* put #n bits in b out, packing into bytes; n=0 flushes bits */
  93.      int b, n; /* n should never be > 8 */
  94. {
  95.    static int out = 0;
  96.    static int cnt = 0;
  97.    static int num = 0;
  98.    static int pack = 0;
  99.    if (n) {
  100.       int xo = 0;
  101.       int xc = 0;
  102.       if (cnt+n > 8) {  /* overflowing current byte? */
  103.      xc = cnt + n - 8;
  104.      xo = (b & ~(-1 << xc)) << (8-xc);
  105.      n -= xc;
  106.      b >>= xc;
  107.       }
  108.       cnt += n;
  109.       out |= (b & ~(-1 << n)) << (8-cnt);
  110.       if (cnt >= 8) {
  111.      inrow[num++] = out;
  112.      out = xo;
  113.      cnt = xc;
  114.       }
  115.    } else { /* flush row */
  116.       int i;
  117.       if (cnt) {
  118.      inrow[num++] = out;
  119.      out = cnt = 0;
  120.       }
  121.       for (; num > 0 && inrow[num-1] == 0; num--); /* remove trailing zeros */
  122.       printf("\033*b"); 
  123.       if (num && !nopack) {            /* TIFF 4.0 packbits encoding */
  124.      int start = 0;
  125.      int next;
  126.      runcnt[start] = 0;
  127.      for (i = 1; i < num; i++) {
  128.         if (inrow[i] == inrow[i-1]) {
  129.            if (runcnt[start] <= 0 && runcnt[start] > -127)
  130.           runcnt[start]--;
  131.            else
  132.           runcnt[start = i] = 0;
  133.         } else {
  134.            if (runcnt[start] >= 0 && runcnt[start] < 127)
  135.           runcnt[start]++;
  136.            else
  137.           runcnt[start = i] = 0;
  138.         }
  139.      }
  140.      start = 0;
  141.      for (i = 0; i < num; i = next) {
  142.         int count = runcnt[i];
  143.         int from = i;
  144.         if (count >= 0) { /* merge two-byte runs */
  145.            for (;;) {
  146.           next = i+1+runcnt[i];
  147.           if(next >= num || runcnt[next] < 0 ||
  148.              count+runcnt[next]+1 > 127)
  149.              break;
  150.           count += runcnt[next]+1;
  151.           i = next;
  152.            }
  153.         }
  154.         next =  i + 1 + ((runcnt[i] < 0) ? -runcnt[i] : runcnt[i]);
  155.         if (next < num && count > 0 &&
  156.         runcnt[next] < 0 && runcnt[next] > -127) {
  157.            count--;
  158.            next--;
  159.            runcnt[next] = runcnt[next+1]-1;
  160.         }
  161.         outrow[start++] = count;
  162.         if (count >= 0) {
  163.            while (count-- >= 0)
  164.           outrow[start++] = inrow[from++];
  165.         } else
  166.            outrow[start++] = inrow[from];
  167.      }
  168.      if (start < num) {
  169.         num = start;
  170.         if (!pack) {
  171.            printf("2m");
  172.            pack = 1;
  173.         }
  174.      } else {
  175.         if (pack) {
  176.            printf("0m");
  177.            pack = 0;
  178.         }
  179.      }
  180.       }
  181.       printf("%dW", num);
  182.       for (i = 0; i < num; i++)
  183.      putchar(pack ? outrow[i] : inrow[i]);
  184.       num = 0; /* new row */
  185.    }
  186. }
  187.  
  188. main(argc, argv)
  189.      int argc;
  190.      char *argv[];
  191. {
  192.    FILE *ifd;
  193.    register pixel **pixels, *pixrow;
  194.    register int  row, col, bpp, i;
  195.    int rows, cols;
  196.    pixval maxval;
  197.    int bpr, bpg, bpb;
  198.    int render;
  199.    int colours, index;
  200.    colorhist_vector chv;
  201.    colorhash_table cht;
  202.    
  203.    pm_progname = argv[0];
  204.    
  205.    while (argc > 1 && argv[1][0] == '-') {
  206.       char *c, *val=argv[1]+1;
  207.       for (i = 0; i < sizeof(options)/sizeof(struct options); i++) {
  208.      if (strlen(val) <= strlen(options[i].name) &&
  209.          !strncmp(val, options[i].name, strlen(val))) {
  210.         switch (options[i].type) {
  211.         case DIM:
  212.            if (++argv, --argc == 1)
  213.           pm_usage(usage);
  214.            for (c = argv[1]; isdigit(*c); c++);
  215.            if (c[0] == 'p' && c[1] == 't') /* points */
  216.           *(int *)(options[i].value) = atoi(argv[1])*10;
  217.            else if (c[0] == 'd' && c[1] == 'p') /* decipoints */
  218.           *(int *)(options[i].value) = atoi(argv[1]);
  219.            else if (c[0] == 'i' && c[1] == 'n') /* inches */
  220.           *(int *)(options[i].value) = atoi(argv[1])*720;
  221.            else if (c[0] == 'c' && c[1] == 'm') /* centimetres */
  222.           *(int *)(options[i].value) = atoi(argv[1])*283.46457;
  223.            else if (!c[0]) /* dots */
  224.           *(int *)(options[i].value) = atoi(argv[1])*4;
  225.            else
  226.           pm_error("illegal unit of measure %s", c);
  227.            break;
  228.         case REAL:
  229.            if (++argv, --argc == 1)
  230.           pm_usage(usage);
  231.            *(double *)(options[i].value) = atof(argv[1]);
  232.            break;
  233.         case BOOL:
  234.            *(int *)(options[i].value) = 1;
  235.            break;
  236.         }
  237.         break;
  238.      }
  239.       }
  240.       if (i >= sizeof(options)/sizeof(struct options))
  241.      pm_usage(usage);
  242.       argv++; argc--;
  243.    }
  244.    if (argc > 2)
  245.       pm_usage(usage);
  246.    else if (argc == 2)
  247.       ifd = pm_openr(argv[1]);
  248.    else
  249.       ifd = stdin ;
  250.  
  251.    /* validate arguments */
  252.    if (diffuse+cluster+dither > 1)
  253.       pm_error("only one of -diffuse, -dither and -cluster may be used");
  254.    render = diffuse ? 4 : dither ? 3 : cluster ? 7 : 0;
  255.  
  256.    if (xsize != 0.0 && xscale != 0.0)
  257.       pm_error("only one of -xsize and -xscale may be used");
  258.  
  259.    if (ysize != 0.0 && yscale != 0.0)
  260.       pm_error("only one of -ysize and -yscale may be used");
  261.  
  262.    pixels = ppm_readppm( ifd, &cols, &rows, &maxval );
  263.    pm_close( ifd );
  264.  
  265.    /* limit checks */
  266.    if (cols > PCL_MAXWIDTH || rows > PCL_MAXHEIGHT)
  267.       pm_error("image too large; reduce with ppmscale");
  268.    if (maxval > PCL_MAXVAL)
  269.       pm_error("colour range too large; reduce with ppmcscale");
  270.  
  271.    /* Figure out the colormap. */
  272.    fprintf( stderr, "(Computing colormap..." ); fflush( stderr );
  273.    chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colours );
  274.    if ( chv == (colorhist_vector) 0 )
  275.       pm_error("too many colours; reduce with ppmquant", 0,0,0,0,0 );
  276.    fprintf( stderr, "  Done.  %d colors found.)\n", colours );
  277.  
  278.    /* And make a hash table for fast lookup. */
  279.    cht = ppm_colorhisttocolorhash( chv, colours );
  280.  
  281.    /* work out colour downloading mode */
  282.    index = bitsperpixel(colours);
  283.    if (index > 8) /* can't use indexed mode */
  284.       index = 0;
  285.    else
  286.       switch (index) { /* round up to 1,2,4,8 */
  287.       case 0: /* direct mode (no palette) */
  288.      bpp = bitsperpixel(maxval); /* bits per pixel */
  289.      bpg = bpp; bpb = bpp;
  290.      bpp = (bpp*3+7)>>3;     /* bytes per pixel now */
  291.      bpr = (bpp<<3)-bpg-bpb; 
  292.      bpp *= cols;            /* bytes per row now */
  293.      break;
  294.       case 5:         index++;
  295.       case 6:         index++;
  296.       case 3: case 7: index++;
  297.       default:
  298.      bpp = 8/index;
  299.      bpp = (cols+bpp-1)/bpp;      /* bytes per row */
  300.       }
  301.  
  302.    if ((inrow = (char *)malloc((unsigned)bpp)) == NULL ||
  303.        (outrow = (char *)malloc((unsigned)bpp*2)) == NULL ||
  304.        (runcnt = (/*signed*/ char *)malloc((unsigned)bpp)) == NULL)
  305.       pm_error("can't allocate space for row", 0,0,0,0,0);
  306.  
  307.    /* set up image details */
  308.    if (xscale != 0.0)
  309.       xsize = cols * xscale * 4;
  310.    if (yscale != 0.0)
  311.       ysize = rows * yscale * 4;
  312.  
  313. #ifdef DEBUG
  314.    fprintf(stderr, "dark    =%d\n", dark);
  315.    fprintf(stderr, "diffuse =%d\n", diffuse);
  316.    fprintf(stderr, "dither  =%d\n", dither);
  317.    fprintf(stderr, "cluster =%d\n", cluster);
  318.    fprintf(stderr, "quality =%d\n", quality);
  319.    fprintf(stderr, "xsize   =%d\n", xsize);
  320.    fprintf(stderr, "ysize   =%d\n", ysize);
  321.    fprintf(stderr, "xshift  =%d\n", xshift);
  322.    fprintf(stderr, "yshift  =%d\n", yshift);
  323.    fprintf(stderr, "xscale  =%lf\n", xscale);
  324.    fprintf(stderr, "yscale  =%lf\n", yscale);
  325.    fprintf(stderr, "gamma   =%lf\n", gamma);
  326.    fprintf(stderr, "index   =%d\n", index);
  327.    fprintf(stderr, "nopack  =%d\n", nopack);
  328. #endif
  329.  
  330.    /* write PCL header */
  331. /*   printf("\033&l26A");                         /* paper size */
  332.    printf("\033*r%ds%dT", cols, rows);          /* source width, height */
  333.    if (xshift != 0 || yshift != 0)
  334.       printf("\033&a%+dh%+dV", xshift, yshift); /* xshift, yshift */
  335.    if (quality)
  336.       printf("\033*o%dQ", quality);             /* print quality */
  337.    printf("\033*t");
  338.    if (xsize == 0 && ysize == 0)
  339.       printf("180r");                   /* resolution */
  340.    else {                               /* destination width, height */
  341.       if (xsize != 0)
  342.      printf("%dh", xsize);
  343.       if (ysize != 0)
  344.      printf("%dv", ysize);
  345.    }
  346.    if (gamma != 0)
  347.       printf("%.3lfi", gamma);                    /* gamma correction */
  348.    if (dark)
  349.       printf("%dk", dark);              /* scaling algorithms */
  350.    printf("%dJ", render);               /* rendering algorithm */
  351.    printf("\033*v18W");                           /* configure image data */
  352.       putchar(0); /* relative colours */
  353.       putchar(index ? 1 : 3); /* index/direct pixel mode */
  354.       putchar(index); /* ignored in direct pixel mode */
  355.       if (index) {
  356.      putchar(0);
  357.      putchar(0);
  358.      putchar(0);
  359.       } else {
  360.      putchar(bpr); /* bits per red */
  361.      putchar(bpg); /* bits per green */
  362.      putchar(bpb); /* bits per blue */
  363.       }
  364.       putword(maxval); /* max red reference */
  365.       putword(maxval); /* max green reference */
  366.       putword(maxval); /* max blue reference */
  367.       putword(0); /* min red reference */
  368.       putword(0); /* min green reference */
  369.       putword(0); /* min blue reference */
  370.    if (index) {                        /* set palette */
  371.       for (i = 0; i < colours; i++) {
  372.      int r, g, b;
  373.      r = PPM_GETR( chv[i].color );
  374.      g = PPM_GETG( chv[i].color );
  375.      b = PPM_GETB( chv[i].color );
  376.      if (i == 0)
  377.         printf("\033*v");
  378.      if (r)
  379.         printf("%da", r);
  380.      if (g)
  381.         printf("%db", g);
  382.      if (b)
  383.         printf("%dc", b);
  384.      if (i == colours-1)
  385.         printf("%dI", i);    /* assign colour index */
  386.      else
  387.         printf("%di", i);    /* assign colour index */
  388.       }
  389.    }
  390.    ppm_freecolorhist( chv );
  391.  
  392.    /* start raster graphics at CAP */
  393.    printf("\033*r%dA", (xsize != 0 || ysize != 0) ? 3 : 1);
  394.  
  395.    for (row = 0; row < rows; row++) {
  396.       if (index) { /* indexed colour mode */
  397.      int out, cnt;
  398.      out = cnt = 0;
  399.      for (col = 0, pixrow=pixels[row]; col < cols; col++, pixrow++) {
  400.         putbits(ppm_lookupcolor( cht, *pixrow ), index);
  401.      }
  402.      putbits(0, 0); /* flush row */
  403.       } else { /* direct colour mode */
  404.      for (col = 0, pixrow=pixels[row]; col < cols; col++, pixrow++) {
  405.         putbits(PPM_GETR( *pixrow ), bpr);
  406.         putbits(PPM_GETG( *pixrow ), bpg);
  407.         putbits(PPM_GETB( *pixrow ), bpb); /* don't need to flush */
  408.      }
  409.      putbits(0, 0); /* flush row */
  410.       }
  411.    }
  412.    printf("\033*rC"); /* end raster graphics */
  413.    exit(0);
  414. }
  415.