]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/image/lbmlib.cpp
some updates to the Linux build system - obtained a core binary and all required...
[xonotic/netradiant.git] / plugins / image / lbmlib.cpp
1 /*\r
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 // lbmlib.c\r
23 \r
24 #include <stdlib.h>\r
25 #include <string.h>\r
26 #include <glib.h>\r
27 #include "image.h"\r
28 #include "lbmlib.h"\r
29 #include "bmp.h"\r
30 \r
31 #define LittleLong(a) GINT32_FROM_LE(a)\r
32 #define LittleShort(a) GINT16_FROM_LE(a)\r
33 \r
34 #include <stdio.h>\r
35 \r
36 #define Sys_Printf g_FuncTable.m_pfnSysPrintf\r
37 #define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf\r
38 \r
39 /*\r
40 ============================================================================\r
41 \r
42 LOAD PCX\r
43 \r
44 ============================================================================\r
45 */\r
46 typedef struct\r
47 {\r
48   char manufacturer;\r
49   char version;\r
50   char encoding;\r
51   char bits_per_pixel;\r
52   unsigned short xmin, ymin, xmax, ymax;\r
53   unsigned short hres, vres;\r
54   unsigned char palette[48];\r
55   char reserved;\r
56   char color_planes;\r
57   unsigned short bytes_per_line;\r
58   unsigned short palette_type;\r
59   char filler[58];\r
60   unsigned char data;           // unbounded\r
61 } pcx_t;\r
62 \r
63 /*\r
64 ============================================================================\r
65 \r
66 TARGA IMAGE\r
67 \r
68 ============================================================================\r
69 */\r
70 typedef struct _TargaHeader\r
71 {\r
72   unsigned char id_length, colormap_type, image_type;\r
73   unsigned short colormap_index, colormap_length;\r
74   unsigned char colormap_size;\r
75   unsigned short x_origin, y_origin, width, height;\r
76   unsigned char pixel_size, attributes;\r
77 } TargaHeader;\r
78 \r
79 /*\r
80 =========================================================\r
81 \r
82 BMP LOADING\r
83 \r
84 =========================================================\r
85 */\r
86 typedef struct\r
87 {\r
88   char id[2];\r
89   unsigned long fileSize;\r
90   unsigned long reserved0;\r
91   unsigned long bitmapDataOffset;\r
92   unsigned long bitmapHeaderSize;\r
93   unsigned long width;\r
94   unsigned long height;\r
95   unsigned short planes;\r
96   unsigned short bitsPerPixel;\r
97   unsigned long compression;\r
98   unsigned long bitmapDataSize;\r
99   unsigned long hRes;\r
100   unsigned long vRes;\r
101   unsigned long colors;\r
102   unsigned long importantColors;\r
103   unsigned char palette[256][4];\r
104 } BMPHeader_t;\r
105 \r
106 static void LoadBMP (const char *name, byte ** pic, int *width, int *height)\r
107 {\r
108   int columns, rows, numPixels;\r
109   byte *pixbuf;\r
110   int row, column;\r
111   byte *buf_p;\r
112   byte *buffer;\r
113   unsigned int length;\r
114   BMPHeader_t bmpHeader;\r
115   byte *bmpRGBA;\r
116 \r
117   *pic = NULL;\r
118 \r
119   //\r
120   // load the file\r
121   //\r
122   length = vfsLoadFile( (char *)name, (void **)&buffer, 0 );\r
123   if (length == (unsigned int) -1)\r
124     return;\r
125 \r
126   buf_p = buffer;\r
127 \r
128   bmpHeader.id[0] = *buf_p++;\r
129   bmpHeader.id[1] = *buf_p++;\r
130   bmpHeader.fileSize = LittleLong (*(long *) buf_p);\r
131   buf_p += 4;\r
132   bmpHeader.reserved0 = LittleLong (*(long *) buf_p);\r
133   buf_p += 4;\r
134   bmpHeader.bitmapDataOffset = LittleLong (*(long *) buf_p);\r
135   buf_p += 4;\r
136   bmpHeader.bitmapHeaderSize = LittleLong (*(long *) buf_p);\r
137   buf_p += 4;\r
138   bmpHeader.width = LittleLong (*(long *) buf_p);\r
139   buf_p += 4;\r
140   bmpHeader.height = LittleLong (*(long *) buf_p);\r
141   buf_p += 4;\r
142   bmpHeader.planes = LittleShort (*(short *) buf_p);\r
143   buf_p += 2;\r
144   bmpHeader.bitsPerPixel = LittleShort (*(short *) buf_p);\r
145   buf_p += 2;\r
146   bmpHeader.compression = LittleLong (*(long *) buf_p);\r
147   buf_p += 4;\r
148   bmpHeader.bitmapDataSize = LittleLong (*(long *) buf_p);\r
149   buf_p += 4;\r
150   bmpHeader.hRes = LittleLong (*(long *) buf_p);\r
151   buf_p += 4;\r
152   bmpHeader.vRes = LittleLong (*(long *) buf_p);\r
153   buf_p += 4;\r
154   bmpHeader.colors = LittleLong (*(long *) buf_p);\r
155   buf_p += 4;\r
156   bmpHeader.importantColors = LittleLong (*(long *) buf_p);\r
157   buf_p += 4;\r
158 \r
159   memcpy (bmpHeader.palette, buf_p, sizeof (bmpHeader.palette));\r
160 \r
161   if (bmpHeader.bitsPerPixel == 8)\r
162     buf_p += 1024;\r
163 \r
164   if (bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M')\r
165   {\r
166     Sys_Printf ("LoadBMP: only Windows-style BMP files supported (%s)\n", name);\r
167     return;\r
168   }\r
169   if (bmpHeader.fileSize != length)\r
170   {\r
171     Sys_Printf ("LoadBMP: header size does not match file size (%d vs. %d) (%s)\n",\r
172                 bmpHeader.fileSize, length, name);\r
173     return;\r
174   }\r
175   if (bmpHeader.compression != 0)\r
176   {\r
177     Sys_Printf ("LoadBMP: only uncompressed BMP files supported (%s)\n", name);\r
178     return;\r
179   }\r
180   if (bmpHeader.bitsPerPixel < 8)\r
181   {\r
182     Sys_Printf ("LoadBMP: monochrome and 4-bit BMP files not supported (%s)\n", name);\r
183     return;\r
184   }\r
185 \r
186   columns = bmpHeader.width;\r
187   rows = bmpHeader.height;\r
188   if (rows < 0)\r
189     rows = -rows;\r
190   numPixels = columns * rows;\r
191 \r
192   if (width)\r
193     *width = columns;\r
194   if (height)\r
195     *height = rows;\r
196 \r
197   bmpRGBA = reinterpret_cast < unsigned char *>(g_malloc (numPixels * 4));\r
198   *pic = bmpRGBA;\r
199 \r
200 \r
201   for (row = rows - 1; row >= 0; row--)\r
202   {\r
203     pixbuf = bmpRGBA + row * columns * 4;\r
204 \r
205     for (column = 0; column < columns; column++)\r
206     {\r
207       unsigned char red, green, blue, alpha;\r
208       int palIndex;\r
209       unsigned short shortPixel;\r
210 \r
211       switch (bmpHeader.bitsPerPixel)\r
212       {\r
213       case 8:\r
214         palIndex = *buf_p++;\r
215         *pixbuf++ = bmpHeader.palette[palIndex][2];\r
216         *pixbuf++ = bmpHeader.palette[palIndex][1];\r
217         *pixbuf++ = bmpHeader.palette[palIndex][0];\r
218         *pixbuf++ = 0xff;\r
219         break;\r
220       case 16:\r
221         shortPixel = *(unsigned short *) pixbuf;\r
222         pixbuf += 2;\r
223         *pixbuf++ = (shortPixel & (31 << 10)) >> 7;\r
224         *pixbuf++ = (shortPixel & (31 << 5)) >> 2;\r
225         *pixbuf++ = (shortPixel & (31)) << 3;\r
226         *pixbuf++ = 0xff;\r
227         break;\r
228       case 24:\r
229         blue = *buf_p++;\r
230         green = *buf_p++;\r
231         red = *buf_p++;\r
232         *pixbuf++ = red;\r
233         *pixbuf++ = green;\r
234         *pixbuf++ = blue;\r
235         *pixbuf++ = 255;\r
236         break;\r
237       case 32:\r
238         blue = *buf_p++;\r
239         green = *buf_p++;\r
240         red = *buf_p++;\r
241         alpha = *buf_p++;\r
242         *pixbuf++ = red;\r
243         *pixbuf++ = green;\r
244         *pixbuf++ = blue;\r
245         *pixbuf++ = alpha;\r
246         break;\r
247       default:\r
248         Sys_Printf ("LoadBMP: illegal pixel_size '%d' in file '%s'\n", bmpHeader.bitsPerPixel,\r
249               name);\r
250         g_free (*pic);\r
251         *pic = NULL;\r
252         return;\r
253         break;\r
254       }\r
255     }\r
256   }\r
257 \r
258   vfsFreeFile (buffer);\r
259 \r
260 }\r
261 \r
262 \r
263 /*\r
264 =================================================================\r
265 \r
266 PCX LOADING\r
267 \r
268 =================================================================\r
269 */\r
270 \r
271 \r
272 /*\r
273 ==============\r
274 LoadPCX\r
275 ==============\r
276 */\r
277 \r
278 /* RR2DO2 */\r
279 #define DECODEPCX( b, d, r ) d=*b++;if((d&0xC0)==0xC0){r=d&0x3F;d=*b++;}else{r=1;}\r
280 \r
281 static void LoadPCX( const char *filename, byte **pic, byte **palette, int *width, int *height )\r
282 {\r
283   byte  *raw;\r
284   pcx_t *pcx;\r
285   int           x, y, lsize;\r
286   int           len;\r
287   int           dataByte, runLength;\r
288   byte  *out, *pix;\r
289         \r
290 \r
291   /* load the file */\r
292   len = vfsLoadFile (filename, (void **)&raw, 0);\r
293   if( len == -1 ) \r
294     Error( "LoadPCX: Couldn't read %s", filename );\r
295 \r
296 \r
297   /* parse the PCX file */\r
298   pcx = (pcx_t *)raw;\r
299   raw = &pcx->data;\r
300   \r
301   pcx->xmin = LittleShort(pcx->xmin);\r
302   pcx->ymin = LittleShort(pcx->ymin);\r
303   pcx->xmax = LittleShort(pcx->xmax);\r
304   pcx->ymax = LittleShort(pcx->ymax);\r
305   pcx->hres = LittleShort(pcx->hres);\r
306   pcx->vres = LittleShort(pcx->vres);\r
307   pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);\r
308   pcx->palette_type = LittleShort(pcx->palette_type);\r
309   \r
310   if (pcx->manufacturer != 0x0a\r
311     || pcx->version != 5\r
312     || pcx->encoding != 1\r
313     || pcx->bits_per_pixel != 8\r
314     || pcx->xmax >= 640\r
315     || pcx->ymax >= 480)\r
316     Error ("Bad pcx file %s", filename);\r
317 \r
318   if (palette)\r
319   {\r
320     *palette = (byte *)malloc(768);\r
321     memcpy (*palette, (byte *)pcx + len - 768, 768);\r
322   }\r
323 \r
324   if (width)\r
325     *width = pcx->xmax+1;\r
326   if (height)\r
327     *height = pcx->ymax+1;\r
328 \r
329   if (!pic)\r
330     return;\r
331 \r
332   out = (byte *)malloc ( (pcx->ymax+1) * (pcx->xmax+1) );\r
333   if (!out)\r
334     Error( "LoadPCX: couldn't allocate");\r
335 \r
336   *pic = out;\r
337   pix = out;\r
338         \r
339   /* RR2DO2: pcx fix  */\r
340   lsize = pcx->color_planes * pcx->bytes_per_line;\r
341         \r
342   /* go scanline by scanline */\r
343   for( y = 0; y <= pcx->ymax; y++, pix += pcx->xmax + 1 )\r
344   {\r
345     /* do a scanline */\r
346     for( x=0; x <= pcx->xmax; )\r
347     {\r
348       /* RR2DO2 */\r
349       DECODEPCX( raw, dataByte, runLength );\r
350       while( runLength-- > 0 )\r
351         pix[ x++ ] = dataByte;\r
352     }\r
353 \r
354     /* RR2DO2: discard any other data */\r
355     while( x < lsize )\r
356     {\r
357       DECODEPCX( raw, dataByte, runLength );\r
358       x++;\r
359     }\r
360     while( runLength-- > 0 )\r
361       x++;\r
362   }\r
363         \r
364   /* validity check */\r
365   if( raw - (byte *) pcx > len)\r
366     Error( "PCX file %s was malformed", filename );\r
367   free( pcx );\r
368 }\r
369 \r
370 /*\r
371 ==============\r
372 LoadPCX32\r
373 ==============\r
374 */\r
375 static void LoadPCX32 (const char *filename, byte ** pic, int *width, int *height)\r
376 {\r
377   byte *palette;\r
378   byte *pic8;\r
379   int i, c, p;\r
380   byte *pic32;\r
381 \r
382   LoadPCX (filename, &pic8, &palette, width, height);\r
383   if (!pic8)\r
384   {\r
385     *pic = NULL;\r
386     return;\r
387   }\r
388 \r
389   c = (*width) * (*height);\r
390   pic32 = *pic = reinterpret_cast < unsigned char *>(g_malloc (4 * c));\r
391   for (i = 0; i < c; i++)\r
392   {\r
393     p = pic8[i];\r
394     pic32[0] = palette[p * 3];\r
395     pic32[1] = palette[p * 3 + 1];\r
396     pic32[2] = palette[p * 3 + 2];\r
397     pic32[3] = 255;\r
398     pic32 += 4;\r
399   }\r
400 \r
401   g_free (pic8);\r
402   g_free (palette);\r
403 }\r
404 \r
405 /*\r
406 =========================================================\r
407 \r
408 TARGA LOADING\r
409 \r
410   TTimo: added code to get rid of alphachannel from prefs or ignore it if completely empty\r
411     was required since Radiant is using alpha channel when binding the textures for proper curry operation\r
412     can be fully turned off from the prefs though\r
413 =========================================================\r
414 */\r
415 \r
416 /*\r
417 =============\r
418 LoadTGA\r
419 =============\r
420 */\r
421 void LoadTGA (const char *name, byte ** pic, int *width, int *height)\r
422 {\r
423   int columns, rows, numPixels;\r
424   byte *pixbuf;\r
425   int row, column;\r
426   byte *buf_p;\r
427   byte *buffer;\r
428   TargaHeader targa_header;\r
429   byte *targa_rgba;\r
430 \r
431   *pic = NULL;\r
432 \r
433   //\r
434   // load the file\r
435   //\r
436   int nLen = vfsLoadFile( (char *)name, (void **)&buffer, 0 );\r
437   if (nLen == -1)\r
438     return;\r
439 \r
440   buf_p = buffer;\r
441 \r
442   targa_header.id_length = *buf_p++;\r
443   targa_header.colormap_type = *buf_p++;\r
444   targa_header.image_type = *buf_p++;\r
445 \r
446   targa_header.colormap_index = LittleShort (*(short *) buf_p);\r
447   buf_p += 2;\r
448   targa_header.colormap_length = LittleShort (*(short *) buf_p);\r
449   buf_p += 2;\r
450   targa_header.colormap_size = *buf_p++;\r
451   targa_header.x_origin = LittleShort (*(short *) buf_p);\r
452   buf_p += 2;\r
453   targa_header.y_origin = LittleShort (*(short *) buf_p);\r
454   buf_p += 2;\r
455   targa_header.width = LittleShort (*(short *) buf_p);\r
456   buf_p += 2;\r
457   targa_header.height = LittleShort (*(short *) buf_p);\r
458   buf_p += 2;\r
459   targa_header.pixel_size = *buf_p++;\r
460   targa_header.attributes = *buf_p++;\r
461 \r
462   bool bAlphaOK = false;\r
463 \r
464   if (targa_header.image_type != 2 && targa_header.image_type != 10 && targa_header.image_type != 3)\r
465   {\r
466     Sys_Printf ("LoadTGA: TGA type %d not supported\n", targa_header.image_type);\r
467     Sys_Printf ("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");\r
468     return;\r
469   }\r
470 \r
471   if (targa_header.colormap_type != 0)\r
472   {\r
473     Sys_Printf ("LoadTGA: colormaps not supported\n");\r
474     return;\r
475   }\r
476 \r
477   if ((targa_header.pixel_size != 32 && targa_header.pixel_size != 24)\r
478       && targa_header.image_type != 3)\r
479   {\r
480     Sys_Printf ("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");\r
481     return;\r
482   }\r
483 \r
484   columns = targa_header.width;\r
485   rows = targa_header.height;\r
486   numPixels = columns * rows;\r
487 \r
488   if (width)\r
489     *width = columns;\r
490   if (height)\r
491     *height = rows;\r
492 \r
493   targa_rgba = reinterpret_cast < unsigned char *>(g_malloc (numPixels * 4));\r
494   *pic = targa_rgba;\r
495 \r
496   if (targa_header.id_length != 0)\r
497     buf_p += targa_header.id_length;    // skip TARGA image comment\r
498 \r
499   if (targa_header.image_type == 2 || targa_header.image_type == 3)\r
500   {\r
501     // Uncompressed RGB or gray scale image\r
502     for (row = rows - 1; row >= 0; row--)\r
503     {\r
504       pixbuf = targa_rgba + row * columns * 4;\r
505       for (column = 0; column < columns; column++)\r
506       {\r
507         unsigned char red, green, blue, alphabyte;\r
508         switch (targa_header.pixel_size)\r
509         {\r
510           case 8:\r
511             blue = *buf_p++;\r
512             green = blue;\r
513             red = blue;\r
514             *pixbuf++ = red;\r
515             *pixbuf++ = green;\r
516             *pixbuf++ = blue;\r
517             *pixbuf++ = 255;\r
518             break;\r
519           \r
520           case 24:\r
521             blue = *buf_p++;\r
522             green = *buf_p++;\r
523             red = *buf_p++;\r
524             *pixbuf++ = red;\r
525             *pixbuf++ = green;\r
526             *pixbuf++ = blue;\r
527             *pixbuf++ = 255;\r
528             break;\r
529           case 32:\r
530             blue = *buf_p++;\r
531             green = *buf_p++;\r
532             red = *buf_p++;\r
533             alphabyte = *buf_p++;\r
534             // detect if the whole alpha channel is 0\r
535             if (alphabyte != 0)\r
536               bAlphaOK = true;\r
537             *pixbuf++ = red;\r
538             *pixbuf++ = green;\r
539             *pixbuf++ = blue;\r
540             *pixbuf++ = alphabyte;\r
541             break;\r
542           default:\r
543             Sys_Printf ("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size,\r
544                   name);\r
545             g_free (*pic);\r
546             *pic = NULL;\r
547             return;\r
548             break;\r
549         }\r
550       }\r
551     }\r
552 \r
553     if (!bAlphaOK)\r
554     {\r
555       // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=444\r
556       if (targa_header.pixel_size == 32) \r
557                                 Sys_FPrintf (SYS_WRN, "WARNING: %s has empty alpha channel\n", name);\r
558       // disable the alpha value\r
559       for (row = rows - 1; row >= 0; row--)\r
560       {\r
561         pixbuf = targa_rgba + row * columns * 4;\r
562         for (column = 0; column < columns; column++)\r
563         {\r
564           // 32 bit\r
565           pixbuf += 3;\r
566           *pixbuf++ = 255;\r
567         }\r
568       }\r
569     }\r
570   }\r
571   else if (targa_header.image_type == 10)\r
572   {                             // Runlength encoded RGB images\r
573     unsigned char red, green, blue, alphabyte, packetHeader, packetSize, j;\r
574 \r
575     red = 0;\r
576     green = 0;\r
577     blue = 0;\r
578     alphabyte = 0xff;\r
579 \r
580     for (row = rows - 1; row >= 0; row--)\r
581     {\r
582       pixbuf = targa_rgba + row * columns * 4;\r
583       for (column = 0; column < columns;)\r
584       {\r
585         packetHeader = *buf_p++;\r
586         packetSize = 1 + (packetHeader & 0x7f);\r
587         if (packetHeader & 0x80)\r
588         {                       // run-length packet\r
589           switch (targa_header.pixel_size)\r
590           {\r
591           case 24:\r
592             blue = *buf_p++;\r
593             green = *buf_p++;\r
594             red = *buf_p++;\r
595             alphabyte = 255;\r
596             break;\r
597           case 32:\r
598             blue = *buf_p++;\r
599             green = *buf_p++;\r
600             red = *buf_p++;\r
601             alphabyte = *buf_p++;\r
602             // detect if the whole alpha channel is 0\r
603             if (alphabyte != 0)\r
604               bAlphaOK = true;\r
605             break;\r
606           default:\r
607             Sys_Printf ("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size,\r
608             name);\r
609             g_free (*pic);\r
610             *pic = NULL;\r
611             return;\r
612             break;\r
613           }\r
614 \r
615           for (j = 0; j < packetSize; j++)\r
616           {\r
617             *pixbuf++ = red;\r
618             *pixbuf++ = green;\r
619             *pixbuf++ = blue;\r
620                   *pixbuf++ = alphabyte;\r
621             column++;\r
622             if (column == columns)\r
623             {                   // run spans across rows\r
624               column = 0;\r
625               if (row > 0)\r
626                 row--;\r
627               else\r
628                 goto breakOut;\r
629             pixbuf = targa_rgba + row * columns * 4;\r
630             }\r
631           }\r
632         }\r
633         else\r
634         {                       // non run-length packet\r
635           for (j = 0; j < packetSize; j++)\r
636           {\r
637             switch (targa_header.pixel_size)\r
638             {\r
639               case 24:\r
640                 blue = *buf_p++;\r
641                 green = *buf_p++;\r
642                 red = *buf_p++;\r
643                 *pixbuf++ = red;\r
644                 *pixbuf++ = green;\r
645                 *pixbuf++ = blue;\r
646                 *pixbuf++ = 255;\r
647                 break;\r
648               case 32:\r
649                 blue = *buf_p++;\r
650                 green = *buf_p++;\r
651                 red = *buf_p++;\r
652                 alphabyte = *buf_p++;\r
653                 // detect if the whole alpha channel is 0\r
654                 if (alphabyte != 0)\r
655                   bAlphaOK = true;\r
656                 *pixbuf++ = red;\r
657                 *pixbuf++ = green;\r
658                 *pixbuf++ = blue;\r
659                 *pixbuf++ = alphabyte;\r
660                 break;\r
661               default:\r
662                 Sys_Printf ("LoadTGA: illegal pixel_size '%d' in file '%s'\n",\r
663                 targa_header.pixel_size, name);\r
664                 g_free (*pic);\r
665                 *pic = NULL;\r
666                 return;\r
667                 break;\r
668             }\r
669             column++;\r
670             if (column == columns)\r
671             {                   // pixel packet run spans across rows\r
672               column = 0;\r
673               if (row > 0)\r
674                 row--;\r
675               else\r
676                 goto breakOut;\r
677               pixbuf = targa_rgba + row * columns * 4;\r
678             }\r
679           }\r
680         }\r
681       }\r
682     breakOut:;\r
683     }\r
684 \r
685     if (!bAlphaOK)\r
686     {\r
687       if (targa_header.pixel_size == 32)\r
688         Sys_FPrintf (SYS_WRN, "WARNING: %s has empty alpha channel\n", name);\r
689       // disable the alpha value\r
690       for (row = rows - 1; row >= 0; row--)\r
691       {\r
692         pixbuf = targa_rgba + row * columns * 4;\r
693         for (column = 0; column < columns; column++)\r
694         {\r
695           // 32 bit\r
696           pixbuf += 3;\r
697           *pixbuf++ = 255;\r
698         }\r
699       }\r
700     }\r
701 \r
702   }\r
703 \r
704   // vertically flipped\r
705   if ( (targa_header.attributes & (1<<5)) ) {\r
706     int flip;\r
707     for (row = 0; row < .5f * rows; row++)\r
708     {\r
709       for (column = 0; column < columns; column++)\r
710       {\r
711         flip = *( (int*)targa_rgba + row * columns + column);\r
712                 *( (int*)targa_rgba + row * columns + column) = *( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column );\r
713                 *( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column ) = flip;\r
714           }\r
715         }\r
716   }\r
717 \r
718   vfsFreeFile (buffer);\r
719 }\r
720 \r
721 //===================================================================\r
722 \r
723 /*\r
724 =================\r
725 LoadImage\r
726 \r
727 Loads any of the supported image types into a cannonical\r
728 32 bit format.\r
729 =================\r
730 */\r
731 void LoadImage (const char *name, byte ** pic, int *width, int *height)\r
732 {\r
733   int len;\r
734   *pic = NULL;\r
735   *width = 0;\r
736   *height = 0;\r
737 \r
738   len = strlen (name);\r
739   if (len < 5)\r
740   {\r
741     return;\r
742   }\r
743 \r
744   if (!g_strcasecmp (name + len - 4, ".tga"))\r
745   {\r
746     LoadTGA (name, pic, width, height);\r
747   }\r
748   else if (!g_strcasecmp (name + len - 4, ".pcx"))\r
749   {\r
750     LoadPCX32 (name, pic, width, height);\r
751   }\r
752   else if (!g_strcasecmp (name + len - 4, ".bmp"))\r
753   {\r
754     LoadBMP (name, pic, width, height);\r
755   }\r
756   /*\r
757   else if (!g_strcasecmp (name + len - 4, ".jpg"))\r
758   {\r
759     LoadJPG (name, pic, width, height);\r
760   }\r
761   */\r
762 }\r