1 | /*
|
---|
2 |
|
---|
3 | gbmpcx.c - ZSoft PC Paintbrush support
|
---|
4 |
|
---|
5 | Reads and writes 1,4,8 and 24 bit colour files.
|
---|
6 |
|
---|
7 | */
|
---|
8 |
|
---|
9 | /*...sincludes:0:*/
|
---|
10 | #include <stdio.h>
|
---|
11 | #include <ctype.h>
|
---|
12 | #include <stddef.h>
|
---|
13 | #include <stdlib.h>
|
---|
14 | #include <string.h>
|
---|
15 | #include "gbm.h"
|
---|
16 | #include "gbmhelp.h"
|
---|
17 |
|
---|
18 | /*...vgbm\46\h:0:*/
|
---|
19 | /*...vgbmhelp\46\h:0:*/
|
---|
20 | /*...e*/
|
---|
21 |
|
---|
22 | /*...suseful:0:*/
|
---|
23 | #define low_byte(w) ((byte) ( (w)&0x00ffU) )
|
---|
24 | #define high_byte(w) ((byte) (((unsigned)(w)&0xff00U)>>8))
|
---|
25 | #define make_word(a,b) (((word)a) + (((word)b) << 8))
|
---|
26 | /*...e*/
|
---|
27 |
|
---|
28 | static GBMFT pcx_gbmft =
|
---|
29 | {
|
---|
30 | "PCX",
|
---|
31 | "ZSoft PC Paintbrush Image format",
|
---|
32 | "PCX PCC",
|
---|
33 | GBM_FT_R1|GBM_FT_R4|GBM_FT_R8|GBM_FT_R24|
|
---|
34 | GBM_FT_W1|GBM_FT_W4|GBM_FT_W8|GBM_FT_W24,
|
---|
35 | };
|
---|
36 |
|
---|
37 | #define GBM_ERR_PCX_BAD_VERSION ((GBM_ERR) 700)
|
---|
38 | #define GBM_ERR_PCX_BAD_ENCMODE ((GBM_ERR) 701)
|
---|
39 | #define GBM_ERR_PCX_BAD_BITS ((GBM_ERR) 702)
|
---|
40 | #define GBM_ERR_PCX_BAD_TRAILER ((GBM_ERR) 703)
|
---|
41 |
|
---|
42 | typedef struct
|
---|
43 | {
|
---|
44 | byte version, bpppp, planes;
|
---|
45 | int bytes_per_line;
|
---|
46 | BOOLEAN trunc;
|
---|
47 | } PCX_PRIV;
|
---|
48 |
|
---|
49 | /*...spcx_qft:0:*/
|
---|
50 | GBM_ERR pcx_qft(GBMFT *gbmft)
|
---|
51 | {
|
---|
52 | *gbmft = pcx_gbmft;
|
---|
53 | return GBM_ERR_OK;
|
---|
54 | }
|
---|
55 | /*...e*/
|
---|
56 | /*...spcx_rhdr:0:*/
|
---|
57 | GBM_ERR pcx_rhdr(const char *fn, int fd, GBM *gbm, const char *opt)
|
---|
58 | {
|
---|
59 | PCX_PRIV *pcx_priv = (PCX_PRIV *) gbm->priv;
|
---|
60 | byte hdr[70];
|
---|
61 | word x1, y1, x2, y2;
|
---|
62 | int w, h, bpp;
|
---|
63 |
|
---|
64 | fn=fn; /* Suppress 'unref arg' compiler warning */
|
---|
65 |
|
---|
66 | pcx_priv->trunc = ( gbm_find_word(opt, "trunc" ) != NULL );
|
---|
67 |
|
---|
68 | gbm_file_read(fd, hdr, 70);
|
---|
69 | if ( hdr[0] != 0x0a )
|
---|
70 | return GBM_ERR_BAD_MAGIC;
|
---|
71 | pcx_priv->version = hdr[1];
|
---|
72 | if ( pcx_priv->version == 4 || pcx_priv->version > 5 )
|
---|
73 | return GBM_ERR_PCX_BAD_VERSION;
|
---|
74 | if ( hdr[2] != 1 )
|
---|
75 | return GBM_ERR_PCX_BAD_ENCMODE;
|
---|
76 |
|
---|
77 | pcx_priv->bpppp = hdr[3]; pcx_priv->planes = hdr[65];
|
---|
78 | #define SWITCH2(a,b) (((a)<<8)|(b))
|
---|
79 | switch ( SWITCH2(pcx_priv->bpppp, pcx_priv->planes) )
|
---|
80 | {
|
---|
81 | case SWITCH2(1,1): bpp = 1; break;
|
---|
82 | case SWITCH2(4,1): bpp = 4; break;
|
---|
83 | case SWITCH2(8,1): bpp = 8; break;
|
---|
84 | case SWITCH2(8,3): bpp = 24; break; /* Extended 24 bit style */
|
---|
85 | case SWITCH2(1,4): bpp = 4; break; /* EGA RGBI style */
|
---|
86 | default: return GBM_ERR_PCX_BAD_BITS;
|
---|
87 | }
|
---|
88 |
|
---|
89 | x1 = make_word(hdr[ 4], hdr[ 5]);
|
---|
90 | y1 = make_word(hdr[ 6], hdr[ 7]);
|
---|
91 | x2 = make_word(hdr[ 8], hdr[ 9]);
|
---|
92 | y2 = make_word(hdr[10], hdr[11]);
|
---|
93 |
|
---|
94 | w = x2 - x1 + 1;
|
---|
95 | h = y2 - y1 + 1;
|
---|
96 |
|
---|
97 | if ( w <= 0 || h <= 0 )
|
---|
98 | return GBM_ERR_BAD_SIZE;
|
---|
99 |
|
---|
100 | pcx_priv->bytes_per_line = make_word(hdr[66], hdr[67]);
|
---|
101 |
|
---|
102 | gbm->w = w;
|
---|
103 | gbm->h = h;
|
---|
104 | gbm->bpp = bpp;
|
---|
105 |
|
---|
106 | return GBM_ERR_OK;
|
---|
107 | }
|
---|
108 | /*...e*/
|
---|
109 | /*...spcx_rpal:0:*/
|
---|
110 | GBM_ERR pcx_rpal(int fd, GBM *gbm, GBMRGB *gbmrgb)
|
---|
111 | {
|
---|
112 | switch ( gbm->bpp )
|
---|
113 | {
|
---|
114 | /*...s1 \45\ fixed b\47\w palette:16:*/
|
---|
115 | case 1:
|
---|
116 | gbmrgb[0].r = gbmrgb[0].g = gbmrgb[0].b = 0x00;
|
---|
117 | gbmrgb[1].r = gbmrgb[1].g = gbmrgb[1].b = 0xff;
|
---|
118 | break;
|
---|
119 | /*...e*/
|
---|
120 | /*...s4 \45\ read palette if 1 plane\44\ fix one if 4 plane RGBI:16:*/
|
---|
121 | case 4:
|
---|
122 | /* Use inline palette */
|
---|
123 | {
|
---|
124 | byte b[16*3];
|
---|
125 | int i;
|
---|
126 |
|
---|
127 | gbm_file_lseek(fd, 16L, SEEK_SET);
|
---|
128 | gbm_file_read(fd, b, 16 * 3);
|
---|
129 | for ( i = 0; i < 16; i++ )
|
---|
130 | {
|
---|
131 | gbmrgb[i].r = b[i * 3 + 0];
|
---|
132 | gbmrgb[i].g = b[i * 3 + 1];
|
---|
133 | gbmrgb[i].b = b[i * 3 + 2];
|
---|
134 | }
|
---|
135 | }
|
---|
136 | break;
|
---|
137 | /*...e*/
|
---|
138 | /*...s8 \45\ read palette from end of file:16:*/
|
---|
139 | case 8:
|
---|
140 | {
|
---|
141 | byte trailer_id;
|
---|
142 | byte b[0x100*3];
|
---|
143 | int i;
|
---|
144 |
|
---|
145 | gbm_file_lseek(fd, -0x301L, SEEK_END);
|
---|
146 | gbm_file_read(fd, &trailer_id, 1);
|
---|
147 | if ( trailer_id != 0x0c )
|
---|
148 | return GBM_ERR_PCX_BAD_TRAILER;
|
---|
149 |
|
---|
150 | gbm_file_read(fd, b, 0x100 * 3);
|
---|
151 | for ( i = 0; i < 0x100; i++ )
|
---|
152 | {
|
---|
153 | gbmrgb[i].r = b[i * 3 + 0];
|
---|
154 | gbmrgb[i].g = b[i * 3 + 1];
|
---|
155 | gbmrgb[i].b = b[i * 3 + 2];
|
---|
156 | }
|
---|
157 | }
|
---|
158 | break;
|
---|
159 | /*...e*/
|
---|
160 | }
|
---|
161 | return GBM_ERR_OK;
|
---|
162 | }
|
---|
163 | /*...e*/
|
---|
164 | /*...spcx_rdata:0:*/
|
---|
165 | /*...sread_pcx_line:0:*/
|
---|
166 | static void read_pcx_line(
|
---|
167 | AHEAD *ahead, byte *line, int bytes_per_line,
|
---|
168 | byte *runleft, byte *runval
|
---|
169 | )
|
---|
170 | {
|
---|
171 | /* Handle left overs from previous line */
|
---|
172 |
|
---|
173 | while ( *runleft > 0 && bytes_per_line > 0 )
|
---|
174 | {
|
---|
175 | *line++ = *runval;
|
---|
176 | (*runleft)--;
|
---|
177 | bytes_per_line--;
|
---|
178 | }
|
---|
179 |
|
---|
180 | /* Normal code */
|
---|
181 |
|
---|
182 | while ( bytes_per_line )
|
---|
183 | {
|
---|
184 | byte b1 = (byte) gbm_read_ahead(ahead);
|
---|
185 |
|
---|
186 | if ( (b1 & 0xc0) == 0xc0 )
|
---|
187 | {
|
---|
188 | byte b2 = (byte) gbm_read_ahead(ahead);
|
---|
189 |
|
---|
190 | b1 &= 0x3f;
|
---|
191 | if ( b1 > bytes_per_line )
|
---|
192 | {
|
---|
193 | (*runleft) = (byte) (b1 - bytes_per_line);
|
---|
194 | (*runval) = b2;
|
---|
195 | b1 = bytes_per_line;
|
---|
196 | }
|
---|
197 | memset(line, b2, b1);
|
---|
198 | line += b1;
|
---|
199 | bytes_per_line -= b1;
|
---|
200 | }
|
---|
201 | else
|
---|
202 | {
|
---|
203 | *line++ = b1;
|
---|
204 | bytes_per_line--;
|
---|
205 | }
|
---|
206 | }
|
---|
207 | }
|
---|
208 | /*...e*/
|
---|
209 | /*...sspread:0:*/
|
---|
210 | static void spread(byte b, byte bit_to_set, byte *dest)
|
---|
211 | {
|
---|
212 | if ( b & 0x80 ) dest[0] |= (bit_to_set & 0xf0);
|
---|
213 | if ( b & 0x40 ) dest[0] |= (bit_to_set & 0x0f);
|
---|
214 | if ( b & 0x20 ) dest[1] |= (bit_to_set & 0xf0);
|
---|
215 | if ( b & 0x10 ) dest[1] |= (bit_to_set & 0x0f);
|
---|
216 | if ( b & 0x08 ) dest[2] |= (bit_to_set & 0xf0);
|
---|
217 | if ( b & 0x04 ) dest[2] |= (bit_to_set & 0x0f);
|
---|
218 | if ( b & 0x02 ) dest[3] |= (bit_to_set & 0xf0);
|
---|
219 | if ( b & 0x01 ) dest[3] |= (bit_to_set & 0x0f);
|
---|
220 | }
|
---|
221 | /*...e*/
|
---|
222 |
|
---|
223 | GBM_ERR pcx_rdata(int fd, GBM *gbm, byte *data)
|
---|
224 | {
|
---|
225 | PCX_PRIV *pcx_priv = (PCX_PRIV *) gbm->priv;
|
---|
226 | BOOLEAN trunc = pcx_priv->trunc;
|
---|
227 | int bytes_per_line = pcx_priv->bytes_per_line;
|
---|
228 | int stride, y;
|
---|
229 | byte *line;
|
---|
230 | AHEAD *ahead;
|
---|
231 | byte runleft = 0, runval;
|
---|
232 |
|
---|
233 | if ( (ahead = gbm_create_ahead(fd)) == NULL )
|
---|
234 | return GBM_ERR_MEM;
|
---|
235 |
|
---|
236 | gbm_file_lseek(fd, 128L, SEEK_SET);
|
---|
237 |
|
---|
238 | if ( (line = malloc((size_t) bytes_per_line)) == NULL )
|
---|
239 | {
|
---|
240 | gbm_destroy_ahead(ahead);
|
---|
241 | return GBM_ERR_MEM;
|
---|
242 | }
|
---|
243 |
|
---|
244 | switch ( gbm->bpp )
|
---|
245 | {
|
---|
246 | /*...s1:16:*/
|
---|
247 | case 1:
|
---|
248 | stride = ((gbm->w + 31) / 32) * 4;
|
---|
249 | for ( y = gbm->h - 1; y >= 0; y-- )
|
---|
250 | {
|
---|
251 | read_pcx_line(ahead, data + y * stride, bytes_per_line, &runleft, &runval);
|
---|
252 | if ( trunc )
|
---|
253 | runleft = 0;
|
---|
254 | }
|
---|
255 | break;
|
---|
256 | /*...e*/
|
---|
257 | /*...s4:16:*/
|
---|
258 | case 4:
|
---|
259 | stride = ((gbm->w * 4 + 31) / 32) * 4;
|
---|
260 | if ( pcx_priv->planes == 1 )
|
---|
261 | for ( y = gbm->h - 1; y >= 0; y-- )
|
---|
262 | {
|
---|
263 | read_pcx_line(ahead, data + y * stride, bytes_per_line, &runleft, &runval);
|
---|
264 | if ( trunc )
|
---|
265 | runleft = 0;
|
---|
266 | }
|
---|
267 | else
|
---|
268 | {
|
---|
269 | int p, x;
|
---|
270 | int bytes = (gbm->w / 8);
|
---|
271 | int bits = (gbm->w & 7);
|
---|
272 |
|
---|
273 | memset(data, 0, gbm->h * stride);
|
---|
274 | for ( y = gbm->h - 1; y >= 0; y-- )
|
---|
275 | for ( p = 0x11; p <= 0x88 ; p <<= 1 )
|
---|
276 | {
|
---|
277 | byte *dest = data + y * stride;
|
---|
278 |
|
---|
279 | read_pcx_line(ahead, line, bytes_per_line, &runleft, &runval);
|
---|
280 | if ( trunc )
|
---|
281 | runleft = 0;
|
---|
282 | for ( x = 0; x < bytes; x++, dest += 4 )
|
---|
283 | spread(line[x], (byte) p, dest);
|
---|
284 | if ( bits )
|
---|
285 | spread((byte) (line[x] & (0xff00U >> bits)), (byte) p, dest);
|
---|
286 | }
|
---|
287 | }
|
---|
288 | break;
|
---|
289 | /*...e*/
|
---|
290 | /*...s8:16:*/
|
---|
291 | case 8:
|
---|
292 | stride = ((gbm->w + 3) & ~3);
|
---|
293 | for ( y = gbm->h - 1; y >= 0; y-- )
|
---|
294 | {
|
---|
295 | read_pcx_line(ahead, data + y * stride, bytes_per_line, &runleft, &runval);
|
---|
296 | if ( trunc )
|
---|
297 | runleft = 0;
|
---|
298 | }
|
---|
299 | break;
|
---|
300 | /*...e*/
|
---|
301 | /*...s24:16:*/
|
---|
302 | case 24:
|
---|
303 | {
|
---|
304 | int p, x;
|
---|
305 |
|
---|
306 | stride = ((gbm->w * 3 + 3) & ~3);
|
---|
307 | for ( y = gbm->h - 1; y >= 0; y-- )
|
---|
308 | for ( p = 2; p >= 0; p-- )
|
---|
309 | {
|
---|
310 | read_pcx_line(ahead, line, bytes_per_line, &runleft, &runval);
|
---|
311 | if ( trunc )
|
---|
312 | runleft = 0;
|
---|
313 | for ( x = 0; x < gbm->w; x++ )
|
---|
314 | data[y * stride + p + x * 3] = line[x];
|
---|
315 | }
|
---|
316 | }
|
---|
317 | break;
|
---|
318 | /*...e*/
|
---|
319 | }
|
---|
320 |
|
---|
321 | free(line);
|
---|
322 |
|
---|
323 | gbm_destroy_ahead(ahead);
|
---|
324 |
|
---|
325 | return GBM_ERR_OK;
|
---|
326 | }
|
---|
327 | /*...e*/
|
---|
328 | /*...spcx_w:0:*/
|
---|
329 | /*...sbright:0:*/
|
---|
330 | static int bright(const GBMRGB *gbmrgb)
|
---|
331 | {
|
---|
332 | return gbmrgb->r*30+gbmrgb->g*60+gbmrgb->b*10;
|
---|
333 | }
|
---|
334 | /*...e*/
|
---|
335 | /*...spcx_rle:0:*/
|
---|
336 | static byte pcx_run(const byte *src, int n_src)
|
---|
337 | {
|
---|
338 | byte cnt = 1;
|
---|
339 | byte b = *src++;
|
---|
340 |
|
---|
341 | --n_src;
|
---|
342 | while ( cnt < 0x3f && n_src > 0 && *src == b )
|
---|
343 | { cnt++; n_src--; src++; }
|
---|
344 |
|
---|
345 | return cnt;
|
---|
346 | }
|
---|
347 |
|
---|
348 | static void pcx_rle(const byte *src, int n_src, byte *dst, int *n_dst)
|
---|
349 | {
|
---|
350 | *n_dst = 0;
|
---|
351 | while ( n_src )
|
---|
352 | {
|
---|
353 | byte len;
|
---|
354 |
|
---|
355 | if ( (len = pcx_run(src, n_src)) > 1 || (*src & 0xc0) == 0xc0 )
|
---|
356 | {
|
---|
357 | *dst++ = (byte) (0xc0 | len);
|
---|
358 | *dst++ = *src;
|
---|
359 | (*n_dst) += 2;
|
---|
360 | }
|
---|
361 | else
|
---|
362 | {
|
---|
363 | *dst++ = *src;
|
---|
364 | (*n_dst)++;
|
---|
365 | }
|
---|
366 | src += len;
|
---|
367 | n_src -= len;
|
---|
368 | }
|
---|
369 | }
|
---|
370 | /*...e*/
|
---|
371 |
|
---|
372 | GBM_ERR pcx_w(const char *fn, int fd, const GBM *gbm, const GBMRGB *gbmrgb, const byte *data, const char *opt)
|
---|
373 | {
|
---|
374 | int i, y, stride = ((gbm->bpp * gbm->w + 31) / 32) * 4;
|
---|
375 | byte *line;
|
---|
376 | byte hdr[128];
|
---|
377 | int bytes_per_line, cnt;
|
---|
378 |
|
---|
379 | fn=fn; opt=opt; /* Suppress 'unref arg' compiler warning */
|
---|
380 |
|
---|
381 | memset(hdr, 0, 128);
|
---|
382 | hdr[ 0] = 0x0a; /* Magic # */
|
---|
383 | hdr[ 1] = 5; /* Version 5 */
|
---|
384 | hdr[ 2] = 1; /* RLE compression */
|
---|
385 | hdr[ 3] = (byte) ( ( gbm->bpp == 24 ) ? 8 : gbm->bpp );
|
---|
386 | /* Bits per plane */
|
---|
387 | hdr[ 4] = low_byte(0);
|
---|
388 | hdr[ 5] = high_byte(0); /* Top left x */
|
---|
389 | hdr[ 6] = low_byte(0);
|
---|
390 | hdr[ 7] = high_byte(0); /* Top left y */
|
---|
391 | hdr[ 8] = low_byte(gbm->w - 1);
|
---|
392 | hdr[ 9] = high_byte(gbm->w - 1); /* Bottom right x */
|
---|
393 | hdr[10] = low_byte(gbm->h - 1);
|
---|
394 | hdr[11] = high_byte(gbm->h - 1); /* Bottom right y */
|
---|
395 | hdr[12] = low_byte(0);
|
---|
396 | hdr[13] = high_byte(0); /* Horizontal resolution ??? */
|
---|
397 | hdr[14] = low_byte(0);
|
---|
398 | hdr[15] = high_byte(0); /* Vertical resolution ??? */
|
---|
399 |
|
---|
400 | if ( gbm->bpp == 4 )
|
---|
401 | for ( i = 0; i < 16; i++ )
|
---|
402 | {
|
---|
403 | hdr[16 + i * 3 ] = gbmrgb[i].r;
|
---|
404 | hdr[16 + i * 3 + 1] = gbmrgb[i].g;
|
---|
405 | hdr[16 + i * 3 + 2] = gbmrgb[i].b;
|
---|
406 | }
|
---|
407 |
|
---|
408 | hdr[65] = (byte) ( ( gbm->bpp == 24 ) ? 3 : 1 );
|
---|
409 | /* Planes */
|
---|
410 | bytes_per_line = (gbm->w * hdr[3] + 7) / 8;
|
---|
411 | if ( bytes_per_line & 1 )
|
---|
412 | bytes_per_line++;
|
---|
413 | hdr[66] = low_byte(bytes_per_line);
|
---|
414 | hdr[67] = high_byte(bytes_per_line);
|
---|
415 | hdr[68] = 1; /* Colour or b/w */
|
---|
416 |
|
---|
417 | gbm_file_write(fd, hdr, 128);
|
---|
418 |
|
---|
419 | if ( (line = malloc((size_t) (bytes_per_line * 2))) == NULL )
|
---|
420 | return GBM_ERR_MEM;
|
---|
421 |
|
---|
422 | switch ( gbm->bpp )
|
---|
423 | {
|
---|
424 | /*...s1:16:*/
|
---|
425 | case 1:
|
---|
426 | if ( bright(&gbmrgb[0]) > bright(&gbmrgb[1]) )
|
---|
427 | /* Need to invert bitmap bits */
|
---|
428 | {
|
---|
429 | byte *b;
|
---|
430 | if ( (b = malloc(bytes_per_line)) == NULL )
|
---|
431 | {
|
---|
432 | free(line);
|
---|
433 | return GBM_ERR_MEM;
|
---|
434 | }
|
---|
435 | for ( y = gbm->h - 1; y >= 0; y-- )
|
---|
436 | {
|
---|
437 | int i;
|
---|
438 | for ( i = 0; i < bytes_per_line; i++ )
|
---|
439 | b[i] = data[y*stride+i] ^ 0xffU;
|
---|
440 | pcx_rle(b, bytes_per_line, line, &cnt);
|
---|
441 | if ( gbm_file_write(fd, line, cnt) != cnt )
|
---|
442 | {
|
---|
443 | free(b);
|
---|
444 | free(line);
|
---|
445 | return GBM_ERR_WRITE;
|
---|
446 | }
|
---|
447 | }
|
---|
448 | free(b);
|
---|
449 | break;
|
---|
450 | }
|
---|
451 | /* Fall through to regular non-invert case */
|
---|
452 | /*...e*/
|
---|
453 | /*...s4\44\8:16:*/
|
---|
454 | case 4:
|
---|
455 | case 8:
|
---|
456 | for ( y = gbm->h - 1; y >= 0; y-- )
|
---|
457 | {
|
---|
458 | pcx_rle(data + y * stride, bytes_per_line, line, &cnt);
|
---|
459 | if ( gbm_file_write(fd, line, cnt) != cnt )
|
---|
460 | {
|
---|
461 | free(line);
|
---|
462 | return GBM_ERR_WRITE;
|
---|
463 | }
|
---|
464 | }
|
---|
465 | break;
|
---|
466 | /*...e*/
|
---|
467 | /*...s24:16:*/
|
---|
468 | case 24:
|
---|
469 | {
|
---|
470 | byte *line2;
|
---|
471 | int p, x;
|
---|
472 |
|
---|
473 | if ( (line2 = malloc((size_t) bytes_per_line)) == NULL )
|
---|
474 | {
|
---|
475 | free(line);
|
---|
476 | return GBM_ERR_MEM;
|
---|
477 | }
|
---|
478 |
|
---|
479 | for ( y = gbm->h - 1; y >= 0; y-- )
|
---|
480 | for ( p = 2; p >= 0; p-- )
|
---|
481 | {
|
---|
482 | const byte *src = data + y * stride;
|
---|
483 |
|
---|
484 | for ( x = 0; x < gbm->w; x++ )
|
---|
485 | line2[x] = src[x * 3 + p];
|
---|
486 |
|
---|
487 | pcx_rle(line2, bytes_per_line, line, &cnt);
|
---|
488 | if ( gbm_file_write(fd, line, cnt) != cnt )
|
---|
489 | {
|
---|
490 | free(line2);
|
---|
491 | free(line);
|
---|
492 | return GBM_ERR_WRITE;
|
---|
493 | }
|
---|
494 | }
|
---|
495 | free(line2);
|
---|
496 | }
|
---|
497 | break;
|
---|
498 | /*...e*/
|
---|
499 | }
|
---|
500 |
|
---|
501 | free(line);
|
---|
502 |
|
---|
503 | if ( gbm->bpp == 8 )
|
---|
504 | {
|
---|
505 | byte pal[1 + 0x100 * 3];
|
---|
506 |
|
---|
507 | pal[0] = 0x0c;
|
---|
508 | for ( i = 0; i < 0x100; i++ )
|
---|
509 | {
|
---|
510 | pal[i * 3 + 1] = gbmrgb[i].r;
|
---|
511 | pal[i * 3 + 2] = gbmrgb[i].g;
|
---|
512 | pal[i * 3 + 3] = gbmrgb[i].b;
|
---|
513 | }
|
---|
514 | gbm_file_write(fd, pal, 1 + 0x100 * 3);
|
---|
515 | }
|
---|
516 |
|
---|
517 | return GBM_ERR_OK;
|
---|
518 | }
|
---|
519 | /*...e*/
|
---|
520 | /*...spcx_err:0:*/
|
---|
521 | const char *pcx_err(GBM_ERR rc)
|
---|
522 | {
|
---|
523 | switch ( (int) rc )
|
---|
524 | {
|
---|
525 | case GBM_ERR_PCX_BAD_VERSION:
|
---|
526 | return "version number not 4 or 5";
|
---|
527 | case GBM_ERR_PCX_BAD_ENCMODE:
|
---|
528 | return "encoding mode not 1";
|
---|
529 | case GBM_ERR_PCX_BAD_BITS:
|
---|
530 | return "unsupported bpp/plane / plane combination";
|
---|
531 | case GBM_ERR_PCX_BAD_TRAILER:
|
---|
532 | return "corrupt file trailer";
|
---|
533 | }
|
---|
534 | return NULL;
|
---|
535 | }
|
---|
536 | /*...e*/
|
---|