1 /*****************************************************************************/
9 /* (C) 2012, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
51 /*****************************************************************************/
53 /*****************************************************************************/
57 /* Some PCX constants */
58 #define PCX_MAGIC_ID 0x0A
60 /* A raw PCX header is just a block of bytes */
61 typedef unsigned char RawPCXHeader[128];
63 /* Structured PCX header */
64 typedef struct PCXHeader PCXHeader;
77 unsigned BytesPerPlane;
80 unsigned ScreenHeight;
87 /* Read a little endian word from a byte array at offset O */
88 #define WORD(H, O) ((H)[O] | ((H)[O+1] << 8))
92 /*****************************************************************************/
94 /*****************************************************************************/
98 static PCXHeader* NewPCXHeader (void)
99 /* Allocate a new PCX header and return it */
101 /* No initialization here */
102 return xmalloc (sizeof (PCXHeader));
107 static PCXHeader* ReadPCXHeader (FILE* F, const char* Name)
108 /* Read a structured PCX header from the given file and return it */
112 /* Allocate a new PCXHeader structure */
113 PCXHeader* P = NewPCXHeader ();
115 /* Read the raw header */
116 ReadData (F, H, sizeof (H));
118 /* Convert the data into structured form */
120 P->FileVersion = H[1];
121 P->Compressed = H[2];
123 P->XMin = WORD (H, 4);
124 P->YMin = WORD (H, 6);
125 P->XMax = WORD (H, 8);
126 P->YMax = WORD (H, 10);
127 P->XDPI = WORD (H, 12);
128 P->YDPI = WORD (H, 14);
130 P->BytesPerPlane = WORD (H, 66);
131 P->PalInfo = WORD (H, 68);
132 P->ScreenWidth = WORD (H, 70);
133 P->ScreenHeight = WORD (H, 72);
134 P->Width = P->XMax - P->XMin + 1;
135 P->Height = P->YMax - P->YMin + 1;
137 /* Check the header data */
138 if (P->Id != PCX_MAGIC_ID || P->FileVersion == 1 || P->FileVersion > 5) {
139 Error ("`%s' is not a PCX file", Name);
141 if (P->Compressed > 1) {
142 Error ("Unsupported compression (%d) in PCX file `%s'",
143 P->Compressed, Name);
145 if (P->BPP != 1 && P->BPP != 4 && P->BPP != 8) {
146 Error ("Unsupported bit depth (%u) in PCX file `%s'",
149 if (P->PalInfo != 1 && P->PalInfo != 2) {
150 Error ("Unsupported palette info (%u) in PCX file `%s'",
153 if (!ValidBitmapSize (P->Width, P->Height)) {
154 Error ("PCX file `%s' has an unsupported size (w=%u, h=%d)",
155 Name, P->Width, P->Height);
158 /* Return the structured header */
164 static void DumpPCXHeader (const PCXHeader* P, const char* Name)
165 /* Dump the header of the PCX file in readable form to stdout */
167 printf ("File name: %s\n", Name);
168 printf ("PCX Version: ");
169 switch (P->FileVersion) {
170 case 0: puts ("2.5"); break;
171 case 2: puts ("2.8 with palette"); break;
172 case 3: puts ("2.8 without palette"); break;
173 case 4: puts ("PCX for Windows without palette"); break;
174 case 5: puts ("3.0"); break;
176 printf ("Image type: %s\n", P->PalInfo? "color" : "grayscale");
177 printf ("Compression: %s\n", P->Compressed? "RLE" : "None");
178 printf ("Structure: %u planes of %u bits\n", P->Planes, P->BPP);
179 printf ("Bounding box: [%u/%u - %u/%u]\n", P->XMin, P->YMin, P->XMax, P->YMax);
180 printf ("Resolution: %u/%u DPI\n", P->XDPI, P->YDPI);
181 printf ("Screen size: %u/%u\n", P->ScreenWidth, P->ScreenHeight);
186 Bitmap* ReadPCXFile (const char* Name)
187 /* Read a bitmap from a PCX file */
193 FILE* F = fopen (Name, "rb");
195 Error ("Cannot open PCX file `%s': %s", Name, strerror (errno));
198 /* Read the PCX header */
199 P = ReadPCXHeader (F, Name);
201 /* Dump the header if requested */
203 DumpPCXHeader (P, Name);
209 /* Return the bitmap */