home *** CD-ROM | disk | FTP | other *** search
- /* ppmtopcl.c - convert portable pixmap into PCL language for HP PaintJet and
- * PaintJet XL colour printers
- * AJCD 12/3/91
- *
- * usage:
- * ppmtopcl [-nopack] [-gamma <n>] [-presentation] [-dark]
- * [-diffuse] [-cluster] [-dither]
- * [-xshift <s>] [-yshift <s>]
- * [-xshift <s>] [-yshift <s>]
- * [-xsize|-width|-xscale <s>] [-ysize|-height|-yscale <s>]
- * [ppmfile]
- *
- */
-
- #include <stdio.h>
- #include <ppm.h>
- #include <ppmcmap.h>
-
- #define MAXCOLORS 1024
-
- extern double atof();
- extern int atoi();
-
- char *usage="[-nopack] [-gamma <n>] [-presentation] [-dark]\n\
- [-diffuse] [-cluster] [-dither]\n\
- [-xshift <s>] [-yshift <s>]\n\
- [-xshift <s>] [-yshift <s>]\n\
- [-xsize|-width|-xscale <s>] [-ysize|-height|-yscale <s>]\n\
- [ppmfile]";
-
- #define PCL_MAXWIDTH 2048
- #define PCL_MAXHEIGHT 32767
- #define PCL_MAXVAL 255
-
- static int nopack = 0;
- static int dark = 0;
- static int diffuse = 0;
- static int dither = 0;
- static int cluster = 0;
- static int xsize = 0;
- static int ysize = 0;
- static int xshift = 0;
- static int yshift = 0;
- static int quality = 0;
- static double xscale = 0.0;
- static double yscale = 0.0;
- static double gamma = 0.0;
-
- /* argument types */
- #define DIM 0
- #define REAL 1
- #define BOOL 2
- static struct options {
- char *name;
- int type;
- char *value;
- } options[] = {
- {"gamma", REAL, (char *)&gamma },
- {"presentation", BOOL, (char *)&quality },
- {"width", DIM, (char *)&xsize },
- {"xsize", DIM, (char *)&xsize },
- {"height", DIM, (char *)&ysize },
- {"ysize", DIM, (char *)&ysize },
- {"xscale", REAL, (char *)&xscale },
- {"yscale", REAL, (char *)&yscale },
- {"xshift", DIM, (char *)&xshift },
- {"yshift", DIM, (char *)&yshift },
- {"dark", BOOL, (char *)&dark },
- {"diffuse", BOOL, (char *)&diffuse },
- {"dither", BOOL, (char *)&dither },
- {"cluster", BOOL, (char *)&cluster },
- {"nopack", BOOL, (char *)&nopack },
- };
-
- #define putword(w) (putchar(((w)>>8) & 255), putchar((w) & 255))
-
- int bitsperpixel(v)
- int v;
- {
- int bpp = 0;
- while (v > 0) { /* calculate # bits for value */
- ++bpp;
- v>>=1;
- }
- return (bpp);
- }
-
- static char *inrow = NULL;
- static char *outrow = NULL;
- static /*signed*/ char *runcnt = NULL;
-
- putbits(b, n) /* put #n bits in b out, packing into bytes; n=0 flushes bits */
- int b, n; /* n should never be > 8 */
- {
- static int out = 0;
- static int cnt = 0;
- static int num = 0;
- static int pack = 0;
- if (n) {
- int xo = 0;
- int xc = 0;
- if (cnt+n > 8) { /* overflowing current byte? */
- xc = cnt + n - 8;
- xo = (b & ~(-1 << xc)) << (8-xc);
- n -= xc;
- b >>= xc;
- }
- cnt += n;
- out |= (b & ~(-1 << n)) << (8-cnt);
- if (cnt >= 8) {
- inrow[num++] = out;
- out = xo;
- cnt = xc;
- }
- } else { /* flush row */
- int i;
- if (cnt) {
- inrow[num++] = out;
- out = cnt = 0;
- }
- for (; num > 0 && inrow[num-1] == 0; num--); /* remove trailing zeros */
- printf("\033*b");
- if (num && !nopack) { /* TIFF 4.0 packbits encoding */
- int start = 0;
- int next;
- runcnt[start] = 0;
- for (i = 1; i < num; i++) {
- if (inrow[i] == inrow[i-1]) {
- if (runcnt[start] <= 0 && runcnt[start] > -127)
- runcnt[start]--;
- else
- runcnt[start = i] = 0;
- } else {
- if (runcnt[start] >= 0 && runcnt[start] < 127)
- runcnt[start]++;
- else
- runcnt[start = i] = 0;
- }
- }
- start = 0;
- for (i = 0; i < num; i = next) {
- int count = runcnt[i];
- int from = i;
- if (count >= 0) { /* merge two-byte runs */
- for (;;) {
- next = i+1+runcnt[i];
- if(next >= num || runcnt[next] < 0 ||
- count+runcnt[next]+1 > 127)
- break;
- count += runcnt[next]+1;
- i = next;
- }
- }
- next = i + 1 + ((runcnt[i] < 0) ? -runcnt[i] : runcnt[i]);
- if (next < num && count > 0 &&
- runcnt[next] < 0 && runcnt[next] > -127) {
- count--;
- next--;
- runcnt[next] = runcnt[next+1]-1;
- }
- outrow[start++] = count;
- if (count >= 0) {
- while (count-- >= 0)
- outrow[start++] = inrow[from++];
- } else
- outrow[start++] = inrow[from];
- }
- if (start < num) {
- num = start;
- if (!pack) {
- printf("2m");
- pack = 1;
- }
- } else {
- if (pack) {
- printf("0m");
- pack = 0;
- }
- }
- }
- printf("%dW", num);
- for (i = 0; i < num; i++)
- putchar(pack ? outrow[i] : inrow[i]);
- num = 0; /* new row */
- }
- }
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- FILE *ifd;
- register pixel **pixels, *pixrow;
- register int row, col, bpp, i;
- int rows, cols;
- pixval maxval;
- int bpr, bpg, bpb;
- int render;
- int colours, index;
- colorhist_vector chv;
- colorhash_table cht;
-
- pm_progname = argv[0];
-
- while (argc > 1 && argv[1][0] == '-') {
- char *c, *val=argv[1]+1;
- for (i = 0; i < sizeof(options)/sizeof(struct options); i++) {
- if (strlen(val) <= strlen(options[i].name) &&
- !strncmp(val, options[i].name, strlen(val))) {
- switch (options[i].type) {
- case DIM:
- if (++argv, --argc == 1)
- pm_usage(usage);
- for (c = argv[1]; isdigit(*c); c++);
- if (c[0] == 'p' && c[1] == 't') /* points */
- *(int *)(options[i].value) = atoi(argv[1])*10;
- else if (c[0] == 'd' && c[1] == 'p') /* decipoints */
- *(int *)(options[i].value) = atoi(argv[1]);
- else if (c[0] == 'i' && c[1] == 'n') /* inches */
- *(int *)(options[i].value) = atoi(argv[1])*720;
- else if (c[0] == 'c' && c[1] == 'm') /* centimetres */
- *(int *)(options[i].value) = atoi(argv[1])*283.46457;
- else if (!c[0]) /* dots */
- *(int *)(options[i].value) = atoi(argv[1])*4;
- else
- pm_error("illegal unit of measure %s", c);
- break;
- case REAL:
- if (++argv, --argc == 1)
- pm_usage(usage);
- *(double *)(options[i].value) = atof(argv[1]);
- break;
- case BOOL:
- *(int *)(options[i].value) = 1;
- break;
- }
- break;
- }
- }
- if (i >= sizeof(options)/sizeof(struct options))
- pm_usage(usage);
- argv++; argc--;
- }
- if (argc > 2)
- pm_usage(usage);
- else if (argc == 2)
- ifd = pm_openr(argv[1]);
- else
- ifd = stdin ;
-
- /* validate arguments */
- if (diffuse+cluster+dither > 1)
- pm_error("only one of -diffuse, -dither and -cluster may be used");
- render = diffuse ? 4 : dither ? 3 : cluster ? 7 : 0;
-
- if (xsize != 0.0 && xscale != 0.0)
- pm_error("only one of -xsize and -xscale may be used");
-
- if (ysize != 0.0 && yscale != 0.0)
- pm_error("only one of -ysize and -yscale may be used");
-
- pixels = ppm_readppm( ifd, &cols, &rows, &maxval );
- pm_close( ifd );
-
- /* limit checks */
- if (cols > PCL_MAXWIDTH || rows > PCL_MAXHEIGHT)
- pm_error("image too large; reduce with ppmscale");
- if (maxval > PCL_MAXVAL)
- pm_error("colour range too large; reduce with ppmcscale");
-
- /* Figure out the colormap. */
- fprintf( stderr, "(Computing colormap..." ); fflush( stderr );
- chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colours );
- if ( chv == (colorhist_vector) 0 )
- pm_error("too many colours; reduce with ppmquant", 0,0,0,0,0 );
- fprintf( stderr, " Done. %d colors found.)\n", colours );
-
- /* And make a hash table for fast lookup. */
- cht = ppm_colorhisttocolorhash( chv, colours );
-
- /* work out colour downloading mode */
- index = bitsperpixel(colours);
- if (index > 8) /* can't use indexed mode */
- index = 0;
- else
- switch (index) { /* round up to 1,2,4,8 */
- case 0: /* direct mode (no palette) */
- bpp = bitsperpixel(maxval); /* bits per pixel */
- bpg = bpp; bpb = bpp;
- bpp = (bpp*3+7)>>3; /* bytes per pixel now */
- bpr = (bpp<<3)-bpg-bpb;
- bpp *= cols; /* bytes per row now */
- break;
- case 5: index++;
- case 6: index++;
- case 3: case 7: index++;
- default:
- bpp = 8/index;
- bpp = (cols+bpp-1)/bpp; /* bytes per row */
- }
-
- if ((inrow = (char *)malloc((unsigned)bpp)) == NULL ||
- (outrow = (char *)malloc((unsigned)bpp*2)) == NULL ||
- (runcnt = (/*signed*/ char *)malloc((unsigned)bpp)) == NULL)
- pm_error("can't allocate space for row", 0,0,0,0,0);
-
- /* set up image details */
- if (xscale != 0.0)
- xsize = cols * xscale * 4;
- if (yscale != 0.0)
- ysize = rows * yscale * 4;
-
- #ifdef DEBUG
- fprintf(stderr, "dark =%d\n", dark);
- fprintf(stderr, "diffuse =%d\n", diffuse);
- fprintf(stderr, "dither =%d\n", dither);
- fprintf(stderr, "cluster =%d\n", cluster);
- fprintf(stderr, "quality =%d\n", quality);
- fprintf(stderr, "xsize =%d\n", xsize);
- fprintf(stderr, "ysize =%d\n", ysize);
- fprintf(stderr, "xshift =%d\n", xshift);
- fprintf(stderr, "yshift =%d\n", yshift);
- fprintf(stderr, "xscale =%lf\n", xscale);
- fprintf(stderr, "yscale =%lf\n", yscale);
- fprintf(stderr, "gamma =%lf\n", gamma);
- fprintf(stderr, "index =%d\n", index);
- fprintf(stderr, "nopack =%d\n", nopack);
- #endif
-
- /* write PCL header */
- /* printf("\033&l26A"); /* paper size */
- printf("\033*r%ds%dT", cols, rows); /* source width, height */
- if (xshift != 0 || yshift != 0)
- printf("\033&a%+dh%+dV", xshift, yshift); /* xshift, yshift */
- if (quality)
- printf("\033*o%dQ", quality); /* print quality */
- printf("\033*t");
- if (xsize == 0 && ysize == 0)
- printf("180r"); /* resolution */
- else { /* destination width, height */
- if (xsize != 0)
- printf("%dh", xsize);
- if (ysize != 0)
- printf("%dv", ysize);
- }
- if (gamma != 0)
- printf("%.3lfi", gamma); /* gamma correction */
- if (dark)
- printf("%dk", dark); /* scaling algorithms */
- printf("%dJ", render); /* rendering algorithm */
- printf("\033*v18W"); /* configure image data */
- putchar(0); /* relative colours */
- putchar(index ? 1 : 3); /* index/direct pixel mode */
- putchar(index); /* ignored in direct pixel mode */
- if (index) {
- putchar(0);
- putchar(0);
- putchar(0);
- } else {
- putchar(bpr); /* bits per red */
- putchar(bpg); /* bits per green */
- putchar(bpb); /* bits per blue */
- }
- putword(maxval); /* max red reference */
- putword(maxval); /* max green reference */
- putword(maxval); /* max blue reference */
- putword(0); /* min red reference */
- putword(0); /* min green reference */
- putword(0); /* min blue reference */
- if (index) { /* set palette */
- for (i = 0; i < colours; i++) {
- int r, g, b;
- r = PPM_GETR( chv[i].color );
- g = PPM_GETG( chv[i].color );
- b = PPM_GETB( chv[i].color );
- if (i == 0)
- printf("\033*v");
- if (r)
- printf("%da", r);
- if (g)
- printf("%db", g);
- if (b)
- printf("%dc", b);
- if (i == colours-1)
- printf("%dI", i); /* assign colour index */
- else
- printf("%di", i); /* assign colour index */
- }
- }
- ppm_freecolorhist( chv );
-
- /* start raster graphics at CAP */
- printf("\033*r%dA", (xsize != 0 || ysize != 0) ? 3 : 1);
-
- for (row = 0; row < rows; row++) {
- if (index) { /* indexed colour mode */
- int out, cnt;
- out = cnt = 0;
- for (col = 0, pixrow=pixels[row]; col < cols; col++, pixrow++) {
- putbits(ppm_lookupcolor( cht, *pixrow ), index);
- }
- putbits(0, 0); /* flush row */
- } else { /* direct colour mode */
- for (col = 0, pixrow=pixels[row]; col < cols; col++, pixrow++) {
- putbits(PPM_GETR( *pixrow ), bpr);
- putbits(PPM_GETG( *pixrow ), bpg);
- putbits(PPM_GETB( *pixrow ), bpb); /* don't need to flush */
- }
- putbits(0, 0); /* flush row */
- }
- }
- printf("\033*rC"); /* end raster graphics */
- exit(0);
- }
-