DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
image.c
Go to the documentation of this file.
1
2#include "quakedef.h"
3#include "image.h"
4#include "jpeg.h"
5#include "image_png.h"
6#include "r_shadow.h"
7#include "wad.h"
8
11
12static unsigned char *Image_GetEmbeddedPicBGRA(const char *name);
13
14static void Image_CopyAlphaFromBlueBGRA(unsigned char *outpixels, const unsigned char *inpixels, int w, int h)
15{
16 int i, n;
17 n = w * h;
18 for(i = 0; i < n; ++i)
19 outpixels[4*i+3] = inpixels[4*i]; // blue channel
20}
21
22#if 1
23// written by LadyHavoc in a readable way, optimized by Vic, further optimized by LadyHavoc (the non-special index case), readable version preserved below this
24void Image_CopyMux(unsigned char *outpixels, const unsigned char *inpixels, int inputwidth, int inputheight, qbool inputflipx, qbool inputflipy, qbool inputflipdiagonal, int numoutputcomponents, int numinputcomponents, int *outputinputcomponentindices)
25{
26 int index, c, x, y;
27 const unsigned char *in, *line;
28 int row_inc = (inputflipy ? -inputwidth : inputwidth) * numinputcomponents, col_inc = (inputflipx ? -1 : 1) * numinputcomponents;
29 int row_ofs = (inputflipy ? (inputheight - 1) * inputwidth * numinputcomponents : 0), col_ofs = (inputflipx ? (inputwidth - 1) * numinputcomponents : 0);
30
31 for (c = 0; c < numoutputcomponents; c++)
32 if (outputinputcomponentindices[c] & 0x80000000)
33 break;
34 if (c < numoutputcomponents)
35 {
36 // special indices used
37 if (inputflipdiagonal)
38 {
39 for (x = 0, line = inpixels + col_ofs; x < inputwidth; x++, line += col_inc)
40 for (y = 0, in = line + row_ofs; y < inputheight; y++, in += row_inc, outpixels += numoutputcomponents)
41 for (c = 0; c < numoutputcomponents; c++)
42 outpixels[c] = ((index = outputinputcomponentindices[c]) & 0x80000000) ? index : in[index];
43 }
44 else
45 {
46 for (y = 0, line = inpixels + row_ofs; y < inputheight; y++, line += row_inc)
47 for (x = 0, in = line + col_ofs; x < inputwidth; x++, in += col_inc, outpixels += numoutputcomponents)
48 for (c = 0; c < numoutputcomponents; c++)
49 outpixels[c] = ((index = outputinputcomponentindices[c]) & 0x80000000) ? index : in[index];
50 }
51 }
52 else
53 {
54 // special indices not used
55 if (inputflipdiagonal)
56 {
57 for (x = 0, line = inpixels + col_ofs; x < inputwidth; x++, line += col_inc)
58 for (y = 0, in = line + row_ofs; y < inputheight; y++, in += row_inc, outpixels += numoutputcomponents)
59 for (c = 0; c < numoutputcomponents; c++)
60 outpixels[c] = in[outputinputcomponentindices[c]];
61 }
62 else
63 {
64 for (y = 0, line = inpixels + row_ofs; y < inputheight; y++, line += row_inc)
65 for (x = 0, in = line + col_ofs; x < inputwidth; x++, in += col_inc, outpixels += numoutputcomponents)
66 for (c = 0; c < numoutputcomponents; c++)
67 outpixels[c] = in[outputinputcomponentindices[c]];
68 }
69 }
70}
71#else
72// intentionally readable version
73void Image_CopyMux(unsigned char *outpixels, const unsigned char *inpixels, int inputwidth, int inputheight, qbool inputflipx, qbool inputflipy, qbool inputflipdiagonal, int numoutputcomponents, int numinputcomponents, int *outputinputcomponentindices)
74{
75 int index, c, x, y;
76 const unsigned char *in, *inrow, *incolumn;
77 if (inputflipdiagonal)
78 {
79 for (x = 0;x < inputwidth;x++)
80 {
81 for (y = 0;y < inputheight;y++)
82 {
83 in = inpixels + ((inputflipy ? inputheight - 1 - y : y) * inputwidth + (inputflipx ? inputwidth - 1 - x : x)) * numinputcomponents;
84 for (c = 0;c < numoutputcomponents;c++)
85 {
86 index = outputinputcomponentindices[c];
87 if (index & 0x80000000)
88 *outpixels++ = index;
89 else
90 *outpixels++ = in[index];
91 }
92 }
93 }
94 }
95 else
96 {
97 for (y = 0;y < inputheight;y++)
98 {
99 for (x = 0;x < inputwidth;x++)
100 {
101 in = inpixels + ((inputflipy ? inputheight - 1 - y : y) * inputwidth + (inputflipx ? inputwidth - 1 - x : x)) * numinputcomponents;
102 for (c = 0;c < numoutputcomponents;c++)
103 {
104 index = outputinputcomponentindices[c];
105 if (index & 0x80000000)
106 *outpixels++ = index;
107 else
108 *outpixels++ = in[index];
109 }
110 }
111 }
112 }
113}
114#endif
115
116void Image_GammaRemapRGB(const unsigned char *in, unsigned char *out, int pixels, const unsigned char *gammar, const unsigned char *gammag, const unsigned char *gammab)
117{
118 while (pixels--)
119 {
120 out[0] = gammar[in[0]];
121 out[1] = gammag[in[1]];
122 out[2] = gammab[in[2]];
123 in += 3;
124 out += 3;
125 }
126}
127
128// note: pal must be 32bit color
129void Image_Copy8bitBGRA(const unsigned char *in, unsigned char *out, int pixels, const unsigned int *pal)
130{
131 int *iout = (int *)out;
132 while (pixels >= 8)
133 {
134 iout[0] = pal[in[0]];
135 iout[1] = pal[in[1]];
136 iout[2] = pal[in[2]];
137 iout[3] = pal[in[3]];
138 iout[4] = pal[in[4]];
139 iout[5] = pal[in[5]];
140 iout[6] = pal[in[6]];
141 iout[7] = pal[in[7]];
142 in += 8;
143 iout += 8;
144 pixels -= 8;
145 }
146 if (pixels & 4)
147 {
148 iout[0] = pal[in[0]];
149 iout[1] = pal[in[1]];
150 iout[2] = pal[in[2]];
151 iout[3] = pal[in[3]];
152 in += 4;
153 iout += 4;
154 }
155 if (pixels & 2)
156 {
157 iout[0] = pal[in[0]];
158 iout[1] = pal[in[1]];
159 in += 2;
160 iout += 2;
161 }
162 if (pixels & 1)
163 iout[0] = pal[in[0]];
164}
165
166/*
167=================================================================
168
169 PCX Loading
170
171=================================================================
172*/
173
174typedef struct pcx_s
175{
180 unsigned short xmin,ymin,xmax,ymax;
181 unsigned short hres,vres;
182 unsigned char palette[48];
185 unsigned short bytes_per_line;
186 unsigned short palette_type;
187 char filler[58];
188} pcx_t;
189
190/*
191============
192LoadPCX
193============
194*/
195static unsigned char* LoadPCX_BGRA (const unsigned char *f, int filesize, int *miplevel)
196{
197 pcx_t pcx;
198 unsigned char *a, *b, *image_buffer, *pbuf;
199 const unsigned char *palette, *fin, *enddata;
200 int x, y, x2, dataByte;
201
202 if (filesize < (int)sizeof(pcx) + 768)
203 {
204 Con_Print("Bad pcx file\n");
205 return NULL;
206 }
207
208 fin = f;
209
210 memcpy(&pcx, fin, sizeof(pcx));
211 fin += sizeof(pcx);
212
213 // LadyHavoc: big-endian support ported from QF newtree
214 pcx.xmax = LittleShort (pcx.xmax);
215 pcx.xmin = LittleShort (pcx.xmin);
216 pcx.ymax = LittleShort (pcx.ymax);
217 pcx.ymin = LittleShort (pcx.ymin);
218 pcx.hres = LittleShort (pcx.hres);
219 pcx.vres = LittleShort (pcx.vres);
222
223 image_width = pcx.xmax + 1 - pcx.xmin;
224 image_height = pcx.ymax + 1 - pcx.ymin;
225 if (pcx.manufacturer != 0x0a || pcx.version != 5 || pcx.encoding != 1 || pcx.bits_per_pixel != 8 || image_width > 32768 || image_height > 32768 || image_width <= 0 || image_height <= 0)
226 {
227 Con_Print("Bad pcx file\n");
228 return NULL;
229 }
230
231 palette = f + filesize - 768;
232
233 image_buffer = (unsigned char *)Mem_Alloc(tempmempool, image_width*image_height*4);
234 if (!image_buffer)
235 {
236 Con_Printf("LoadPCX: not enough memory for %i by %i image\n", image_width, image_height);
237 return NULL;
238 }
239 pbuf = image_buffer + image_width*image_height*3;
240 enddata = palette;
241
242 for (y = 0;y < image_height && fin < enddata;y++)
243 {
244 a = pbuf + y * image_width;
245 for (x = 0;x < image_width && fin < enddata;)
246 {
247 dataByte = *fin++;
248 if(dataByte >= 0xC0)
249 {
250 if (fin >= enddata)
251 break;
252 x2 = x + (dataByte & 0x3F);
253 dataByte = *fin++;
254 if (x2 > image_width)
255 x2 = image_width; // technically an error
256 while(x < x2)
257 a[x++] = dataByte;
258 }
259 else
260 a[x++] = dataByte;
261 }
262 while(x < image_width)
263 a[x++] = 0;
264 }
265
266 a = image_buffer;
267 b = pbuf;
268
269 for(x = 0;x < image_width*image_height;x++)
270 {
271 y = *b++ * 3;
272 *a++ = palette[y+2];
273 *a++ = palette[y+1];
274 *a++ = palette[y];
275 *a++ = 255;
276 }
277
278 return image_buffer;
279}
280
281/*
282============
283LoadPCX
284============
285*/
286qbool LoadPCX_QWSkin(const unsigned char *f, int filesize, unsigned char *pixels, int outwidth, int outheight)
287{
288 pcx_t pcx;
289 unsigned char *a;
290 const unsigned char *fin, *enddata;
291 int x, y, x2, dataByte, pcxwidth, pcxheight;
292
293 if (filesize < (int)sizeof(pcx) + 768)
294 return false;
295
296 image_width = outwidth;
297 image_height = outheight;
298 fin = f;
299
300 memcpy(&pcx, fin, sizeof(pcx));
301 fin += sizeof(pcx);
302
303 // LadyHavoc: big-endian support ported from QF newtree
304 pcx.xmax = LittleShort (pcx.xmax);
305 pcx.xmin = LittleShort (pcx.xmin);
306 pcx.ymax = LittleShort (pcx.ymax);
307 pcx.ymin = LittleShort (pcx.ymin);
308 pcx.hres = LittleShort (pcx.hres);
309 pcx.vres = LittleShort (pcx.vres);
312
313 pcxwidth = pcx.xmax + 1 - pcx.xmin;
314 pcxheight = pcx.ymax + 1 - pcx.ymin;
315 if (pcx.manufacturer != 0x0a || pcx.version != 5 || pcx.encoding != 1 || pcx.bits_per_pixel != 8 || pcxwidth > 4096 || pcxheight > 4096 || pcxwidth <= 0 || pcxheight <= 0)
316 return false;
317
318 enddata = f + filesize - 768;
319
320 for (y = 0;y < outheight && fin < enddata;y++)
321 {
322 a = pixels + y * outwidth;
323 // pad the output with blank lines if needed
324 if (y >= pcxheight)
325 {
326 memset(a, 0, outwidth);
327 continue;
328 }
329 for (x = 0;x < pcxwidth;)
330 {
331 if (fin >= enddata)
332 return false;
333 dataByte = *fin++;
334 if(dataByte >= 0xC0)
335 {
336 x2 = x + (dataByte & 0x3F);
337 if (fin >= enddata)
338 return false;
339 if (x2 > pcxwidth)
340 return false;
341 dataByte = *fin++;
342 for (;x < x2;x++)
343 if (x < outwidth)
344 a[x] = dataByte;
345 }
346 else
347 {
348 if (x < outwidth) // truncate to destination width
349 a[x] = dataByte;
350 x++;
351 }
352 }
353 while(x < outwidth)
354 a[x++] = 0;
355 }
356
357 return true;
358}
359
360/*
361============
362LoadPCX
363============
364*/
365qbool LoadPCX_PaletteOnly(const unsigned char *f, int filesize, unsigned char *palette768b)
366{
367 if (filesize < 768)
368 return false;
369 memcpy(palette768b, f + filesize - 768, 768);
370 return true;
371}
372
373/*
374=========================================================
375
376TARGA LOADING
377
378=========================================================
379*/
380
381typedef struct _TargaHeader
382{
383 unsigned char id_length, colormap_type, image_type;
384 unsigned short colormap_index, colormap_length;
385 unsigned char colormap_size;
386 unsigned short x_origin, y_origin, width, height;
387 unsigned char pixel_size, attributes;
388}
390
392{
393 Con_Printf("TargaHeader:\nuint8 id_length = %i;\nuint8 colormap_type = %i;\nuint8 image_type = %i;\nuint16 colormap_index = %i;\nuint16 colormap_length = %i;\nuint8 colormap_size = %i;\nuint16 x_origin = %i;\nuint16 y_origin = %i;\nuint16 width = %i;\nuint16 height = %i;\nuint8 pixel_size = %i;\nuint8 attributes = %i;\n", t->id_length, t->colormap_type, t->image_type, t->colormap_index, t->colormap_length, t->colormap_size, t->x_origin, t->y_origin, t->width, t->height, t->pixel_size, t->attributes);
394}
395
396/*
397=============
398LoadTGA
399=============
400*/
401unsigned char *LoadTGA_BGRA (const unsigned char *f, int filesize, int *miplevel)
402{
403 int x, y, pix_inc, row_inci, runlen, alphabits;
404 unsigned char *image_buffer;
405 unsigned int *pixbufi;
406 const unsigned char *fin, *enddata;
407 TargaHeader targa_header;
408 unsigned int palettei[256];
409 union
410 {
411 unsigned int i;
412 unsigned char b[4];
413 }
414 bgra;
415
416 if (filesize < 19)
417 return NULL;
418
419 enddata = f + filesize;
420
421 targa_header.id_length = f[0];
422 targa_header.colormap_type = f[1];
423 targa_header.image_type = f[2];
424
425 targa_header.colormap_index = f[3] + f[4] * 256;
426 targa_header.colormap_length = f[5] + f[6] * 256;
427 targa_header.colormap_size = f[7];
428 targa_header.x_origin = f[8] + f[9] * 256;
429 targa_header.y_origin = f[10] + f[11] * 256;
430 targa_header.width = image_width = f[12] + f[13] * 256;
431 targa_header.height = image_height = f[14] + f[15] * 256;
432 targa_header.pixel_size = f[16];
433 targa_header.attributes = f[17];
434
435 if (image_width > 32768 || image_height > 32768 || image_width <= 0 || image_height <= 0)
436 {
437 Con_Print("LoadTGA: invalid size\n");
438 PrintTargaHeader(&targa_header);
439 return NULL;
440 }
441
442 memset(palettei, 0, sizeof(palettei));
443
444 // advance to end of header
445 fin = f + 18;
446
447 // skip TARGA image comment (usually 0 bytes)
448 fin += targa_header.id_length;
449
450 // read/skip the colormap if present (note: according to the TARGA spec it
451 // can be present even on truecolor or greyscale images, just not used by
452 // the image data)
453 if (targa_header.colormap_type)
454 {
455 if (targa_header.colormap_length > 256)
456 {
457 Con_Print("LoadTGA: only up to 256 colormap_length supported\n");
458 PrintTargaHeader(&targa_header);
459 return NULL;
460 }
461 if (targa_header.colormap_index)
462 {
463 Con_Print("LoadTGA: colormap_index not supported\n");
464 PrintTargaHeader(&targa_header);
465 return NULL;
466 }
467 if (targa_header.colormap_size == 24)
468 {
469 for (x = 0;x < targa_header.colormap_length;x++)
470 {
471 bgra.b[0] = *fin++;
472 bgra.b[1] = *fin++;
473 bgra.b[2] = *fin++;
474 bgra.b[3] = 255;
475 palettei[x] = bgra.i;
476 }
477 }
478 else if (targa_header.colormap_size == 32)
479 {
480 memcpy(palettei, fin, targa_header.colormap_length*4);
481 fin += targa_header.colormap_length * 4;
482 }
483 else
484 {
485 Con_Print("LoadTGA: Only 32 and 24 bit colormap_size supported\n");
486 PrintTargaHeader(&targa_header);
487 return NULL;
488 }
489 }
490
491 // check our pixel_size restrictions according to image_type
492 switch (targa_header.image_type & ~8)
493 {
494 case 2:
495 if (targa_header.pixel_size != 24 && targa_header.pixel_size != 32)
496 {
497 Con_Print("LoadTGA: only 24bit and 32bit pixel sizes supported for type 2 and type 10 images\n");
498 PrintTargaHeader(&targa_header);
499 return NULL;
500 }
501 break;
502 case 3:
503 // set up a palette to make the loader easier
504 for (x = 0;x < 256;x++)
505 {
506 bgra.b[0] = bgra.b[1] = bgra.b[2] = x;
507 bgra.b[3] = 255;
508 palettei[x] = bgra.i;
509 }
510 // fall through to colormap case
511 case 1:
512 if (targa_header.pixel_size != 8)
513 {
514 Con_Print("LoadTGA: only 8bit pixel size for type 1, 3, 9, and 11 images supported\n");
515 PrintTargaHeader(&targa_header);
516 return NULL;
517 }
518 break;
519 default:
520 Con_Printf("LoadTGA: Only type 1, 2, 3, 9, 10, and 11 targa RGB images supported, image_type = %i\n", targa_header.image_type);
521 PrintTargaHeader(&targa_header);
522 return NULL;
523 }
524
525 if (targa_header.attributes & 0x10)
526 {
527 Con_Print("LoadTGA: origin must be in top left or bottom left, top right and bottom right are not supported\n");
528 return NULL;
529 }
530
531 // number of attribute bits per pixel, we only support 0 or 8
532 alphabits = targa_header.attributes & 0x0F;
533 if (alphabits != 8 && alphabits != 0)
534 {
535 Con_Print("LoadTGA: only 0 or 8 attribute (alpha) bits supported\n");
536 return NULL;
537 }
538
539 image_buffer = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
540 if (!image_buffer)
541 {
542 Con_Printf("LoadTGA: not enough memory for %i by %i image\n", image_width, image_height);
543 return NULL;
544 }
545
546 // If bit 5 of attributes isn't set, the image has been stored from bottom to top
547 if ((targa_header.attributes & 0x20) == 0)
548 {
549 pixbufi = (unsigned int*)image_buffer + (image_height - 1)*image_width;
550 row_inci = -image_width*2;
551 }
552 else
553 {
554 pixbufi = (unsigned int*)image_buffer;
555 row_inci = 0;
556 }
557
558 pix_inc = 1;
559 if ((targa_header.image_type & ~8) == 2)
560 pix_inc = (targa_header.pixel_size + 7) / 8;
561 switch (targa_header.image_type)
562 {
563 case 1: // colormapped, uncompressed
564 case 3: // greyscale, uncompressed
565 if (fin + image_width * image_height * pix_inc > enddata)
566 break;
567 for (y = 0;y < image_height;y++, pixbufi += row_inci)
568 for (x = 0;x < image_width;x++)
569 *pixbufi++ = palettei[*fin++];
570 break;
571 case 2:
572 // BGR or BGRA, uncompressed
573 if (fin + image_width * image_height * pix_inc > enddata)
574 break;
575 if (targa_header.pixel_size == 32 && alphabits)
576 {
577 for (y = 0;y < image_height;y++)
578 memcpy(pixbufi + y * (image_width + row_inci), fin + y * image_width * pix_inc, image_width*4);
579 }
580 else
581 {
582 for (y = 0;y < image_height;y++, pixbufi += row_inci)
583 {
584 for (x = 0;x < image_width;x++, fin += pix_inc)
585 {
586 bgra.b[0] = fin[0];
587 bgra.b[1] = fin[1];
588 bgra.b[2] = fin[2];
589 bgra.b[3] = 255;
590 *pixbufi++ = bgra.i;
591 }
592 }
593 }
594 break;
595 case 9: // colormapped, RLE
596 case 11: // greyscale, RLE
597 for (y = 0;y < image_height;y++, pixbufi += row_inci)
598 {
599 for (x = 0;x < image_width;)
600 {
601 if (fin >= enddata)
602 break; // error - truncated file
603 runlen = *fin++;
604 if (runlen & 0x80)
605 {
606 // RLE - all pixels the same color
607 runlen += 1 - 0x80;
608 if (fin + pix_inc > enddata)
609 break; // error - truncated file
610 if (x + runlen > image_width)
611 break; // error - line exceeds width
612 bgra.i = palettei[*fin++];
613 for (;runlen--;x++)
614 *pixbufi++ = bgra.i;
615 }
616 else
617 {
618 // uncompressed - all pixels different color
619 runlen++;
620 if (fin + pix_inc * runlen > enddata)
621 break; // error - truncated file
622 if (x + runlen > image_width)
623 break; // error - line exceeds width
624 for (;runlen--;x++)
625 *pixbufi++ = palettei[*fin++];
626 }
627 }
628
629 if (x != image_width)
630 {
631 // pixbufi is useless now
632 Con_Printf("LoadTGA: corrupt file\n");
633 break;
634 }
635 }
636 break;
637 case 10:
638 // BGR or BGRA, RLE
639 if (targa_header.pixel_size == 32 && alphabits)
640 {
641 for (y = 0;y < image_height;y++, pixbufi += row_inci)
642 {
643 for (x = 0;x < image_width;)
644 {
645 if (fin >= enddata)
646 break; // error - truncated file
647 runlen = *fin++;
648 if (runlen & 0x80)
649 {
650 // RLE - all pixels the same color
651 runlen += 1 - 0x80;
652 if (fin + pix_inc > enddata)
653 break; // error - truncated file
654 if (x + runlen > image_width)
655 break; // error - line exceeds width
656 bgra.b[0] = fin[0];
657 bgra.b[1] = fin[1];
658 bgra.b[2] = fin[2];
659 bgra.b[3] = fin[3];
660 fin += pix_inc;
661 for (;runlen--;x++)
662 *pixbufi++ = bgra.i;
663 }
664 else
665 {
666 // uncompressed - all pixels different color
667 runlen++;
668 if (fin + pix_inc * runlen > enddata)
669 break; // error - truncated file
670 if (x + runlen > image_width)
671 break; // error - line exceeds width
672 for (;runlen--;x++)
673 {
674 bgra.b[0] = fin[0];
675 bgra.b[1] = fin[1];
676 bgra.b[2] = fin[2];
677 bgra.b[3] = fin[3];
678 fin += pix_inc;
679 *pixbufi++ = bgra.i;
680 }
681 }
682 }
683
684 if (x != image_width)
685 {
686 // pixbufi is useless now
687 Con_Printf("LoadTGA: corrupt file\n");
688 break;
689 }
690 }
691 }
692 else
693 {
694 for (y = 0;y < image_height;y++, pixbufi += row_inci)
695 {
696 for (x = 0;x < image_width;)
697 {
698 if (fin >= enddata)
699 break; // error - truncated file
700 runlen = *fin++;
701 if (runlen & 0x80)
702 {
703 // RLE - all pixels the same color
704 runlen += 1 - 0x80;
705 if (fin + pix_inc > enddata)
706 break; // error - truncated file
707 if (x + runlen > image_width)
708 break; // error - line exceeds width
709 bgra.b[0] = fin[0];
710 bgra.b[1] = fin[1];
711 bgra.b[2] = fin[2];
712 bgra.b[3] = 255;
713 fin += pix_inc;
714 for (;runlen--;x++)
715 *pixbufi++ = bgra.i;
716 }
717 else
718 {
719 // uncompressed - all pixels different color
720 runlen++;
721 if (fin + pix_inc * runlen > enddata)
722 break; // error - truncated file
723 if (x + runlen > image_width)
724 break; // error - line exceeds width
725 for (;runlen--;x++)
726 {
727 bgra.b[0] = fin[0];
728 bgra.b[1] = fin[1];
729 bgra.b[2] = fin[2];
730 bgra.b[3] = 255;
731 fin += pix_inc;
732 *pixbufi++ = bgra.i;
733 }
734 }
735 }
736
737 if (x != image_width)
738 {
739 // pixbufi is useless now
740 Con_Printf("LoadTGA: corrupt file\n");
741 break;
742 }
743 }
744 }
745 break;
746 default:
747 // unknown image_type
748 break;
749 }
750
751 return image_buffer;
752}
753
754typedef struct q2wal_s
755{
756 char name[32];
757 unsigned width, height;
758 unsigned offsets[MIPLEVELS]; // four mip maps stored
759 char animname[32]; // next frame in animation chain
760 int flags;
762 int value;
763} q2wal_t;
764
765static unsigned char *LoadWAL_BGRA (const unsigned char *f, int filesize, int *miplevel)
766{
767 unsigned char *image_buffer;
768 const q2wal_t *inwal = (const q2wal_t *)f;
769
770 if (filesize < (int) sizeof(q2wal_t))
771 {
772 Con_Print("LoadWAL: invalid WAL file\n");
773 return NULL;
774 }
775
776 image_width = LittleLong(inwal->width);
778 if (image_width > 32768 || image_height > 32768 || image_width <= 0 || image_height <= 0)
779 {
780 Con_Printf("LoadWAL: invalid size %ix%i\n", image_width, image_height);
781 return NULL;
782 }
783
784 if (filesize < (int) LittleLong(inwal->offsets[0]) + image_width * image_height)
785 {
786 Con_Print("LoadWAL: invalid WAL file\n");
787 return NULL;
788 }
789
790 image_buffer = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
791 if (!image_buffer)
792 {
793 Con_Printf("LoadWAL: not enough memory for %i by %i image\n", image_width, image_height);
794 return NULL;
795 }
797 return image_buffer;
798}
799
800qbool LoadWAL_GetMetadata(const unsigned char *f, int filesize, int *retwidth, int *retheight, int *retflags, int *retvalue, int *retcontents, char *retanimname32c)
801{
802 const q2wal_t *inwal = (const q2wal_t *)f;
803
804 if (filesize < (int) sizeof(q2wal_t))
805 {
806 Con_Print("LoadWAL: invalid WAL file\n");
807 if (retwidth)
808 *retwidth = 16;
809 if (retheight)
810 *retheight = 16;
811 if (retflags)
812 *retflags = 0;
813 if (retvalue)
814 *retvalue = 0;
815 if (retcontents)
816 *retcontents = 0;
817 if (retanimname32c)
818 memset(retanimname32c, 0, 32);
819 return false;
820 }
821
822 if (retwidth)
823 *retwidth = LittleLong(inwal->width);
824 if (retheight)
825 *retheight = LittleLong(inwal->height);
826 if (retflags)
827 *retflags = LittleLong(inwal->flags);
828 if (retvalue)
829 *retvalue = LittleLong(inwal->value);
830 if (retcontents)
831 *retcontents = LittleLong(inwal->contents);
832 if (retanimname32c)
833 {
834 memcpy(retanimname32c, inwal->animname, 32);
835 retanimname32c[31] = 0;
836 }
837 return true;
838}
839
840// gfx/* wad lumps and gfx/*.lmp files are simply width and height and paletted pixels, with color 255 as transparent
841static unsigned char* LoadLMP_BGRA(const unsigned char *f, int filesize, int *miplevel)
842{
843 unsigned char *image_buffer;
844 int i;
845
846 if (filesize < 9)
847 {
848 Con_Print("Bad lmp file\n");
849 return NULL;
850 }
851
852 image_width = f[0] + f[1] * 0x100 + f[2] * 0x10000 + f[3] * 0x1000000;
853 image_height = f[4] + f[5] * 0x100 + f[6] * 0x10000 + f[7] * 0x1000000;
854
855 if (image_width > 32768 || image_height > 32768 || image_width <= 0 || image_height <= 0 || image_width * image_height > filesize - 8)
856 {
857 Con_Print("Bad lmp file\n");
858 return NULL;
859 }
860
861 image_buffer = (unsigned char *)Mem_Alloc(tempmempool, image_width*image_height * 4);
862 if (!image_buffer)
863 {
864 Con_Printf("LoadLMP: not enough memory for %i by %i image\n", image_width, image_height);
865 return NULL;
866 }
867
868 for (i = 0; i < image_width * image_height; i++)
869 {
870 const unsigned char *p = (const unsigned char *)palette_bgra_transparent + 4 * f[8 + i];
871 image_buffer[i * 4 + 0] = p[0];
872 image_buffer[i * 4 + 1] = p[1];
873 image_buffer[i * 4 + 2] = p[2];
874 image_buffer[i * 4 + 3] = p[3];
875 }
876
877 return image_buffer;
878}
879
880// gfx/conchars is a raw 128x128 image with 0 as transparent color rather than 255
881static unsigned char *LoadConChars_BGRA(const unsigned char *f, int filesize, int *miplevel)
882{
883 unsigned char *image_buffer;
884 int i;
885
886 image_width = 128;
887 image_height = 128;
888 if (image_width * image_height > filesize)
889 {
890 Con_Print("Bad lmp file\n");
891 return NULL;
892 }
893
894 image_buffer = (unsigned char *)Mem_Alloc(tempmempool, image_width*image_height * 4);
895 if (!image_buffer)
896 {
897 Con_Printf("LoadConChars: not enough memory for %i by %i image\n", image_width, image_height);
898 return NULL;
899 }
900
901 for (i = 0; i < image_width * image_height; i++)
902 {
903 const unsigned char *p = (const unsigned char *)palette_bgra_font + 4 * f[i];
904 image_buffer[i * 4 + 0] = p[0];
905 image_buffer[i * 4 + 1] = p[1];
906 image_buffer[i * 4 + 2] = p[2];
907 image_buffer[i * 4 + 3] = p[3];
908 }
909
910 return image_buffer;
911}
912
913void Image_StripImageExtension (const char *in, char *out, size_t size_out)
914{
915 const char *ext;
916
917 if (size_out == 0)
918 return;
919
920 ext = FS_FileExtension(in);
921 if (ext && (!strcmp(ext, "tga") || !strcmp(ext, "pcx") || !strcmp(ext, "lmp") || !strcmp(ext, "png") || !strcmp(ext, "jpg") || !strcmp(ext, "wal")))
922 FS_StripExtension(in, out, size_out);
923 else
924 dp_strlcpy(out, in, size_out);
925}
926
927static unsigned char image_linearfromsrgb[256];
928static unsigned char image_srgbfromlinear_lightmap[256];
929
930void Image_MakeLinearColorsFromsRGB(unsigned char *pout, const unsigned char *pin, int numpixels)
931{
932 int i;
933 // this math from http://www.opengl.org/registry/specs/EXT/texture_sRGB.txt
934 if (!image_linearfromsrgb[255])
935 for (i = 0;i < 256;i++)
936 image_linearfromsrgb[i] = (unsigned char)floor(Image_LinearFloatFromsRGB(i) * 255.0f + 0.5f);
937 for (i = 0;i < numpixels;i++)
938 {
939 pout[i*4+0] = image_linearfromsrgb[pin[i*4+0]];
940 pout[i*4+1] = image_linearfromsrgb[pin[i*4+1]];
941 pout[i*4+2] = image_linearfromsrgb[pin[i*4+2]];
942 pout[i*4+3] = pin[i*4+3];
943 }
944}
945
946void Image_MakesRGBColorsFromLinear_Lightmap(unsigned char *pout, const unsigned char *pin, int numpixels)
947{
948 int i;
949 // this math from http://www.opengl.org/registry/specs/EXT/texture_sRGB.txt
951 for (i = 0;i < 256;i++)
952 image_srgbfromlinear_lightmap[i] = (unsigned char)floor(bound(0.0f, Image_sRGBFloatFromLinear_Lightmap(i), 1.0f) * 255.0f + 0.5f);
953 for (i = 0;i < numpixels;i++)
954 {
955 pout[i*4+0] = image_srgbfromlinear_lightmap[pin[i*4+0]];
956 pout[i*4+1] = image_srgbfromlinear_lightmap[pin[i*4+1]];
957 pout[i*4+2] = image_srgbfromlinear_lightmap[pin[i*4+2]];
958 pout[i*4+3] = pin[i*4+3];
959 }
960}
961
962typedef struct imageformat_s
963{
964 const char *formatstring;
965 unsigned char *(*loadfunc)(const unsigned char *f, int filesize, int *miplevel);
966}
968
969// GAME_TENEBRAE only
971{
972 {"override/%s.tga", LoadTGA_BGRA},
973 {"override/%s.png", PNG_LoadImage_BGRA},
974 {"override/%s.jpg", JPEG_LoadImage_BGRA},
975 {"override/%s.pcx", LoadPCX_BGRA},
976 {"%s.tga", LoadTGA_BGRA},
977 {"%s.png", PNG_LoadImage_BGRA},
978 {"%s.jpg", JPEG_LoadImage_BGRA},
979 {"%s.pcx", LoadPCX_BGRA},
980 {NULL, NULL}
981};
982
984{
985 {"override/%s.tga", LoadTGA_BGRA},
986 {"override/%s.png", PNG_LoadImage_BGRA},
987 {"override/%s.jpg", JPEG_LoadImage_BGRA},
988 {"textures/%s.tga", LoadTGA_BGRA},
989 {"textures/%s.png", PNG_LoadImage_BGRA},
990 {"textures/%s.jpg", JPEG_LoadImage_BGRA},
991 {"%s.tga", LoadTGA_BGRA},
992 {"%s.png", PNG_LoadImage_BGRA},
993 {"%s.jpg", JPEG_LoadImage_BGRA},
994 {"%s.pcx", LoadPCX_BGRA},
995 {NULL, NULL}
996};
997
998// GAME_DELUXEQUAKE only
999// VorteX: the point why i use such messy texture paths is
1000// that GtkRadiant can't detect normal/gloss textures
1001// and exclude them from texture browser
1002// so i just use additional folder to store this textures
1004{
1005 {"%s.tga", LoadTGA_BGRA},
1006 {"%s.jpg", JPEG_LoadImage_BGRA},
1007 {"texturemaps/%s.tga", LoadTGA_BGRA},
1008 {"texturemaps/%s.jpg", JPEG_LoadImage_BGRA},
1009 {NULL, NULL}
1010};
1011
1013{
1014 {"%s.tga", LoadTGA_BGRA},
1015 {"%s.png", PNG_LoadImage_BGRA},
1016 {"%s.jpg", JPEG_LoadImage_BGRA},
1017 {"%s.pcx", LoadPCX_BGRA},
1018 {"%s.wal", LoadWAL_BGRA},
1019 {NULL, NULL}
1020};
1021
1023{
1024 {"%s.tga", LoadTGA_BGRA},
1025 {"%s.png", PNG_LoadImage_BGRA},
1026 {"%s.jpg", JPEG_LoadImage_BGRA},
1027 {"%s.pcx", LoadPCX_BGRA},
1028 {"%s.lmp", LoadLMP_BGRA},
1029 {NULL, NULL}
1030};
1031
1033{
1034 {"%s.tga", LoadTGA_BGRA},
1035 {"%s.png", PNG_LoadImage_BGRA},
1036 {"%s.jpg", JPEG_LoadImage_BGRA},
1037 {"%s.pcx", LoadPCX_BGRA},
1038 {"%s.lmp", LoadLMP_BGRA},
1039 {NULL, NULL}
1040};
1041
1042int fixtransparentpixels(unsigned char *data, int w, int h);
1043unsigned char *loadimagepixelsbgra (const char *filename, qbool complain, qbool allowFixtrans, qbool convertsRGB, int *miplevel)
1044{
1045 fs_offset_t filesize;
1046 imageformat_t *firstformat, *format;
1047 int mymiplevel;
1048 unsigned char *f, *data = NULL, *data2 = NULL;
1049 char basename[MAX_QPATH], name[MAX_QPATH], name2[MAX_QPATH], path[MAX_QPATH], afterpath[MAX_QPATH], *c;
1050 char vabuf[1024];
1051 //if (developer_memorydebug.integer)
1052 // Mem_CheckSentinelsGlobal();
1054 Log_Printf("textures.log", "%s\n", filename);
1055 Image_StripImageExtension(filename, basename, sizeof(basename)); // strip filename extensions to allow replacement by other types
1056 // replace *'s with #, so commandline utils don't get confused when dealing with the external files
1057 for (c = basename;*c;c++)
1058 if (*c == '*')
1059 *c = '#';
1060 path[0] = 0;
1061 name[0] = 0;
1062 dp_strlcpy(afterpath, basename, sizeof(afterpath));
1063 if (strchr(basename, '/'))
1064 {
1065 int i;
1066 for (i = 0;i < (int)sizeof(path)-1 && basename[i] != '/' && basename[i];i++)
1067 path[i] = basename[i];
1068 path[i] = 0;
1069 dp_strlcpy(afterpath, basename + i + 1, sizeof(afterpath));
1070 }
1071 if (gamemode == GAME_TENEBRAE)
1072 firstformat = imageformats_tenebrae;
1073 else if (gamemode == GAME_DELUXEQUAKE)
1074 firstformat = imageformats_dq;
1075 else if (!strcasecmp(path, "textures"))
1076 firstformat = imageformats_textures;
1077 else if (!strcasecmp(path, "gfx") || !strcasecmp(path, "locale")) // locale/ is used in GAME_BLOODOMNICIDE
1078 firstformat = imageformats_gfx;
1079 else if (!path[0])
1080 firstformat = imageformats_nopath;
1081 else
1082 firstformat = imageformats_other;
1083 // now try all the formats in the selected list
1084 for (format = firstformat;format->formatstring;format++)
1085 {
1086 dpsnprintf (name, sizeof(name), format->formatstring, basename);
1087
1089
1090 if(FS_FileExists(name) && (f = FS_LoadFile(name, tempmempool, true, &filesize)) != NULL)
1091 {
1092 mymiplevel = miplevel ? *miplevel : 0;
1093 image_width = 0;
1094 image_height = 0;
1095 data = format->loadfunc(f, (int)filesize, &mymiplevel);
1096 Mem_Free(f);
1097 if (data)
1098 {
1099 if(format->loadfunc == JPEG_LoadImage_BGRA) // jpeg can't do alpha, so let's simulate it by loading another jpeg
1100 {
1101 dpsnprintf (name2, sizeof(name2), format->formatstring, va(vabuf, sizeof(vabuf), "%s_alpha", basename));
1102 f = FS_LoadFile(name2, tempmempool, true, &filesize);
1103 if(f)
1104 {
1105 int mymiplevel2 = miplevel ? *miplevel : 0;
1106 int image_width_save = image_width;
1107 int image_height_save = image_height;
1108 data2 = format->loadfunc(f, (int)filesize, &mymiplevel2);
1109 if(data2 && mymiplevel == mymiplevel2 && image_width == image_width_save && image_height == image_height_save)
1111 else
1112 Con_Printf("loadimagepixelsrgba: corrupt or invalid alpha image %s_alpha\n", basename);
1113 image_width = image_width_save;
1114 image_height = image_height_save;
1115 if(data2)
1116 Mem_Free(data2);
1117 Mem_Free(f);
1118 }
1119 }
1121 Con_DPrintf("loaded image %s (%dx%d)\n", name, image_width, image_height);
1122 if(miplevel)
1123 *miplevel = mymiplevel;
1124 //if (developer_memorydebug.integer)
1125 // Mem_CheckSentinelsGlobal();
1126 if(allowFixtrans && r_fixtrans_auto.integer)
1127 {
1129 if(n)
1130 {
1131 Con_Printf("- had to fix %s (%d pixels changed)\n", name, n);
1132 if(r_fixtrans_auto.integer >= 2)
1133 {
1134 char outfilename[MAX_QPATH], buf[MAX_QPATH];
1136 dpsnprintf(outfilename, sizeof(outfilename), "fixtrans/%s.tga", buf);
1138 Con_Printf("- %s written.\n", outfilename);
1139 }
1140 }
1141 }
1142 if (convertsRGB)
1144 return data;
1145 }
1146 else
1147 Con_DPrintf("Error loading image %s (file loaded but decode failed)\n", name);
1148 }
1149 }
1150 if (!strcasecmp(path, "gfx"))
1151 {
1152 unsigned char *lmpdata;
1153 if ((lmpdata = W_GetLumpName(afterpath, &filesize)))
1154 {
1156 Con_Printf("loading gfx.wad lump \"%s\"\n", afterpath);
1157
1158 mymiplevel = miplevel ? *miplevel : 0;
1159 if (!strcmp(afterpath, "conchars"))
1160 {
1161 // conchars is a raw image and with color 0 as transparent instead of 255
1162 data = LoadConChars_BGRA(lmpdata, filesize, &mymiplevel);
1163 }
1164 else
1165 data = LoadLMP_BGRA(lmpdata, filesize, &mymiplevel);
1166 // no cleanup after looking up a wad lump - the whole gfx.wad is loaded at once
1167 if (data)
1168 return data;
1169 Con_DPrintf("Error loading image %s (file loaded but decode failed)\n", name);
1170 }
1171 }
1172
1173 // check if the image name exists as an embedded pic
1174 if ((data = Image_GetEmbeddedPicBGRA(basename)))
1175 return data;
1176
1177 if (complain)
1178 {
1179 Con_Printf(CON_ERROR "Couldn't load %s using ", filename);
1180 for (format = firstformat;format->formatstring;format++)
1181 {
1182 dpsnprintf (name, sizeof(name), format->formatstring, basename);
1183 Con_Printf(format == firstformat ? "\"%s\"" : (format[1].formatstring ? ", \"%s\"" : " or \"%s\".\n"), format->formatstring);
1184 }
1185 }
1186
1187 // texture loading can take a while, so make sure we're sending keepalives
1188 CL_KeepaliveMessage(false);
1189
1190 //if (developer_memorydebug.integer)
1191 // Mem_CheckSentinelsGlobal();
1192
1193 return NULL;
1194}
1195
1196qbool Image_GetStockPicSize(const char *filename, int *returnwidth, int *returnheight)
1197{
1198 unsigned char *data;
1199 fs_offset_t filesize;
1200 char lmppath[MAX_QPATH];
1201 if (!strcasecmp(filename, "gfx/conchars"))
1202 {
1203 *returnwidth = 128;
1204 *returnheight = 128;
1205 return true;
1206 }
1207
1208 dpsnprintf(lmppath, sizeof(lmppath), "%s.lmp", filename);
1209 data = FS_LoadFile(lmppath, tempmempool, true, &filesize);
1210 if (data)
1211 {
1212 if (filesize > 8)
1213 {
1214 int w = data[0] + data[1] * 0x100 + data[2] * 0x10000 + data[3] * 0x1000000;
1215 int h = data[4] + data[5] * 0x100 + data[6] * 0x10000 + data[7] * 0x1000000;
1216 if (w >= 1 && w <= 32768 && h >= 1 && h <= 32768)
1217 {
1218 *returnwidth = w;
1219 *returnheight = h;
1220 Mem_Free(data);
1221 return true;
1222 }
1223 }
1224 Mem_Free(data);
1225 }
1226 if (!strncasecmp(filename, "gfx/", 4))
1227 {
1228 data = W_GetLumpName(filename + 4, &filesize);
1229 if (data && filesize > 8)
1230 {
1231 int w = data[0] + data[1] * 0x100 + data[2] * 0x10000 + data[3] * 0x1000000;
1232 int h = data[4] + data[5] * 0x100 + data[6] * 0x10000 + data[7] * 0x1000000;
1233 if (w >= 1 && w <= 32768 && h >= 1 && h <= 32768)
1234 {
1235 *returnwidth = w;
1236 *returnheight = h;
1237 return true;
1238 }
1239 }
1240 }
1241 return false;
1242}
1243
1244extern cvar_t gl_picmip;
1245rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, qbool complain, int flags, qbool allowFixtrans, qbool sRGB)
1246{
1247 unsigned char *data;
1248 rtexture_t *rt;
1249 int miplevel = R_PicmipForFlags(flags);
1250 if (!(data = loadimagepixelsbgra (filename, complain, allowFixtrans, false, &miplevel)))
1251 return 0;
1252 rt = R_LoadTexture2D(pool, filename, image_width, image_height, data, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, flags, miplevel, NULL);
1253 Mem_Free(data);
1254 return rt;
1255}
1256
1257int fixtransparentpixels(unsigned char *data, int w, int h)
1258{
1259 int const FIXTRANS_NEEDED = 1;
1260 int const FIXTRANS_HAS_L = 2;
1261 int const FIXTRANS_HAS_R = 4;
1262 int const FIXTRANS_HAS_U = 8;
1263 int const FIXTRANS_HAS_D = 16;
1264 int const FIXTRANS_FIXED = 32;
1265 unsigned char *fixMask = (unsigned char *) Mem_Alloc(tempmempool, w * h);
1266 int fixPixels = 0;
1267 int changedPixels = 0;
1268 int x, y;
1269
1270#define FIXTRANS_PIXEL (y*w+x)
1271#define FIXTRANS_PIXEL_U (((y+h-1)%h)*w+x)
1272#define FIXTRANS_PIXEL_D (((y+1)%h)*w+x)
1273#define FIXTRANS_PIXEL_L (y*w+((x+w-1)%w))
1274#define FIXTRANS_PIXEL_R (y*w+((x+1)%w))
1275
1276 memset(fixMask, 0, w * h);
1277 for(y = 0; y < h; ++y)
1278 for(x = 0; x < w; ++x)
1279 {
1280 if(data[FIXTRANS_PIXEL * 4 + 3] == 0)
1281 {
1282 fixMask[FIXTRANS_PIXEL] |= FIXTRANS_NEEDED;
1283 ++fixPixels;
1284 }
1285 else
1286 {
1287 fixMask[FIXTRANS_PIXEL_D] |= FIXTRANS_HAS_U;
1288 fixMask[FIXTRANS_PIXEL_U] |= FIXTRANS_HAS_D;
1289 fixMask[FIXTRANS_PIXEL_R] |= FIXTRANS_HAS_L;
1290 fixMask[FIXTRANS_PIXEL_L] |= FIXTRANS_HAS_R;
1291 }
1292 }
1293 if(fixPixels == w * h)
1294 return 0; // sorry, can't do anything about this
1295 while(fixPixels)
1296 {
1297 for(y = 0; y < h; ++y)
1298 for(x = 0; x < w; ++x)
1299 if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_NEEDED)
1300 {
1301 unsigned int sumR = 0, sumG = 0, sumB = 0, sumA = 0, sumRA = 0, sumGA = 0, sumBA = 0, cnt = 0;
1302 unsigned char r, g, b, a, r0, g0, b0;
1303 if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_HAS_U)
1304 {
1305 r = data[FIXTRANS_PIXEL_U * 4 + 2];
1306 g = data[FIXTRANS_PIXEL_U * 4 + 1];
1307 b = data[FIXTRANS_PIXEL_U * 4 + 0];
1308 a = data[FIXTRANS_PIXEL_U * 4 + 3];
1309 sumR += r; sumG += g; sumB += b; sumA += a; sumRA += r*a; sumGA += g*a; sumBA += b*a; ++cnt;
1310 }
1311 if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_HAS_D)
1312 {
1313 r = data[FIXTRANS_PIXEL_D * 4 + 2];
1314 g = data[FIXTRANS_PIXEL_D * 4 + 1];
1315 b = data[FIXTRANS_PIXEL_D * 4 + 0];
1316 a = data[FIXTRANS_PIXEL_D * 4 + 3];
1317 sumR += r; sumG += g; sumB += b; sumA += a; sumRA += r*a; sumGA += g*a; sumBA += b*a; ++cnt;
1318 }
1319 if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_HAS_L)
1320 {
1321 r = data[FIXTRANS_PIXEL_L * 4 + 2];
1322 g = data[FIXTRANS_PIXEL_L * 4 + 1];
1323 b = data[FIXTRANS_PIXEL_L * 4 + 0];
1324 a = data[FIXTRANS_PIXEL_L * 4 + 3];
1325 sumR += r; sumG += g; sumB += b; sumA += a; sumRA += r*a; sumGA += g*a; sumBA += b*a; ++cnt;
1326 }
1327 if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_HAS_R)
1328 {
1329 r = data[FIXTRANS_PIXEL_R * 4 + 2];
1330 g = data[FIXTRANS_PIXEL_R * 4 + 1];
1331 b = data[FIXTRANS_PIXEL_R * 4 + 0];
1332 a = data[FIXTRANS_PIXEL_R * 4 + 3];
1333 sumR += r; sumG += g; sumB += b; sumA += a; sumRA += r*a; sumGA += g*a; sumBA += b*a; ++cnt;
1334 }
1335 if(!cnt)
1336 continue;
1337 r0 = data[FIXTRANS_PIXEL * 4 + 2];
1338 g0 = data[FIXTRANS_PIXEL * 4 + 1];
1339 b0 = data[FIXTRANS_PIXEL * 4 + 0];
1340 if(sumA)
1341 {
1342 // there is a surrounding non-alpha pixel
1343 r = (sumRA + sumA / 2) / sumA;
1344 g = (sumGA + sumA / 2) / sumA;
1345 b = (sumBA + sumA / 2) / sumA;
1346 }
1347 else
1348 {
1349 // need to use a "regular" average
1350 r = (sumR + cnt / 2) / cnt;
1351 g = (sumG + cnt / 2) / cnt;
1352 b = (sumB + cnt / 2) / cnt;
1353 }
1354 if(r != r0 || g != g0 || b != b0)
1355 ++changedPixels;
1356 data[FIXTRANS_PIXEL * 4 + 2] = r;
1357 data[FIXTRANS_PIXEL * 4 + 1] = g;
1358 data[FIXTRANS_PIXEL * 4 + 0] = b;
1359 fixMask[FIXTRANS_PIXEL] |= FIXTRANS_FIXED;
1360 }
1361 for(y = 0; y < h; ++y)
1362 for(x = 0; x < w; ++x)
1363 if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_FIXED)
1364 {
1365 fixMask[FIXTRANS_PIXEL] &= ~(FIXTRANS_NEEDED | FIXTRANS_FIXED);
1366 fixMask[FIXTRANS_PIXEL_D] |= FIXTRANS_HAS_U;
1367 fixMask[FIXTRANS_PIXEL_U] |= FIXTRANS_HAS_D;
1368 fixMask[FIXTRANS_PIXEL_R] |= FIXTRANS_HAS_L;
1369 fixMask[FIXTRANS_PIXEL_L] |= FIXTRANS_HAS_R;
1370 --fixPixels;
1371 }
1372 }
1373 return changedPixels;
1374}
1375
1377{
1378 const char *filename, *filename_pattern;
1379 fssearch_t *search;
1380 int i, n;
1381 char outfilename[MAX_QPATH], buf[MAX_QPATH];
1382 unsigned char *data;
1383 if(Cmd_Argc(cmd) != 2)
1384 {
1385 Con_Printf("Usage: %s imagefile\n", Cmd_Argv(cmd, 0));
1386 return;
1387 }
1388 filename_pattern = Cmd_Argv(cmd, 1);
1389 search = FS_Search(filename_pattern, true, true, NULL);
1390 if(!search)
1391 return;
1392 for(i = 0; i < search->numfilenames; ++i)
1393 {
1394 filename = search->filenames[i];
1395 Con_Printf("Processing %s... ", filename);
1396 Image_StripImageExtension(filename, buf, sizeof(buf));
1397 dpsnprintf(outfilename, sizeof(outfilename), "fixtrans/%s.tga", buf);
1398 if(!(data = loadimagepixelsbgra(filename, true, false, false, NULL)))
1399 return;
1401 {
1403 Con_Printf("%s written (%d pixels changed).\n", outfilename, n);
1404 }
1405 else
1406 Con_Printf("unchanged.\n");
1407 Mem_Free(data);
1408 }
1409 FS_FreeSearch(search);
1410}
1411
1412qbool Image_WriteTGABGR_preflipped (const char *filename, int width, int height, const unsigned char *data)
1413{
1414 qbool ret;
1415 unsigned char buffer[18];
1416 const void *buffers[2];
1417 fs_offset_t sizes[2];
1418
1419 memset (buffer, 0, 18);
1420 buffer[2] = 2; // uncompressed type
1421 buffer[12] = (width >> 0) & 0xFF;
1422 buffer[13] = (width >> 8) & 0xFF;
1423 buffer[14] = (height >> 0) & 0xFF;
1424 buffer[15] = (height >> 8) & 0xFF;
1425 buffer[16] = 24; // pixel size
1426
1427 buffers[0] = buffer;
1428 sizes[0] = 18;
1429 buffers[1] = data;
1430 sizes[1] = width*height*3;
1431 ret = FS_WriteFileInBlocks(filename, buffers, sizes, 2);
1432
1433 return ret;
1434}
1435
1436qbool Image_WriteTGABGRA (const char *filename, int width, int height, const unsigned char *data)
1437{
1438 int y;
1439 unsigned char *buffer, *out;
1440 const unsigned char *in, *end;
1441 qbool ret;
1442
1443 buffer = (unsigned char *)Mem_Alloc(tempmempool, width*height*4 + 18);
1444
1445 memset (buffer, 0, 18);
1446 buffer[2] = 2; // uncompressed type
1447 buffer[12] = (width >> 0) & 0xFF;
1448 buffer[13] = (width >> 8) & 0xFF;
1449 buffer[14] = (height >> 0) & 0xFF;
1450 buffer[15] = (height >> 8) & 0xFF;
1451
1452 for (y = 3;y < width*height*4;y += 4)
1453 if (data[y] < 255)
1454 break;
1455
1456 if (y < width*height*4)
1457 {
1458 // save the alpha channel
1459 buffer[16] = 32; // pixel size
1460 buffer[17] = 8; // 8 bits of alpha
1461
1462 // flip upside down
1463 out = buffer + 18;
1464 for (y = height - 1;y >= 0;y--)
1465 {
1466 memcpy(out, data + y * width * 4, width * 4);
1467 out += width*4;
1468 }
1469 }
1470 else
1471 {
1472 // save only the color channels
1473 buffer[16] = 24; // pixel size
1474 buffer[17] = 0; // 8 bits of alpha
1475
1476 // truncate bgra to bgr and flip upside down
1477 out = buffer + 18;
1478 for (y = height - 1;y >= 0;y--)
1479 {
1480 in = data + y * width * 4;
1481 end = in + width * 4;
1482 for (;in < end;in += 4)
1483 {
1484 *out++ = in[0];
1485 *out++ = in[1];
1486 *out++ = in[2];
1487 }
1488 }
1489 }
1490 ret = FS_WriteFile (filename, buffer, out - buffer);
1491
1493
1494 return ret;
1495}
1496
1497static void Image_Resample32LerpLine (const unsigned char *in, unsigned char *out, int inwidth, int outwidth)
1498{
1499 int j, xi, oldx = 0, f, fstep, endx, lerp;
1500 fstep = (int) (inwidth*65536.0f/outwidth);
1501 endx = (inwidth-1);
1502 for (j = 0,f = 0;j < outwidth;j++, f += fstep)
1503 {
1504 xi = f >> 16;
1505 if (xi != oldx)
1506 {
1507 in += (xi - oldx) * 4;
1508 oldx = xi;
1509 }
1510 if (xi < endx)
1511 {
1512 lerp = f & 0xFFFF;
1513 *out++ = (unsigned char) ((((in[4] - in[0]) * lerp) >> 16) + in[0]);
1514 *out++ = (unsigned char) ((((in[5] - in[1]) * lerp) >> 16) + in[1]);
1515 *out++ = (unsigned char) ((((in[6] - in[2]) * lerp) >> 16) + in[2]);
1516 *out++ = (unsigned char) ((((in[7] - in[3]) * lerp) >> 16) + in[3]);
1517 }
1518 else // last pixel of the line has no pixel to lerp to
1519 {
1520 *out++ = in[0];
1521 *out++ = in[1];
1522 *out++ = in[2];
1523 *out++ = in[3];
1524 }
1525 }
1526}
1527
1528#define LERPBYTE(i) r = resamplerow1[i];out[i] = (unsigned char) ((((resamplerow2[i] - r) * lerp) >> 16) + r)
1529static void Image_Resample32Lerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
1530{
1531 int i, j, r, yi, oldy, f, fstep, lerp, endy = (inheight-1), inwidth4 = inwidth*4, outwidth4 = outwidth*4;
1532 unsigned char *out;
1533 const unsigned char *inrow;
1534 unsigned char *resamplerow1;
1535 unsigned char *resamplerow2;
1536 out = (unsigned char *)outdata;
1537 fstep = (int) (inheight*65536.0f/outheight);
1538
1539 resamplerow1 = (unsigned char *)Mem_Alloc(tempmempool, outwidth*4*2);
1540 resamplerow2 = resamplerow1 + outwidth*4;
1541
1542 inrow = (const unsigned char *)indata;
1543 oldy = 0;
1544 Image_Resample32LerpLine (inrow, resamplerow1, inwidth, outwidth);
1545 Image_Resample32LerpLine (inrow + inwidth4, resamplerow2, inwidth, outwidth);
1546 for (i = 0, f = 0;i < outheight;i++,f += fstep)
1547 {
1548 yi = f >> 16;
1549 if (yi < endy)
1550 {
1551 lerp = f & 0xFFFF;
1552 if (yi != oldy)
1553 {
1554 inrow = (unsigned char *)indata + inwidth4*yi;
1555 if (yi == oldy+1)
1556 memcpy(resamplerow1, resamplerow2, outwidth4);
1557 else
1558 Image_Resample32LerpLine (inrow, resamplerow1, inwidth, outwidth);
1559 Image_Resample32LerpLine (inrow + inwidth4, resamplerow2, inwidth, outwidth);
1560 oldy = yi;
1561 }
1562 j = outwidth - 4;
1563 while(j >= 0)
1564 {
1565 LERPBYTE( 0);
1566 LERPBYTE( 1);
1567 LERPBYTE( 2);
1568 LERPBYTE( 3);
1569 LERPBYTE( 4);
1570 LERPBYTE( 5);
1571 LERPBYTE( 6);
1572 LERPBYTE( 7);
1573 LERPBYTE( 8);
1574 LERPBYTE( 9);
1575 LERPBYTE(10);
1576 LERPBYTE(11);
1577 LERPBYTE(12);
1578 LERPBYTE(13);
1579 LERPBYTE(14);
1580 LERPBYTE(15);
1581 out += 16;
1582 resamplerow1 += 16;
1583 resamplerow2 += 16;
1584 j -= 4;
1585 }
1586 if (j & 2)
1587 {
1588 LERPBYTE( 0);
1589 LERPBYTE( 1);
1590 LERPBYTE( 2);
1591 LERPBYTE( 3);
1592 LERPBYTE( 4);
1593 LERPBYTE( 5);
1594 LERPBYTE( 6);
1595 LERPBYTE( 7);
1596 out += 8;
1597 resamplerow1 += 8;
1598 resamplerow2 += 8;
1599 }
1600 if (j & 1)
1601 {
1602 LERPBYTE( 0);
1603 LERPBYTE( 1);
1604 LERPBYTE( 2);
1605 LERPBYTE( 3);
1606 out += 4;
1607 resamplerow1 += 4;
1608 resamplerow2 += 4;
1609 }
1610 resamplerow1 -= outwidth4;
1611 resamplerow2 -= outwidth4;
1612 }
1613 else
1614 {
1615 if (yi != oldy)
1616 {
1617 inrow = (unsigned char *)indata + inwidth4*yi;
1618 if (yi == oldy+1)
1619 memcpy(resamplerow1, resamplerow2, outwidth4);
1620 else
1621 Image_Resample32LerpLine (inrow, resamplerow1, inwidth, outwidth);
1622 oldy = yi;
1623 }
1624 memcpy(out, resamplerow1, outwidth4);
1625 }
1626 }
1627
1628 Mem_Free(resamplerow1);
1629 resamplerow1 = NULL;
1630 resamplerow2 = NULL;
1631}
1632
1633static void Image_Resample32Nolerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
1634{
1635 int i, j;
1636 unsigned frac, fracstep;
1637 // relies on int being 4 bytes
1638 int *inrow, *out;
1639 out = (int *)outdata;
1640
1641 fracstep = inwidth*0x10000/outwidth;
1642 for (i = 0;i < outheight;i++)
1643 {
1644 inrow = (int *)indata + inwidth*(i*inheight/outheight);
1645 frac = fracstep >> 1;
1646 j = outwidth - 4;
1647 while (j >= 0)
1648 {
1649 out[0] = inrow[frac >> 16];frac += fracstep;
1650 out[1] = inrow[frac >> 16];frac += fracstep;
1651 out[2] = inrow[frac >> 16];frac += fracstep;
1652 out[3] = inrow[frac >> 16];frac += fracstep;
1653 out += 4;
1654 j -= 4;
1655 }
1656 if (j & 2)
1657 {
1658 out[0] = inrow[frac >> 16];frac += fracstep;
1659 out[1] = inrow[frac >> 16];frac += fracstep;
1660 out += 2;
1661 }
1662 if (j & 1)
1663 {
1664 out[0] = inrow[frac >> 16];frac += fracstep;
1665 out += 1;
1666 }
1667 }
1668}
1669
1670/*
1671================
1672Image_Resample
1673================
1674*/
1675void Image_Resample32(const void *indata, int inwidth, int inheight, int indepth, void *outdata, int outwidth, int outheight, int outdepth, int quality)
1676{
1677 if (indepth != 1 || outdepth != 1)
1678 {
1679 Con_Printf ("Image_Resample: 3D resampling not supported\n");
1680 return;
1681 }
1682 if (quality)
1683 Image_Resample32Lerp(indata, inwidth, inheight, outdata, outwidth, outheight);
1684 else
1685 Image_Resample32Nolerp(indata, inwidth, inheight, outdata, outwidth, outheight);
1686}
1687
1688// in can be the same as out
1689void Image_MipReduce32(const unsigned char *in, unsigned char *out, int *width, int *height, int *depth, int destwidth, int destheight, int destdepth)
1690{
1691 const unsigned char *inrow;
1692 int x, y, nextrow;
1693 if (*depth != 1 || destdepth != 1)
1694 {
1695 Con_Printf ("Image_Resample: 3D resampling not supported\n");
1696 if (*width > destwidth)
1697 *width >>= 1;
1698 if (*height > destheight)
1699 *height >>= 1;
1700 if (*depth > destdepth)
1701 *depth >>= 1;
1702 return;
1703 }
1704 // note: if given odd width/height this discards the last row/column of
1705 // pixels, rather than doing a proper box-filter scale down
1706 inrow = in;
1707 nextrow = *width * 4;
1708 if (*width > destwidth)
1709 {
1710 *width >>= 1;
1711 if (*height > destheight)
1712 {
1713 // reduce both
1714 *height >>= 1;
1715 for (y = 0;y < *height;y++, inrow += nextrow * 2)
1716 {
1717 for (in = inrow, x = 0;x < *width;x++)
1718 {
1719 out[0] = (unsigned char) ((in[0] + in[4] + in[nextrow ] + in[nextrow+4]) >> 2);
1720 out[1] = (unsigned char) ((in[1] + in[5] + in[nextrow+1] + in[nextrow+5]) >> 2);
1721 out[2] = (unsigned char) ((in[2] + in[6] + in[nextrow+2] + in[nextrow+6]) >> 2);
1722 out[3] = (unsigned char) ((in[3] + in[7] + in[nextrow+3] + in[nextrow+7]) >> 2);
1723 out += 4;
1724 in += 8;
1725 }
1726 }
1727 }
1728 else
1729 {
1730 // reduce width
1731 for (y = 0;y < *height;y++, inrow += nextrow)
1732 {
1733 for (in = inrow, x = 0;x < *width;x++)
1734 {
1735 out[0] = (unsigned char) ((in[0] + in[4]) >> 1);
1736 out[1] = (unsigned char) ((in[1] + in[5]) >> 1);
1737 out[2] = (unsigned char) ((in[2] + in[6]) >> 1);
1738 out[3] = (unsigned char) ((in[3] + in[7]) >> 1);
1739 out += 4;
1740 in += 8;
1741 }
1742 }
1743 }
1744 }
1745 else
1746 {
1747 if (*height > destheight)
1748 {
1749 // reduce height
1750 *height >>= 1;
1751 for (y = 0;y < *height;y++, inrow += nextrow * 2)
1752 {
1753 for (in = inrow, x = 0;x < *width;x++)
1754 {
1755 out[0] = (unsigned char) ((in[0] + in[nextrow ]) >> 1);
1756 out[1] = (unsigned char) ((in[1] + in[nextrow+1]) >> 1);
1757 out[2] = (unsigned char) ((in[2] + in[nextrow+2]) >> 1);
1758 out[3] = (unsigned char) ((in[3] + in[nextrow+3]) >> 1);
1759 out += 4;
1760 in += 4;
1761 }
1762 }
1763 }
1764 else
1765 Con_Printf ("Image_MipReduce: desired size already achieved\n");
1766 }
1767}
1768
1769void Image_HeightmapToNormalmap_BGRA(const unsigned char *inpixels, unsigned char *outpixels, int width, int height, int clamp, float bumpscale)
1770{
1771 int x, y, x1, x2, y1, y2;
1772 const unsigned char *b, *row[3];
1773 int p[5];
1774 unsigned char *out;
1775 float ibumpscale, n[3];
1776 ibumpscale = (255.0f * 6.0f) / bumpscale;
1777 out = outpixels;
1778 for (y = 0, y1 = height-1;y < height;y1 = y, y++)
1779 {
1780 y2 = y + 1;if (y2 >= height) y2 = 0;
1781 row[0] = inpixels + (y1 * width) * 4;
1782 row[1] = inpixels + (y * width) * 4;
1783 row[2] = inpixels + (y2 * width) * 4;
1784 for (x = 0, x1 = width-1;x < width;x1 = x, x++)
1785 {
1786 x2 = x + 1;if (x2 >= width) x2 = 0;
1787 // left, right
1788 b = row[1] + x1 * 4;p[0] = (b[0] + b[1] + b[2]);
1789 b = row[1] + x2 * 4;p[1] = (b[0] + b[1] + b[2]);
1790 // above, below
1791 b = row[0] + x * 4;p[2] = (b[0] + b[1] + b[2]);
1792 b = row[2] + x * 4;p[3] = (b[0] + b[1] + b[2]);
1793 // center
1794 b = row[1] + x * 4;p[4] = (b[0] + b[1] + b[2]);
1795 // calculate a normal from the slopes
1796 n[0] = p[0] - p[1];
1797 n[1] = p[3] - p[2];
1798 n[2] = ibumpscale;
1800 // turn it into a dot3 rgb vector texture
1801 out[2] = (int)(128.0f + n[0] * 127.0f);
1802 out[1] = (int)(128.0f + n[1] * 127.0f);
1803 out[0] = (int)(128.0f + n[2] * 127.0f);
1804 out[3] = (p[4]) / 3;
1805 out += 4;
1806 }
1807 }
1808}
1809
1810
1811#include "lhfont.h"
1812
1813static unsigned char *Image_GenerateConChars(void)
1814{
1815 int i;
1816 unsigned char *data;
1817 double random;
1818
1819 image_width = 256;
1820 image_height = 256;
1821
1823 // Gold numbers
1824 for (i = 0; i < 8192; i++)
1825 {
1826 random = lhrandom(0.0, 1.0);
1827 data[i * 4 + 3] = data[i * 4 + 0];
1828 data[i * 4 + 2] = 83 + (unsigned char)(random * 64);
1829 data[i * 4 + 1] = 71 + (unsigned char)(random * 32);
1830 data[i * 4 + 0] = 23 + (unsigned char)(random * 16);
1831 }
1832 // White chars
1833 for (i = 8192; i < 32768; i++)
1834 {
1835 random = lhrandom(0.0, 1.0);
1836 data[i * 4 + 3] = data[i * 4 + 0];
1837 data[i * 4 + 2] = 95 + (unsigned char)(random * 64);
1838 data[i * 4 + 1] = 95 + (unsigned char)(random * 64);
1839 data[i * 4 + 0] = 95 + (unsigned char)(random * 64);
1840 }
1841 // Gold numbers
1842 for (i = 32768; i < 40960; i++)
1843 {
1844 random = lhrandom(0.0, 1.0);
1845 data[i * 4 + 3] = data[i * 4 + 0];
1846 data[i * 4 + 2] = 83 + (unsigned char)(random * 64);
1847 data[i * 4 + 1] = 71 + (unsigned char)(random * 32);
1848 data[i * 4 + 0] = 23 + (unsigned char)(random * 16);
1849 }
1850 // Red chars
1851 for (i = 40960; i < 65536; i++)
1852 {
1853 random = lhrandom(0.0, 1.0);
1854 data[i * 4 + 3] = data[i * 4 + 0];
1855 data[i * 4 + 2] = 96 + (unsigned char)(random * 64);
1856 data[i * 4 + 1] = 43 + (unsigned char)(random * 32);
1857 data[i * 4 + 0] = 27 + (unsigned char)(random * 32);
1858 }
1859
1860#if 0
1861 Image_WriteTGABGRA("gfx/generated_conchars.tga", 256, 256, data);
1862#endif
1863
1864 return data;
1865}
1866
1867static unsigned char *Image_GenerateDitherPattern(void)
1868{
1869 int x, y;
1870 unsigned char *data = (unsigned char *)Mem_Alloc(tempmempool, 8 * 8 * 4);
1871 image_width = 8;
1872 image_height = 8;
1873 for (y = 0; y < 8; y++)
1874 {
1875 for (x = 0; x < 8; x++)
1876 {
1877 data[(y * 8 + x) * 4 + 0] = ((x^y) & 4) ? 255 : 0;
1878 data[(y * 8 + x) * 4 + 1] = ((x^y) & 4) ? 255 : 0;
1879 data[(y * 8 + x) * 4 + 2] = ((x^y) & 4) ? 255 : 0;
1880 data[(y * 8 + x) * 4 + 3] = 255;
1881 }
1882 }
1883 return data;
1884}
1885
1886// also used in R_SkinFrame code
1887unsigned char *Image_GenerateNoTexture(void)
1888{
1889 int x, y;
1890 unsigned char *data = (unsigned char *)Mem_Alloc(tempmempool, 16 * 16 * 4);
1891 image_width = 16;
1892 image_height = 16;
1893 // this makes a light grey/dark grey checkerboard texture
1894 for (y = 0; y < 16; y++)
1895 {
1896 for (x = 0; x < 16; x++)
1897 {
1898 data[(y * 16 + x) * 4 + 0] =
1899 data[(y * 16 + x) * 4 + 1] =
1900 data[(y * 16 + x) * 4 + 2] = (y < 8) ^ (x < 8) ? 128 : 64;
1901 data[(y * 16 + x) * 4 + 3] = 255;
1902 }
1903 }
1904 return data;
1905}
1906
1907static unsigned char *Image_GenerateWhite(void)
1908{
1909 unsigned char *data = (unsigned char *)Mem_Alloc(tempmempool, 1 * 1 * 4);
1910 image_width = 1;
1911 image_height = 1;
1912 data[0] = data[1] = data[2] = data[3] = 255;
1913 return data;
1914}
1915
1916typedef struct embeddedpic_s
1917{
1918const char *name;
1921const char *pixels;
1922}
1924
1926{
1927 {
1928 "gfx/prydoncursor001", 16, 16,
1929 "477777774......."
1930 "77.....6........"
1931 "7.....6........."
1932 "7....6.........."
1933 "7.....6........."
1934 "7..6...6........"
1935 "7.6.6...6......."
1936 "76...6...6......"
1937 "4.....6.6......."
1938 ".......6........"
1939 "................"
1940 "................"
1941 "................"
1942 "................"
1943 "................"
1944 "................"
1945 },
1946 {
1947 "ui/mousepointer", 16, 16,
1948 "477777774......."
1949 "77.....6........"
1950 "7.....6........."
1951 "7....6.........."
1952 "7.....6........."
1953 "7..6...6........"
1954 "7.6.6...6......."
1955 "76...6...6......"
1956 "4.....6.6......."
1957 ".......6........"
1958 "................"
1959 "................"
1960 "................"
1961 "................"
1962 "................"
1963 "................"
1964 },
1965 {
1966 "gfx/crosshair1", 16, 16,
1967 "................"
1968 "................"
1969 "................"
1970 "...33......33..."
1971 "...355....553..."
1972 "....577..775...."
1973 ".....77..77....."
1974 "................"
1975 "................"
1976 ".....77..77....."
1977 "....577..775...."
1978 "...355....553..."
1979 "...33......33..."
1980 "................"
1981 "................"
1982 "................"
1983 },
1984 {
1985 "gfx/crosshair2", 16, 16,
1986 "................"
1987 "................"
1988 "................"
1989 "...3........3..."
1990 "....5......5...."
1991 ".....7....7....."
1992 "......7..7......"
1993 "................"
1994 "................"
1995 "......7..7......"
1996 ".....7....7....."
1997 "....5......5...."
1998 "...3........3..."
1999 "................"
2000 "................"
2001 "................"
2002 },
2003 {
2004 "gfx/crosshair3", 16, 16,
2005 "................"
2006 ".......77......."
2007 ".......77......."
2008 "................"
2009 "................"
2010 ".......44......."
2011 ".......44......."
2012 ".77..44..44..77."
2013 ".77..44..44..77."
2014 ".......44......."
2015 ".......44......."
2016 "................"
2017 "................"
2018 ".......77......."
2019 ".......77......."
2020 "................"
2021 },
2022 {
2023 "gfx/crosshair4", 16, 16,
2024 "................"
2025 "................"
2026 "................"
2027 "................"
2028 "................"
2029 "................"
2030 "................"
2031 "................"
2032 "........7777777."
2033 "........752....."
2034 "........72......"
2035 "........7......."
2036 "........7......."
2037 "........7......."
2038 "........7......."
2039 "................"
2040 },
2041 {
2042 "gfx/crosshair5", 8, 8,
2043 "........"
2044 "........"
2045 "....7..."
2046 "........"
2047 "..7.7.7."
2048 "........"
2049 "....7..."
2050 "........"
2051 },
2052 {
2053 "gfx/crosshair6", 2, 2,
2054 "77"
2055 "77"
2056 },
2057 {
2058 "gfx/crosshair7", 16, 16,
2059 "................"
2060 ".3............3."
2061 "..5...2332...5.."
2062 "...7.3....3.7..."
2063 "....7......7...."
2064 "...3.7....7.3..."
2065 "..2...7..7...2.."
2066 "..3..........3.."
2067 "..3..........3.."
2068 "..2...7..7...2.."
2069 "...3.7....7.3..."
2070 "....7......7...."
2071 "...7.3....3.7..."
2072 "..5...2332...5.."
2073 ".3............3."
2074 "................"
2075 },
2076 { NULL, 0, 0, NULL }
2077};
2078
2079unsigned char *Image_GetEmbeddedPicBGRA(const char *name)
2080{
2081 const embeddedpic_t *p;
2082 for (p = embeddedpics; p->name; p++)
2083 {
2084 if (!strcmp(name, p->name))
2085 {
2086 int i;
2087 unsigned char *data = (unsigned char *)Mem_Alloc(tempmempool, p->width * p->height * 4);
2088 image_width = p->width;
2089 image_height = p->height;
2090 for (i = 0; i < p->width * p->height; i++)
2091 {
2092 const unsigned char *c = (const unsigned char *)palette_bgra_embeddedpic + 4 * p->pixels[i];
2093 Vector4Copy(c, data + 4 * i);
2094 }
2095 return data;
2096 }
2097 }
2098 if (!strcmp(name, "white") || !strcmp(name, "#white") || !strcmp(name, "*white") || !strcmp(name, "$whiteimage"))
2099 return Image_GenerateWhite();
2100 if (!strcmp(name, "gfx/conchars"))
2101 return Image_GenerateConChars();
2102 if (!strcmp(name, "gfx/colorcontrol/ditherpattern"))
2104 return NULL;
2105}
#define MIPLEVELS
Definition bspfile.h:95
cvar_t r_fixtrans_auto
Definition cl_cmd.c:42
static vec3_t offsets[NUMOFFSETS]
Definition cl_input.c:838
void CL_KeepaliveMessage(qbool readmessages)
Definition cl_parse.c:314
static int Cmd_Argc(cmd_state_t *cmd)
Definition cmd.h:249
static const char * Cmd_Argv(cmd_state_t *cmd, int arg)
Cmd_Argv(cmd, ) will return an empty string (not a NULL) if arg > argc, so string operations are alwa...
Definition cmd.h:254
gamemode_t gamemode
Definition com_game.c:26
@ GAME_TENEBRAE
full of evil hackery
Definition com_game.h:41
@ GAME_DELUXEQUAKE
Definition com_game.h:45
char * va(char *buf, size_t buflen, const char *format,...)
Definition common.c:972
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
Definition common.c:997
#define LittleShort(l)
Definition common.h:90
#define LittleLong(l)
Definition common.h:92
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
Definition console.c:1544
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
void Log_Printf(const char *logfilename, const char *fmt,...)
Definition console.c:655
#define CON_ERROR
Definition console.h:102
float flags
#define n(x, y)
const char * FS_FileExtension(const char *in)
Definition fs.c:1403
qbool FS_WriteFile(const char *filename, const void *data, fs_offset_t len)
Definition fs.c:3592
unsigned char * FS_LoadFile(const char *path, mempool_t *pool, qbool quiet, fs_offset_t *filesizepointer)
Definition fs.c:3540
void FS_FreeSearch(fssearch_t *search)
Definition fs.c:3963
fssearch_t * FS_Search(const char *pattern, int caseinsensitive, int quiet, const char *packfile)
Definition fs.c:3756
static int(ZEXPORT *qz_inflate)(z_stream *strm
void FS_StripExtension(const char *in, char *out, size_t size_out)
Definition fs.c:3611
void FS_SanitizePath(char *path)
Definition fs.c:2673
qbool FS_WriteFileInBlocks(const char *filename, const void *const *data, const fs_offset_t *len, size_t count)
Definition fs.c:3569
const char * FS_FileExists(const char *filename)
Look for a file in the packages and in the filesystem Returns its canonical name (same case as used i...
Definition fs.c:3693
int64_t fs_offset_t
Definition fs.h:37
cvar_t developer_texturelogging
Definition gl_rmain.c:231
int R_PicmipForFlags(int flags)
rtexture_t * R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette)
GLenum GLsizei width
Definition glquake.h:622
GLenum GLsizei GLsizei height
Definition glquake.h:622
GLubyte GLubyte GLubyte GLubyte w
Definition glquake.h:782
GLuint buffer
Definition glquake.h:630
GLint GLint GLint GLsizei GLsizei GLenum format
Definition glquake.h:649
GLint GLenum GLint GLint y
Definition glquake.h:651
GLint GLenum GLsizei GLsizei GLsizei depth
Definition glquake.h:648
const GLuint * buffers
Definition glquake.h:658
GLint GLenum GLint x
Definition glquake.h:651
GLsizeiptr const GLvoid * data
Definition glquake.h:639
GLint GLenum GLenum GLvoid * pixels
Definition glquake.h:706
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glquake.h:657
const GLchar * name
Definition glquake.h:601
GLuint index
Definition glquake.h:629
cvar_t developer_loading
Definition host.c:52
static unsigned char * Image_GetEmbeddedPicBGRA(const char *name)
Definition image.c:2079
void Image_MakeLinearColorsFromsRGB(unsigned char *pout, const unsigned char *pin, int numpixels)
Definition image.c:930
static unsigned char image_srgbfromlinear_lightmap[256]
Definition image.c:928
rtexture_t * loadtextureimage(rtexturepool_t *pool, const char *filename, qbool complain, int flags, qbool allowFixtrans, qbool sRGB)
Definition image.c:1245
imageformat_t imageformats_gfx[]
Definition image.c:1022
static void Image_Resample32Lerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
Definition image.c:1529
#define FIXTRANS_PIXEL_D
static unsigned char * LoadWAL_BGRA(const unsigned char *f, int filesize, int *miplevel)
Definition image.c:765
qbool Image_GetStockPicSize(const char *filename, int *returnwidth, int *returnheight)
Definition image.c:1196
unsigned char * Image_GenerateNoTexture(void)
Definition image.c:1887
static unsigned char * Image_GenerateWhite(void)
Definition image.c:1907
qbool LoadWAL_GetMetadata(const unsigned char *f, int filesize, int *retwidth, int *retheight, int *retflags, int *retvalue, int *retcontents, char *retanimname32c)
Definition image.c:800
int image_height
Definition image.c:10
static unsigned char image_linearfromsrgb[256]
Definition image.c:927
unsigned char * LoadTGA_BGRA(const unsigned char *f, int filesize, int *miplevel)
Definition image.c:401
void Image_FixTransparentPixels_f(cmd_state_t *cmd)
Definition image.c:1376
static void Image_CopyAlphaFromBlueBGRA(unsigned char *outpixels, const unsigned char *inpixels, int w, int h)
Definition image.c:14
void Image_Resample32(const void *indata, int inwidth, int inheight, int indepth, void *outdata, int outwidth, int outheight, int outdepth, int quality)
Definition image.c:1675
static unsigned char * Image_GenerateConChars(void)
Definition image.c:1813
cvar_t gl_picmip
Definition gl_textures.c:29
imageformat_t imageformats_other[]
Definition image.c:1032
static void PrintTargaHeader(TargaHeader *t)
Definition image.c:391
imageformat_t imageformats_textures[]
Definition image.c:1012
void Image_HeightmapToNormalmap_BGRA(const unsigned char *inpixels, unsigned char *outpixels, int width, int height, int clamp, float bumpscale)
Definition image.c:1769
#define FIXTRANS_PIXEL
static unsigned char * Image_GenerateDitherPattern(void)
Definition image.c:1867
void Image_Copy8bitBGRA(const unsigned char *in, unsigned char *out, int pixels, const unsigned int *pal)
Definition image.c:129
void Image_MipReduce32(const unsigned char *in, unsigned char *out, int *width, int *height, int *depth, int destwidth, int destheight, int destdepth)
Definition image.c:1689
static unsigned char * LoadConChars_BGRA(const unsigned char *f, int filesize, int *miplevel)
Definition image.c:881
#define FIXTRANS_PIXEL_L
#define FIXTRANS_PIXEL_R
qbool Image_WriteTGABGR_preflipped(const char *filename, int width, int height, const unsigned char *data)
Definition image.c:1412
qbool LoadPCX_PaletteOnly(const unsigned char *f, int filesize, unsigned char *palette768b)
Definition image.c:365
void Image_MakesRGBColorsFromLinear_Lightmap(unsigned char *pout, const unsigned char *pin, int numpixels)
Definition image.c:946
imageformat_t imageformats_nopath[]
Definition image.c:983
static const embeddedpic_t embeddedpics[]
Definition image.c:1925
void Image_CopyMux(unsigned char *outpixels, const unsigned char *inpixels, int inputwidth, int inputheight, qbool inputflipx, qbool inputflipy, qbool inputflipdiagonal, int numoutputcomponents, int numinputcomponents, int *outputinputcomponentindices)
Definition image.c:24
imageformat_t imageformats_dq[]
Definition image.c:1003
qbool Image_WriteTGABGRA(const char *filename, int width, int height, const unsigned char *data)
Definition image.c:1436
imageformat_t imageformats_tenebrae[]
Definition image.c:970
unsigned char * loadimagepixelsbgra(const char *filename, qbool complain, qbool allowFixtrans, qbool convertsRGB, int *miplevel)
Definition image.c:1043
#define FIXTRANS_PIXEL_U
static void Image_Resample32LerpLine(const unsigned char *in, unsigned char *out, int inwidth, int outwidth)
Definition image.c:1497
qbool LoadPCX_QWSkin(const unsigned char *f, int filesize, unsigned char *pixels, int outwidth, int outheight)
Definition image.c:286
#define LERPBYTE(i)
Definition image.c:1528
int image_width
Definition image.c:9
static void Image_Resample32Nolerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
Definition image.c:1633
void Image_GammaRemapRGB(const unsigned char *in, unsigned char *out, int pixels, const unsigned char *gammar, const unsigned char *gammag, const unsigned char *gammab)
Definition image.c:116
void Image_StripImageExtension(const char *in, char *out, size_t size_out)
Definition image.c:913
int fixtransparentpixels(unsigned char *data, int w, int h)
Definition image.c:1257
static unsigned char * LoadPCX_BGRA(const unsigned char *f, int filesize, int *miplevel)
Definition image.c:195
static unsigned char * LoadLMP_BGRA(const unsigned char *f, int filesize, int *miplevel)
Definition image.c:841
#define Image_LinearFloatFromsRGB(c)
Definition image.h:69
#define Image_sRGBFloatFromLinear_Lightmap(c)
Definition image.h:71
unsigned char * PNG_LoadImage_BGRA(const unsigned char *raw, int filesize, int *miplevel)
Definition image_png.c:294
unsigned char * JPEG_LoadImage_BGRA(const unsigned char *f, int filesize, int *miplevel)
Definition jpeg.c:606
static const unsigned char concharimage[]
Definition lhfont.h:1
#define VectorNormalize(v)
Definition mathlib.h:104
#define bound(min, num, max)
Definition mathlib.h:34
#define lhrandom(MIN, MAX)
LadyHavoc: this function never returns exactly MIN or exactly MAX, because of a QuakeC bug in id1 whe...
Definition mathlib.h:48
#define Vector4Copy(in, out)
Definition mathlib.h:84
float random(void)
void cmd(string command,...)
float floor(float f)
unsigned int palette_bgra_transparent[256]
Definition palette.c:24
unsigned int palette_bgra_font[256]
Definition palette.c:14
unsigned int q2palette_bgra_complete[256]
Definition palette.c:28
unsigned int palette_bgra_embeddedpic[256]
Definition palette.c:25
int i
#define MAX_QPATH
max length of a quake game pathname
Definition qdefs.h:169
#define NULL
Definition qtypes.h:12
bool qbool
Definition qtypes.h:9
@ TEXTYPE_SRGB_BGRA
Definition r_textures.h:73
@ TEXTYPE_BGRA
Definition r_textures.h:53
dp_FragColor r
return ret
dp_FragColor g
float f
vec3 y2
vec3 x2
dp_FragColor b
vec3 x1
ret a
unsigned char attributes
Definition image.c:387
unsigned char colormap_size
Definition image.c:385
unsigned short width
Definition image.c:386
unsigned short height
Definition image.c:386
unsigned short x_origin
Definition image.c:386
unsigned char pixel_size
Definition image.c:387
unsigned char colormap_type
Definition image.c:383
unsigned short colormap_length
Definition image.c:384
unsigned short colormap_index
Definition image.c:384
unsigned char image_type
Definition image.c:383
unsigned char id_length
Definition image.c:383
unsigned short y_origin
Definition image.c:386
command interpreter state - the tokenizing and execution of commands, as well as pointers to which cv...
Definition cmd.h:127
Definition cvar.h:66
int integer
Definition cvar.h:73
const char * pixels
Definition image.c:1921
const char * name
Definition image.c:1918
char ** filenames
Definition fs.h:117
int numfilenames
Definition fs.h:116
const char * formatstring
Definition image.c:964
Definition image.c:175
unsigned short palette_type
Definition image.c:186
unsigned short hres
Definition image.c:181
char reserved
Definition image.c:183
unsigned short ymax
Definition image.c:180
unsigned short bytes_per_line
Definition image.c:185
char color_planes
Definition image.c:184
unsigned short ymin
Definition image.c:180
unsigned short xmax
Definition image.c:180
unsigned short xmin
Definition image.c:180
char version
Definition image.c:177
char manufacturer
Definition image.c:176
char encoding
Definition image.c:178
char bits_per_pixel
Definition image.c:179
unsigned short vres
Definition image.c:181
int value
Definition image.c:762
int flags
Definition image.c:760
unsigned offsets[MIPLEVELS]
Definition image.c:758
unsigned width
Definition image.c:757
char animname[32]
Definition image.c:759
unsigned height
Definition image.c:757
int contents
Definition image.c:761
unsigned char * W_GetLumpName(const char *name, fs_offset_t *returnfilesize)
Definition wad.c:114
mempool_t * tempmempool
Definition zone.c:794
#define Mem_Free(mem)
Definition zone.h:96
#define Mem_Alloc(pool, size)
Definition zone.h:92