1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
16 #define PCX_MAGIC 0x0a /* first byte in a PCX image file */
17 #define PCX_LAST_VERSION 5 /* last acceptable version number */
18 #define PCX_ENCODING 1 /* PCX encoding method */
19 #define PCX_256COLORS_MAGIC 0x0c /* first byte of a PCX 256 color map */
20 #define PCX_MAXDEPTH 8 /* supports up to 8 bits per pixel */
21 #define PCX_MAXCOLORS 256 /* maximum number of colors */
22 #define PCX_HEADER_SIZE 128
23 #define PCX_PALETTE_SIZE (3 * PCX_MAXCOLORS)
27 unsigned char signature; /* PCX file identifier */
28 unsigned char version; /* version compatibility level */
29 unsigned char encoding; /* encoding method */
30 unsigned char bits_per_pixel; /* bits per pixel, or depth */
31 unsigned short xmin; /* X position of left edge */
32 unsigned short ymin; /* Y position of top edge */
33 unsigned short xmax; /* X position of right edge */
34 unsigned short ymax; /* Y position of bottom edge */
35 unsigned short hres; /* X screen resolution of source image */
36 unsigned short vres; /* Y screen resolution of source image */
37 unsigned char palette[16][3]; /* PCX color map */
38 unsigned char reserved; /* should be 0, 1 if std res fax */
39 unsigned char color_planes; /* bit planes in image */
40 unsigned short bytes_per_line;/* byte delta between scanlines */
41 unsigned short palette_type; /* 0 = undef, 1 = color, 2 = grayscale */
42 unsigned char filler[58]; /* fill to struct size of 128 */
45 static boolean PCX_LoadImage(); /* Routine to load PCX bitmap */
46 static boolean PCX_LoadColormap(); /* Routine to load PCX colormap */
48 Image *Read_PCX_to_Image(char *filename)
51 unsigned char buffer[PCX_HEADER_SIZE];
52 struct PCX_Header pcx;
54 int width, height, depth;
56 if (!(file = fopen(filename, "r")))
60 if (fread(buffer, 1, PCX_HEADER_SIZE, file) != PCX_HEADER_SIZE)
66 pcx.signature = buffer[0];
67 pcx.version = buffer[1];
68 pcx.encoding = buffer[2];
69 pcx.bits_per_pixel = buffer[3];
70 pcx.xmin = buffer[4] + 256 * buffer[5];
71 pcx.ymin = buffer[6] + 256 * buffer[7];
72 pcx.xmax = buffer[8] + 256 * buffer[9];
73 pcx.ymax = buffer[10] + 256 * buffer[11];
74 pcx.color_planes = buffer[65];
75 pcx.bytes_per_line = buffer[66] + 256 * buffer[67];
76 pcx.palette_type = buffer[68] + 256 * buffer[69];
78 width = pcx.xmax - pcx.xmin + 1;
79 height = pcx.ymax - pcx.ymin + 1;
80 depth = pcx.bits_per_pixel;
82 if (pcx.signature != PCX_MAGIC || pcx.version > PCX_LAST_VERSION ||
83 pcx.encoding != PCX_ENCODING || pcx.color_planes > PCX_MAXDEPTH ||
84 width < 0 || height < 0)
92 printf("%s is a %dx%d PC Paintbrush image with %d bitplanes\n",
93 filename, pcx.xmax, pcx.ymax,
95 printf("depth: %d\n", pcx.bits_per_pixel);
96 printf("bytes_per_line: %d\n", pcx.bytes_per_line);
97 printf("palette type: %s\n",
98 (pcx.palette_type == 1 ? "color" :
99 pcx.palette_type == 2 ? "grayscale" : "undefined"));
102 /* allocate new image structure */
103 image = newRGBImage(width, height, depth);
105 /* read compressed bitmap data */
106 if (!PCX_LoadImage(file, image))
112 /* read colormap data */
113 if (!PCX_LoadColormap(file, image))
123 static boolean PCX_LoadImage(FILE *file, Image *image)
125 /* Run Length Encoding: If the two high bits are set,
126 * then the low 6 bits contain a repeat count, and the byte to
127 * repeat is the next byte in the file. If the two high bits are
128 * not set, then this is the byte to write.
131 register unsigned char *ptr, *ptr_last;
135 ptr_last = ptr + (image->width * image->height * image->pixlen);
137 while (ptr < ptr_last)
139 if ((value = fgetc(file)) == EOF)
142 if ((value & 0xc0) == 0xc0)
144 count = value & 0x3f;
146 if ((value = fgetc(file)) == EOF)
149 for ( ; count && (ptr < ptr_last); count--)
150 *ptr++ = (unsigned char)value;
153 printf("Repeat count spans end of image!\n");
156 *ptr++ = (unsigned char)value;
162 static boolean PCX_LoadColormap(FILE *file, Image *image)
164 unsigned char buffer[PCX_PALETTE_SIZE];
165 int i, result, magic;
167 /* read colormap magic byte */
168 if ((magic = fgetc(file)) == EOF)
171 if (magic != PCX_256COLORS_MAGIC)
174 /* read PCX 256 colors colormap */
175 if ((result = fread(buffer, 1, PCX_PALETTE_SIZE, file)) != PCX_PALETTE_SIZE)
178 for (i=0; i<PCX_MAXCOLORS; i++)
180 image->rgb.red[i] = buffer[i*3 + 0] << 8;
181 image->rgb.green[i] = buffer[i*3 + 1] << 8;
182 image->rgb.blue[i] = buffer[i*3 + 2] << 8;
184 image->rgb.used = PCX_MAXCOLORS;