mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (07/21/89)
Submitted-by: gfr@cobra.mitre.org (Glenn Roberts) Posting-number: Volume 1, Issue 53 Archive-name: pc-paintbrush [ I couldn't test this one out - but here it is. Note that this is not a 'shar' format posting. -CWM ] The program below converts PC-paintbrush images to Sun rasterfile format. We've found this to be of some use for creating images, logos, etc. Please feel free to place this program in the Sun-Spots archives. - Glenn Roberts, The MITRE Corp., McLean VA (703) 883-6820 gfr@cobra.mitre.org =-=-=-=- cut here =-=-=-=-=-= /* ** pcx2ras -- Convert PC Paintbrush files to Sun rasterfile format ** ** Version: 2.1 ** ** Usage: pcx2ras [-d] [-e] [-t type] [input.pcx] [output.pr] ** ** Options: ** ** -d Display the pixrect before outputting to file (user ** must be in SunView). ** ** -e Shorthand for -t 2 ** ** -t type Specify the type of rasterfile to write: ** 0 Old format files compatible with Release 1.1. ** 1 Standard format. ** 2 Run-length encoding of bytes. ** 65535 To experiment with private encodings. ** ** Authors: ** Glenn F. Roberts, 703-883-6820 (gfr@cobra.mitre.org) ** Frederick Kuhl, 703-883-7559 (fkuhl@amadeus.mitre.org) ** MITRE Corporation ** 7525 Colshire Drive, McLean VA 22102 ** ** History: ** ** Version 1.0, 11 Aug 87 Frederick Kuhl ** ** This version handles only EGA images and it treats them as if ** they were monochrome; specifically, it converts only the first ** (red) plane of multiplane images and ignores the other planes. ** Pixels are converted to pixels (and negated). Coordinate systems ** of Paintbrush and Sun are the same. The rasterfile definition ** requires that each scan line be extended to an integral multiple ** of 16 bits. But the number of scan lines is the same. ** ** Version 2.0, 12 Aug 87 Glenn F. Roberts ** ** 1) Program now functions by converting paintbrush file into ** Sun pixrect form. This makes it easy to perform any ** pixrect operation on the image. Image can be displayed ** using Sun's screenload program. ** 2) Input can be either piped (stdin and stdout) or from ** command line file names. ** 3) Color is now supported. To obtain black and white image ** pipe the output of this program through rasfilter8to1. ** ** 4) Image can be previewed using -d switch. ** ** Version 2.1, 13 Aug 87 Glenn F. Roberts ** ** -t and -e switches added. ** ** Version 2.1.1, 6 Jan 89 Glenn F. Roberts ** ** added SWAB constant so can be compiled for 80386 ** (previously hard-wired for 68000). */ #include <stdio.h> #include <suntool/sunview.h> #include <suntool/canvas.h> #define COLORMAP_SIZE 16 /* define SWAB here for 68000 machines */ /* #define SWAB */ char *malloc(); /* This is the header for .PCX files */ struct pcx_hdr_st { unsigned char manufacturer; /* mfg. code (ignore) */ unsigned char version; /* version should be 5 */ unsigned char encoding; /* should be 1 */ unsigned char bitsPerPix; /* 1 for EGA images */ short window [4]; /* xmin,ymin,xmax,ymax */ short hres; /* 640 for EGA */ short vres; /* 350 for EGA */ unsigned char colormap [48]; /* color map */ unsigned char reserved; /* reserved */ unsigned char nplanes; /* 4 for EGA */ short bytesPerLine; /* this IS used! */ short unused [30]; /* filler (to 128) */ } hdr; int display, prtype; FILE *fin, *fout; main (argc, argv) int argc; char *argv[]; { int i; struct pixrect *picture, *pcx_load(); Frame frame; Canvas canvas; Pixwin *pw; colormap_t prcolormap; unsigned char red[COLORMAP_SIZE]; unsigned char green[COLORMAP_SIZE]; unsigned char blue[COLORMAP_SIZE]; /* set defaults for user-controlled arguments */ prtype = RT_STANDARD; display = FALSE; fin = stdin; fout = stdout; /* parse any command line arguments */ parse_arguments(argc, argv); /* load pixrect from paintbrush file */ picture = pcx_load(fin, &hdr); fprintf(stderr, "\nImage loaded... width = %d, height = %d\n", picture->pr_size.x, picture->pr_size.y); /* create corresponding Sun color maps */ for (i=0; i<COLORMAP_SIZE; i++) { red[i] = hdr.colormap[i*3]; green[i] = hdr.colormap[i*3+1]; blue[i] = hdr.colormap[i*3+2]; } prcolormap.type = RMT_EQUAL_RGB; prcolormap.length = COLORMAP_SIZE; prcolormap.map[0] = red; prcolormap.map[1] = green; prcolormap.map[2] = blue; /* if requested, show image to user, then wait for user to 'quit' */ if (display) { frame = window_create(NULL, FRAME, WIN_WIDTH, picture->pr_size.x+10, WIN_HEIGHT, picture->pr_size.y+25, FRAME_LABEL, "Paintbrush", 0); canvas = window_create(frame, CANVAS, CANVAS_RETAINED, FALSE, CANVAS_AUTO_EXPAND, TRUE, CANVAS_AUTO_SHRINK, TRUE, CANVAS_WIDTH, picture->pr_size.x, CANVAS_HEIGHT, picture->pr_size.y, 0); pw = canvas_pixwin(canvas); pw_setcmsname(pw, "paint"); pw_putcolormap(pw, 0, COLORMAP_SIZE, red, green, blue); window_set(canvas, CANVAS_RETAINED, TRUE, 0); pw_rop(pw, 0, 0, picture->pr_size.x, picture->pr_size.y, PIX_SRC, picture, 0, 0); window_main_loop(frame); } /* now write the pixrect output */ pr_dump(picture, fout, &prcolormap, prtype, prtype==RT_BYTE_ENCODED); /* return normally */ exit(0); } /* parse_arguments -- parse command-line arguments (file names ** and switches). */ parse_arguments(argc, argv) int argc; char *argv[]; { int nfiles; nfiles = 0; while (--argc > 0) { ++argv; if ((*argv)[0] == '-') /* process switches */ switch ((*argv)[1]) { case 'd': display = TRUE; break; case 'e': prtype = RT_BYTE_ENCODED; break; case 't': prtype = atoi(*++argv); --argc; break; } else /* process file names */ switch (nfiles) { case 0: if ((fin = fopen(*argv, "r")) == NULL) { fprintf(stderr, "Error opening input file\n"); exit(1); } nfiles++; break; case 1: if ((fout = fopen(*argv, "w")) == NULL) { fprintf(stderr, "Error opening output file\n"); exit(1); } nfiles++; break; } } } /* pcx_load -- Load paintbrush file into memory pixrect ** (similar to SunView pr_load() routine). */ struct pixrect *pcx_load(input, hdr) FILE *input; struct pcx_hdr_st *hdr; { int width, height, depth, byte, col, row, i; int value; struct pixrect *pr; char *buff0, *buff1, *buff2, *buff3; char byte0, byte1, byte2, byte3; /* first load the paintbrush header */ pcx_load_header(input, hdr); width = hdr->window[2] - hdr->window[0] + 1; height = hdr->window[3] - hdr->window[1] + 1; depth = 8; /* create a memory pixrect to store the image */ pr = mem_create(width, height, depth); /* allocate line buffers for 4 planes */ buff0 = malloc (hdr->bytesPerLine); buff1 = malloc (hdr->bytesPerLine); buff2 = malloc (hdr->bytesPerLine); buff3 = malloc (hdr->bytesPerLine); /* process each PCX scan line */ fprintf(stderr, "\nConverting image ..."); for (row = 0; row < height; row++) { get_line(input, buff0, hdr->bytesPerLine); get_line(input, buff1, hdr->bytesPerLine); get_line(input, buff2, hdr->bytesPerLine); get_line(input, buff3, hdr->bytesPerLine); for (byte=0; byte<hdr->bytesPerLine; byte++) { byte0 = buff0[byte]; byte1 = buff1[byte]; byte2 = buff2[byte]; byte3 = buff3[byte]; for (col=byte*8+7, i=7; i>=0; i--) { value = ((byte3 & 0x01) << 3) + ((byte2 & 0x01) << 2) + ((byte1 & 0x01) << 1) + (byte0 & 0x01); if (col < width) pr_put(pr, col--, row, value); byte0 >>= 1; byte1 >>= 1; byte2 >>= 1; byte3 >>= 1; } } } free(buff0); free(buff1); free(buff2); free(buff3); return pr; } /* get_line -- Get a scan line from paintbrush file */ get_line(input, buffer, len) FILE *input; char *buffer; int len; { int i, aByte; for (i=0; i<len; ++i) { if ((aByte = encgetc(input)) == EOF) { fprintf(stderr, "Unexpected EOF\n"); exit (1); } *buffer++ = aByte; } } /* pcx_load_header -- Load header from a paintbrush file ** (similar to SunView pr_load_header() routine). */ pcx_load_header(input, hdr) FILE *input; struct pcx_hdr_st *hdr; { fread (hdr, sizeof(struct pcx_hdr_st), 1, input); #ifdef SWAB /* byte order is reversed between 8088 and 68000: */ swab (hdr->window, hdr->window, 8); swab (&hdr->hres, &hdr->hres, 2); swab (&hdr->vres, &hdr->vres, 2); swab (&hdr->bytesPerLine, &hdr->bytesPerLine, 2); #endif fprintf (stderr,"\n*** Header Information:\n\n"); fprintf (stderr,"mfg. code: %d\n", hdr->manufacturer); fprintf (stderr,"version: %d\n", hdr->version); fprintf (stderr,"encoding: %d\n", hdr->encoding); fprintf (stderr,"bits per pixel: %d\n", hdr->bitsPerPix); fprintf (stderr,"window: %d %d %d %d\n", hdr->window[0], hdr->window[1], hdr->window[2], hdr->window[3]); fprintf (stderr,"horiz. resolution: %d\n", hdr->hres); fprintf (stderr,"vert. resolution: %d\n", hdr->vres); fprintf (stderr,"number of planes: %d\n", hdr->nplanes); fprintf (stderr,"bytes per line: %d\n", hdr->bytesPerLine); } /* encgetc -- Return next encoded picture byte from input ** crack the run-length encoding */ encgetc (input) FILE *input; { static int theByte, count = 0; int next; if (count > 0) { --count; return theByte; } else { if ((next=getc(input)) == EOF) return EOF; if ((next & 0xC0) == 0xC0) { count = ((int)next & 0x003F) - 1; if ((next=getc(input)) == EOF) { fprintf (stderr, "read failed\n"); exit (1); } theByte = next; return theByte; } else return next; } }