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{
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
983// GAME_DELUXEQUAKE only
984// VorteX: the point why i use such messy texture paths is
985// that GtkRadiant can't detect normal/gloss textures
986// and exclude them from texture browser
987// so i just use additional folder to store this textures
989{
990 {"%s.tga", LoadTGA_BGRA},
991 {"%s.jpg", JPEG_LoadImage_BGRA},
992 {"texturemaps/%s.tga", LoadTGA_BGRA},
993 {"texturemaps/%s.jpg", JPEG_LoadImage_BGRA},
994 {NULL, NULL}
995};
996
998{
999 {"%s.tga", LoadTGA_BGRA},
1000 {"%s.png", PNG_LoadImage_BGRA},
1001 {"%s.jpg", JPEG_LoadImage_BGRA},
1002 {"%s.pcx", LoadPCX_BGRA},
1003 {"%s.wal", LoadWAL_BGRA},
1004 {NULL, NULL}
1005};
1006
1008{
1009 {"%s.tga", LoadTGA_BGRA},
1010 {"%s.png", PNG_LoadImage_BGRA},
1011 {"%s.jpg", JPEG_LoadImage_BGRA},
1012 {"%s.pcx", LoadPCX_BGRA},
1013 {"%s.lmp", LoadLMP_BGRA},
1014 {NULL, NULL}
1015};
1016
1018{
1019 {"override/%s.tga", LoadTGA_BGRA},
1020 {"override/%s.png", PNG_LoadImage_BGRA},
1021 {"override/%s.jpg", JPEG_LoadImage_BGRA},
1022 {"textures/%s.tga", LoadTGA_BGRA},
1023 {"textures/%s.png", PNG_LoadImage_BGRA},
1024 {"textures/%s.jpg", JPEG_LoadImage_BGRA},
1025 {"%s.tga", LoadTGA_BGRA},
1026 {"%s.png", PNG_LoadImage_BGRA},
1027 {"%s.jpg", JPEG_LoadImage_BGRA},
1028 {"%s.pcx", LoadPCX_BGRA},
1029 {"%s.lmp", LoadLMP_BGRA},
1030 {NULL, NULL}
1031};
1032
1033int fixtransparentpixels(unsigned char *data, int w, int h);
1034unsigned char *loadimagepixelsbgra (const char *filename, qbool complain, qbool allowFixtrans, qbool convertsRGB, int *miplevel)
1035{
1036 fs_offset_t filesize;
1037 imageformat_t *firstformat, *format;
1038 int mymiplevel;
1039 unsigned char *f, *data = NULL, *data2 = NULL;
1040 char basename[MAX_QPATH], name[MAX_QPATH], name2[MAX_QPATH], path[MAX_QPATH], afterpath[MAX_QPATH], *c;
1041 char vabuf[1024];
1042 //if (developer_memorydebug.integer)
1043 // Mem_CheckSentinelsGlobal();
1044 if (developer_texturelogging.integer)
1045 Log_Printf("textures.log", "%s\n", filename);
1046 Image_StripImageExtension(filename, basename, sizeof(basename)); // strip filename extensions to allow replacement by other types
1047 // replace *'s with #, so commandline utils don't get confused when dealing with the external files
1048 for (c = basename;*c;c++)
1049 if (*c == '*')
1050 *c = '#';
1051 path[0] = 0;
1052 name[0] = 0;
1053 dp_strlcpy(afterpath, basename, sizeof(afterpath));
1054 if (strchr(basename, '/'))
1055 {
1056 int i;
1057 for (i = 0;i < (int)sizeof(path)-1 && basename[i] != '/' && basename[i];i++)
1058 path[i] = basename[i];
1059 path[i] = 0;
1060 dp_strlcpy(afterpath, basename + i + 1, sizeof(afterpath));
1061 }
1062 if (gamemode == GAME_TENEBRAE)
1063 firstformat = imageformats_tenebrae;
1064 else if (gamemode == GAME_DELUXEQUAKE)
1065 firstformat = imageformats_dq;
1066 else if (!strcasecmp(path, "textures"))
1067 firstformat = imageformats_textures;
1068 else if (!strcasecmp(path, "gfx") || !strcasecmp(path, "locale")) // locale/ is used in GAME_BLOODOMNICIDE
1069 firstformat = imageformats_gfx;
1070 else
1071 firstformat = imageformats_other;
1072 // now try all the formats in the selected list
1073 for (format = firstformat;format->formatstring;format++)
1074 {
1075 dpsnprintf (name, sizeof(name), format->formatstring, basename);
1076
1078
1079 if(FS_FileExists(name) && (f = FS_LoadFile(name, tempmempool, true, &filesize)) != NULL)
1080 {
1081 mymiplevel = miplevel ? *miplevel : 0;
1082 image_width = 0;
1083 image_height = 0;
1084 data = format->loadfunc(f, (int)filesize, &mymiplevel);
1085 Mem_Free(f);
1086 if (data)
1087 {
1088 if(format->loadfunc == JPEG_LoadImage_BGRA) // jpeg can't do alpha, so let's simulate it by loading another jpeg
1089 {
1090 dpsnprintf (name2, sizeof(name2), format->formatstring, va(vabuf, sizeof(vabuf), "%s_alpha", basename));
1091 f = FS_LoadFile(name2, tempmempool, true, &filesize);
1092 if(f)
1093 {
1094 int mymiplevel2 = miplevel ? *miplevel : 0;
1095 int image_width_save = image_width;
1096 int image_height_save = image_height;
1097 data2 = format->loadfunc(f, (int)filesize, &mymiplevel2);
1098 if(data2 && mymiplevel == mymiplevel2 && image_width == image_width_save && image_height == image_height_save)
1100 else
1101 Con_Printf("loadimagepixelsrgba: corrupt or invalid alpha image %s_alpha\n", basename);
1102 image_width = image_width_save;
1103 image_height = image_height_save;
1104 if(data2)
1105 Mem_Free(data2);
1106 Mem_Free(f);
1107 }
1108 }
1109 if (developer_loading.integer)
1110 Con_DPrintf("loaded image %s (%dx%d)\n", name, image_width, image_height);
1111 if(miplevel)
1112 *miplevel = mymiplevel;
1113 //if (developer_memorydebug.integer)
1114 // Mem_CheckSentinelsGlobal();
1115 if(allowFixtrans && r_fixtrans_auto.integer)
1116 {
1118 if(n)
1119 {
1120 Con_Printf("- had to fix %s (%d pixels changed)\n", name, n);
1121 if(r_fixtrans_auto.integer >= 2)
1122 {
1123 char outfilename[MAX_QPATH], buf[MAX_QPATH];
1125 dpsnprintf(outfilename, sizeof(outfilename), "fixtrans/%s.tga", buf);
1127 Con_Printf("- %s written.\n", outfilename);
1128 }
1129 }
1130 }
1131 if (convertsRGB)
1133 return data;
1134 }
1135 else
1136 Con_DPrintf("Error loading image %s (file loaded but decode failed)\n", name);
1137 }
1138 }
1139 if (!strcasecmp(path, "gfx"))
1140 {
1141 unsigned char *lmpdata;
1142 if ((lmpdata = W_GetLumpName(afterpath, &filesize)))
1143 {
1144 if (developer_loading.integer)
1145 Con_Printf("loading gfx.wad lump \"%s\"\n", afterpath);
1146
1147 mymiplevel = miplevel ? *miplevel : 0;
1148 if (!strcmp(afterpath, "conchars"))
1149 {
1150 // conchars is a raw image and with color 0 as transparent instead of 255
1151 data = LoadConChars_BGRA(lmpdata, filesize, &mymiplevel);
1152 }
1153 else
1154 data = LoadLMP_BGRA(lmpdata, filesize, &mymiplevel);
1155 // no cleanup after looking up a wad lump - the whole gfx.wad is loaded at once
1156 if (data)
1157 return data;
1158 Con_DPrintf("Error loading image %s (file loaded but decode failed)\n", name);
1159 }
1160 }
1161
1162 // check if the image name exists as an embedded pic
1163 if ((data = Image_GetEmbeddedPicBGRA(basename)))
1164 return data;
1165
1166 if (complain)
1167 {
1168 Con_Printf(CON_ERROR "Couldn't load %s using ", filename);
1169 for (format = firstformat;format->formatstring;format++)
1170 {
1171 dpsnprintf (name, sizeof(name), format->formatstring, basename);
1172 Con_Printf(format == firstformat ? "\"%s\"" : (format[1].formatstring ? ", \"%s\"" : " or \"%s\".\n"), format->formatstring);
1173 }
1174 }
1175
1176 // texture loading can take a while, so make sure we're sending keepalives
1177 CL_KeepaliveMessage(false);
1178
1179 //if (developer_memorydebug.integer)
1180 // Mem_CheckSentinelsGlobal();
1181
1182 return NULL;
1183}
1184
1185qbool Image_GetStockPicSize(const char *filename, int *returnwidth, int *returnheight)
1186{
1187 unsigned char *data;
1188 fs_offset_t filesize;
1189 char lmppath[MAX_QPATH];
1190 if (!strcasecmp(filename, "gfx/conchars"))
1191 {
1192 *returnwidth = 128;
1193 *returnheight = 128;
1194 return true;
1195 }
1196
1197 dpsnprintf(lmppath, sizeof(lmppath), "%s.lmp", filename);
1198 data = FS_LoadFile(lmppath, tempmempool, true, &filesize);
1199 if (data)
1200 {
1201 if (filesize > 8)
1202 {
1203 int w = data[0] + data[1] * 0x100 + data[2] * 0x10000 + data[3] * 0x1000000;
1204 int h = data[4] + data[5] * 0x100 + data[6] * 0x10000 + data[7] * 0x1000000;
1205 if (w >= 1 && w <= 32768 && h >= 1 && h <= 32768)
1206 {
1207 *returnwidth = w;
1208 *returnheight = h;
1209 Mem_Free(data);
1210 return true;
1211 }
1212 }
1213 Mem_Free(data);
1214 }
1215 if (!strncasecmp(filename, "gfx/", 4))
1216 {
1217 data = W_GetLumpName(filename + 4, &filesize);
1218 if (data && filesize > 8)
1219 {
1220 int w = data[0] + data[1] * 0x100 + data[2] * 0x10000 + data[3] * 0x1000000;
1221 int h = data[4] + data[5] * 0x100 + data[6] * 0x10000 + data[7] * 0x1000000;
1222 if (w >= 1 && w <= 32768 && h >= 1 && h <= 32768)
1223 {
1224 *returnwidth = w;
1225 *returnheight = h;
1226 return true;
1227 }
1228 }
1229 }
1230 return false;
1231}
1232
1233extern cvar_t gl_picmip;
1234rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, qbool complain, int flags, qbool allowFixtrans, qbool sRGB)
1235{
1236 unsigned char *data;
1237 rtexture_t *rt;
1238 int miplevel = R_PicmipForFlags(flags);
1239 if (!(data = loadimagepixelsbgra (filename, complain, allowFixtrans, false, &miplevel)))
1240 return 0;
1241 rt = R_LoadTexture2D(pool, filename, image_width, image_height, data, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, flags, miplevel, NULL);
1242 Mem_Free(data);
1243 return rt;
1244}
1245
1246int fixtransparentpixels(unsigned char *data, int w, int h)
1247{
1248 int const FIXTRANS_NEEDED = 1;
1249 int const FIXTRANS_HAS_L = 2;
1250 int const FIXTRANS_HAS_R = 4;
1251 int const FIXTRANS_HAS_U = 8;
1252 int const FIXTRANS_HAS_D = 16;
1253 int const FIXTRANS_FIXED = 32;
1254 unsigned char *fixMask = (unsigned char *) Mem_Alloc(tempmempool, w * h);
1255 int fixPixels = 0;
1256 int changedPixels = 0;
1257 int x, y;
1258
1259#define FIXTRANS_PIXEL (y*w+x)
1260#define FIXTRANS_PIXEL_U (((y+h-1)%h)*w+x)
1261#define FIXTRANS_PIXEL_D (((y+1)%h)*w+x)
1262#define FIXTRANS_PIXEL_L (y*w+((x+w-1)%w))
1263#define FIXTRANS_PIXEL_R (y*w+((x+1)%w))
1264
1265 memset(fixMask, 0, w * h);
1266 for(y = 0; y < h; ++y)
1267 for(x = 0; x < w; ++x)
1268 {
1269 if(data[FIXTRANS_PIXEL * 4 + 3] == 0)
1270 {
1271 fixMask[FIXTRANS_PIXEL] |= FIXTRANS_NEEDED;
1272 ++fixPixels;
1273 }
1274 else
1275 {
1276 fixMask[FIXTRANS_PIXEL_D] |= FIXTRANS_HAS_U;
1277 fixMask[FIXTRANS_PIXEL_U] |= FIXTRANS_HAS_D;
1278 fixMask[FIXTRANS_PIXEL_R] |= FIXTRANS_HAS_L;
1279 fixMask[FIXTRANS_PIXEL_L] |= FIXTRANS_HAS_R;
1280 }
1281 }
1282 if(fixPixels == w * h)
1283 return 0; // sorry, can't do anything about this
1284 while(fixPixels)
1285 {
1286 for(y = 0; y < h; ++y)
1287 for(x = 0; x < w; ++x)
1288 if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_NEEDED)
1289 {
1290 unsigned int sumR = 0, sumG = 0, sumB = 0, sumA = 0, sumRA = 0, sumGA = 0, sumBA = 0, cnt = 0;
1291 unsigned char r, g, b, a, r0, g0, b0;
1292 if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_HAS_U)
1293 {
1294 r = data[FIXTRANS_PIXEL_U * 4 + 2];
1295 g = data[FIXTRANS_PIXEL_U * 4 + 1];
1296 b = data[FIXTRANS_PIXEL_U * 4 + 0];
1297 a = data[FIXTRANS_PIXEL_U * 4 + 3];
1298 sumR += r; sumG += g; sumB += b; sumA += a; sumRA += r*a; sumGA += g*a; sumBA += b*a; ++cnt;
1299 }
1300 if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_HAS_D)
1301 {
1302 r = data[FIXTRANS_PIXEL_D * 4 + 2];
1303 g = data[FIXTRANS_PIXEL_D * 4 + 1];
1304 b = data[FIXTRANS_PIXEL_D * 4 + 0];
1305 a = data[FIXTRANS_PIXEL_D * 4 + 3];
1306 sumR += r; sumG += g; sumB += b; sumA += a; sumRA += r*a; sumGA += g*a; sumBA += b*a; ++cnt;
1307 }
1308 if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_HAS_L)
1309 {
1310 r = data[FIXTRANS_PIXEL_L * 4 + 2];
1311 g = data[FIXTRANS_PIXEL_L * 4 + 1];
1312 b = data[FIXTRANS_PIXEL_L * 4 + 0];
1313 a = data[FIXTRANS_PIXEL_L * 4 + 3];
1314 sumR += r; sumG += g; sumB += b; sumA += a; sumRA += r*a; sumGA += g*a; sumBA += b*a; ++cnt;
1315 }
1316 if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_HAS_R)
1317 {
1318 r = data[FIXTRANS_PIXEL_R * 4 + 2];
1319 g = data[FIXTRANS_PIXEL_R * 4 + 1];
1320 b = data[FIXTRANS_PIXEL_R * 4 + 0];
1321 a = data[FIXTRANS_PIXEL_R * 4 + 3];
1322 sumR += r; sumG += g; sumB += b; sumA += a; sumRA += r*a; sumGA += g*a; sumBA += b*a; ++cnt;
1323 }
1324 if(!cnt)
1325 continue;
1326 r0 = data[FIXTRANS_PIXEL * 4 + 2];
1327 g0 = data[FIXTRANS_PIXEL * 4 + 1];
1328 b0 = data[FIXTRANS_PIXEL * 4 + 0];
1329 if(sumA)
1330 {
1331 // there is a surrounding non-alpha pixel
1332 r = (sumRA + sumA / 2) / sumA;
1333 g = (sumGA + sumA / 2) / sumA;
1334 b = (sumBA + sumA / 2) / sumA;
1335 }
1336 else
1337 {
1338 // need to use a "regular" average
1339 r = (sumR + cnt / 2) / cnt;
1340 g = (sumG + cnt / 2) / cnt;
1341 b = (sumB + cnt / 2) / cnt;
1342 }
1343 if(r != r0 || g != g0 || b != b0)
1344 ++changedPixels;
1345 data[FIXTRANS_PIXEL * 4 + 2] = r;
1346 data[FIXTRANS_PIXEL * 4 + 1] = g;
1347 data[FIXTRANS_PIXEL * 4 + 0] = b;
1348 fixMask[FIXTRANS_PIXEL] |= FIXTRANS_FIXED;
1349 }
1350 for(y = 0; y < h; ++y)
1351 for(x = 0; x < w; ++x)
1352 if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_FIXED)
1353 {
1354 fixMask[FIXTRANS_PIXEL] &= ~(FIXTRANS_NEEDED | FIXTRANS_FIXED);
1355 fixMask[FIXTRANS_PIXEL_D] |= FIXTRANS_HAS_U;
1356 fixMask[FIXTRANS_PIXEL_U] |= FIXTRANS_HAS_D;
1357 fixMask[FIXTRANS_PIXEL_R] |= FIXTRANS_HAS_L;
1358 fixMask[FIXTRANS_PIXEL_L] |= FIXTRANS_HAS_R;
1359 --fixPixels;
1360 }
1361 }
1362 return changedPixels;
1363}
1364
1366{
1367 const char *filename, *filename_pattern;
1368 fssearch_t *search;
1369 int i, n;
1370 char outfilename[MAX_QPATH], buf[MAX_QPATH];
1371 unsigned char *data;
1372 if(Cmd_Argc(cmd) != 2)
1373 {
1374 Con_Printf("Usage: %s imagefile\n", Cmd_Argv(cmd, 0));
1375 return;
1376 }
1377 filename_pattern = Cmd_Argv(cmd, 1);
1378 search = FS_Search(filename_pattern, true, true, NULL);
1379 if(!search)
1380 return;
1381 for(i = 0; i < search->numfilenames; ++i)
1382 {
1383 filename = search->filenames[i];
1384 Con_Printf("Processing %s... ", filename);
1385 Image_StripImageExtension(filename, buf, sizeof(buf));
1386 dpsnprintf(outfilename, sizeof(outfilename), "fixtrans/%s.tga", buf);
1387 if(!(data = loadimagepixelsbgra(filename, true, false, false, NULL)))
1388 return;
1390 {
1392 Con_Printf("%s written (%d pixels changed).\n", outfilename, n);
1393 }
1394 else
1395 Con_Printf("unchanged.\n");
1396 Mem_Free(data);
1397 }
1398 FS_FreeSearch(search);
1399}
1400
1401qbool Image_WriteTGABGR_preflipped (const char *filename, int width, int height, const unsigned char *data)
1402{
1403 qbool ret;
1404 unsigned char buffer[18];
1405 const void *buffers[2];
1406 fs_offset_t sizes[2];
1407
1408 memset (buffer, 0, 18);
1409 buffer[2] = 2; // uncompressed type
1410 buffer[12] = (width >> 0) & 0xFF;
1411 buffer[13] = (width >> 8) & 0xFF;
1412 buffer[14] = (height >> 0) & 0xFF;
1413 buffer[15] = (height >> 8) & 0xFF;
1414 buffer[16] = 24; // pixel size
1415
1416 buffers[0] = buffer;
1417 sizes[0] = 18;
1418 buffers[1] = data;
1419 sizes[1] = width*height*3;
1420 ret = FS_WriteFileInBlocks(filename, buffers, sizes, 2);
1421
1422 return ret;
1423}
1424
1425qbool Image_WriteTGABGRA (const char *filename, int width, int height, const unsigned char *data)
1426{
1427 int y;
1428 unsigned char *buffer, *out;
1429 const unsigned char *in, *end;
1430 qbool ret;
1431
1432 buffer = (unsigned char *)Mem_Alloc(tempmempool, width*height*4 + 18);
1433
1434 memset (buffer, 0, 18);
1435 buffer[2] = 2; // uncompressed type
1436 buffer[12] = (width >> 0) & 0xFF;
1437 buffer[13] = (width >> 8) & 0xFF;
1438 buffer[14] = (height >> 0) & 0xFF;
1439 buffer[15] = (height >> 8) & 0xFF;
1440
1441 for (y = 3;y < width*height*4;y += 4)
1442 if (data[y] < 255)
1443 break;
1444
1445 if (y < width*height*4)
1446 {
1447 // save the alpha channel
1448 buffer[16] = 32; // pixel size
1449 buffer[17] = 8; // 8 bits of alpha
1450
1451 // flip upside down
1452 out = buffer + 18;
1453 for (y = height - 1;y >= 0;y--)
1454 {
1455 memcpy(out, data + y * width * 4, width * 4);
1456 out += width*4;
1457 }
1458 }
1459 else
1460 {
1461 // save only the color channels
1462 buffer[16] = 24; // pixel size
1463 buffer[17] = 0; // 8 bits of alpha
1464
1465 // truncate bgra to bgr and flip upside down
1466 out = buffer + 18;
1467 for (y = height - 1;y >= 0;y--)
1468 {
1469 in = data + y * width * 4;
1470 end = in + width * 4;
1471 for (;in < end;in += 4)
1472 {
1473 *out++ = in[0];
1474 *out++ = in[1];
1475 *out++ = in[2];
1476 }
1477 }
1478 }
1479 ret = FS_WriteFile (filename, buffer, out - buffer);
1480
1482
1483 return ret;
1484}
1485
1486static void Image_Resample32LerpLine (const unsigned char *in, unsigned char *out, int inwidth, int outwidth)
1487{
1488 int j, xi, oldx = 0, f, fstep, endx, lerp;
1489 fstep = (int) (inwidth*65536.0f/outwidth);
1490 endx = (inwidth-1);
1491 for (j = 0,f = 0;j < outwidth;j++, f += fstep)
1492 {
1493 xi = f >> 16;
1494 if (xi != oldx)
1495 {
1496 in += (xi - oldx) * 4;
1497 oldx = xi;
1498 }
1499 if (xi < endx)
1500 {
1501 lerp = f & 0xFFFF;
1502 *out++ = (unsigned char) ((((in[4] - in[0]) * lerp) >> 16) + in[0]);
1503 *out++ = (unsigned char) ((((in[5] - in[1]) * lerp) >> 16) + in[1]);
1504 *out++ = (unsigned char) ((((in[6] - in[2]) * lerp) >> 16) + in[2]);
1505 *out++ = (unsigned char) ((((in[7] - in[3]) * lerp) >> 16) + in[3]);
1506 }
1507 else // last pixel of the line has no pixel to lerp to
1508 {
1509 *out++ = in[0];
1510 *out++ = in[1];
1511 *out++ = in[2];
1512 *out++ = in[3];
1513 }
1514 }
1515}
1516
1517#define LERPBYTE(i) r = resamplerow1[i];out[i] = (unsigned char) ((((resamplerow2[i] - r) * lerp) >> 16) + r)
1518static void Image_Resample32Lerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
1519{
1520 int i, j, r, yi, oldy, f, fstep, lerp, endy = (inheight-1), inwidth4 = inwidth*4, outwidth4 = outwidth*4;
1521 unsigned char *out;
1522 const unsigned char *inrow;
1523 unsigned char *resamplerow1;
1524 unsigned char *resamplerow2;
1525 out = (unsigned char *)outdata;
1526 fstep = (int) (inheight*65536.0f/outheight);
1527
1528 resamplerow1 = (unsigned char *)Mem_Alloc(tempmempool, outwidth*4*2);
1529 resamplerow2 = resamplerow1 + outwidth*4;
1530
1531 inrow = (const unsigned char *)indata;
1532 oldy = 0;
1533 Image_Resample32LerpLine (inrow, resamplerow1, inwidth, outwidth);
1534 Image_Resample32LerpLine (inrow + inwidth4, resamplerow2, inwidth, outwidth);
1535 for (i = 0, f = 0;i < outheight;i++,f += fstep)
1536 {
1537 yi = f >> 16;
1538 if (yi < endy)
1539 {
1540 lerp = f & 0xFFFF;
1541 if (yi != oldy)
1542 {
1543 inrow = (unsigned char *)indata + inwidth4*yi;
1544 if (yi == oldy+1)
1545 memcpy(resamplerow1, resamplerow2, outwidth4);
1546 else
1547 Image_Resample32LerpLine (inrow, resamplerow1, inwidth, outwidth);
1548 Image_Resample32LerpLine (inrow + inwidth4, resamplerow2, inwidth, outwidth);
1549 oldy = yi;
1550 }
1551 j = outwidth - 4;
1552 while(j >= 0)
1553 {
1554 LERPBYTE( 0);
1555 LERPBYTE( 1);
1556 LERPBYTE( 2);
1557 LERPBYTE( 3);
1558 LERPBYTE( 4);
1559 LERPBYTE( 5);
1560 LERPBYTE( 6);
1561 LERPBYTE( 7);
1562 LERPBYTE( 8);
1563 LERPBYTE( 9);
1564 LERPBYTE(10);
1565 LERPBYTE(11);
1566 LERPBYTE(12);
1567 LERPBYTE(13);
1568 LERPBYTE(14);
1569 LERPBYTE(15);
1570 out += 16;
1571 resamplerow1 += 16;
1572 resamplerow2 += 16;
1573 j -= 4;
1574 }
1575 if (j & 2)
1576 {
1577 LERPBYTE( 0);
1578 LERPBYTE( 1);
1579 LERPBYTE( 2);
1580 LERPBYTE( 3);
1581 LERPBYTE( 4);
1582 LERPBYTE( 5);
1583 LERPBYTE( 6);
1584 LERPBYTE( 7);
1585 out += 8;
1586 resamplerow1 += 8;
1587 resamplerow2 += 8;
1588 }
1589 if (j & 1)
1590 {
1591 LERPBYTE( 0);
1592 LERPBYTE( 1);
1593 LERPBYTE( 2);
1594 LERPBYTE( 3);
1595 out += 4;
1596 resamplerow1 += 4;
1597 resamplerow2 += 4;
1598 }
1599 resamplerow1 -= outwidth4;
1600 resamplerow2 -= outwidth4;
1601 }
1602 else
1603 {
1604 if (yi != oldy)
1605 {
1606 inrow = (unsigned char *)indata + inwidth4*yi;
1607 if (yi == oldy+1)
1608 memcpy(resamplerow1, resamplerow2, outwidth4);
1609 else
1610 Image_Resample32LerpLine (inrow, resamplerow1, inwidth, outwidth);
1611 oldy = yi;
1612 }
1613 memcpy(out, resamplerow1, outwidth4);
1614 }
1615 }
1616
1617 Mem_Free(resamplerow1);
1618 resamplerow1 = NULL;
1619 resamplerow2 = NULL;
1620}
1621
1622static void Image_Resample32Nolerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
1623{
1624 int i, j;
1625 unsigned frac, fracstep;
1626 // relies on int being 4 bytes
1627 int *inrow, *out;
1628 out = (int *)outdata;
1629
1630 fracstep = inwidth*0x10000/outwidth;
1631 for (i = 0;i < outheight;i++)
1632 {
1633 inrow = (int *)indata + inwidth*(i*inheight/outheight);
1634 frac = fracstep >> 1;
1635 j = outwidth - 4;
1636 while (j >= 0)
1637 {
1638 out[0] = inrow[frac >> 16];frac += fracstep;
1639 out[1] = inrow[frac >> 16];frac += fracstep;
1640 out[2] = inrow[frac >> 16];frac += fracstep;
1641 out[3] = inrow[frac >> 16];frac += fracstep;
1642 out += 4;
1643 j -= 4;
1644 }
1645 if (j & 2)
1646 {
1647 out[0] = inrow[frac >> 16];frac += fracstep;
1648 out[1] = inrow[frac >> 16];frac += fracstep;
1649 out += 2;
1650 }
1651 if (j & 1)
1652 {
1653 out[0] = inrow[frac >> 16];frac += fracstep;
1654 out += 1;
1655 }
1656 }
1657}
1658
1659/*
1660================
1661Image_Resample
1662================
1663*/
1664void Image_Resample32(const void *indata, int inwidth, int inheight, int indepth, void *outdata, int outwidth, int outheight, int outdepth, int quality)
1665{
1666 if (indepth != 1 || outdepth != 1)
1667 {
1668 Con_Printf ("Image_Resample: 3D resampling not supported\n");
1669 return;
1670 }
1671 if (quality)
1672 Image_Resample32Lerp(indata, inwidth, inheight, outdata, outwidth, outheight);
1673 else
1674 Image_Resample32Nolerp(indata, inwidth, inheight, outdata, outwidth, outheight);
1675}
1676
1677// in can be the same as out
1678void Image_MipReduce32(const unsigned char *in, unsigned char *out, int *width, int *height, int *depth, int destwidth, int destheight, int destdepth)
1679{
1680 const unsigned char *inrow;
1681 int x, y, nextrow;
1682 if (*depth != 1 || destdepth != 1)
1683 {
1684 Con_Printf ("Image_Resample: 3D resampling not supported\n");
1685 if (*width > destwidth)
1686 *width >>= 1;
1687 if (*height > destheight)
1688 *height >>= 1;
1689 if (*depth > destdepth)
1690 *depth >>= 1;
1691 return;
1692 }
1693 // note: if given odd width/height this discards the last row/column of
1694 // pixels, rather than doing a proper box-filter scale down
1695 inrow = in;
1696 nextrow = *width * 4;
1697 if (*width > destwidth)
1698 {
1699 *width >>= 1;
1700 if (*height > destheight)
1701 {
1702 // reduce both
1703 *height >>= 1;
1704 for (y = 0;y < *height;y++, inrow += nextrow * 2)
1705 {
1706 for (in = inrow, x = 0;x < *width;x++)
1707 {
1708 out[0] = (unsigned char) ((in[0] + in[4] + in[nextrow ] + in[nextrow+4]) >> 2);
1709 out[1] = (unsigned char) ((in[1] + in[5] + in[nextrow+1] + in[nextrow+5]) >> 2);
1710 out[2] = (unsigned char) ((in[2] + in[6] + in[nextrow+2] + in[nextrow+6]) >> 2);
1711 out[3] = (unsigned char) ((in[3] + in[7] + in[nextrow+3] + in[nextrow+7]) >> 2);
1712 out += 4;
1713 in += 8;
1714 }
1715 }
1716 }
1717 else
1718 {
1719 // reduce width
1720 for (y = 0;y < *height;y++, inrow += nextrow)
1721 {
1722 for (in = inrow, x = 0;x < *width;x++)
1723 {
1724 out[0] = (unsigned char) ((in[0] + in[4]) >> 1);
1725 out[1] = (unsigned char) ((in[1] + in[5]) >> 1);
1726 out[2] = (unsigned char) ((in[2] + in[6]) >> 1);
1727 out[3] = (unsigned char) ((in[3] + in[7]) >> 1);
1728 out += 4;
1729 in += 8;
1730 }
1731 }
1732 }
1733 }
1734 else
1735 {
1736 if (*height > destheight)
1737 {
1738 // reduce height
1739 *height >>= 1;
1740 for (y = 0;y < *height;y++, inrow += nextrow * 2)
1741 {
1742 for (in = inrow, x = 0;x < *width;x++)
1743 {
1744 out[0] = (unsigned char) ((in[0] + in[nextrow ]) >> 1);
1745 out[1] = (unsigned char) ((in[1] + in[nextrow+1]) >> 1);
1746 out[2] = (unsigned char) ((in[2] + in[nextrow+2]) >> 1);
1747 out[3] = (unsigned char) ((in[3] + in[nextrow+3]) >> 1);
1748 out += 4;
1749 in += 4;
1750 }
1751 }
1752 }
1753 else
1754 Con_Printf ("Image_MipReduce: desired size already achieved\n");
1755 }
1756}
1757
1758void Image_HeightmapToNormalmap_BGRA(const unsigned char *inpixels, unsigned char *outpixels, int width, int height, int clamp, float bumpscale)
1759{
1760 int x, y, x1, x2, y1, y2;
1761 const unsigned char *b, *row[3];
1762 int p[5];
1763 unsigned char *out;
1764 float ibumpscale, n[3];
1765 ibumpscale = (255.0f * 6.0f) / bumpscale;
1766 out = outpixels;
1767 for (y = 0, y1 = height-1;y < height;y1 = y, y++)
1768 {
1769 y2 = y + 1;if (y2 >= height) y2 = 0;
1770 row[0] = inpixels + (y1 * width) * 4;
1771 row[1] = inpixels + (y * width) * 4;
1772 row[2] = inpixels + (y2 * width) * 4;
1773 for (x = 0, x1 = width-1;x < width;x1 = x, x++)
1774 {
1775 x2 = x + 1;if (x2 >= width) x2 = 0;
1776 // left, right
1777 b = row[1] + x1 * 4;p[0] = (b[0] + b[1] + b[2]);
1778 b = row[1] + x2 * 4;p[1] = (b[0] + b[1] + b[2]);
1779 // above, below
1780 b = row[0] + x * 4;p[2] = (b[0] + b[1] + b[2]);
1781 b = row[2] + x * 4;p[3] = (b[0] + b[1] + b[2]);
1782 // center
1783 b = row[1] + x * 4;p[4] = (b[0] + b[1] + b[2]);
1784 // calculate a normal from the slopes
1785 n[0] = p[0] - p[1];
1786 n[1] = p[3] - p[2];
1787 n[2] = ibumpscale;
1789 // turn it into a dot3 rgb vector texture
1790 out[2] = (int)(128.0f + n[0] * 127.0f);
1791 out[1] = (int)(128.0f + n[1] * 127.0f);
1792 out[0] = (int)(128.0f + n[2] * 127.0f);
1793 out[3] = (p[4]) / 3;
1794 out += 4;
1795 }
1796 }
1797}
1798
1799
1800#include "lhfont.h"
1801
1802static unsigned char *Image_GenerateConChars(void)
1803{
1804 int i;
1805 unsigned char *data;
1806 double random;
1807
1808 image_width = 256;
1809 image_height = 256;
1810
1812 // Gold numbers
1813 for (i = 0; i < 8192; i++)
1814 {
1815 random = lhrandom(0.0, 1.0);
1816 data[i * 4 + 3] = data[i * 4 + 0];
1817 data[i * 4 + 2] = 83 + (unsigned char)(random * 64);
1818 data[i * 4 + 1] = 71 + (unsigned char)(random * 32);
1819 data[i * 4 + 0] = 23 + (unsigned char)(random * 16);
1820 }
1821 // White chars
1822 for (i = 8192; i < 32768; i++)
1823 {
1824 random = lhrandom(0.0, 1.0);
1825 data[i * 4 + 3] = data[i * 4 + 0];
1826 data[i * 4 + 2] = 95 + (unsigned char)(random * 64);
1827 data[i * 4 + 1] = 95 + (unsigned char)(random * 64);
1828 data[i * 4 + 0] = 95 + (unsigned char)(random * 64);
1829 }
1830 // Gold numbers
1831 for (i = 32768; i < 40960; i++)
1832 {
1833 random = lhrandom(0.0, 1.0);
1834 data[i * 4 + 3] = data[i * 4 + 0];
1835 data[i * 4 + 2] = 83 + (unsigned char)(random * 64);
1836 data[i * 4 + 1] = 71 + (unsigned char)(random * 32);
1837 data[i * 4 + 0] = 23 + (unsigned char)(random * 16);
1838 }
1839 // Red chars
1840 for (i = 40960; i < 65536; i++)
1841 {
1842 random = lhrandom(0.0, 1.0);
1843 data[i * 4 + 3] = data[i * 4 + 0];
1844 data[i * 4 + 2] = 96 + (unsigned char)(random * 64);
1845 data[i * 4 + 1] = 43 + (unsigned char)(random * 32);
1846 data[i * 4 + 0] = 27 + (unsigned char)(random * 32);
1847 }
1848
1849#if 0
1850 Image_WriteTGABGRA("gfx/generated_conchars.tga", 256, 256, data);
1851#endif
1852
1853 return data;
1854}
1855
1856static unsigned char *Image_GenerateDitherPattern(void)
1857{
1858 int x, y;
1859 unsigned char *data = (unsigned char *)Mem_Alloc(tempmempool, 8 * 8 * 4);
1860 image_width = 8;
1861 image_height = 8;
1862 for (y = 0; y < 8; y++)
1863 {
1864 for (x = 0; x < 8; x++)
1865 {
1866 data[(y * 8 + x) * 4 + 0] = ((x^y) & 4) ? 255 : 0;
1867 data[(y * 8 + x) * 4 + 1] = ((x^y) & 4) ? 255 : 0;
1868 data[(y * 8 + x) * 4 + 2] = ((x^y) & 4) ? 255 : 0;
1869 data[(y * 8 + x) * 4 + 3] = 255;
1870 }
1871 }
1872 return data;
1873}
1874
1875// also used in R_SkinFrame code
1876unsigned char *Image_GenerateNoTexture(void)
1877{
1878 int x, y;
1879 unsigned char *data = (unsigned char *)Mem_Alloc(tempmempool, 16 * 16 * 4);
1880 image_width = 16;
1881 image_height = 16;
1882 // this makes a light grey/dark grey checkerboard texture
1883 for (y = 0; y < 16; y++)
1884 {
1885 for (x = 0; x < 16; x++)
1886 {
1887 data[(y * 16 + x) * 4 + 0] =
1888 data[(y * 16 + x) * 4 + 1] =
1889 data[(y * 16 + x) * 4 + 2] = (y < 8) ^ (x < 8) ? 128 : 64;
1890 data[(y * 16 + x) * 4 + 3] = 255;
1891 }
1892 }
1893 return data;
1894}
1895
1896static unsigned char *Image_GenerateWhite(void)
1897{
1898 unsigned char *data = (unsigned char *)Mem_Alloc(tempmempool, 1 * 1 * 4);
1899 image_width = 1;
1900 image_height = 1;
1901 data[0] = data[1] = data[2] = data[3] = 255;
1902 return data;
1903}
1904
1905typedef struct embeddedpic_s
1906{
1907const char *name;
1910const char *pixels;
1911}
1913
1915{
1916 {
1917 "gfx/prydoncursor001", 16, 16,
1918 "477777774......."
1919 "77.....6........"
1920 "7.....6........."
1921 "7....6.........."
1922 "7.....6........."
1923 "7..6...6........"
1924 "7.6.6...6......."
1925 "76...6...6......"
1926 "4.....6.6......."
1927 ".......6........"
1928 "................"
1929 "................"
1930 "................"
1931 "................"
1932 "................"
1933 "................"
1934 },
1935 {
1936 "ui/mousepointer", 16, 16,
1937 "477777774......."
1938 "77.....6........"
1939 "7.....6........."
1940 "7....6.........."
1941 "7.....6........."
1942 "7..6...6........"
1943 "7.6.6...6......."
1944 "76...6...6......"
1945 "4.....6.6......."
1946 ".......6........"
1947 "................"
1948 "................"
1949 "................"
1950 "................"
1951 "................"
1952 "................"
1953 },
1954 {
1955 "gfx/crosshair1", 16, 16,
1956 "................"
1957 "................"
1958 "................"
1959 "...33......33..."
1960 "...355....553..."
1961 "....577..775...."
1962 ".....77..77....."
1963 "................"
1964 "................"
1965 ".....77..77....."
1966 "....577..775...."
1967 "...355....553..."
1968 "...33......33..."
1969 "................"
1970 "................"
1971 "................"
1972 },
1973 {
1974 "gfx/crosshair2", 16, 16,
1975 "................"
1976 "................"
1977 "................"
1978 "...3........3..."
1979 "....5......5...."
1980 ".....7....7....."
1981 "......7..7......"
1982 "................"
1983 "................"
1984 "......7..7......"
1985 ".....7....7....."
1986 "....5......5...."
1987 "...3........3..."
1988 "................"
1989 "................"
1990 "................"
1991 },
1992 {
1993 "gfx/crosshair3", 16, 16,
1994 "................"
1995 ".......77......."
1996 ".......77......."
1997 "................"
1998 "................"
1999 ".......44......."
2000 ".......44......."
2001 ".77..44..44..77."
2002 ".77..44..44..77."
2003 ".......44......."
2004 ".......44......."
2005 "................"
2006 "................"
2007 ".......77......."
2008 ".......77......."
2009 "................"
2010 },
2011 {
2012 "gfx/crosshair4", 16, 16,
2013 "................"
2014 "................"
2015 "................"
2016 "................"
2017 "................"
2018 "................"
2019 "................"
2020 "................"
2021 "........7777777."
2022 "........752....."
2023 "........72......"
2024 "........7......."
2025 "........7......."
2026 "........7......."
2027 "........7......."
2028 "................"
2029 },
2030 {
2031 "gfx/crosshair5", 8, 8,
2032 "........"
2033 "........"
2034 "....7..."
2035 "........"
2036 "..7.7.7."
2037 "........"
2038 "....7..."
2039 "........"
2040 },
2041 {
2042 "gfx/crosshair6", 2, 2,
2043 "77"
2044 "77"
2045 },
2046 {
2047 "gfx/crosshair7", 16, 16,
2048 "................"
2049 ".3............3."
2050 "..5...2332...5.."
2051 "...7.3....3.7..."
2052 "....7......7...."
2053 "...3.7....7.3..."
2054 "..2...7..7...2.."
2055 "..3..........3.."
2056 "..3..........3.."
2057 "..2...7..7...2.."
2058 "...3.7....7.3..."
2059 "....7......7...."
2060 "...7.3....3.7..."
2061 "..5...2332...5.."
2062 ".3............3."
2063 "................"
2064 },
2065 { NULL, 0, 0, NULL }
2066};
2067
2068unsigned char *Image_GetEmbeddedPicBGRA(const char *name)
2069{
2070 const embeddedpic_t *p;
2071 for (p = embeddedpics; p->name; p++)
2072 {
2073 if (!strcmp(name, p->name))
2074 {
2075 int i;
2076 unsigned char *data = (unsigned char *)Mem_Alloc(tempmempool, p->width * p->height * 4);
2077 image_width = p->width;
2078 image_height = p->height;
2079 for (i = 0; i < p->width * p->height; i++)
2080 {
2081 const unsigned char *c = (const unsigned char *)palette_bgra_embeddedpic + 4 * p->pixels[i];
2082 Vector4Copy(c, data + 4 * i);
2083 }
2084 return data;
2085 }
2086 }
2087 if (!strcmp(name, "white") || !strcmp(name, "#white") || !strcmp(name, "*white") || !strcmp(name, "$whiteimage"))
2088 return Image_GenerateWhite();
2089 if (!strcmp(name, "gfx/conchars"))
2090 return Image_GenerateConChars();
2091 if (!strcmp(name, "gfx/colorcontrol/ditherpattern"))
2093 return NULL;
2094}
#define MIPLEVELS
Definition bspfile.h:95
cvar_t r_fixtrans_auto
Definition cl_cmd.c:42
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:3593
unsigned char * FS_LoadFile(const char *path, mempool_t *pool, qbool quiet, fs_offset_t *filesizepointer)
Definition fs.c:3541
void FS_FreeSearch(fssearch_t *search)
Definition fs.c:3964
fssearch_t * FS_Search(const char *pattern, int caseinsensitive, int quiet, const char *packfile)
Definition fs.c:3757
static int(ZEXPORT *qz_inflate)(z_stream *strm
void FS_StripExtension(const char *in, char *out, size_t size_out)
Definition fs.c:3612
void FS_SanitizePath(char *path)
Definition fs.c:2674
qbool FS_WriteFileInBlocks(const char *filename, const void *const *data, const fs_offset_t *len, size_t count)
Definition fs.c:3570
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:3694
int64_t fs_offset_t
Definition fs.h:37
cvar_t gl_picmip
Definition gl_textures.c:29
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:2068
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:1234
imageformat_t imageformats_gfx[]
Definition image.c:1007
static void Image_Resample32Lerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
Definition image.c:1518
#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:1185
unsigned char * Image_GenerateNoTexture(void)
Definition image.c:1876
static unsigned char * Image_GenerateWhite(void)
Definition image.c:1896
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:1365
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:1664
static unsigned char * Image_GenerateConChars(void)
Definition image.c:1802
imageformat_t imageformats_other[]
Definition image.c:1017
static void PrintTargaHeader(TargaHeader *t)
Definition image.c:391
imageformat_t imageformats_textures[]
Definition image.c:997
void Image_HeightmapToNormalmap_BGRA(const unsigned char *inpixels, unsigned char *outpixels, int width, int height, int clamp, float bumpscale)
Definition image.c:1758
#define FIXTRANS_PIXEL
static unsigned char * Image_GenerateDitherPattern(void)
Definition image.c:1856
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:1678
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:1401
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
static const embeddedpic_t embeddedpics[]
Definition image.c:1914
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:988
qbool Image_WriteTGABGRA(const char *filename, int width, int height, const unsigned char *data)
Definition image.c:1425
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:1034
#define FIXTRANS_PIXEL_U
static void Image_Resample32LerpLine(const unsigned char *in, unsigned char *out, int inwidth, int outwidth)
Definition image.c:1486
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:1517
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:1622
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:1246
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
#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
const char * pixels
Definition image.c:1910
const char * name
Definition image.c:1907
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 filler[58]
Definition image.c:187
char manufacturer
Definition image.c:176
unsigned char palette[48]
Definition image.c:182
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
char name[32]
Definition image.c:756
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