]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/qdata_heretic2/common/lbmlib.c
set eol-style
[xonotic/netradiant.git] / tools / quake2 / qdata_heretic2 / common / lbmlib.c
1 /*
2 Copyright (C) 1999-2007 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 // lbmlib.c
23
24 #include "cmdlib.h"
25 #include "inout.h"
26 #include "lbmlib.h"
27
28 // Ups the palette values so no pixels except 0 appear transparent
29 // Need a value of 8 to cater for 16bit renderers
30
31 typedef struct
32 {
33         byte    r;
34         byte    g;
35         byte    b;
36 } paletteRGB_t;
37
38
39 void CorrectPalette(byte *pal)
40 {
41         paletteRGB_t    *p;
42
43         p = (paletteRGB_t *)pal;
44         // Color 0 always transparent
45         p->r = 0;
46         p->g = 0;
47         p->b = 0;
48 }
49
50 /*
51 ============================================================================
52
53                                                 LBM STUFF
54
55 ============================================================================
56 */
57
58
59 typedef unsigned char   UBYTE;
60 //conflicts with windows typedef short                  WORD;
61 typedef unsigned short  UWORD;
62 typedef long                    LONG;
63
64 typedef enum
65 {
66         ms_none,
67         ms_mask,
68         ms_transcolor,
69         ms_lasso
70 } mask_t;
71
72 typedef enum
73 {
74         cm_none,
75         cm_rle1
76 } compress_t;
77
78 typedef struct
79 {
80         UWORD           w,h;
81         short           x,y;
82         UBYTE           nPlanes;
83         UBYTE           masking;
84         UBYTE           compression;
85         UBYTE           pad1;
86         UWORD           transparentColor;
87         UBYTE           xAspect,yAspect;
88         short           pageWidth,pageHeight;
89 } bmhd_t;
90
91 extern  bmhd_t  bmhd;                                           // will be in native byte order
92
93
94
95 #define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
96 #define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
97 #define PBMID  ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
98 #define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
99 #define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
100 #define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
101
102
103 bmhd_t  bmhd;
104
105 int    Align (int l)
106 {
107         if (l&1)
108                 return l+1;
109         return l;
110 }
111
112
113
114 /*
115 ================
116 LBMRLEdecompress
117
118 Source must be evenly aligned!
119 ================
120 */
121 byte  *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
122 {
123         int     count;
124         byte    b,rept;
125
126         count = 0;
127
128         do
129         {
130                 rept = *source++;
131
132                 if (rept > 0x80)
133                 {
134                         rept = (rept^0xff)+2;
135                         b = *source++;
136                         memset(unpacked,b,rept);
137                         unpacked += rept;
138                 }
139                 else if (rept < 0x80)
140                 {
141                         rept++;
142                         memcpy(unpacked,source,rept);
143                         unpacked += rept;
144                         source += rept;
145                 }
146                 else
147                         rept = 0;               // rept of 0x80 is NOP
148
149                 count += rept;
150
151         } while (count<bpwidth);
152
153         if (count>bpwidth)
154                 Error ("Decompression exceeded width!\n");
155
156
157         return source;
158 }
159
160
161 /*
162 =================
163 LoadLBM
164 =================
165 */
166 void LoadLBM (char *filename, byte **picture, byte **palette)
167 {
168         byte    *LBMbuffer, *picbuffer, *cmapbuffer;
169         int             y;
170         byte    *LBM_P, *LBMEND_P;
171         byte    *pic_p;
172         byte    *body_p;
173
174         int    formtype,formlength;
175         int    chunktype,chunklength;
176
177 // qiet compiler warnings
178         picbuffer = NULL;
179         cmapbuffer = NULL;
180
181 //
182 // load the LBM
183 //
184         LoadFile (filename, (void **)&LBMbuffer);
185
186 //
187 // parse the LBM header
188 //
189         LBM_P = LBMbuffer;
190         if ( *(int *)LBMbuffer != LittleLong(FORMID) )
191            Error ("No FORM ID at start of file!\n");
192
193         LBM_P += 4;
194         formlength = BigLong( *(int *)LBM_P );
195         LBM_P += 4;
196         LBMEND_P = LBM_P + Align(formlength);
197
198         formtype = LittleLong(*(int *)LBM_P);
199
200         if (formtype != ILBMID && formtype != PBMID)
201                 Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
202                 ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
203
204         LBM_P += 4;
205
206 //
207 // parse chunks
208 //
209
210         while (LBM_P < LBMEND_P)
211         {
212                 chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
213                 LBM_P += 4;
214                 chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
215                 LBM_P += 4;
216
217                 switch ( chunktype )
218                 {
219                 case BMHDID:
220                         memcpy (&bmhd,LBM_P,sizeof(bmhd));
221                         bmhd.w = BigShort(bmhd.w);
222                         bmhd.h = BigShort(bmhd.h);
223                         bmhd.x = BigShort(bmhd.x);
224                         bmhd.y = BigShort(bmhd.y);
225                         bmhd.pageWidth = BigShort(bmhd.pageWidth);
226                         bmhd.pageHeight = BigShort(bmhd.pageHeight);
227                         break;
228
229                 case CMAPID:
230                         cmapbuffer = malloc (768);
231                         memset (cmapbuffer, 0, 768);
232                         memcpy (cmapbuffer, LBM_P, chunklength);
233                         CorrectPalette(cmapbuffer);
234                         break;
235
236                 case BODYID:
237                         body_p = LBM_P;
238
239                         pic_p = picbuffer = malloc (bmhd.w*bmhd.h);
240                         if (formtype == PBMID)
241                         {
242                         //
243                         // unpack PBM
244                         //
245                                 for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
246                                 {
247                                         if (bmhd.compression == cm_rle1)
248                                                 body_p = LBMRLEDecompress ((byte *)body_p
249                                                 , pic_p , bmhd.w);
250                                         else if (bmhd.compression == cm_none)
251                                         {
252                                                 memcpy (pic_p,body_p,bmhd.w);
253                                                 body_p += Align(bmhd.w);
254                                         }
255                                 }
256
257                         }
258                         else
259                         {
260                         //
261                         // unpack ILBM
262                         //
263                                 Error ("%s is an interlaced LBM, not packed", filename);
264                         }
265                         break;
266                 }
267
268                 LBM_P += Align(chunklength);
269         }
270
271         free (LBMbuffer);
272
273         *picture = picbuffer;
274
275         if (palette)
276                 *palette = cmapbuffer;
277 }
278
279
280 /*
281 ============================================================================
282
283                                                         WRITE LBM
284
285 ============================================================================
286 */
287
288 /*
289 ==============
290 WriteLBMfile
291 ==============
292 */
293 void WriteLBMfile (char *filename, byte *data,
294                                    int width, int height, byte *palette)
295 {
296         byte    *lbm, *lbmptr;
297         int    *formlength, *bmhdlength, *cmaplength, *bodylength;
298         int    length;
299         bmhd_t  basebmhd;
300
301         lbm = lbmptr = malloc (width*height+1000);
302
303 //
304 // start FORM
305 //
306         *lbmptr++ = 'F';
307         *lbmptr++ = 'O';
308         *lbmptr++ = 'R';
309         *lbmptr++ = 'M';
310
311         formlength = (int*)lbmptr;
312         lbmptr+=4;                      // leave space for length
313
314         *lbmptr++ = 'P';
315         *lbmptr++ = 'B';
316         *lbmptr++ = 'M';
317         *lbmptr++ = ' ';
318
319 //
320 // write BMHD
321 //
322         *lbmptr++ = 'B';
323         *lbmptr++ = 'M';
324         *lbmptr++ = 'H';
325         *lbmptr++ = 'D';
326
327         bmhdlength = (int *)lbmptr;
328         lbmptr+=4;                      // leave space for length
329
330         memset (&basebmhd,0,sizeof(basebmhd));
331         basebmhd.w = BigShort((short)width);
332         basebmhd.h = BigShort((short)height);
333         basebmhd.nPlanes = BigShort(8);
334         basebmhd.xAspect = BigShort(5);
335         basebmhd.yAspect = BigShort(6);
336         basebmhd.pageWidth = BigShort((short)width);
337         basebmhd.pageHeight = BigShort((short)height);
338
339         memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
340         lbmptr += sizeof(basebmhd);
341
342         length = lbmptr-(byte *)bmhdlength-4;
343         *bmhdlength = BigLong(length);
344         if (length&1)
345                 *lbmptr++ = 0;          // pad chunk to even offset
346
347 //
348 // write CMAP
349 //
350         *lbmptr++ = 'C';
351         *lbmptr++ = 'M';
352         *lbmptr++ = 'A';
353         *lbmptr++ = 'P';
354
355         cmaplength = (int *)lbmptr;
356         lbmptr+=4;                      // leave space for length
357
358         memcpy (lbmptr,palette,768);
359         lbmptr += 768;
360
361         length = lbmptr-(byte *)cmaplength-4;
362         *cmaplength = BigLong(length);
363         if (length&1)
364                 *lbmptr++ = 0;          // pad chunk to even offset
365
366 //
367 // write BODY
368 //
369         *lbmptr++ = 'B';
370         *lbmptr++ = 'O';
371         *lbmptr++ = 'D';
372         *lbmptr++ = 'Y';
373
374         bodylength = (int *)lbmptr;
375         lbmptr+=4;                      // leave space for length
376
377         memcpy (lbmptr,data,width*height);
378         lbmptr += width*height;
379
380         length = lbmptr-(byte *)bodylength-4;
381         *bodylength = BigLong(length);
382         if (length&1)
383                 *lbmptr++ = 0;          // pad chunk to even offset
384
385 //
386 // done
387 //
388         length = lbmptr-(byte *)formlength-4;
389         *formlength = BigLong(length);
390         if (length&1)
391                 *lbmptr++ = 0;          // pad chunk to even offset
392
393 //
394 // write output file
395 //
396         SaveFile (filename, lbm, lbmptr-lbm);
397         free (lbm);
398 }
399
400
401 /*
402 ============================================================================
403
404 LOAD PCX
405
406 ============================================================================
407 */
408
409 typedef struct
410 {
411     char        manufacturer;
412     char        version;
413     char        encoding;
414     char        bits_per_pixel;
415     unsigned short      xmin,ymin,xmax,ymax;
416     unsigned short      hres,vres;
417     unsigned char       palette[48];
418     char        reserved;
419     char        color_planes;
420     unsigned short      bytes_per_line;
421     unsigned short      palette_type;
422     char        filler[58];
423     unsigned char       data;                   // unbounded
424 } pcx_t;
425
426 /*
427 ==============
428 LoadPCX
429 ==============
430 */
431 void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
432 {
433         byte    *raw;
434         pcx_t   *pcx;
435         int             x, y;
436         int             len;
437         int             dataByte, runLength;
438         byte    *out, *pix;
439
440         //
441         // load the file
442         //
443         len = LoadFile (filename, (void **)&raw);
444
445         //
446         // parse the PCX file
447         //
448         pcx = (pcx_t *)raw;
449         raw = &pcx->data;
450
451         pcx->xmin = LittleShort(pcx->xmin);
452         pcx->ymin = LittleShort(pcx->ymin);
453         pcx->xmax = LittleShort(pcx->xmax);
454         pcx->ymax = LittleShort(pcx->ymax);
455         pcx->hres = LittleShort(pcx->hres);
456         pcx->vres = LittleShort(pcx->vres);
457         pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
458         pcx->palette_type = LittleShort(pcx->palette_type);
459
460         if (pcx->manufacturer != 0x0a
461                 || pcx->version != 5
462                 || pcx->encoding != 1
463                 || pcx->bits_per_pixel != 8
464                 || pcx->xmax >= 640
465                 || pcx->ymax >= 480)
466                 Error ("Bad pcx file %s", filename);
467         
468         if (palette)
469         {
470                 *palette = malloc(768);
471                 memcpy (*palette, (byte *)pcx + len - 768, 768);
472                 CorrectPalette(*palette);
473         }
474
475         if (width)
476                 *width = pcx->xmax+1;
477         if (height)
478                 *height = pcx->ymax+1;
479
480         if (!pic)
481                 return;
482
483         out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
484         if (!out)
485                 Error ("Skin_Cache: couldn't allocate");
486
487         *pic = out;
488
489         pix = out;
490
491         for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
492         {
493                 for (x=0 ; x<=pcx->xmax ; )
494                 {
495                         dataByte = *raw++;
496
497                         if((dataByte & 0xC0) == 0xC0)
498                         {
499                                 runLength = dataByte & 0x3F;
500                                 dataByte = *raw++;
501                         }
502                         else
503                                 runLength = 1;
504
505                         while(runLength-- > 0)
506                                 pix[x++] = dataByte;
507                 }
508
509         }
510
511         if ( raw - (byte *)pcx > len)
512                 Error ("PCX file %s was malformed", filename);
513
514         free (pcx);
515 }
516
517 /* 
518 ============== 
519 WritePCXfile 
520 ============== 
521 */ 
522
523 void StuffPackedByte(int curRepCount, byte curByte, byte** packPtr)
524 {
525         byte* pack;
526         
527         pack = *packPtr;
528
529         while(curRepCount > 0)
530         {
531                 if (curRepCount == 1)
532                 {
533                         if ((curByte & 0xc0) != 0xc0)
534                         {
535                                 *pack++ = curByte;
536                         }
537                         else
538                         {
539                                 *pack++ = 0xc1;
540                                 *pack++ = curByte;
541                         }
542                         break;
543                 }
544                 if (curRepCount < 0x0040)
545                 {
546                         *pack++ = (0x00c0 | curRepCount);
547                         curRepCount = 0;
548                 }
549                 else
550                 {
551                         *pack++ = 0xff;
552                         curRepCount -= 0x003f;
553                 }
554                 *pack++ = curByte;
555         }
556         *packPtr = pack;
557 }
558
559 void WritePCXfile (char *filename, byte *data, 
560                                    int width, int height, byte *palette) 
561 {
562         int             i, j, length;
563         pcx_t           *pcx;
564         byte            *pack;
565         byte            curByte;
566         int                     curRepCount;
567           
568         pcx = 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;              // RLE
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         for (i=0 ; i<height ; i++)
603         {
604                 curByte = *data;
605                 curRepCount = 0;
606                 for (j=0 ; j<width ; j++)
607                 {
608                         if (*data == curByte)
609                         {
610                                 curRepCount++;
611                                 data++;
612                                 continue;
613                         }
614                         StuffPackedByte(curRepCount, curByte, &pack);
615                         curByte = *data++;
616                         curRepCount = 1;
617                 }
618                 StuffPackedByte(curRepCount, curByte, &pack);
619         }
620         // write the palette
621         *pack++ = 0x0c; // palette ID byte
622         for (i=0 ; i<768 ; i++)
623                 *pack++ = *palette++;
624                 
625 // write output file 
626         length = pack - (byte *)pcx;
627         SaveFile (filename, pcx, length);
628
629         free (pcx);
630
631  
632
633 /*
634 ============================================================================
635
636 LOAD IMAGE
637
638 ============================================================================
639 */
640
641 /*
642 ==============
643 Load256Image
644
645 Will load either an lbm or pcx, depending on extension.
646 Any of the return pointers can be NULL if you don't want them.
647 ==============
648 */
649 void Load256Image (char *name, byte **pixels, byte **palette,
650                                    int *width, int *height)
651 {
652         char    ext[128];
653
654         ExtractFileExtension (name, ext);
655         if (!Q_strcasecmp (ext, "lbm"))
656         {
657                 LoadLBM (name, pixels, palette);
658                 if (width)
659                         *width = bmhd.w;
660                 if (height)
661                         *height = bmhd.h;
662         }
663         else if (!Q_strcasecmp (ext, "pcx"))
664         {
665                 LoadPCX (name, pixels, palette, width, height);
666         }
667         else
668                 Error ("%s doesn't have a known image extension", name);
669 }
670
671
672 /*
673 ==============
674 Save256Image
675
676 Will save either an lbm or pcx, depending on extension.
677 ==============
678 */
679 void Save256Image (char *name, byte *pixels, byte *palette,
680                                    int width, int height)
681 {
682         char    ext[128];
683
684         ExtractFileExtension (name, ext);
685         if (!Q_strcasecmp (ext, "lbm"))
686         {
687                 WriteLBMfile (name, pixels, width, height, palette);
688         }
689         else if (!Q_strcasecmp (ext, "pcx"))
690         {
691                 WritePCXfile (name, pixels, width, height, palette);
692         }
693         else
694                 Error ("%s doesn't have a known image extension", name);
695 }
696
697
698
699
700 /*
701 ============================================================================
702
703 TARGA IMAGE
704
705 ============================================================================
706 */
707
708 typedef struct _TargaHeader
709 {
710         unsigned char   id_length, colormap_type, image_type;
711         unsigned short  colormap_index, colormap_length;
712         unsigned char   colormap_size;
713         unsigned short  x_origin, y_origin, width, height;
714         unsigned char   pixel_size, attributes;
715 } TargaHeader;
716
717 int fgetLittleShort (FILE *f)
718 {
719         byte    b1, b2;
720
721         b1 = fgetc(f);
722         b2 = fgetc(f);
723
724         return((short)(b1 + (b2 << 8)));
725 }
726
727 int fgetLittleLong (FILE *f)
728 {
729         byte    b1, b2, b3, b4;
730
731         b1 = fgetc(f);
732         b2 = fgetc(f);
733         b3 = fgetc(f);
734         b4 = fgetc(f);
735
736         return(b1 + (b2 << 8) + (b3 << 16) + (b4 << 24));
737 }
738
739
740 /*
741 =============
742 LoadTGA
743 =============
744 */
745 void LoadTGA(char *name, byte **pixels, int *width, int *height)
746 {
747         int                             columns, rows, numPixels;
748         byte                    *pixbuf;
749         byte                    *rowBuf;
750         int                             row, column;
751         FILE                    *fin;
752         byte                    *targa_rgba;
753         TargaHeader             targa_header;
754         unsigned char   red, green, blue, alphabyte;
755         unsigned char   packetHeader, packetSize, j;
756         int                             flip;
757         int                             mirror;
758         int                             rowOffset;
759         int                             pixDirection;
760
761         fin = fopen(name, "rb");
762         if (!fin)
763                 Error ("Couldn't read %s", name);
764
765         targa_header.id_length = fgetc(fin);
766         targa_header.colormap_type = fgetc(fin);
767         targa_header.image_type = fgetc(fin);
768         
769         targa_header.colormap_index = fgetLittleShort(fin);
770         targa_header.colormap_length = fgetLittleShort(fin);
771         targa_header.colormap_size = fgetc(fin);
772         targa_header.x_origin = fgetLittleShort(fin);
773         targa_header.y_origin = fgetLittleShort(fin);
774         targa_header.width = fgetLittleShort(fin);
775         targa_header.height = fgetLittleShort(fin);
776         targa_header.pixel_size = fgetc(fin);
777         targa_header.attributes = fgetc(fin);
778         flip = (targa_header.attributes & 0x020) == 0;
779         mirror = (targa_header.attributes & 0x010) != 0;
780
781         if ((targa_header.image_type != 2) && (targa_header.image_type != 10)) 
782                 Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
783
784         if (targa_header.colormap_type || ((targa_header.pixel_size != 32) && (targa_header.pixel_size != 24)))
785                 Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
786
787         columns = targa_header.width;
788         rows = targa_header.height;
789         numPixels = columns * rows;
790
791         if (width)
792                 *width = columns;
793         if (height)
794                 *height = rows;
795
796         if(!pixels)
797                 return;
798
799         targa_rgba = malloc(numPixels * 4);
800         *pixels = targa_rgba;
801
802         if (flip)
803         {
804                 pixbuf = targa_rgba + ((rows - 1) * columns * 4);
805                 rowOffset = -columns * 4;
806         }
807         else
808         {
809                 pixbuf = targa_rgba;
810                 rowOffset = columns * 4;
811         }
812         if (mirror)
813         {
814                 pixDirection = -4;
815                 pixbuf += ((columns - 1) * 4);
816         }
817         else
818         {
819                 pixDirection = 4;
820         }
821
822         if (targa_header.id_length)
823                 fseek(fin, targa_header.id_length, SEEK_CUR);  // skip TARGA image comment
824         
825         if (targa_header.image_type == 2)
826         {                                                                                                       // Uncompressed, RGB images
827                 for(row = 0; row < rows; row++)
828                 {
829                         rowBuf = pixbuf;
830                         for(column = 0; column < columns; column++)
831                         {
832                                 switch (targa_header.pixel_size)
833                                 {
834                                         case 24:
835                                                 blue = getc(fin);
836                                                 green = getc(fin);
837                                                 red = getc(fin);
838                                                 rowBuf[0] = red;
839                                                 rowBuf[1] = green;
840                                                 rowBuf[2] = blue;
841                                                 rowBuf[3] = 255;
842                                                 rowBuf += pixDirection;
843                                         break;
844                                         case 32:
845                                                 blue = getc(fin);
846                                                 green = getc(fin);
847                                                 red = getc(fin);
848                                                 alphabyte = getc(fin);
849                                                 rowBuf[0] = red;
850                                                 rowBuf[1] = green;
851                                                 rowBuf[2] = blue;
852                                                 rowBuf[3] = alphabyte;
853                                                 rowBuf += pixDirection;
854                                         break;
855                                 }
856                         }
857                         pixbuf += rowOffset;
858                 }
859         }
860         else if(targa_header.image_type == 10)
861         {                                                                                               // Runlength encoded RGB images
862                 for(row = 0; row < rows; row++)
863                 {
864                         rowBuf = pixbuf;
865                         for(column = 0; column < columns; )
866                         {
867                                 packetHeader = getc(fin);
868                                 packetSize = 1 + (packetHeader & 0x7f);
869                                 if (packetHeader & 0x80)
870                                 {                                                                       // run-length packet
871                                         switch (targa_header.pixel_size)
872                                         {
873                                                 case 24:
874                                                         blue = getc(fin);
875                                                         green = getc(fin);
876                                                         red = getc(fin);
877                                                         alphabyte = 255;
878                                                 break;
879                                                 case 32:
880                                                         blue = getc(fin);
881                                                         green = getc(fin);
882                                                         red = getc(fin);
883                                                         alphabyte = getc(fin);
884                                                 break;
885                                         }
886         
887                                         for(j = 0; j < packetSize; j++)
888                                         {
889                                                 rowBuf[0] = red;
890                                                 rowBuf[1] = green;
891                                                 rowBuf[2] = blue;
892                                                 rowBuf[3] = alphabyte;
893                                                 rowBuf += pixDirection;
894                                                 column++;
895                                                 if(column == columns)
896                                                 {                                                                       // run spans across rows
897                                                         column = 0;
898                                                         row++;
899                                                         if (row >= rows)
900                                                                 goto breakOut;
901                                                         pixbuf += rowOffset;
902                                                         rowBuf = pixbuf;
903                                                 }
904                                         }
905                                 }
906                                 else
907                                 {                                                   // non run-length packet
908                                         for(j = 0; j < packetSize; j++)
909                                         {
910                                                 switch (targa_header.pixel_size)
911                                                 {
912                                                         case 24:
913                                                                 blue = getc(fin);
914                                                                 green = getc(fin);
915                                                                 red = getc(fin);
916                                                                 rowBuf[0] = red;
917                                                                 rowBuf[1] = green;
918                                                                 rowBuf[2] = blue;
919                                                                 rowBuf[3] = 255;
920                                                                 rowBuf += pixDirection;
921                                                         break;
922                                                         case 32:
923                                                                 blue = getc(fin);
924                                                                 green = getc(fin);
925                                                                 red = getc(fin);
926                                                                 alphabyte = getc(fin);
927                                                                 rowBuf[0] = red;
928                                                                 rowBuf[1] = green;
929                                                                 rowBuf[2] = blue;
930                                                                 rowBuf[3] = alphabyte;
931                                                                 rowBuf += pixDirection;
932                                                         break;
933                                                 }
934                                                 column++;
935                                                 if (column == columns)
936                                                 {                                                       // pixel packet run spans across rows
937                                                         column = 0;
938                                                         row++;
939                                                         if (row >= rows)
940                                                                 goto breakOut;
941                                                         pixbuf += rowOffset;
942                                                         rowBuf = pixbuf;
943                                                 }                                               
944                                         }
945                                 }
946                         }
947                         breakOut:;
948                         pixbuf += rowOffset;
949                 }
950         }
951         fclose(fin);
952 }
953
954 void MergeAlpha(byte *pix, byte *alpha, byte *pal, byte **out, int width, int height)
955 {
956         int             size, i;
957         byte    *data, *src, *srca;
958
959         size = width * height;
960         data = malloc(size * 4);
961         if(!data)
962                 Error("Could not allocate memory for true color image");
963
964         *out = data;
965         src = pix;
966         srca = alpha;
967
968         for(i = 0; i < size; i++, src++, srca++)
969         {
970                 *data++ = pal[*src * 3 + 0];      // r
971                 *data++ = pal[*src * 3 + 1];      // g
972                 *data++ = pal[*src * 3 + 2];      // b
973                 *data++ = *srca;                                  // a
974         }
975         free(pix);
976         free(alpha);
977         free(pal);
978 }
979
980 /*
981 ==============
982 LoadAnyImage
983
984 Return Value:
985         false: paletted texture
986         true:  true color RGBA image (no palette)
987 ==============
988 */
989 qboolean LoadAnyImage (char *name, byte **pixels, byte **palette, int *width, int *height)
990 {
991         char    ext[128];
992         int             len;
993         int             alpha_width, alpha_height;
994         char    alpha_name[128];
995         byte    *alpha_pixels;
996
997         ExtractFileExtension (name, ext);
998
999         if(palette)
1000         {
1001                 *palette = NULL;
1002         }
1003
1004         if (!Q_strcasecmp (ext, "lbm"))
1005         {
1006                 LoadLBM (name, pixels, palette);
1007                 if (width)
1008                         *width = bmhd.w;
1009                 if (height)
1010                         *height = bmhd.h;
1011                 return false;
1012         }
1013         else if (!Q_strcasecmp (ext, "pcx"))
1014         {
1015                 len = strlen(name);
1016                 strcpy(alpha_name, name);
1017                 strcpy(&alpha_name[len - 4], "_a.pcx");                                 // Alpha map name (may not exist)
1018
1019                 if(FileExists(alpha_name))
1020                 {
1021                         LoadPCX (name, pixels, palette, width, height);                                                 // Load in image
1022                         LoadPCX (alpha_name, &alpha_pixels, NULL, &alpha_width, &alpha_height); // Load in alpha map    
1023                         if((*width != alpha_width) || (*height != alpha_height))
1024                         {
1025                                 Error("Alpha image dimensions not equal to graphic image dimensions");
1026                         }
1027                         MergeAlpha(*pixels, alpha_pixels, *palette, pixels, *width, *height);
1028                         *palette = NULL;//Merge Frees pal
1029                         return true;
1030                 }
1031                 else
1032                 {
1033                         LoadPCX (name, pixels, palette, width, height);                 // Load in image
1034                         return false;
1035                 }
1036         }
1037         else if (!Q_strcasecmp (ext, "tga"))
1038         {
1039                 LoadTGA(name, pixels, width, height);
1040                 if (palette)
1041                 {
1042                         *palette = NULL;
1043                 }
1044
1045                 return true;
1046         }
1047         else
1048                 Error ("%s doesn't have a known image extension", name);
1049
1050         return false;
1051 }
1052