]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/common/lbmlib.c
my own uncrustify run
[xonotic/netradiant.git] / tools / quake2 / common / lbmlib.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 // lbmlib.c
22
23 #include "cmdlib.h"
24 #include "inout.h"
25 #include "lbmlib.h"
26
27
28
29 /*
30    ============================================================================
31
32                         LBM STUFF
33
34    ============================================================================
35  */
36
37
38 typedef unsigned char UBYTE;
39 //conflicts with windows typedef short                  WORD;
40 typedef unsigned short UWORD;
41 typedef long LONG;
42
43 typedef enum
44 {
45         ms_none,
46         ms_mask,
47         ms_transcolor,
48         ms_lasso
49 } mask_t;
50
51 typedef enum
52 {
53         cm_none,
54         cm_rle1
55 } compress_t;
56
57 typedef struct
58 {
59         UWORD w,h;
60         short x,y;
61         UBYTE nPlanes;
62         UBYTE masking;
63         UBYTE compression;
64         UBYTE pad1;
65         UWORD transparentColor;
66         UBYTE xAspect,yAspect;
67         short pageWidth,pageHeight;
68 } bmhd_t;
69
70 extern bmhd_t bmhd;                         // will be in native byte order
71
72
73
74 #define FORMID ( 'F' + ( 'O' << 8 ) + ( (int)'R' << 16 ) + ( (int)'M' << 24 ) )
75 #define ILBMID ( 'I' + ( 'L' << 8 ) + ( (int)'B' << 16 ) + ( (int)'M' << 24 ) )
76 #define PBMID  ( 'P' + ( 'B' << 8 ) + ( (int)'M' << 16 ) + ( (int)' ' << 24 ) )
77 #define BMHDID ( 'B' + ( 'M' << 8 ) + ( (int)'H' << 16 ) + ( (int)'D' << 24 ) )
78 #define BODYID ( 'B' + ( 'O' << 8 ) + ( (int)'D' << 16 ) + ( (int)'Y' << 24 ) )
79 #define CMAPID ( 'C' + ( 'M' << 8 ) + ( (int)'A' << 16 ) + ( (int)'P' << 24 ) )
80
81
82 bmhd_t bmhd;
83
84 int    Align( int l ){
85         if ( l & 1 ) {
86                 return l + 1;
87         }
88         return l;
89 }
90
91
92
93 /*
94    ================
95    LBMRLEdecompress
96
97    Source must be evenly aligned!
98    ================
99  */
100 byte  *LBMRLEDecompress( byte *source,byte *unpacked, int bpwidth ){
101         int count;
102         byte b,rept;
103
104         count = 0;
105
106         do
107         {
108                 rept = *source++;
109
110                 if ( rept > 0x80 ) {
111                         rept = ( rept ^ 0xff ) + 2;
112                         b = *source++;
113                         memset( unpacked,b,rept );
114                         unpacked += rept;
115                 }
116                 else if ( rept < 0x80 ) {
117                         rept++;
118                         memcpy( unpacked,source,rept );
119                         unpacked += rept;
120                         source += rept;
121                 }
122                 else{
123                         rept = 0;               // rept of 0x80 is NOP
124
125                 }
126                 count += rept;
127
128         } while ( count < bpwidth );
129
130         if ( count > bpwidth ) {
131                 Error( "Decompression exceeded width!\n" );
132         }
133
134
135         return source;
136 }
137
138
139 /*
140    =================
141    LoadLBM
142    =================
143  */
144 void LoadLBM( char *filename, byte **picture, byte **palette ){
145         byte    *LBMbuffer, *picbuffer, *cmapbuffer;
146         int y;
147         byte    *LBM_P, *LBMEND_P;
148         byte    *pic_p;
149         byte    *body_p;
150
151         int formtype,formlength;
152         int chunktype,chunklength;
153
154 // qiet compiler warnings
155         picbuffer = NULL;
156         cmapbuffer = NULL;
157
158 //
159 // load the LBM
160 //
161         LoadFile( filename, (void **)&LBMbuffer );
162
163 //
164 // parse the LBM header
165 //
166         LBM_P = LBMbuffer;
167         if ( *(int *)LBMbuffer != LittleLong( FORMID ) ) {
168                 Error( "No FORM ID at start of file!\n" );
169         }
170
171         LBM_P += 4;
172         formlength = BigLong( *(int *)LBM_P );
173         LBM_P += 4;
174         LBMEND_P = LBM_P + Align( formlength );
175
176         formtype = LittleLong( *(int *)LBM_P );
177
178         if ( formtype != ILBMID && formtype != PBMID ) {
179                 Error( "Unrecognized form type: %c%c%c%c\n", formtype & 0xff
180                            ,( formtype >> 8 ) & 0xff,( formtype >> 16 ) & 0xff,( formtype >> 24 ) & 0xff );
181         }
182
183         LBM_P += 4;
184
185 //
186 // parse chunks
187 //
188
189         while ( LBM_P < LBMEND_P )
190         {
191                 chunktype = LBM_P[0] + ( LBM_P[1] << 8 ) + ( LBM_P[2] << 16 ) + ( LBM_P[3] << 24 );
192                 LBM_P += 4;
193                 chunklength = LBM_P[3] + ( LBM_P[2] << 8 ) + ( LBM_P[1] << 16 ) + ( LBM_P[0] << 24 );
194                 LBM_P += 4;
195
196                 switch ( chunktype )
197                 {
198                 case BMHDID:
199                         memcpy( &bmhd,LBM_P,sizeof( bmhd ) );
200                         bmhd.w = BigShort( bmhd.w );
201                         bmhd.h = BigShort( bmhd.h );
202                         bmhd.x = BigShort( bmhd.x );
203                         bmhd.y = BigShort( bmhd.y );
204                         bmhd.pageWidth = BigShort( bmhd.pageWidth );
205                         bmhd.pageHeight = BigShort( bmhd.pageHeight );
206                         break;
207
208                 case CMAPID:
209                         cmapbuffer = malloc( 768 );
210                         memset( cmapbuffer, 0, 768 );
211                         memcpy( cmapbuffer, LBM_P, chunklength );
212                         break;
213
214                 case BODYID:
215                         body_p = LBM_P;
216
217                         pic_p = picbuffer = malloc( bmhd.w * bmhd.h );
218                         if ( formtype == PBMID ) {
219                                 //
220                                 // unpack PBM
221                                 //
222                                 for ( y = 0 ; y < bmhd.h ; y++, pic_p += bmhd.w )
223                                 {
224                                         if ( bmhd.compression == cm_rle1 ) {
225                                                 body_p = LBMRLEDecompress( (byte *)body_p
226                                                                                                    , pic_p, bmhd.w );
227                                         }
228                                         else if ( bmhd.compression == cm_none ) {
229                                                 memcpy( pic_p,body_p,bmhd.w );
230                                                 body_p += Align( bmhd.w );
231                                         }
232                                 }
233
234                         }
235                         else
236                         {
237                                 //
238                                 // unpack ILBM
239                                 //
240                                 Error( "%s is an interlaced LBM, not packed", filename );
241                         }
242                         break;
243                 }
244
245                 LBM_P += Align( chunklength );
246         }
247
248         free( LBMbuffer );
249
250         *picture = picbuffer;
251
252         if ( palette ) {
253                 *palette = cmapbuffer;
254         }
255 }
256
257
258 /*
259    ============================================================================
260
261                             WRITE LBM
262
263    ============================================================================
264  */
265
266 /*
267    ==============
268    WriteLBMfile
269    ==============
270  */
271 void WriteLBMfile( char *filename, byte *data,
272                                    int width, int height, byte *palette ){
273         byte    *lbm, *lbmptr;
274         int    *formlength, *bmhdlength, *cmaplength, *bodylength;
275         int length;
276         bmhd_t basebmhd;
277
278         lbm = lbmptr = malloc( width * height + 1000 );
279
280 //
281 // start FORM
282 //
283         *lbmptr++ = 'F';
284         *lbmptr++ = 'O';
285         *lbmptr++ = 'R';
286         *lbmptr++ = 'M';
287
288         formlength = (int*)lbmptr;
289         lbmptr += 4;                      // leave space for length
290
291         *lbmptr++ = 'P';
292         *lbmptr++ = 'B';
293         *lbmptr++ = 'M';
294         *lbmptr++ = ' ';
295
296 //
297 // write BMHD
298 //
299         *lbmptr++ = 'B';
300         *lbmptr++ = 'M';
301         *lbmptr++ = 'H';
302         *lbmptr++ = 'D';
303
304         bmhdlength = (int *)lbmptr;
305         lbmptr += 4;                      // leave space for length
306
307         memset( &basebmhd,0,sizeof( basebmhd ) );
308         basebmhd.w = BigShort( (short)width );
309         basebmhd.h = BigShort( (short)height );
310         basebmhd.nPlanes = BigShort( 8 );
311         basebmhd.xAspect = BigShort( 5 );
312         basebmhd.yAspect = BigShort( 6 );
313         basebmhd.pageWidth = BigShort( (short)width );
314         basebmhd.pageHeight = BigShort( (short)height );
315
316         memcpy( lbmptr,&basebmhd,sizeof( basebmhd ) );
317         lbmptr += sizeof( basebmhd );
318
319         length = lbmptr - (byte *)bmhdlength - 4;
320         *bmhdlength = BigLong( length );
321         if ( length & 1 ) {
322                 *lbmptr++ = 0;          // pad chunk to even offset
323
324         }
325 //
326 // write CMAP
327 //
328         *lbmptr++ = 'C';
329         *lbmptr++ = 'M';
330         *lbmptr++ = 'A';
331         *lbmptr++ = 'P';
332
333         cmaplength = (int *)lbmptr;
334         lbmptr += 4;                      // leave space for length
335
336         memcpy( lbmptr,palette,768 );
337         lbmptr += 768;
338
339         length = lbmptr - (byte *)cmaplength - 4;
340         *cmaplength = BigLong( length );
341         if ( length & 1 ) {
342                 *lbmptr++ = 0;          // pad chunk to even offset
343
344         }
345 //
346 // write BODY
347 //
348         *lbmptr++ = 'B';
349         *lbmptr++ = 'O';
350         *lbmptr++ = 'D';
351         *lbmptr++ = 'Y';
352
353         bodylength = (int *)lbmptr;
354         lbmptr += 4;                      // leave space for length
355
356         memcpy( lbmptr,data,width * height );
357         lbmptr += width * height;
358
359         length = lbmptr - (byte *)bodylength - 4;
360         *bodylength = BigLong( length );
361         if ( length & 1 ) {
362                 *lbmptr++ = 0;          // pad chunk to even offset
363
364         }
365 //
366 // done
367 //
368         length = lbmptr - (byte *)formlength - 4;
369         *formlength = BigLong( length );
370         if ( length & 1 ) {
371                 *lbmptr++ = 0;          // pad chunk to even offset
372
373         }
374 //
375 // write output file
376 //
377         SaveFile( filename, lbm, lbmptr - lbm );
378         free( lbm );
379 }
380
381
382 /*
383    ============================================================================
384
385    LOAD PCX
386
387    ============================================================================
388  */
389
390 typedef struct
391 {
392         char manufacturer;
393         char version;
394         char encoding;
395         char bits_per_pixel;
396         unsigned short xmin,ymin,xmax,ymax;
397         unsigned short hres,vres;
398         unsigned char palette[48];
399         char reserved;
400         char color_planes;
401         unsigned short bytes_per_line;
402         unsigned short palette_type;
403         char filler[58];
404         unsigned char data;             // unbounded
405 } pcx_t;
406
407
408 /*
409    ==============
410    LoadPCX
411    ==============
412  */
413 void LoadPCX( char *filename, byte **pic, byte **palette, int *width, int *height ){
414         byte    *raw;
415         pcx_t   *pcx;
416         int x, y;
417         int len;
418         int dataByte, runLength;
419         byte    *out, *pix;
420
421         //
422         // load the file
423         //
424         len = LoadFile( filename, (void **)&raw );
425
426         //
427         // parse the PCX file
428         //
429         pcx = (pcx_t *)raw;
430         raw = &pcx->data;
431
432         pcx->xmin = LittleShort( pcx->xmin );
433         pcx->ymin = LittleShort( pcx->ymin );
434         pcx->xmax = LittleShort( pcx->xmax );
435         pcx->ymax = LittleShort( pcx->ymax );
436         pcx->hres = LittleShort( pcx->hres );
437         pcx->vres = LittleShort( pcx->vres );
438         pcx->bytes_per_line = LittleShort( pcx->bytes_per_line );
439         pcx->palette_type = LittleShort( pcx->palette_type );
440
441         if ( pcx->manufacturer != 0x0a
442                  || pcx->version != 5
443                  || pcx->encoding != 1
444                  || pcx->bits_per_pixel != 8
445                  || pcx->xmax >= 640
446                  || pcx->ymax >= 480 ) {
447                 Error( "Bad pcx file %s", filename );
448         }
449
450         if ( palette ) {
451                 *palette = malloc( 768 );
452                 memcpy( *palette, (byte *)pcx + len - 768, 768 );
453         }
454
455         if ( width ) {
456                 *width = pcx->xmax + 1;
457         }
458         if ( height ) {
459                 *height = pcx->ymax + 1;
460         }
461
462         if ( !pic ) {
463                 return;
464         }
465
466         out = malloc( ( pcx->ymax + 1 ) * ( pcx->xmax + 1 ) );
467         if ( !out ) {
468                 Error( "Skin_Cache: couldn't allocate" );
469         }
470
471         *pic = out;
472
473         pix = out;
474
475         for ( y = 0 ; y <= pcx->ymax ; y++, pix += pcx->xmax + 1 )
476         {
477                 for ( x = 0 ; x <= pcx->xmax ; )
478                 {
479                         dataByte = *raw++;
480
481                         if ( ( dataByte & 0xC0 ) == 0xC0 ) {
482                                 runLength = dataByte & 0x3F;
483                                 dataByte = *raw++;
484                         }
485                         else{
486                                 runLength = 1;
487                         }
488
489                         while ( runLength-- > 0 )
490                                 pix[x++] = dataByte;
491                 }
492
493         }
494
495         if ( raw - (byte *)pcx > len ) {
496                 Error( "PCX file %s was malformed", filename );
497         }
498
499         free( pcx );
500 }
501
502 /*
503    ==============
504    WritePCXfile
505    ==============
506  */
507 void WritePCXfile( char *filename, byte *data,
508                                    int width, int height, byte *palette ){
509         int i, j, length;
510         pcx_t   *pcx;
511         byte        *pack;
512
513         pcx = malloc( width * height * 2 + 1000 );
514         memset( pcx, 0, sizeof( *pcx ) );
515
516         pcx->manufacturer = 0x0a;   // PCX id
517         pcx->version = 5;           // 256 color
518         pcx->encoding = 1;      // uncompressed
519         pcx->bits_per_pixel = 8;        // 256 color
520         pcx->xmin = 0;
521         pcx->ymin = 0;
522         pcx->xmax = LittleShort( (short)( width - 1 ) );
523         pcx->ymax = LittleShort( (short)( height - 1 ) );
524         pcx->hres = LittleShort( (short)width );
525         pcx->vres = LittleShort( (short)height );
526         pcx->color_planes = 1;      // chunky image
527         pcx->bytes_per_line = LittleShort( (short)width );
528         pcx->palette_type = LittleShort( 2 );     // not a grey scale
529
530         // pack the image
531         pack = &pcx->data;
532
533         for ( i = 0 ; i < height ; i++ )
534         {
535                 for ( j = 0 ; j < width ; j++ )
536                 {
537                         if ( ( *data & 0xc0 ) != 0xc0 ) {
538                                 *pack++ = *data++;
539                         }
540                         else
541                         {
542                                 *pack++ = 0xc1;
543                                 *pack++ = *data++;
544                         }
545                 }
546         }
547
548         // write the palette
549         *pack++ = 0x0c; // palette ID byte
550         for ( i = 0 ; i < 768 ; i++ )
551                 *pack++ = *palette++;
552
553 // write output file
554         length = pack - (byte *)pcx;
555         SaveFile( filename, pcx, length );
556
557         free( pcx );
558 }
559
560
561 /*
562    ============================================================================
563
564    LOAD IMAGE
565
566    ============================================================================
567  */
568
569 /*
570    ==============
571    Load256Image
572
573    Will load either an lbm or pcx, depending on extension.
574    Any of the return pointers can be NULL if you don't want them.
575    ==============
576  */
577 void Load256Image( char *name, byte **pixels, byte **palette,
578                                    int *width, int *height ){
579         char ext[128];
580
581         ExtractFileExtension( name, ext );
582         if ( !Q_strncasecmp( ext, "lbm", strlen( ext ) ) ) {
583                 LoadLBM( name, pixels, palette );
584                 if ( width ) {
585                         *width = bmhd.w;
586                 }
587                 if ( height ) {
588                         *height = bmhd.h;
589                 }
590         }
591         else if ( !Q_strncasecmp( ext, "pcx",strlen( ext ) ) ) {
592                 LoadPCX( name, pixels, palette, width, height );
593         }
594         else{
595                 Error( "%s doesn't have a known image extension", name );
596         }
597 }
598
599
600 /*
601    ==============
602    Save256Image
603
604    Will save either an lbm or pcx, depending on extension.
605    ==============
606  */
607 void Save256Image( char *name, byte *pixels, byte *palette,
608                                    int width, int height ){
609         char ext[128];
610
611         ExtractFileExtension( name, ext );
612         if ( !Q_strncasecmp( ext, "lbm",strlen( ext ) ) ) {
613                 WriteLBMfile( name, pixels, width, height, palette );
614         }
615         else if ( !Q_strncasecmp( ext, "pcx",strlen( ext ) ) ) {
616                 WritePCXfile( name, pixels, width, height, palette );
617         }
618         else{
619                 Error( "%s doesn't have a known image extension", name );
620         }
621 }
622
623
624
625
626 /*
627    ============================================================================
628
629    TARGA IMAGE
630
631    ============================================================================
632  */
633
634 typedef struct _TargaHeader {
635         unsigned char id_length, colormap_type, image_type;
636         unsigned short colormap_index, colormap_length;
637         unsigned char colormap_size;
638         unsigned short x_origin, y_origin, width, height;
639         unsigned char pixel_size, attributes;
640 } TargaHeader;
641
642 int fgetLittleShort( FILE *f ){
643         byte b1, b2;
644
645         b1 = fgetc( f );
646         b2 = fgetc( f );
647
648         return (short)( b1 + b2 * 256 );
649 }
650
651 int fgetLittleLong( FILE *f ){
652         byte b1, b2, b3, b4;
653
654         b1 = fgetc( f );
655         b2 = fgetc( f );
656         b3 = fgetc( f );
657         b4 = fgetc( f );
658
659         return b1 + ( b2 << 8 ) + ( b3 << 16 ) + ( b4 << 24 );
660 }
661
662
663 /*
664    =============
665    LoadTGA
666    =============
667  */
668 void LoadTGA( char *name, byte **pixels, int *width, int *height ){
669         int columns, rows, numPixels;
670         byte            *pixbuf;
671         int row, column;
672         FILE            *fin;
673         byte            *targa_rgba;
674         TargaHeader targa_header;
675
676         fin = fopen( name, "rb" );
677         if ( !fin ) {
678                 Error( "Couldn't read %s", name );
679         }
680
681         targa_header.id_length = fgetc( fin );
682         targa_header.colormap_type = fgetc( fin );
683         targa_header.image_type = fgetc( fin );
684
685         targa_header.colormap_index = fgetLittleShort( fin );
686         targa_header.colormap_length = fgetLittleShort( fin );
687         targa_header.colormap_size = fgetc( fin );
688         targa_header.x_origin = fgetLittleShort( fin );
689         targa_header.y_origin = fgetLittleShort( fin );
690         targa_header.width = fgetLittleShort( fin );
691         targa_header.height = fgetLittleShort( fin );
692         targa_header.pixel_size = fgetc( fin );
693         targa_header.attributes = fgetc( fin );
694
695         if ( targa_header.image_type != 2
696                  && targa_header.image_type != 10 ) {
697                 Error( "LoadTGA: Only type 2 and 10 targa RGB images supported\n" );
698         }
699
700         if ( targa_header.colormap_type != 0
701                  || ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) ) {
702                 Error( "Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n" );
703         }
704
705         columns = targa_header.width;
706         rows = targa_header.height;
707         numPixels = columns * rows;
708
709         if ( width ) {
710                 *width = columns;
711         }
712         if ( height ) {
713                 *height = rows;
714         }
715         targa_rgba = malloc( numPixels * 4 );
716         *pixels = targa_rgba;
717
718         if ( targa_header.id_length != 0 ) {
719                 fseek( fin, targa_header.id_length, SEEK_CUR );  // skip TARGA image comment
720
721         }
722         if ( targa_header.image_type == 2 ) {  // Uncompressed, RGB images
723                 for ( row = rows - 1; row >= 0; row-- ) {
724                         pixbuf = targa_rgba + row * columns * 4;
725                         for ( column = 0; column < columns; column++ ) {
726                                 unsigned char red,green,blue,alphabyte;
727                                 switch ( targa_header.pixel_size ) {
728                                 case 24:
729
730                                         blue = getc( fin );
731                                         green = getc( fin );
732                                         red = getc( fin );
733                                         *pixbuf++ = red;
734                                         *pixbuf++ = green;
735                                         *pixbuf++ = blue;
736                                         *pixbuf++ = 255;
737                                         break;
738                                 case 32:
739                                         blue = getc( fin );
740                                         green = getc( fin );
741                                         red = getc( fin );
742                                         alphabyte = getc( fin );
743                                         *pixbuf++ = red;
744                                         *pixbuf++ = green;
745                                         *pixbuf++ = blue;
746                                         *pixbuf++ = alphabyte;
747                                         break;
748                                 }
749                         }
750                 }
751         }
752         else if ( targa_header.image_type == 10 ) {   // Runlength encoded RGB images
753                 unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
754                 for ( row = rows - 1; row >= 0; row-- ) {
755                         pixbuf = targa_rgba + row * columns * 4;
756                         for ( column = 0; column < columns; ) {
757                                 packetHeader = getc( fin );
758                                 packetSize = 1 + ( packetHeader & 0x7f );
759                                 if ( packetHeader & 0x80 ) {        // run-length packet
760                                         switch ( targa_header.pixel_size ) {
761                                         case 24:
762                                                 blue = getc( fin );
763                                                 green = getc( fin );
764                                                 red = getc( fin );
765                                                 alphabyte = 255;
766                                                 break;
767                                         case 32:
768                                                 blue = getc( fin );
769                                                 green = getc( fin );
770                                                 red = getc( fin );
771                                                 alphabyte = getc( fin );
772                                                 break;
773                                         }
774
775                                         for ( j = 0; j < packetSize; j++ ) {
776                                                 *pixbuf++ = red;
777                                                 *pixbuf++ = green;
778                                                 *pixbuf++ = blue;
779                                                 *pixbuf++ = alphabyte;
780                                                 column++;
781                                                 if ( column == columns ) { // run spans across rows
782                                                         column = 0;
783                                                         if ( row > 0 ) {
784                                                                 row--;
785                                                         }
786                                                         else{
787                                                                 goto breakOut;
788                                                         }
789                                                         pixbuf = targa_rgba + row * columns * 4;
790                                                 }
791                                         }
792                                 }
793                                 else {                            // non run-length packet
794                                         for ( j = 0; j < packetSize; j++ ) {
795                                                 switch ( targa_header.pixel_size ) {
796                                                 case 24:
797                                                         blue = getc( fin );
798                                                         green = getc( fin );
799                                                         red = getc( fin );
800                                                         *pixbuf++ = red;
801                                                         *pixbuf++ = green;
802                                                         *pixbuf++ = blue;
803                                                         *pixbuf++ = 255;
804                                                         break;
805                                                 case 32:
806                                                         blue = getc( fin );
807                                                         green = getc( fin );
808                                                         red = getc( fin );
809                                                         alphabyte = getc( fin );
810                                                         *pixbuf++ = red;
811                                                         *pixbuf++ = green;
812                                                         *pixbuf++ = blue;
813                                                         *pixbuf++ = alphabyte;
814                                                         break;
815                                                 }
816                                                 column++;
817                                                 if ( column == columns ) { // pixel packet run spans across rows
818                                                         column = 0;
819                                                         if ( row > 0 ) {
820                                                                 row--;
821                                                         }
822                                                         else{
823                                                                 goto breakOut;
824                                                         }
825                                                         pixbuf = targa_rgba + row * columns * 4;
826                                                 }
827                                         }
828                                 }
829                         }
830 breakOut:;
831                 }
832         }
833
834         // vertically flipped
835         if ( ( targa_header.attributes & ( 1 << 5 ) ) ) {
836                 int flip;
837                 for ( row = 0; row < .5f * rows; row++ )
838                 {
839                         for ( column = 0; column < columns; column++ )
840                         {
841                                 flip = *( (int*)targa_rgba + row * columns + column );
842                                 *( (int*)targa_rgba + row * columns + column ) = *( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column );
843                                 *( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column ) = flip;
844                         }
845                 }
846         }
847
848         fclose( fin );
849 }