158e #include #include #include #include static RGB egapal[16] = { {0, 0, 0}, {0, 0, 170}, {0, 170, 0}, {0, 170, 170}, {170, 0, 0}, {170, 0, 170}, {170, 85, 0}, {170, 170, 170}, {85, 85, 85}, {85, 85, 255}, {85, 255, 85}, {85, 255, 255}, {255, 85, 85}, {255, 85, 255}, {255, 255, 85}, {255, 255, 255} }; static RGB monopal[2] = {{0, 0, 0}, {255, 255, 255}}; static void planes_to_pixels(unsigned char *pixels, unsigned char *bitplanes, int bytesperline, int planes, int bitsperpixel) { int i, j; int npixels; unsigned char *p; /* truecolor */ if (bitsperpixel == 8) { unsigned char *bp = bitplanes; for (i = 0; i < 3; i++) { p = pixels + i; for (j = 0; j < bytesperline; j++, p += 3) *p = *(bp++); } return; } /* clear the pixel buffer */ npixels = (bytesperline * 8) / bitsperpixel; p = pixels; while (--npixels >= 0) *p++ = 0; /* do the format conversion */ for (i = 0; i < planes; i++) { int pixbit, bits, mask; p = pixels; pixbit = (1 << i); for (j = 0; j < bytesperline; j++) { bits = *bitplanes++; for (mask = 0x80; mask != 0; mask >>= 1, p++) { if (bits & mask) *p |= pixbit; } } } } static void unpack_pixels(unsigned char *pixels, unsigned char *bitplanes, int bytesperline, int bitsperpixel) { register int bits; if (bitsperpixel == 8) { while (--bytesperline >= 0) *pixels++ = *bitplanes++; } else if (bitsperpixel == 4) { while (--bytesperline >= 0) { bits = *bitplanes++; *pixels++ = (bits >> 4) & 0x0f; *pixels++ = bits & 0x0f; } } else if (bitsperpixel == 2) { while (--bytesperline >= 0) { bits = *bitplanes++; *pixels++ = (bits >> 6) & 0x03; *pixels++ = (bits >> 4) & 0x03; *pixels++ = (bits >> 2) & 0x03; *pixels++ = bits & 0x03; } } else if (bitsperpixel == 1) { while (--bytesperline >= 0) { bits = *bitplanes++; *pixels++ = ((bits & 0x80) != 0); *pixels++ = ((bits & 0x40) != 0); *pixels++ = ((bits & 0x20) != 0); *pixels++ = ((bits & 0x10) != 0); *pixels++ = ((bits & 0x08) != 0); *pixels++ = ((bits & 0x04) != 0); *pixels++ = ((bits & 0x02) != 0); *pixels++ = ((bits & 0x01) != 0); } } } static unsigned char *read_image(FILE *fp, int totbytes) { unsigned char *buf, *bp; int c, count; buf = bp = (unsigned char *)malloc(totbytes); while (totbytes > 0) { if ((c = getc(fp)) == EOF) { fprintf(stderr, "Premature end of file\n"); return NULL; } if ((c & 0xc0) != 0xc0) { *(bp++) = c; --totbytes; continue; } count = c & 0x3f; if ((c = getc(fp)) == EOF) { fprintf(stderr, "Premature end of file\n"); return NULL; } if (count > totbytes) { fprintf(stderr, "Repeat count spans end of image, " "count = %d, totbytes = %d\n", count, totbytes); return NULL; } totbytes -= count; while (--count >= 0) *(bp++) = c; } return buf; } RGB *read_pcx(char *filename, int *width, int *height) { FILE *f; PCXHDR hdr; int w, h; RGB pal256[256], *pal = NULL; int truecolor = 0; unsigned char *image = NULL, *pixels = NULL; int linebytes; RGB *buf = NULL, *bp; int x, y; if (! (f = fopen(filename,"r"))) return (0); if (fread(&hdr, 1, sizeof(PCXHDR), f) < sizeof(PCXHDR)) { fprintf(stderr, "Premature end of file\n"); goto err; } switch (hdr.bitsperpixel) { case 1: if (hdr.planes > 4) goto fail; break; case 2: case 4: if (hdr.planes != 1) goto fail; break; case 8: if (hdr.planes != 1) { if (hdr.planes == 3 || hdr.planes == 4) truecolor++; else goto fail; } break; default: fail: fprintf(stderr, "Can't handle %d bits per pixel image with " "%d planes\n", hdr.bitsperpixel, hdr.planes); goto err; } if (! truecolor) { if (hdr.bitsperpixel == 8) { fseek(f, -(sizeof(pal256) + 1), SEEK_END); if (getc(f) != 0x0c) { fprintf(stderr, "Bad color map signature\n"); goto err; } fread(pal256, 1, sizeof(pal256), f); fseek(f, sizeof(PCXHDR), SEEK_SET); pal = pal256; } else { pal = (hdr.bitsperpixel == 1 && hdr.planes == 1 ? monopal : (hdr.version == 0 || hdr.version == 3 ? egapal : hdr.palette)); } } w = (hdr.xmax - hdr.xmin) + 1; h = (hdr.ymax - hdr.ymin) + 1; linebytes = hdr.bytesperline * hdr.planes; if (! (image = read_image(f, linebytes * h))) goto err; buf = bp = (RGB *)malloc(w * sizeof(RGB) * h); pixels = (unsigned char *)malloc(truecolor ? hdr.bytesperline * 3 : hdr.bytesperline * 8 / hdr.bitsperpixel); for (y = 0; y < h; y++) { if (hdr.planes == 1) unpack_pixels(pixels, image + y * linebytes, hdr.bytesperline, hdr.bitsperpixel); else planes_to_pixels(pixels, image + y * linebytes, hdr.bytesperline, hdr.planes, hdr.bitsperpixel); if (truecolor) { RGB *p = (RGB *)pixels; for (x = 0; x < w; x++) *(bp++) = *(p++); } else { for (x = 0; x < w; x++) *(bp++) = pal[pixels[x]]; } } *width = w; *height = h; err: if (image) free(image); if (pixels) free(pixels); fclose(f); return buf; } . 0