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