]> icculus.org git repositories - taylor/freespace2.git/blob - src/pcxutils/pcxutils.cpp
Initial revision
[taylor/freespace2.git] / src / pcxutils / pcxutils.cpp
1 /*
2  * $Logfile: /Freespace2/code/PcxUtils/pcxutils.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * code to deal with pcx files
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:10  root
11  * Initial revision
12  *
13  * 
14  * 11    8/10/99 6:54p Dave
15  * Mad optimizations. Added paging to the nebula effect.
16  * 
17  * 10    7/13/99 1:16p Dave
18  * 32 bit support. Whee!
19  * 
20  * 9     2/05/99 12:52p Dave
21  * Fixed Glide nondarkening textures.
22  * 
23  * 8     2/03/99 6:06p Dave
24  * Groundwork for FS2 PXO usertracker support.  Gametracker support next.
25  * 
26  * 7     2/03/99 11:44a Dave
27  * Fixed d3d transparent textures.
28  * 
29  * 6     12/01/98 5:54p Dave
30  * Simplified the way pixel data is swizzled. Fixed tga bitmaps to work
31  * properly in D3D and Glide.
32  * 
33  * 5     12/01/98 4:46p Dave
34  * Put in targa bitmap support (16 bit).
35  * 
36  * 4     12/01/98 8:06a Dave
37  * Temporary checkin to fix some texture transparency problems in d3d.
38  * 
39  * 3     11/30/98 1:07p Dave
40  * 16 bit conversion, first run.
41  * 
42  * 2     10/07/98 10:53a Dave
43  * Initial checkin.
44  * 
45  * 1     10/07/98 10:50a Dave
46  * 
47  * 16    1/19/98 11:37p Lawrance
48  * Fixing Optimization build warnings
49  * 
50  * 15    9/09/97 3:39p Sandeep
51  * warning level 4 bugs
52  * 
53  * 14    9/03/97 4:32p John
54  * changed bmpman to only accept ani and pcx's.  made passing .pcx or .ani
55  * to bm_load functions not needed.   Made bmpman keep track of palettes
56  * for bitmaps not mapped into game palettes.
57  * 
58  * 13    7/20/97 6:59p Lawrance
59  * fixed bug that was writing out PCX files with an extra bogus line
60  * 
61  * 12    6/05/97 6:07p John
62  * fixed warning
63  * 
64  * 11    6/05/97 3:59p John
65  * Fixed a bug in PCX reader
66  * 
67  * 10    2/25/97 12:06p John
68  * fixed a pcx potential bug.
69  * 
70  * 9     2/25/97 12:03p John
71  * fixed a pcx reading bug.
72  * 
73  * 8     2/20/97 4:18p John
74  * fixed bug reading odd-width pcx files
75  * 
76  * 7     11/26/96 9:28a Allender
77  * get palette info when getting pcx info
78  * 
79  * 6     11/18/96 12:36p John
80  * Added code to dump screen to a PCX file.
81  * 
82  * 5     11/13/96 4:51p Allender
83  * started overhaul of bitmap manager.  bm_load no longer actually load
84  * the data, only the info for the bitmap.  Locking the bitmap now forces
85  * load when no data present (or will if bpp changes)
86  *
87  * $NoKeywords: $
88  */
89
90 #include "cfile.h"
91 #include "pcxutils.h"
92 #include "palman.h"
93 #include "bmpman.h"
94
95 /* PCX Header data type */
96 typedef struct  {
97         ubyte           Manufacturer;
98         ubyte           Version;
99         ubyte           Encoding;
100         ubyte           BitsPerPixel;
101         short           Xmin;
102         short           Ymin;
103         short           Xmax;
104         short           Ymax;
105         short           Hdpi;
106         short           Vdpi;
107         ubyte           ColorMap[16][3];
108         ubyte           Reserved;
109         ubyte           Nplanes;
110         short           BytesPerLine;
111         ubyte           filler[60];
112 } PCXHeader;
113
114 // reads header information from the PCX file into the bitmap pointer
115 int pcx_read_header(char *real_filename, int *w, int *h, ubyte *pal )
116 {
117         PCXHeader header;
118         CFILE * PCXfile;
119         char filename[MAX_FILENAME_LEN];
120                 
121         strcpy( filename, real_filename );
122         char *p = strchr( filename, '.' );
123         if ( p ) *p = 0;
124         strcat( filename, ".pcx" );
125
126         PCXfile = cfopen( filename , "rb" );
127         if ( !PCXfile )
128                 return PCX_ERROR_OPENING;
129
130         // read 128 char PCX header
131         if (cfread( &header, sizeof(PCXHeader), 1, PCXfile )!=1)        {
132                 cfclose( PCXfile );
133                 return PCX_ERROR_NO_HEADER;
134         }
135
136         // Is it a 256 color PCX file?
137         if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5))      {
138                 cfclose( PCXfile );
139                 return PCX_ERROR_WRONG_VERSION;
140         }
141
142         if (w) *w = header.Xmax - header.Xmin + 1;
143         if (h) *h = header.Ymax - header.Ymin + 1;
144         
145         if ( pal ) {
146                 cfseek( PCXfile, -768, CF_SEEK_END );
147                 cfread( pal, 3, 256, PCXfile );
148         }
149
150         cfclose(PCXfile);
151         return PCX_ERROR_NONE;
152 }
153
154 // static ubyte Pcx_load[1024*768 + 768 + sizeof(PCXHeader)];
155 // int Pcx_load_offset = 0;
156 // int Pcx_load_size = 0;
157
158 // #define GET_BUF()                    do { buffer = &Pcx_load[Pcx_load_offset]; if(Pcx_load_offset + buffer_size > Pcx_load_size) { buffer_size = Pcx_load_size - Pcx_load_offset; } } while(0);
159 int pcx_read_bitmap_8bpp( char * real_filename, ubyte *org_data, ubyte *palette )
160 {
161                 PCXHeader header;
162         CFILE * PCXfile;
163         int row, col, count, xsize, ysize;
164         ubyte data=0;
165         int buffer_size, buffer_pos;
166         ubyte buffer[1024];
167         ubyte *pixdata;
168         char filename[MAX_FILENAME_LEN];
169                 
170         strcpy( filename, real_filename );
171         char *p = strchr( filename, '.' );
172         if ( p ) *p = 0;
173         strcat( filename, ".pcx" );
174
175         PCXfile = cfopen( filename , "rb" );
176         if ( !PCXfile )
177                 return PCX_ERROR_OPENING;
178
179         // read 128 char PCX header
180         if (cfread( &header, sizeof(PCXHeader), 1, PCXfile )!=1)        {
181                 cfclose( PCXfile );
182                 return PCX_ERROR_NO_HEADER;
183         }
184
185         // Is it a 256 color PCX file?
186         if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5))      {
187                 cfclose( PCXfile );
188                 return PCX_ERROR_WRONG_VERSION;
189         }
190
191         // Find the size of the image
192         xsize = header.Xmax - header.Xmin + 1;
193         ysize = header.Ymax - header.Ymin + 1;
194
195         // Read the extended palette at the end of PCX file
196         // Read in a character which should be 12 to be extended palette file
197
198         cfseek( PCXfile, -768, CF_SEEK_END );
199         cfread( palette, 3, 256, PCXfile );
200         cfseek( PCXfile, sizeof(PCXHeader), CF_SEEK_SET );
201         
202         buffer_size = 1024;
203         buffer_pos = 0;
204         
205 //      Assert( buffer_size == 1024 );  // AL: removed to avoid optimized warning 'unreachable code'
206         buffer_size = cfread( buffer, 1, buffer_size, PCXfile );
207
208         count = 0;
209
210         for (row=0; row<ysize;row++)      {
211                 pixdata = org_data;
212                 for (col=0; col<header.BytesPerLine;col++)     {
213                         if ( count == 0 )       {
214                                 data = buffer[buffer_pos++];
215                                 if ( buffer_pos == buffer_size )        {
216                                         buffer_size = cfread( buffer, 1, buffer_size, PCXfile );
217                                         Assert( buffer_size > 0 );
218                                         buffer_pos = 0;
219                                 }
220                                 if ((data & 0xC0) == 0xC0)     {
221                                         count = data & 0x3F;
222                                         data = buffer[buffer_pos++];
223                                         if ( buffer_pos == buffer_size )        {
224                                                 buffer_size = cfread( buffer, 1, buffer_size, PCXfile );
225                                                 Assert( buffer_size > 0 );
226                                                 buffer_pos = 0;
227                                         }
228                                 } else {
229                                         count = 1;
230                                 }
231                         }
232                         if ( col < xsize )
233                                 *pixdata++ = data;
234                         count--;
235                 }
236                 org_data += xsize;
237         }
238         cfclose(PCXfile);
239         return PCX_ERROR_NONE;
240 }
241
242 int pcx_read_bitmap_16bpp( char * real_filename, ubyte *org_data )
243 {
244         PCXHeader header;
245         CFILE * PCXfile;
246         int row, col, count, xsize, ysize;
247         ubyte data=0;
248         int buffer_size, buffer_pos;
249         ubyte buffer[1024];
250         ubyte *pixdata;
251         char filename[MAX_FILENAME_LEN];
252         ubyte palette[768];     
253         ushort bit_16;  
254         ubyte r, g, b, al;
255                 
256         strcpy( filename, real_filename );
257         char *p = strchr( filename, '.' );
258         if ( p ) *p = 0;
259         strcat( filename, ".pcx" );
260
261         PCXfile = cfopen( filename , "rb" );
262         if ( !PCXfile ){
263                 return PCX_ERROR_OPENING;
264         }
265
266         // read 128 char PCX header
267         if (cfread( &header, sizeof(PCXHeader), 1, PCXfile )!=1)        {
268                 cfclose( PCXfile );
269                 return PCX_ERROR_NO_HEADER;
270         }
271
272         // Is it a 256 color PCX file?
273         if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5))      {
274                 cfclose( PCXfile );
275                 return PCX_ERROR_WRONG_VERSION;
276         }
277
278         // Find the size of the image
279         xsize = header.Xmax - header.Xmin + 1;
280         ysize = header.Ymax - header.Ymin + 1;
281
282         // Read the extended palette at the end of PCX file
283         // Read in a character which should be 12 to be extended palette file
284
285         cfseek( PCXfile, -768, CF_SEEK_END );
286         cfread( palette, 3, 256, PCXfile );
287         cfseek( PCXfile, sizeof(PCXHeader), CF_SEEK_SET );
288         
289         buffer_size = 1024;
290         buffer_pos = 0;
291         
292 //      Assert( buffer_size == 1024 );  // AL: removed to avoid optimized warning 'unreachable code'
293         buffer_size = cfread( buffer, 1, buffer_size, PCXfile );
294
295         count = 0;      
296
297         for (row=0; row<ysize;row++)      {
298                 pixdata = org_data;
299                 for (col=0; col<header.BytesPerLine;col++)     {
300                         if ( count == 0 )       {
301                                 data = buffer[buffer_pos++];
302                                 if ( buffer_pos == buffer_size )        {
303                                         buffer_size = cfread( buffer, 1, buffer_size, PCXfile );
304                                         Assert( buffer_size > 0 );
305                                         buffer_pos = 0;
306                                 }
307                                 if ((data & 0xC0) == 0xC0)     {
308                                         count = data & 0x3F;
309                                         data = buffer[buffer_pos++];
310                                         if ( buffer_pos == buffer_size )        {
311                                                 buffer_size = cfread( buffer, 1, buffer_size, PCXfile );
312                                                 Assert( buffer_size > 0 );
313                                                 buffer_pos = 0;
314                                         }
315                                 } else {
316                                         count = 1;
317                                 }
318                         }
319                         // stuff the pixel
320                         if ( col < xsize ){                                                             
321                                 // stuff the 24 bit value                               
322                                 r = palette[data*3];
323                                 g = palette[data*3 + 1];
324                                 b = palette[data*3 + 2];
325
326                                 // clear the pixel
327                                 bit_16 = 0;
328                                         
329                                 // if the color matches the transparent color, make it so
330                                 al = 255;
331                                 if((0 == (int)palette[data*3]) && (255 == (int)palette[data*3+1]) && (0 == (int)palette[data*3+2])){
332                                         r = b = 0;
333                                         g = 255;
334                                         al = 0;                                 
335                                 } 
336
337                                 // stuff the color
338                                 bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);                            
339                                 
340                                 // stuff the pixel
341                                 *((ushort*)pixdata) = bit_16;                           
342                                 pixdata += 2;
343                         }
344                         count--;
345                 }
346
347                 org_data += (xsize * 2);
348         }
349         cfclose(PCXfile);
350         return PCX_ERROR_NONE;
351 }
352
353 int pcx_read_bitmap_16bpp_aabitmap( char * real_filename, ubyte *org_data )
354 {       
355         PCXHeader header;
356         CFILE * PCXfile;
357         int row, col, count, xsize, ysize;
358         ubyte data=0;
359         int buffer_size, buffer_pos;
360         ubyte buffer[1024];
361         ubyte *pixdata;
362         char filename[MAX_FILENAME_LEN];
363         ubyte palette[768];             
364                 
365         strcpy( filename, real_filename );
366         char *p = strchr( filename, '.' );
367         if ( p ) *p = 0;
368
369         strcat( filename, ".pcx" );
370
371         PCXfile = cfopen( filename , "rb" );
372         if ( !PCXfile ){
373                 return PCX_ERROR_OPENING;
374         }
375
376         // read 128 char PCX header
377         if (cfread( &header, sizeof(PCXHeader), 1, PCXfile )!=1)        {
378                 cfclose( PCXfile );
379                 return PCX_ERROR_NO_HEADER;
380         }
381
382         // Is it a 256 color PCX file?
383         if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5))      {
384                 cfclose( PCXfile );
385                 return PCX_ERROR_WRONG_VERSION;
386         }
387
388         // Find the size of the image
389         xsize = header.Xmax - header.Xmin + 1;
390         ysize = header.Ymax - header.Ymin + 1;
391
392         // Read the extended palette at the end of PCX file
393         // Read in a character which should be 12 to be extended palette file
394
395         cfseek( PCXfile, -768, CF_SEEK_END );
396         cfread( palette, 3, 256, PCXfile );
397         cfseek( PCXfile, sizeof(PCXHeader), CF_SEEK_SET );
398         
399         buffer_size = 1024;
400         buffer_pos = 0;
401         
402 //      Assert( buffer_size == 1024 );  // AL: removed to avoid optimized warning 'unreachable code'
403         buffer_size = cfread( buffer, 1, buffer_size, PCXfile );
404
405         count = 0;
406
407         for (row=0; row<ysize;row++)      {
408                 pixdata = org_data;
409                 for (col=0; col<header.BytesPerLine;col++)     {
410                         if ( count == 0 )       {
411                                 data = buffer[buffer_pos++];
412                                 if ( buffer_pos == buffer_size )        {
413                                         buffer_size = cfread( buffer, 1, buffer_size, PCXfile );
414                                         Assert( buffer_size > 0 );
415                                         buffer_pos = 0;
416                                 }
417                                 if ((data & 0xC0) == 0xC0)     {
418                                         count = data & 0x3F;
419                                         data = buffer[buffer_pos++];
420                                         if ( buffer_pos == buffer_size )        {
421                                                 buffer_size = cfread( buffer, 1, buffer_size, PCXfile );
422                                                 Assert( buffer_size > 0 );
423                                                 buffer_pos = 0;
424                                         }
425                                 } else {
426                                         count = 1;
427                                 }
428                         }
429                         // stuff the pixel
430                         if ( col < xsize ){                             
431                                 // stuff the pixel
432                                 // memcpy(pixdata, &data, 2);
433                                 *((ushort*)pixdata) = (ushort)data;
434
435                                 pixdata += 2;
436                         }
437                         count--;
438                 }
439
440                 org_data += (xsize * 2);
441         }
442         cfclose(PCXfile);
443         return PCX_ERROR_NONE;
444 }
445
446 int pcx_read_bitmap_16bpp_nondark( char * real_filename, ubyte *org_data )
447 {       
448         PCXHeader header;
449         CFILE * PCXfile;
450         int row, col, count, xsize, ysize;
451         ubyte data=0;
452         int buffer_size, buffer_pos;
453         ubyte buffer[1024];
454         ubyte *pixdata;
455         char filename[MAX_FILENAME_LEN];
456         ubyte palette[768];     
457         ushort bit_16;  
458         ubyte r, g, b, al;
459                 
460         strcpy( filename, real_filename );
461         char *p = strchr( filename, '.' );
462         if ( p ) *p = 0;
463         strcat( filename, ".pcx" );
464
465         PCXfile = cfopen( filename , "rb" );
466         if ( !PCXfile ){
467                 return PCX_ERROR_OPENING;
468         }
469
470         // read 128 char PCX header
471         if (cfread( &header, sizeof(PCXHeader), 1, PCXfile )!=1)        {
472                 cfclose( PCXfile );
473                 return PCX_ERROR_NO_HEADER;
474         }
475
476         // Is it a 256 color PCX file?
477         if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5))      {
478                 cfclose( PCXfile );
479                 return PCX_ERROR_WRONG_VERSION;
480         }
481
482         // Find the size of the image
483         xsize = header.Xmax - header.Xmin + 1;
484         ysize = header.Ymax - header.Ymin + 1;
485
486         // Read the extended palette at the end of PCX file
487         // Read in a character which should be 12 to be extended palette file
488
489         cfseek( PCXfile, -768, CF_SEEK_END );
490         cfread( palette, 3, 256, PCXfile );
491         cfseek( PCXfile, sizeof(PCXHeader), CF_SEEK_SET );
492         
493         buffer_size = 1024;
494         buffer_pos = 0;
495         
496 //      Assert( buffer_size == 1024 );  // AL: removed to avoid optimized warning 'unreachable code'
497         buffer_size = cfread( buffer, 1, buffer_size, PCXfile );
498
499         count = 0;
500
501         for (row=0; row<ysize;row++)      {
502                 pixdata = org_data;
503                 for (col=0; col<header.BytesPerLine;col++)     {
504                         if ( count == 0 )       {
505                                 data = buffer[buffer_pos++];
506                                 if ( buffer_pos == buffer_size )        {
507                                         buffer_size = cfread( buffer, 1, buffer_size, PCXfile );
508                                         Assert( buffer_size > 0 );
509                                         buffer_pos = 0;
510                                 }
511                                 if ((data & 0xC0) == 0xC0)     {
512                                         count = data & 0x3F;
513                                         data = buffer[buffer_pos++];
514                                         if ( buffer_pos == buffer_size )        {
515                                                 buffer_size = cfread( buffer, 1, buffer_size, PCXfile );
516                                                 Assert( buffer_size > 0 );
517                                                 buffer_pos = 0;
518                                         }
519                                 } else {
520                                         count = 1;
521                                 }
522                         }
523                         // stuff the pixel
524                         if ( col < xsize ){                             
525                                 // stuff the 24 bit value                               
526                                 r = palette[data*3];
527                                 g = palette[data*3 + 1];
528                                 b = palette[data*3 + 2];                                                        
529
530                                 // if this is a nondarkening texture                            
531                                 // if this color matches a nondarkening pixel color, set the alpha to high
532                                 al = 0;
533                                 if(palman_is_nondarkening(r, g, b)){
534                                         al = 255;
535                                 }
536
537                                 // set the pixel
538                                 bit_16 = 0;
539                                 bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);                                    
540                                 
541                                 // stuff the pixel
542                                 *((ushort*)pixdata) = bit_16;                           
543                                 pixdata += 2;
544                         }
545                         count--;
546                 }
547
548                 org_data += (xsize * 2);
549         }
550         cfclose(PCXfile);
551         return PCX_ERROR_NONE;
552 }
553
554 // subroutine for writing an encoded byte pair
555 // returns count of bytes written, 0 if error
556 int pcx_encode_byte(ubyte byt, ubyte cnt, FILE * fid)
557 {
558         if (cnt) {
559                 if ( (cnt==1) && (0xc0 != (0xc0 & byt)) )       {
560                         if(EOF == putc((int)byt, fid))
561                                 return 0;       // disk write error (probably full)
562                         return 1;
563                 } else {
564                         if(EOF == putc((int)0xC0 | cnt, fid))
565                                 return 0;       // disk write error
566                         if(EOF == putc((int)byt, fid))
567                                 return 0;       // disk write error
568                         return 2;
569                 }
570         }
571         return 0;
572 }
573
574 // returns number of bytes written into outBuff, 0 if failed
575 int pcx_encode_line(ubyte *inBuff, int inLen, FILE * fp)
576 {
577         ubyte this_ptr, last;
578
579         int srcIndex, i;
580         register int total;
581         register ubyte runCount;        // max single runlength is 63
582         total = 0;
583         last = *(inBuff);
584         runCount = 1;
585
586         for (srcIndex = 1; srcIndex < inLen; srcIndex++) {
587                 this_ptr = *(++inBuff);
588                 if (this_ptr == last)   {
589                         runCount++;                     // it encodes
590                         if (runCount == 63)     {
591                                 i = pcx_encode_byte(last, runCount, fp);
592                                 if(!i){
593                                         return(0);
594                                 }
595                                 total += i;
596                                 runCount = 0;
597                         }
598                 } else {        // this_ptr != last
599                         if (runCount)   {
600                                 i = pcx_encode_byte(last, runCount, fp);
601                                 if (!i){
602                                         return(0);
603                                 }
604                                 total += i;
605                         }
606                         last = this_ptr;
607                         runCount = 1;
608                 }
609         }
610
611         if (runCount)   {               // finish up
612                 i = pcx_encode_byte(last, runCount, fp);
613                 if (!i){
614                         return 0;
615                 }
616                 return total + i;
617         }
618         return total;
619 }
620
621
622 int pcx_write_bitmap( char * real_filename, int w, int h, ubyte ** row_ptrs, ubyte * palette )
623 {
624         int retval;
625         int i;
626         ubyte data;
627         PCXHeader header;
628         FILE * PCXfile;
629         char filename[MAX_FILENAME_LEN];
630                 
631         strcpy( filename, real_filename );
632         char *p = strchr( filename, '.' );
633         if ( p ) *p = 0;
634         strcat( filename, ".pcx" );
635
636         memset( &header, 0, sizeof( PCXHeader ) );
637
638         header.Manufacturer = 10;
639         header.Encoding = 1;
640         header.Nplanes = 1;
641         header.BitsPerPixel = 8;
642         header.Version = 5;
643         header.Xmax = (short)(w-1);
644         header.Ymax = (short)(h-1);
645         header.Ymin = 0;
646         header.Xmin = 0;
647         header.BytesPerLine =(short)(w);
648
649         PCXfile = fopen( filename , "wb" );
650         if ( !PCXfile )
651                 return PCX_ERROR_OPENING;
652
653         if ( fwrite( &header, sizeof( PCXHeader ), 1, PCXfile ) != 1 )  {
654                 fclose( PCXfile );
655                 return PCX_ERROR_WRITING;
656         }
657
658         for (i=0; i<h; i++ )    {
659                 if (!pcx_encode_line( row_ptrs[i], w, PCXfile ))        {
660                         fclose( PCXfile );
661                         return PCX_ERROR_WRITING;
662                 }
663         }
664
665         // Mark an extended palette
666         data = 12;
667         if (fwrite( &data, 1, 1, PCXfile )!=1)  {
668                 fclose( PCXfile );
669                 return PCX_ERROR_WRITING;
670         }
671
672         // Write the extended palette
673 //      for (i=0; i<768; i++ )
674 //              palette[i] <<= 2;
675
676         retval = fwrite( palette, 768, 1, PCXfile );
677
678 //      for (i=0; i<768; i++ )
679 //              palette[i] >>= 2;
680
681         if (retval !=1) {
682                 fclose( PCXfile );
683                 return PCX_ERROR_WRITING;
684         }
685
686         fclose( PCXfile );
687         return PCX_ERROR_NONE;
688
689 }
690
691 //text for error messges
692 char pcx_error_messages[] = {
693         "No error.\0"
694         "Error opening file.\0"
695         "Couldn't read PCX header.\0"
696         "Unsupported PCX version.\0"
697         "Error reading data.\0"
698         "Couldn't find palette information.\0"
699         "Error writing data.\0"
700 };
701
702
703 //function to return pointer to error message
704 char *pcx_errormsg(int error_number)
705 {
706         char *p = pcx_error_messages;
707
708         while (error_number--) {
709
710                 if (!p) return NULL;
711
712                 p += strlen(p)+1;
713
714         }
715
716         return p;
717
718 }