]> icculus.org git repositories - divverent/netradiant.git/blob - tools/quake3/common/imagelib.c
fix bugs in skin load code
[divverent/netradiant.git] / tools / quake3 / common / imagelib.c
1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 // imagelib.c
23
24 #include "inout.h"
25 #include "cmdlib.h"
26 #include "imagelib.h"
27 #include "vfs.h"
28
29 int fgetLittleShort (FILE *f)
30 {
31         byte    b1, b2;
32
33         b1 = fgetc(f);
34         b2 = fgetc(f);
35
36         return (short)(b1 + b2*256);
37 }
38
39 int fgetLittleLong (FILE *f)
40 {
41         byte    b1, b2, b3, b4;
42
43         b1 = fgetc(f);
44         b2 = fgetc(f);
45         b3 = fgetc(f);
46         b4 = fgetc(f);
47
48         return b1 + (b2<<8) + (b3<<16) + (b4<<24);
49 }
50
51 int bufLittleShort (byte *buf, int len, int *pos)
52 {
53   byte  b1, b2;
54
55   if ((len - *pos) < 2)
56     Error ("Unexpected buffer end");
57
58   b1 = buf[*pos]; *pos += 1;
59   b2 = buf[*pos]; *pos += 1;
60
61   return (short)(b1 + b2*256);
62 }
63
64 int bufLittleLong (byte *buf, int len, int *pos)
65 {
66   byte b1, b2, b3, b4;
67
68   if ((len - *pos) < 4)
69     Error ("Unexpected buffer end");
70
71   b1 = buf[*pos]; *pos += 1;
72   b2 = buf[*pos]; *pos += 1;
73   b3 = buf[*pos]; *pos += 1;
74   b4 = buf[*pos]; *pos += 1;
75
76   return b1 + (b2<<8) + (b3<<16) + (b4<<24);
77 }
78
79
80 /*
81 ============================================================================
82
83                                                 LBM STUFF
84
85 ============================================================================
86 */
87
88
89 typedef unsigned char   UBYTE;
90 //conflicts with windows typedef short                  WORD;
91 typedef unsigned short  UWORD;
92 typedef long                    LONG;
93
94 typedef enum
95 {
96         ms_none,
97         ms_mask,
98         ms_transcolor,
99         ms_lasso
100 } mask_t;
101
102 typedef enum
103 {
104         cm_none,
105         cm_rle1
106 } compress_t;
107
108 typedef struct
109 {
110         UWORD           w,h;
111         short           x,y;
112         UBYTE           nPlanes;
113         UBYTE           masking;
114         UBYTE           compression;
115         UBYTE           pad1;
116         UWORD           transparentColor;
117         UBYTE           xAspect,yAspect;
118         short           pageWidth,pageHeight;
119 } bmhd_t;
120
121 extern  bmhd_t  bmhd;                                           // will be in native byte order
122
123
124
125 #define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
126 #define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
127 #define PBMID  ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
128 #define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
129 #define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
130 #define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
131
132
133 bmhd_t  bmhd;
134
135 int    Align (int l)
136 {
137         if (l&1)
138                 return l+1;
139         return l;
140 }
141
142
143
144 /*
145 ================
146 LBMRLEdecompress
147
148 Source must be evenly aligned!
149 ================
150 */
151 byte  *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
152 {
153         int     count;
154         byte    b,rept;
155
156         count = 0;
157
158         do
159         {
160                 rept = *source++;
161
162                 if (rept > 0x80)
163                 {
164                         rept = (rept^0xff)+2;
165                         b = *source++;
166                         memset(unpacked,b,rept);
167                         unpacked += rept;
168                 }
169                 else if (rept < 0x80)
170                 {
171                         rept++;
172                         memcpy(unpacked,source,rept);
173                         unpacked += rept;
174                         source += rept;
175                 }
176                 else
177                         rept = 0;               // rept of 0x80 is NOP
178
179                 count += rept;
180
181         } while (count<bpwidth);
182
183         if (count>bpwidth)
184                 Error ("Decompression exceeded width!\n");
185
186
187         return source;
188 }
189
190
191 /*
192 =================
193 LoadLBM
194 =================
195 */
196 void LoadLBM (const char *filename, byte **picture, byte **palette)
197 {
198         byte    *LBMbuffer, *picbuffer, *cmapbuffer;
199         int             y;
200         byte    *LBM_P, *LBMEND_P;
201         byte    *pic_p;
202         byte    *body_p;
203
204         int    formtype,formlength;
205         int    chunktype,chunklength;
206
207 // qiet compiler warnings
208         picbuffer = NULL;
209         cmapbuffer = NULL;
210
211 //
212 // load the LBM
213 //
214         LoadFile (filename, (void **)&LBMbuffer);
215
216 //
217 // parse the LBM header
218 //
219         LBM_P = LBMbuffer;
220         if ( *(int *)LBMbuffer != LittleLong(FORMID) )
221            Error ("No FORM ID at start of file!\n");
222
223         LBM_P += 4;
224         formlength = BigLong( *(int *)LBM_P );
225         LBM_P += 4;
226         LBMEND_P = LBM_P + Align(formlength);
227
228         formtype = LittleLong(*(int *)LBM_P);
229
230         if (formtype != ILBMID && formtype != PBMID)
231                 Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
232                 ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
233
234         LBM_P += 4;
235
236 //
237 // parse chunks
238 //
239
240         while (LBM_P < LBMEND_P)
241         {
242                 chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
243                 LBM_P += 4;
244                 chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
245                 LBM_P += 4;
246
247                 switch ( chunktype )
248                 {
249                 case BMHDID:
250                         memcpy (&bmhd,LBM_P,sizeof(bmhd));
251                         bmhd.w = BigShort(bmhd.w);
252                         bmhd.h = BigShort(bmhd.h);
253                         bmhd.x = BigShort(bmhd.x);
254                         bmhd.y = BigShort(bmhd.y);
255                         bmhd.pageWidth = BigShort(bmhd.pageWidth);
256                         bmhd.pageHeight = BigShort(bmhd.pageHeight);
257                         break;
258
259                 case CMAPID:
260                         cmapbuffer = safe_malloc (768);
261                         memset (cmapbuffer, 0, 768);
262                         memcpy (cmapbuffer, LBM_P, chunklength);
263                         break;
264
265                 case BODYID:
266                         body_p = LBM_P;
267
268                         pic_p = picbuffer = safe_malloc (bmhd.w*bmhd.h);
269                         if (formtype == PBMID)
270                         {
271                         //
272                         // unpack PBM
273                         //
274                                 for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
275                                 {
276                                         if (bmhd.compression == cm_rle1)
277                                                 body_p = LBMRLEDecompress ((byte *)body_p
278                                                 , pic_p , bmhd.w);
279                                         else if (bmhd.compression == cm_none)
280                                         {
281                                                 memcpy (pic_p,body_p,bmhd.w);
282                                                 body_p += Align(bmhd.w);
283                                         }
284                                 }
285
286                         }
287                         else
288                         {
289                         //
290                         // unpack ILBM
291                         //
292                                 Error ("%s is an interlaced LBM, not packed", filename);
293                         }
294                         break;
295                 }
296
297                 LBM_P += Align(chunklength);
298         }
299
300         free (LBMbuffer);
301
302         *picture = picbuffer;
303
304         if (palette)
305                 *palette = cmapbuffer;
306 }
307
308
309 /*
310 ============================================================================
311
312                                                         WRITE LBM
313
314 ============================================================================
315 */
316
317 /*
318 ==============
319 WriteLBMfile
320 ==============
321 */
322 void WriteLBMfile (const char *filename, byte *data,
323                                    int width, int height, byte *palette)
324 {
325         byte    *lbm, *lbmptr;
326         int    *formlength, *bmhdlength, *cmaplength, *bodylength;
327         int    length;
328         bmhd_t  basebmhd;
329
330         lbm = lbmptr = safe_malloc (width*height+1000);
331
332 //
333 // start FORM
334 //
335         *lbmptr++ = 'F';
336         *lbmptr++ = 'O';
337         *lbmptr++ = 'R';
338         *lbmptr++ = 'M';
339
340         formlength = (int*)lbmptr;
341         lbmptr+=4;                      // leave space for length
342
343         *lbmptr++ = 'P';
344         *lbmptr++ = 'B';
345         *lbmptr++ = 'M';
346         *lbmptr++ = ' ';
347
348 //
349 // write BMHD
350 //
351         *lbmptr++ = 'B';
352         *lbmptr++ = 'M';
353         *lbmptr++ = 'H';
354         *lbmptr++ = 'D';
355
356         bmhdlength = (int *)lbmptr;
357         lbmptr+=4;                      // leave space for length
358
359         memset (&basebmhd,0,sizeof(basebmhd));
360         basebmhd.w = BigShort((short)width);
361         basebmhd.h = BigShort((short)height);
362         basebmhd.nPlanes = BigShort(8);
363         basebmhd.xAspect = BigShort(5);
364         basebmhd.yAspect = BigShort(6);
365         basebmhd.pageWidth = BigShort((short)width);
366         basebmhd.pageHeight = BigShort((short)height);
367
368         memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
369         lbmptr += sizeof(basebmhd);
370
371         length = lbmptr-(byte *)bmhdlength-4;
372         *bmhdlength = BigLong(length);
373         if (length&1)
374                 *lbmptr++ = 0;          // pad chunk to even offset
375
376 //
377 // write CMAP
378 //
379         *lbmptr++ = 'C';
380         *lbmptr++ = 'M';
381         *lbmptr++ = 'A';
382         *lbmptr++ = 'P';
383
384         cmaplength = (int *)lbmptr;
385         lbmptr+=4;                      // leave space for length
386
387         memcpy (lbmptr,palette,768);
388         lbmptr += 768;
389
390         length = lbmptr-(byte *)cmaplength-4;
391         *cmaplength = BigLong(length);
392         if (length&1)
393                 *lbmptr++ = 0;          // pad chunk to even offset
394
395 //
396 // write BODY
397 //
398         *lbmptr++ = 'B';
399         *lbmptr++ = 'O';
400         *lbmptr++ = 'D';
401         *lbmptr++ = 'Y';
402
403         bodylength = (int *)lbmptr;
404         lbmptr+=4;                      // leave space for length
405
406         memcpy (lbmptr,data,width*height);
407         lbmptr += width*height;
408
409         length = lbmptr-(byte *)bodylength-4;
410         *bodylength = BigLong(length);
411         if (length&1)
412                 *lbmptr++ = 0;          // pad chunk to even offset
413
414 //
415 // done
416 //
417         length = lbmptr-(byte *)formlength-4;
418         *formlength = BigLong(length);
419         if (length&1)
420                 *lbmptr++ = 0;          // pad chunk to even offset
421
422 //
423 // write output file
424 //
425         SaveFile (filename, lbm, lbmptr-lbm);
426         free (lbm);
427 }
428
429
430 /*
431 ============================================================================
432
433 LOAD PCX
434
435 ============================================================================
436 */
437
438 typedef struct
439 {
440     char        manufacturer;
441     char        version;
442     char        encoding;
443     char        bits_per_pixel;
444     unsigned short      xmin,ymin,xmax,ymax;
445     unsigned short      hres,vres;
446     unsigned char       palette[48];
447     char        reserved;
448     char        color_planes;
449     unsigned short      bytes_per_line;
450     unsigned short      palette_type;
451     char        filler[58];
452     unsigned char       data;                   // unbounded
453 } pcx_t;
454
455
456 /*
457 ==============
458 LoadPCX
459 ==============
460 */
461
462 /* RR2DO2 */
463 #define DECODEPCX( b, d, r ) d=*b++;if((d&0xC0)==0xC0){r=d&0x3F;d=*b++;}else{r=1;}
464
465 void LoadPCX( const char *filename, byte **pic, byte **palette, int *width, int *height )
466 {
467         byte    *raw;
468         pcx_t   *pcx;
469         int             x, y, lsize;
470         int             len;
471         int             dataByte, runLength;
472         byte    *out, *pix;
473         
474
475         /* load the file */
476         len = vfsLoadFile (filename, (void **)&raw, 0);
477     if( len == -1 ) 
478                 Error( "LoadPCX: Couldn't read %s", filename );
479
480         
481         /* parse the PCX file */
482         pcx = (pcx_t *)raw;
483         raw = &pcx->data;
484
485         pcx->xmin = LittleShort(pcx->xmin);
486         pcx->ymin = LittleShort(pcx->ymin);
487         pcx->xmax = LittleShort(pcx->xmax);
488         pcx->ymax = LittleShort(pcx->ymax);
489         pcx->hres = LittleShort(pcx->hres);
490         pcx->vres = LittleShort(pcx->vres);
491         pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
492         pcx->palette_type = LittleShort(pcx->palette_type);
493
494         if (pcx->manufacturer != 0x0a
495                 || pcx->version != 5
496                 || pcx->encoding != 1
497                 || pcx->bits_per_pixel != 8
498                 || pcx->xmax >= 640
499                 || pcx->ymax >= 480)
500                 Error ("Bad pcx file %s", filename);
501         
502         if (palette)
503         {
504                 *palette = safe_malloc(768);
505                 memcpy (*palette, (byte *)pcx + len - 768, 768);
506         }
507
508         if (width)
509                 *width = pcx->xmax+1;
510         if (height)
511                 *height = pcx->ymax+1;
512
513         if (!pic)
514                 return;
515
516         out = safe_malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
517         if (!out)
518                 Error( "LoadPCX: couldn't allocate");
519
520         *pic = out;
521         pix = out;
522         
523         /* RR2DO2: pcx fix  */
524         lsize = pcx->color_planes * pcx->bytes_per_line;
525         
526         /* go scanline by scanline */
527         for( y = 0; y <= pcx->ymax; y++, pix += pcx->xmax + 1 )
528         {
529                 /* do a scanline */
530                 for( x=0; x <= pcx->xmax; )
531                 {
532                         /* RR2DO2 */
533                         DECODEPCX( raw, dataByte, runLength );
534                         while( runLength-- > 0 )
535                                 pix[ x++ ] = dataByte;
536                 }
537
538                 /* RR2DO2: discard any other data */
539                 while( x < lsize )
540                 {
541                         DECODEPCX( raw, dataByte, runLength );
542                         x++;
543                 }
544                 while( runLength-- > 0 )
545                         x++;
546         }
547         
548         /* validity check */
549         if( raw - (byte *) pcx > len)
550                 Error( "PCX file %s was malformed", filename );
551         free( pcx );
552 }
553
554
555
556 /* 
557 ============== 
558 WritePCXfile 
559 ============== 
560 */ 
561 void WritePCXfile (const char *filename, byte *data, 
562                                    int width, int height, byte *palette) 
563 {
564         int             i, j, length;
565         pcx_t   *pcx;
566         byte            *pack;
567           
568         pcx = safe_malloc (width*height*2+1000);
569         memset (pcx, 0, sizeof(*pcx));
570
571         pcx->manufacturer = 0x0a;       // PCX id
572         pcx->version = 5;                       // 256 color
573         pcx->encoding = 1;              // uncompressed
574         pcx->bits_per_pixel = 8;                // 256 color
575         pcx->xmin = 0;
576         pcx->ymin = 0;
577         pcx->xmax = LittleShort((short)(width-1));
578         pcx->ymax = LittleShort((short)(height-1));
579         pcx->hres = LittleShort((short)width);
580         pcx->vres = LittleShort((short)height);
581         pcx->color_planes = 1;          // chunky image
582         pcx->bytes_per_line = LittleShort((short)width);
583         pcx->palette_type = LittleShort(1);             // not a grey scale
584
585         // pack the image
586         pack = &pcx->data;
587         
588         for (i=0 ; i<height ; i++)
589         {
590                 for (j=0 ; j<width ; j++)
591                 {
592                         if ( (*data & 0xc0) != 0xc0)
593                                 *pack++ = *data++;
594                         else
595                         {
596                                 *pack++ = 0xc1;
597                                 *pack++ = *data++;
598                         }
599                 }
600         }
601                         
602         // write the palette
603         *pack++ = 0x0c; // palette ID byte
604         for (i=0 ; i<768 ; i++)
605                 *pack++ = *palette++;
606                 
607 // write output file 
608         length = pack - (byte *)pcx;
609         SaveFile (filename, pcx, length);
610
611         free (pcx);
612
613  
614 /*
615 ============================================================================
616
617 LOAD BMP
618
619 ============================================================================
620 */
621
622
623 /*
624
625 // we can't just use these structures, because
626 // compiler structure alignment will not be portable
627 // on this unaligned stuff
628
629 typedef struct tagBITMAPFILEHEADER { // bmfh 
630         WORD    bfType;                         // BM
631         DWORD   bfSize; 
632         WORD    bfReserved1; 
633         WORD    bfReserved2; 
634         DWORD   bfOffBits; 
635 } BITMAPFILEHEADER; 
636  
637 typedef struct tagBITMAPINFOHEADER{ // bmih 
638    DWORD  biSize; 
639    LONG   biWidth; 
640    LONG   biHeight; 
641    WORD   biPlanes; 
642    WORD   biBitCount 
643    DWORD  biCompression; 
644    DWORD  biSizeImage; 
645    LONG   biXPelsPerMeter; 
646    LONG   biYPelsPerMeter; 
647    DWORD  biClrUsed; 
648    DWORD  biClrImportant; 
649 } BITMAPINFOHEADER; 
650  
651 typedef struct tagBITMAPINFO { // bmi 
652    BITMAPINFOHEADER bmiHeader; 
653    RGBQUAD          bmiColors[1]; 
654 } BITMAPINFO; 
655
656 typedef struct tagBITMAPCOREHEADER { // bmch 
657         DWORD   bcSize; 
658         WORD    bcWidth; 
659         WORD    bcHeight; 
660         WORD    bcPlanes; 
661         WORD    bcBitCount; 
662 } BITMAPCOREHEADER; 
663  
664 typedef struct _BITMAPCOREINFO {    // bmci 
665         BITMAPCOREHEADER  bmciHeader; 
666         RGBTRIPLE         bmciColors[1]; 
667 } BITMAPCOREINFO; 
668  
669 */
670
671 /*
672 ==============
673 LoadBMP
674 ==============
675 */
676 void LoadBMP (const char *filename, byte **pic, byte **palette, int *width, int *height)
677 {
678   byte  *out;
679   int           i;
680   int           bfSize; 
681   int           bfOffBits; 
682   int           structSize;
683   int           bcWidth; 
684   int     bcHeight; 
685   int       bcPlanes; 
686   int           bcBitCount; 
687   byte  bcPalette[1024];
688   qboolean      flipped;
689   byte *in;
690   int len, pos = 0;
691
692   len = vfsLoadFile (filename, (void **)&in, 0);
693   if (len == -1) 
694   {
695     Error ("Couldn't read %s", filename);
696   }
697
698   i = bufLittleShort (in, len, &pos);
699   if (i != 'B' + ('M'<<8) ) {
700     Error ("%s is not a bmp file", filename);
701   }
702
703   bfSize = bufLittleLong (in, len, &pos);
704   bufLittleShort(in, len, &pos);
705   bufLittleShort(in, len, &pos);
706   bfOffBits = bufLittleLong (in, len, &pos);
707
708   // the size will tell us if it is a
709   // bitmapinfo or a bitmapcore
710   structSize = bufLittleLong (in, len, &pos);
711   if (structSize == 40)
712   {
713     // bitmapinfo
714     bcWidth = bufLittleLong(in, len, &pos); 
715     bcHeight= bufLittleLong(in, len, &pos); 
716     bcPlanes = bufLittleShort(in, len, &pos); 
717     bcBitCount = bufLittleShort(in, len, &pos); 
718
719     pos += 24;
720
721     if (palette)
722     {
723       memcpy (bcPalette, in+pos, 1024);
724       pos += 1024;
725       *palette = safe_malloc(768);
726
727       for (i = 0 ; i < 256 ; i++)
728       {
729         (*palette)[i * 3 + 0] = bcPalette[i * 4 + 2];
730         (*palette)[i * 3 + 1] = bcPalette[i * 4 + 1];
731         (*palette)[i * 3 + 2] = bcPalette[i * 4 + 0];
732       }
733     }
734   }
735   else if (structSize == 12)
736   {
737     // bitmapcore
738     bcWidth = bufLittleShort(in, len, &pos); 
739     bcHeight= bufLittleShort(in, len, &pos); 
740     bcPlanes = bufLittleShort(in, len, &pos); 
741     bcBitCount = bufLittleShort(in, len, &pos); 
742
743     if (palette)
744     {
745       memcpy (bcPalette, in+pos, 768);
746       pos += 768;
747       *palette = safe_malloc(768);
748
749       for (i = 0 ; i < 256 ; i++) {
750         (*palette)[i * 3 + 0] = bcPalette[i * 3 + 2];
751         (*palette)[i * 3 + 1] = bcPalette[i * 3 + 1];
752         (*palette)[i * 3 + 2] = bcPalette[i * 3 + 0];
753       }
754     }
755   } else {
756     Error ("%s had strange struct size", filename);
757   }
758
759   if (bcPlanes != 1) {
760     Error ("%s was not a single plane image", filename);
761   }
762
763   if (bcBitCount != 8) {
764     Error ("%s was not an 8 bit image", filename);
765   }
766
767   if (bcHeight < 0) {
768     bcHeight = -bcHeight;
769     flipped = qtrue;
770   } else {
771     flipped = qfalse;
772   }
773
774   if (width)
775     *width = bcWidth;
776   if (height)
777     *height = bcHeight;
778
779   if (!pic) {
780     free (in);
781     return;
782   }
783
784   out = safe_malloc ( bcWidth * bcHeight );
785   *pic = out;
786   pos = bfOffBits;
787
788   if (flipped) {
789     for (i = 0 ; i < bcHeight ; i++) {
790       memcpy (out + bcWidth * (bcHeight - 1 - i), in+pos, bcWidth);
791       pos += bcWidth;
792     }
793   } else {
794     memcpy (out, in+pos, bcWidth*bcHeight);
795     pos += bcWidth*bcHeight;
796   }
797
798   free (in);
799 }
800
801
802 /*
803 ============================================================================
804
805 LOAD IMAGE
806
807 ============================================================================
808 */
809
810 /*
811 ==============
812 Load256Image
813
814 Will load either an lbm or pcx, depending on extension.
815 Any of the return pointers can be NULL if you don't want them.
816 ==============
817 */
818 void Load256Image (const char *name, byte **pixels, byte **palette, int *width, int *height)
819 {
820   char ext[128];
821
822   ExtractFileExtension (name, ext);
823   if (!Q_stricmp (ext, "lbm"))
824   {
825     LoadLBM (name, pixels, palette);
826     if (width)
827       *width = bmhd.w;
828     if (height)
829       *height = bmhd.h;
830   }
831   else if (!Q_stricmp (ext, "pcx"))
832   {
833     LoadPCX (name, pixels, palette, width, height);
834   }
835   else if (!Q_stricmp (ext, "bmp"))
836   {
837     LoadBMP (name, pixels, palette, width, height);
838   }
839   else
840     Error ("%s doesn't have a known image extension", name);
841 }
842
843
844 /*
845 ==============
846 Save256Image
847
848 Will save either an lbm or pcx, depending on extension.
849 ==============
850 */
851 void Save256Image (const char *name, byte *pixels, byte *palette,
852                                    int width, int height)
853 {
854         char    ext[128];
855
856         ExtractFileExtension (name, ext);
857         if (!Q_stricmp (ext, "lbm"))
858         {
859                 WriteLBMfile (name, pixels, width, height, palette);
860         }
861         else if (!Q_stricmp (ext, "pcx"))
862         {
863                 WritePCXfile (name, pixels, width, height, palette);
864         }
865         else
866                 Error ("%s doesn't have a known image extension", name);
867 }
868
869
870
871
872 /*
873 ============================================================================
874
875 TARGA IMAGE
876
877 ============================================================================
878 */
879
880 typedef struct _TargaHeader {
881         unsigned char   id_length, colormap_type, image_type;
882         unsigned short  colormap_index, colormap_length;
883         unsigned char   colormap_size;
884         unsigned short  x_origin, y_origin, width, height;
885         unsigned char   pixel_size, attributes;
886 } TargaHeader;
887
888 void TargaError(TargaHeader *t, const char *message)
889 {
890         Sys_Printf("%s\n:TargaHeader:\nuint8 id_length = %i;\nuint8 colormap_type = %i;\nuint8 image_type = %i;\nuint16 colormap_index = %i;\nuint16 colormap_length = %i;\nuint8 colormap_size = %i;\nuint16 x_origin = %i;\nuint16 y_origin = %i;\nuint16 width = %i;\nuint16 height = %i;\nuint8 pixel_size = %i;\nuint8 attributes = %i;\n", message, t->id_length, t->colormap_type, t->image_type, t->colormap_index, t->colormap_length, t->colormap_size, t->x_origin, t->y_origin, t->width, t->height, t->pixel_size, t->attributes);
891 }
892
893 /*
894 =============
895 LoadTGABuffer
896 =============
897 */
898 void LoadTGABuffer (const byte *f, const byte *enddata, byte **pic, int *width, int *height)
899 {
900         int x, y, row_inc, compressed, readpixelcount, red, green, blue, alpha, runlen, pindex, alphabits, image_width, image_height;
901         byte *pixbuf, *image_rgba;
902         const byte *fin;
903         unsigned char *p;
904         TargaHeader targa_header;
905         unsigned char palette[256*4];
906
907         *pic = NULL;
908
909         // abort if it is too small to parse
910         if (enddata - f < 19)
911                 return;
912
913         targa_header.id_length = f[0];
914         targa_header.colormap_type = f[1];
915         targa_header.image_type = f[2];
916
917         targa_header.colormap_index = f[3] + f[4] * 256;
918         targa_header.colormap_length = f[5] + f[6] * 256;
919         targa_header.colormap_size = f[7];
920         targa_header.x_origin = f[8] + f[9] * 256;
921         targa_header.y_origin = f[10] + f[11] * 256;
922         targa_header.width = image_width = f[12] + f[13] * 256;
923         targa_header.height = image_height = f[14] + f[15] * 256;
924
925         targa_header.pixel_size = f[16];
926         targa_header.attributes = f[17];
927
928         // advance to end of header
929         fin = f + 18;
930
931         // skip TARGA image comment (usually 0 bytes)
932         fin += targa_header.id_length;
933
934         // read/skip the colormap if present (note: according to the TARGA spec it
935         // can be present even on truecolor or greyscale images, just not used by
936         // the image data)
937         if (targa_header.colormap_type)
938         {
939                 if (targa_header.colormap_length > 256)
940                 {
941                         TargaError(&targa_header, "LoadTGA: only up to 256 colormap_length supported\n");
942                         return;
943                 }
944                 if (targa_header.colormap_index)
945                 {
946                         TargaError(&targa_header, "LoadTGA: colormap_index not supported\n");
947                         return;
948                 }
949                 if (targa_header.colormap_size == 24)
950                 {
951                         for (x = 0;x < targa_header.colormap_length;x++)
952                         {
953                                 palette[x*4+2] = *fin++;
954                                 palette[x*4+1] = *fin++;
955                                 palette[x*4+0] = *fin++;
956                                 palette[x*4+3] = 255;
957                         }
958                 }
959                 else if (targa_header.colormap_size == 32)
960                 {
961                         for (x = 0;x < targa_header.colormap_length;x++)
962                         {
963                                 palette[x*4+2] = *fin++;
964                                 palette[x*4+1] = *fin++;
965                                 palette[x*4+0] = *fin++;
966                                 palette[x*4+3] = *fin++;
967                         }
968                 }
969                 else
970                 {
971                         TargaError(&targa_header, "LoadTGA: Only 32 and 24 bit colormap_size supported\n");
972                         return;
973                 }
974         }
975
976         // check our pixel_size restrictions according to image_type
977         if (targa_header.image_type == 2 || targa_header.image_type == 10)
978         {
979                 if (targa_header.pixel_size != 24 && targa_header.pixel_size != 32)
980                 {
981                         TargaError(&targa_header, "LoadTGA: only 24bit and 32bit pixel sizes supported for type 2 and type 10 images\n");
982                         return;
983                 }
984         }
985         else if (targa_header.image_type == 1 || targa_header.image_type == 9)
986         {
987                 if (targa_header.pixel_size != 8)
988                 {
989                         TargaError(&targa_header, "LoadTGA: only 8bit pixel size for type 1, 3, 9, and 11 images supported\n");
990                         return;
991                 }
992         }
993         else if (targa_header.image_type == 3 || targa_header.image_type == 11)
994         {
995                 if (targa_header.pixel_size != 8)
996                 {
997                         TargaError(&targa_header, "LoadTGA: only 8bit pixel size for type 1, 3, 9, and 11 images supported\n");
998                         return;
999                 }
1000         }
1001         else
1002         {
1003                 TargaError(&targa_header, "LoadTGA: Only type 1, 2, 3, 9, 10, and 11 targa RGB images supported");
1004                 return;
1005         }
1006
1007         if (targa_header.attributes & 0x10)
1008         {
1009                 TargaError(&targa_header, "LoadTGA: origin must be in top left or bottom left, top right and bottom right are not supported\n");
1010                 return;
1011         }
1012
1013         // number of attribute bits per pixel, we only support 0 or 8
1014         alphabits = targa_header.attributes & 0x0F;
1015         if (alphabits != 8 && alphabits != 0)
1016         {
1017                 TargaError(&targa_header, "LoadTGA: only 0 or 8 attribute (alpha) bits supported\n");
1018                 return;
1019         }
1020
1021         image_rgba = safe_malloc(image_width * image_height * 4);
1022         if (!image_rgba)
1023         {
1024                 Sys_Printf("LoadTGA: not enough memory for %i by %i image\n", image_width, image_height);
1025                 return;
1026         }
1027
1028         // If bit 5 of attributes isn't set, the image has been stored from bottom to top
1029         if ((targa_header.attributes & 0x20) == 0)
1030         {
1031                 pixbuf = image_rgba + (image_height - 1)*image_width*4;
1032                 row_inc = -image_width*4*2;
1033         }
1034         else
1035         {
1036                 pixbuf = image_rgba;
1037                 row_inc = 0;
1038         }
1039
1040         compressed = targa_header.image_type == 9 || targa_header.image_type == 10 || targa_header.image_type == 11;
1041         x = 0;
1042         y = 0;
1043         red = green = blue = alpha = 255;
1044         while (y < image_height)
1045         {
1046                 // decoder is mostly the same whether it's compressed or not
1047                 readpixelcount = 1000000;
1048                 runlen = 1000000;
1049                 if (compressed && fin < enddata)
1050                 {
1051                         runlen = *fin++;
1052                         // high bit indicates this is an RLE compressed run
1053                         if (runlen & 0x80)
1054                                 readpixelcount = 1;
1055                         runlen = 1 + (runlen & 0x7f);
1056                 }
1057
1058                 while((runlen--) && y < image_height)
1059                 {
1060                         if (readpixelcount > 0)
1061                         {
1062                                 readpixelcount--;
1063                                 red = green = blue = alpha = 255;
1064                                 if (fin < enddata)
1065                                 {
1066                                         switch(targa_header.image_type)
1067                                         {
1068                                         case 1:
1069                                         case 9:
1070                                                 // colormapped
1071                                                 pindex = *fin++;
1072                                                 if (pindex >= targa_header.colormap_length)
1073                                                         pindex = 0; // error
1074                                                 p = palette + pindex * 4;
1075                                                 red = p[0];
1076                                                 green = p[1];
1077                                                 blue = p[2];
1078                                                 alpha = p[3];
1079                                                 break;
1080                                         case 2:
1081                                         case 10:
1082                                                 // BGR or BGRA
1083                                                 blue = *fin++;
1084                                                 if (fin < enddata)
1085                                                         green = *fin++;
1086                                                 if (fin < enddata)
1087                                                         red = *fin++;
1088                                                 if (targa_header.pixel_size == 32 && fin < enddata)
1089                                                         alpha = *fin++;
1090                                                 break;
1091                                         case 3:
1092                                         case 11:
1093                                                 // greyscale
1094                                                 red = green = blue = *fin++;
1095                                                 break;
1096                                         }
1097                                         if (!alphabits)
1098                                                 alpha = 255;
1099                                 }
1100                         }
1101                         *pixbuf++ = red;
1102                         *pixbuf++ = green;
1103                         *pixbuf++ = blue;
1104                         *pixbuf++ = alpha;
1105                         x++;
1106                         if (x == image_width)
1107                         {
1108                                 // end of line, advance to next
1109                                 x = 0;
1110                                 y++;
1111                                 pixbuf += row_inc;
1112                         }
1113                 }
1114         }
1115
1116         *pic = image_rgba;
1117         if (width)
1118                 *width = image_width;
1119         if (height)
1120                 *height = image_height;
1121 }
1122
1123
1124 /*
1125 =============
1126 LoadTGA
1127 =============
1128 */
1129 void LoadTGA (const char *name, byte **pixels, int *width, int *height)
1130 {
1131         byte                    *buffer;
1132         int nLen;
1133         //
1134         // load the file
1135         //
1136         nLen = vfsLoadFile ( ( char * ) name, (void **)&buffer, 0);
1137         if (nLen == -1)
1138         {
1139                 Error ("Couldn't read %s", name);
1140         }
1141
1142         LoadTGABuffer(buffer, buffer + nLen, pixels, width, height);
1143
1144 }
1145
1146
1147 /*
1148 ================
1149 WriteTGA
1150 ================
1151 */
1152 void WriteTGA (const char *filename, byte *data, int width, int height) {
1153         byte    *buffer;
1154         int             i;
1155         int             c;
1156         FILE    *f;
1157
1158         buffer = safe_malloc(width*height*4 + 18);
1159         memset (buffer, 0, 18);
1160         buffer[2] = 2;          // uncompressed type
1161         buffer[12] = width&255;
1162         buffer[13] = width>>8;
1163         buffer[14] = height&255;
1164         buffer[15] = height>>8;
1165         buffer[16] = 32;        // pixel size
1166
1167         // swap rgb to bgr
1168         c = 18 + width * height * 4;
1169         for (i=18 ; i<c ; i+=4)
1170         {
1171                 buffer[i] = data[i-18+2];               // blue
1172                 buffer[i+1] = data[i-18+1];             // green
1173                 buffer[i+2] = data[i-18+0];             // red
1174                 buffer[i+3] = data[i-18+3];             // alpha
1175         }
1176
1177         f = fopen (filename, "wb");
1178         fwrite (buffer, 1, c, f);
1179         fclose (f);
1180
1181         free (buffer);
1182 }
1183
1184 void WriteTGAGray (const char *filename, byte *data, int width, int height) {
1185         byte    buffer[18];
1186         int             i;
1187         int             c;
1188         FILE    *f;
1189
1190         memset (buffer, 0, 18);
1191         buffer[2] = 3;          // uncompressed type
1192         buffer[12] = width&255;
1193         buffer[13] = width>>8;
1194         buffer[14] = height&255;
1195         buffer[15] = height>>8;
1196         buffer[16] = 8; // pixel size
1197
1198         f = fopen (filename, "wb");
1199         fwrite (buffer, 1, 18, f);
1200         fwrite (data, 1, width * height, f);
1201         fclose (f);
1202 }
1203
1204 /*
1205 ============================================================================
1206
1207 LOAD32BITIMAGE
1208
1209 ============================================================================
1210 */
1211
1212 /*
1213 ==============
1214 Load32BitImage
1215
1216 Any of the return pointers can be NULL if you don't want them.
1217 ==============
1218 */
1219 void Load32BitImage (const char *name, unsigned **pixels,  int *width, int *height)
1220 {
1221         char    ext[128];
1222         byte    *palette;
1223         byte    *pixels8;
1224         byte    *pixels32;
1225         int             size;
1226         int             i;
1227         int             v;
1228
1229         ExtractFileExtension (name, ext);
1230         if (!Q_stricmp (ext, "tga")) {
1231                 LoadTGA (name, (byte **)pixels, width, height);
1232         } else {
1233                 Load256Image (name, &pixels8, &palette, width, height);
1234                 if (!pixels) {
1235                         return;
1236                 }
1237                 size = *width * *height;
1238                 pixels32 = safe_malloc(size * 4);
1239                 *pixels = (unsigned *)pixels32;
1240                 for (i = 0 ; i < size ; i++) {
1241                         v = pixels8[i];
1242                         pixels32[i*4 + 0] = palette[ v * 3 + 0 ];
1243                         pixels32[i*4 + 1] = palette[ v * 3 + 1 ];
1244                         pixels32[i*4 + 2] = palette[ v * 3 + 2 ];
1245                         pixels32[i*4 + 3] = 0xff;
1246                 }
1247         }
1248 }
1249
1250