1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "sys/platform.h"
30
31 #include "renderer/tr_local.h"
32
33 #include "renderer/Image.h"
34
35 #include <jpeglib.h>
36 #include <jerror.h>
37
38 /*
39
40 This file only has a single entry point:
41
42 void R_LoadImage( const char *name, byte **pic, int *width, int *height, bool makePowerOf2 );
43
44 */
45
46 /*
47 ================
48 R_WriteTGA
49 ================
50 */
R_WriteTGA(const char * filename,const byte * data,int width,int height,bool flipVertical)51 void R_WriteTGA( const char *filename, const byte *data, int width, int height, bool flipVertical ) {
52 byte *buffer;
53 int i;
54 int bufferSize = width*height*4 + 18;
55 int imgStart = 18;
56
57 buffer = (byte *)Mem_Alloc( bufferSize );
58 memset( buffer, 0, 18 );
59 buffer[2] = 2; // uncompressed type
60 buffer[12] = width&255;
61 buffer[13] = width>>8;
62 buffer[14] = height&255;
63 buffer[15] = height>>8;
64 buffer[16] = 32; // pixel size
65 if ( !flipVertical ) {
66 buffer[17] = (1<<5); // flip bit, for normal top to bottom raster order
67 }
68
69 // swap rgb to bgr
70 for ( i=imgStart ; i<bufferSize ; i+=4 ) {
71 buffer[i] = data[i-imgStart+2]; // blue
72 buffer[i+1] = data[i-imgStart+1]; // green
73 buffer[i+2] = data[i-imgStart+0]; // red
74 buffer[i+3] = data[i-imgStart+3]; // alpha
75 }
76
77 fileSystem->WriteFile( filename, buffer, bufferSize );
78
79 Mem_Free (buffer);
80 }
81
82
83 /*
84 ================
85 R_WritePalTGA
86 ================
87 */
R_WritePalTGA(const char * filename,const byte * data,const byte * palette,int width,int height,bool flipVertical)88 void R_WritePalTGA( const char *filename, const byte *data, const byte *palette, int width, int height, bool flipVertical ) {
89 byte *buffer;
90 int i;
91 int bufferSize = (width * height) + (256 * 3) + 18;
92 int palStart = 18;
93 int imgStart = 18 + (256 * 3);
94
95 buffer = (byte *)Mem_Alloc( bufferSize );
96 memset( buffer, 0, 18 );
97 buffer[1] = 1; // color map type
98 buffer[2] = 1; // uncompressed color mapped image
99 buffer[5] = 0; // number of palette entries (lo)
100 buffer[6] = 1; // number of palette entries (hi)
101 buffer[7] = 24; // color map bpp
102 buffer[12] = width&255;
103 buffer[13] = width>>8;
104 buffer[14] = height&255;
105 buffer[15] = height>>8;
106 buffer[16] = 8; // pixel size
107 if ( !flipVertical ) {
108 buffer[17] = (1<<5); // flip bit, for normal top to bottom raster order
109 }
110
111 // store palette, swapping rgb to bgr
112 for ( i=palStart ; i<imgStart ; i+=3 ) {
113 buffer[i] = palette[i-palStart+2]; // blue
114 buffer[i+1] = palette[i-palStart+1]; // green
115 buffer[i+2] = palette[i-palStart+0]; // red
116 }
117
118 // store the image data
119 for ( i=imgStart ; i<bufferSize ; i++ ) {
120 buffer[i] = data[i-imgStart];
121 }
122
123 fileSystem->WriteFile( filename, buffer, bufferSize );
124
125 Mem_Free (buffer);
126 }
127
128
129 static void LoadBMP( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp );
130 static void LoadTGA( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp );
131 static void LoadJPG( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp );
132
133
134 /*
135 ========================================================================
136
137 PCX files are used for 8 bit images
138
139 ========================================================================
140 */
141
142 typedef struct {
143 char manufacturer;
144 char version;
145 char encoding;
146 char bits_per_pixel;
147 unsigned short xmin,ymin,xmax,ymax;
148 unsigned short hres,vres;
149 unsigned char palette[48];
150 char reserved;
151 char color_planes;
152 unsigned short bytes_per_line;
153 unsigned short palette_type;
154 char filler[58];
155 unsigned char data; // unbounded
156 } pcx_t;
157
158
159 /*
160 ========================================================================
161
162 TGA files are used for 24/32 bit images
163
164 ========================================================================
165 */
166
167 typedef struct _TargaHeader {
168 unsigned char id_length, colormap_type, image_type;
169 unsigned short colormap_index, colormap_length;
170 unsigned char colormap_size;
171 unsigned short x_origin, y_origin, width, height;
172 unsigned char pixel_size, attributes;
173 } TargaHeader;
174
175
176
177 /*
178 =========================================================
179
180 BMP LOADING
181
182 =========================================================
183 */
184 typedef struct
185 {
186 char id[2];
187 unsigned int fileSize;
188 unsigned int reserved0;
189 unsigned int bitmapDataOffset;
190 unsigned int bitmapHeaderSize;
191 unsigned int width;
192 unsigned int height;
193 unsigned short planes;
194 unsigned short bitsPerPixel;
195 unsigned int compression;
196 unsigned int bitmapDataSize;
197 unsigned int hRes;
198 unsigned int vRes;
199 unsigned int colors;
200 unsigned int importantColors;
201 unsigned char palette[256][4];
202 } BMPHeader_t;
203
204 /*
205 ==============
206 LoadBMP
207 ==============
208 */
LoadBMP(const char * name,byte ** pic,int * width,int * height,ID_TIME_T * timestamp)209 static void LoadBMP( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp )
210 {
211 int columns, rows, numPixels;
212 byte *pixbuf;
213 int row, column;
214 byte *buf_p;
215 byte *buffer;
216 int length;
217 BMPHeader_t bmpHeader;
218 byte *bmpRGBA;
219
220 if ( !pic ) {
221 fileSystem->ReadFile ( name, NULL, timestamp );
222 return; // just getting timestamp
223 }
224
225 *pic = NULL;
226
227 //
228 // load the file
229 //
230 length = fileSystem->ReadFile( name, (void **)&buffer, timestamp );
231 if ( !buffer ) {
232 return;
233 }
234
235 buf_p = buffer;
236
237 bmpHeader.id[0] = *buf_p++;
238 bmpHeader.id[1] = *buf_p++;
239 bmpHeader.fileSize = LittleInt( * ( int * ) buf_p );
240 buf_p += 4;
241 bmpHeader.reserved0 = LittleInt( * ( int * ) buf_p );
242 buf_p += 4;
243 bmpHeader.bitmapDataOffset = LittleInt( * ( int * ) buf_p );
244 buf_p += 4;
245 bmpHeader.bitmapHeaderSize = LittleInt( * ( int * ) buf_p );
246 buf_p += 4;
247 bmpHeader.width = LittleInt( * ( int * ) buf_p );
248 buf_p += 4;
249 bmpHeader.height = LittleInt( * ( int * ) buf_p );
250 buf_p += 4;
251 bmpHeader.planes = LittleShort( * ( short * ) buf_p );
252 buf_p += 2;
253 bmpHeader.bitsPerPixel = LittleShort( * ( short * ) buf_p );
254 buf_p += 2;
255 bmpHeader.compression = LittleInt( * ( int * ) buf_p );
256 buf_p += 4;
257 bmpHeader.bitmapDataSize = LittleInt( * ( int * ) buf_p );
258 buf_p += 4;
259 bmpHeader.hRes = LittleInt( * ( int * ) buf_p );
260 buf_p += 4;
261 bmpHeader.vRes = LittleInt( * ( int * ) buf_p );
262 buf_p += 4;
263 bmpHeader.colors = LittleInt( * ( int * ) buf_p );
264 buf_p += 4;
265 bmpHeader.importantColors = LittleInt( * ( int * ) buf_p );
266 buf_p += 4;
267
268 memcpy( bmpHeader.palette, buf_p, sizeof( bmpHeader.palette ) );
269
270 if ( bmpHeader.bitsPerPixel == 8 )
271 buf_p += 1024;
272
273 if ( bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M' )
274 {
275 common->Error( "LoadBMP: only Windows-style BMP files supported (%s)\n", name );
276 }
277 if ( bmpHeader.fileSize != length )
278 {
279 common->Error( "LoadBMP: header size does not match file size (%u vs. %d) (%s)\n", bmpHeader.fileSize, length, name );
280 }
281 if ( bmpHeader.compression != 0 )
282 {
283 common->Error( "LoadBMP: only uncompressed BMP files supported (%s)\n", name );
284 }
285 if ( bmpHeader.bitsPerPixel < 8 )
286 {
287 common->Error( "LoadBMP: monochrome and 4-bit BMP files not supported (%s)\n", name );
288 }
289
290 columns = bmpHeader.width;
291 rows = bmpHeader.height;
292 if ( rows < 0 )
293 rows = -rows;
294 numPixels = columns * rows;
295
296 if ( width )
297 *width = columns;
298 if ( height )
299 *height = rows;
300
301 bmpRGBA = (byte *)R_StaticAlloc( numPixels * 4 );
302 *pic = bmpRGBA;
303
304
305 for ( row = rows-1; row >= 0; row-- )
306 {
307 pixbuf = bmpRGBA + row*columns*4;
308
309 for ( column = 0; column < columns; column++ )
310 {
311 unsigned char red, green, blue, alpha;
312 int palIndex;
313 unsigned short shortPixel;
314
315 switch ( bmpHeader.bitsPerPixel )
316 {
317 case 8:
318 palIndex = *buf_p++;
319 *pixbuf++ = bmpHeader.palette[palIndex][2];
320 *pixbuf++ = bmpHeader.palette[palIndex][1];
321 *pixbuf++ = bmpHeader.palette[palIndex][0];
322 *pixbuf++ = 0xff;
323 break;
324 case 16:
325 shortPixel = * ( unsigned short * ) pixbuf;
326 pixbuf += 2;
327 *pixbuf++ = ( shortPixel & ( 31 << 10 ) ) >> 7;
328 *pixbuf++ = ( shortPixel & ( 31 << 5 ) ) >> 2;
329 *pixbuf++ = ( shortPixel & ( 31 ) ) << 3;
330 *pixbuf++ = 0xff;
331 break;
332
333 case 24:
334 blue = *buf_p++;
335 green = *buf_p++;
336 red = *buf_p++;
337 *pixbuf++ = red;
338 *pixbuf++ = green;
339 *pixbuf++ = blue;
340 *pixbuf++ = 255;
341 break;
342 case 32:
343 blue = *buf_p++;
344 green = *buf_p++;
345 red = *buf_p++;
346 alpha = *buf_p++;
347 *pixbuf++ = red;
348 *pixbuf++ = green;
349 *pixbuf++ = blue;
350 *pixbuf++ = alpha;
351 break;
352 default:
353 common->Error( "LoadBMP: illegal pixel_size '%d' in file '%s'\n", bmpHeader.bitsPerPixel, name );
354 break;
355 }
356 }
357 }
358
359 fileSystem->FreeFile( buffer );
360
361 }
362
363
364 /*
365 =================================================================
366
367 PCX LOADING
368
369 =================================================================
370 */
371
372
373 /*
374 ==============
375 LoadPCX
376 ==============
377 */
LoadPCX(const char * filename,byte ** pic,byte ** palette,int * width,int * height,ID_TIME_T * timestamp)378 static void LoadPCX ( const char *filename, byte **pic, byte **palette, int *width, int *height,
379 ID_TIME_T *timestamp ) {
380 byte *raw;
381 pcx_t *pcx;
382 int x, y;
383 int len;
384 int dataByte, runLength;
385 byte *out, *pix;
386 int xmax, ymax;
387
388 if ( !pic ) {
389 fileSystem->ReadFile( filename, NULL, timestamp );
390 return; // just getting timestamp
391 }
392
393 *pic = NULL;
394 *palette = NULL;
395
396 //
397 // load the file
398 //
399 len = fileSystem->ReadFile( filename, (void **)&raw, timestamp );
400 if (!raw) {
401 return;
402 }
403
404 //
405 // parse the PCX file
406 //
407 pcx = (pcx_t *)raw;
408 raw = &pcx->data;
409
410 xmax = LittleShort(pcx->xmax);
411 ymax = LittleShort(pcx->ymax);
412
413 if (pcx->manufacturer != 0x0a
414 || pcx->version != 5
415 || pcx->encoding != 1
416 || pcx->bits_per_pixel != 8
417 || xmax >= 1024
418 || ymax >= 1024)
419 {
420 common->Printf( "Bad pcx file %s (%i x %i) (%i x %i)\n", filename, xmax+1, ymax+1, pcx->xmax, pcx->ymax);
421 return;
422 }
423
424 out = (byte *)R_StaticAlloc( (ymax+1) * (xmax+1) );
425
426 *pic = out;
427
428 pix = out;
429
430 if (palette)
431 {
432 *palette = (byte *)R_StaticAlloc(768);
433 memcpy (*palette, (byte *)pcx + len - 768, 768);
434 }
435
436 if (width)
437 *width = xmax+1;
438 if (height)
439 *height = ymax+1;
440 // FIXME: use bytes_per_line here?
441
442 for (y=0 ; y<=ymax ; y++, pix += xmax+1)
443 {
444 for (x=0 ; x<=xmax ; )
445 {
446 dataByte = *raw++;
447
448 if((dataByte & 0xC0) == 0xC0)
449 {
450 runLength = dataByte & 0x3F;
451 dataByte = *raw++;
452 }
453 else
454 runLength = 1;
455
456 while(runLength-- > 0)
457 pix[x++] = dataByte;
458 }
459
460 }
461
462 if ( raw - (byte *)pcx > len)
463 {
464 common->Printf( "PCX file %s was malformed", filename );
465 R_StaticFree (*pic);
466 *pic = NULL;
467 }
468
469 fileSystem->FreeFile( pcx );
470 }
471
472
473 /*
474 ==============
475 LoadPCX32
476 ==============
477 */
LoadPCX32(const char * filename,byte ** pic,int * width,int * height,ID_TIME_T * timestamp)478 static void LoadPCX32 ( const char *filename, byte **pic, int *width, int *height, ID_TIME_T *timestamp) {
479 byte *palette;
480 byte *pic8;
481 int i, c, p;
482 byte *pic32;
483
484 if ( !pic ) {
485 fileSystem->ReadFile( filename, NULL, timestamp );
486 return; // just getting timestamp
487 }
488 LoadPCX (filename, &pic8, &palette, width, height, timestamp);
489 if (!pic8) {
490 *pic = NULL;
491 return;
492 }
493
494 c = (*width) * (*height);
495 pic32 = *pic = (byte *)R_StaticAlloc(4 * c );
496 for (i = 0 ; i < c ; i++) {
497 p = pic8[i];
498 pic32[0] = palette[p*3];
499 pic32[1] = palette[p*3 + 1];
500 pic32[2] = palette[p*3 + 2];
501 pic32[3] = 255;
502 pic32 += 4;
503 }
504
505 R_StaticFree( pic8 );
506 R_StaticFree( palette );
507 }
508
509 /*
510 =========================================================
511
512 TARGA LOADING
513
514 =========================================================
515 */
516
517 /*
518 =============
519 LoadTGA
520 =============
521 */
LoadTGA(const char * name,byte ** pic,int * width,int * height,ID_TIME_T * timestamp)522 static void LoadTGA( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp ) {
523 int columns, rows, numPixels, fileSize, numBytes;
524 byte *pixbuf;
525 int row, column;
526 byte *buf_p;
527 byte *buffer;
528 TargaHeader targa_header;
529 byte *targa_rgba;
530
531 if ( !pic ) {
532 fileSystem->ReadFile( name, NULL, timestamp );
533 return; // just getting timestamp
534 }
535
536 *pic = NULL;
537
538 //
539 // load the file
540 //
541 fileSize = fileSystem->ReadFile( name, (void **)&buffer, timestamp );
542 if ( !buffer ) {
543 return;
544 }
545
546 buf_p = buffer;
547
548 targa_header.id_length = *buf_p++;
549 targa_header.colormap_type = *buf_p++;
550 targa_header.image_type = *buf_p++;
551
552 targa_header.colormap_index = LittleShort ( *(short *)buf_p );
553 buf_p += 2;
554 targa_header.colormap_length = LittleShort ( *(short *)buf_p );
555 buf_p += 2;
556 targa_header.colormap_size = *buf_p++;
557 targa_header.x_origin = LittleShort ( *(short *)buf_p );
558 buf_p += 2;
559 targa_header.y_origin = LittleShort ( *(short *)buf_p );
560 buf_p += 2;
561 targa_header.width = LittleShort ( *(short *)buf_p );
562 buf_p += 2;
563 targa_header.height = LittleShort ( *(short *)buf_p );
564 buf_p += 2;
565 targa_header.pixel_size = *buf_p++;
566 targa_header.attributes = *buf_p++;
567
568 if ( targa_header.image_type != 2 && targa_header.image_type != 10 && targa_header.image_type != 3 ) {
569 common->Error( "LoadTGA( %s ): Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n", name );
570 }
571
572 if ( targa_header.colormap_type != 0 ) {
573 common->Error( "LoadTGA( %s ): colormaps not supported\n", name );
574 }
575
576 if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 ) {
577 common->Error( "LoadTGA( %s ): Only 32 or 24 bit images supported (no colormaps)\n", name );
578 }
579
580 if ( targa_header.image_type == 2 || targa_header.image_type == 3 ) {
581 numBytes = targa_header.width * targa_header.height * ( targa_header.pixel_size >> 3 );
582 if ( numBytes > fileSize - 18 - targa_header.id_length ) {
583 common->Error( "LoadTGA( %s ): incomplete file\n", name );
584 }
585 }
586
587 columns = targa_header.width;
588 rows = targa_header.height;
589 numPixels = columns * rows;
590
591 if ( width ) {
592 *width = columns;
593 }
594 if ( height ) {
595 *height = rows;
596 }
597
598 targa_rgba = (byte *)R_StaticAlloc(numPixels*4);
599 *pic = targa_rgba;
600
601 if ( targa_header.id_length != 0 ) {
602 buf_p += targa_header.id_length; // skip TARGA image comment
603 }
604
605 if ( targa_header.image_type == 2 || targa_header.image_type == 3 )
606 {
607 // Uncompressed RGB or gray scale image
608 for( row = rows - 1; row >= 0; row-- )
609 {
610 pixbuf = targa_rgba + row*columns*4;
611 for( column = 0; column < columns; column++)
612 {
613 unsigned char red,green,blue,alphabyte;
614 switch( targa_header.pixel_size )
615 {
616
617 case 8:
618 blue = *buf_p++;
619 green = blue;
620 red = blue;
621 *pixbuf++ = red;
622 *pixbuf++ = green;
623 *pixbuf++ = blue;
624 *pixbuf++ = 255;
625 break;
626
627 case 24:
628 blue = *buf_p++;
629 green = *buf_p++;
630 red = *buf_p++;
631 *pixbuf++ = red;
632 *pixbuf++ = green;
633 *pixbuf++ = blue;
634 *pixbuf++ = 255;
635 break;
636 case 32:
637 blue = *buf_p++;
638 green = *buf_p++;
639 red = *buf_p++;
640 alphabyte = *buf_p++;
641 *pixbuf++ = red;
642 *pixbuf++ = green;
643 *pixbuf++ = blue;
644 *pixbuf++ = alphabyte;
645 break;
646 default:
647 common->Error( "LoadTGA( %s ): illegal pixel_size '%d'\n", name, targa_header.pixel_size );
648 break;
649 }
650 }
651 }
652 }
653 else if ( targa_header.image_type == 10 ) { // Runlength encoded RGB images
654 unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
655
656 red = 0;
657 green = 0;
658 blue = 0;
659 alphabyte = 0xff;
660
661 for( row = rows - 1; row >= 0; row-- ) {
662 pixbuf = targa_rgba + row*columns*4;
663 for( column = 0; column < columns; ) {
664 packetHeader= *buf_p++;
665 packetSize = 1 + (packetHeader & 0x7f);
666 if ( packetHeader & 0x80 ) { // run-length packet
667 switch( targa_header.pixel_size ) {
668 case 24:
669 blue = *buf_p++;
670 green = *buf_p++;
671 red = *buf_p++;
672 alphabyte = 255;
673 break;
674 case 32:
675 blue = *buf_p++;
676 green = *buf_p++;
677 red = *buf_p++;
678 alphabyte = *buf_p++;
679 break;
680 default:
681 common->Error( "LoadTGA( %s ): illegal pixel_size '%d'\n", name, targa_header.pixel_size );
682 break;
683 }
684
685 for( j = 0; j < packetSize; j++ ) {
686 *pixbuf++=red;
687 *pixbuf++=green;
688 *pixbuf++=blue;
689 *pixbuf++=alphabyte;
690 column++;
691 if ( column == columns ) { // run spans across rows
692 column = 0;
693 if ( row > 0) {
694 row--;
695 }
696 else {
697 goto breakOut;
698 }
699 pixbuf = targa_rgba + row*columns*4;
700 }
701 }
702 }
703 else { // non run-length packet
704 for( j = 0; j < packetSize; j++ ) {
705 switch( targa_header.pixel_size ) {
706 case 24:
707 blue = *buf_p++;
708 green = *buf_p++;
709 red = *buf_p++;
710 *pixbuf++ = red;
711 *pixbuf++ = green;
712 *pixbuf++ = blue;
713 *pixbuf++ = 255;
714 break;
715 case 32:
716 blue = *buf_p++;
717 green = *buf_p++;
718 red = *buf_p++;
719 alphabyte = *buf_p++;
720 *pixbuf++ = red;
721 *pixbuf++ = green;
722 *pixbuf++ = blue;
723 *pixbuf++ = alphabyte;
724 break;
725 default:
726 common->Error( "LoadTGA( %s ): illegal pixel_size '%d'\n", name, targa_header.pixel_size );
727 break;
728 }
729 column++;
730 if ( column == columns ) { // pixel packet run spans across rows
731 column = 0;
732 if ( row > 0 ) {
733 row--;
734 }
735 else {
736 goto breakOut;
737 }
738 pixbuf = targa_rgba + row*columns*4;
739 }
740 }
741 }
742 }
743 breakOut: ;
744 }
745 }
746
747 if ( (targa_header.attributes & (1<<5)) ) { // image flp bit
748 R_VerticalFlip( *pic, *width, *height );
749 }
750
751 fileSystem->FreeFile( buffer );
752 }
753
754 /*
755 =============
756 LoadJPG
757 =============
758 */
LoadJPG(const char * filename,unsigned char ** pic,int * width,int * height,ID_TIME_T * timestamp)759 static void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height, ID_TIME_T *timestamp ) {
760 /* This struct contains the JPEG decompression parameters and pointers to
761 * working space (which is allocated as needed by the JPEG library).
762 */
763 struct jpeg_decompress_struct cinfo;
764 /* We use our private extension JPEG error handler.
765 * Note that this struct must live as long as the main JPEG parameter
766 * struct, to avoid dangling-pointer problems.
767 */
768 /* This struct represents a JPEG error handler. It is declared separately
769 * because applications often want to supply a specialized error handler
770 * (see the second half of this file for an example). But here we just
771 * take the easy way out and use the standard error handler, which will
772 * print a message on stderr and call exit() if compression fails.
773 * Note that this struct must live as long as the main JPEG parameter
774 * struct, to avoid dangling-pointer problems.
775 */
776 struct jpeg_error_mgr jerr;
777 /* More stuff */
778 JSAMPARRAY buffer; /* Output row buffer */
779 int row_stride; /* physical row width in output buffer */
780 unsigned char *out;
781 byte *fbuffer;
782 byte *bbuf;
783
784 /* In this example we want to open the input file before doing anything else,
785 * so that the setjmp() error recovery below can assume the file is open.
786 * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
787 * requires it in order to read binary files.
788 */
789
790 // JDC: because fill_input_buffer() blindly copies INPUT_BUF_SIZE bytes,
791 // we need to make sure the file buffer is padded or it may crash
792 if ( pic ) {
793 *pic = NULL; // until proven otherwise
794 }
795
796 int len;
797 idFile *f;
798
799 f = fileSystem->OpenFileRead( filename );
800 if ( !f ) {
801 return;
802 }
803 len = f->Length();
804 if ( timestamp ) {
805 *timestamp = f->Timestamp();
806 }
807 if ( !pic ) {
808 fileSystem->CloseFile( f );
809 return; // just getting timestamp
810 }
811 fbuffer = (byte *)Mem_ClearedAlloc( len + 4096 );
812 f->Read( fbuffer, len );
813 fileSystem->CloseFile( f );
814
815 /* Step 1: allocate and initialize JPEG decompression object */
816
817 /* We have to set up the error handler first, in case the initialization
818 * step fails. (Unlikely, but it could happen if you are out of memory.)
819 * This routine fills in the contents of struct jerr, and returns jerr's
820 * address which we place into the link field in cinfo.
821 */
822 cinfo.err = jpeg_std_error(&jerr);
823
824 /* Now we can initialize the JPEG decompression object. */
825 jpeg_create_decompress(&cinfo);
826
827 /* Step 2: specify data source (eg, a file) */
828
829 jpeg_mem_src(&cinfo, fbuffer, len);
830
831 /* Step 3: read file parameters with jpeg_read_header() */
832
833 (void) jpeg_read_header(&cinfo, (boolean)true);
834 /* We can ignore the return value from jpeg_read_header since
835 * (a) suspension is not possible with the stdio data source, and
836 * (b) we passed TRUE to reject a tables-only JPEG file as an error.
837 * See libjpeg.doc for more info.
838 */
839
840 /* Step 4: set parameters for decompression */
841
842 /* In this example, we don't need to change any of the defaults set by
843 * jpeg_read_header(), so we do nothing here.
844 */
845
846 /* Step 5: Start decompressor */
847
848 (void) jpeg_start_decompress(&cinfo);
849 /* We can ignore the return value since suspension is not possible
850 * with the stdio data source.
851 */
852
853 /* We may need to do some setup of our own at this point before reading
854 * the data. After jpeg_start_decompress() we have the correct scaled
855 * output image dimensions available, as well as the output colormap
856 * if we asked for color quantization.
857 * In this example, we need to make an output work buffer of the right size.
858 */
859 /* JSAMPLEs per row in output buffer */
860 row_stride = cinfo.output_width * cinfo.output_components;
861
862 if (cinfo.output_components!=4) {
863 common->DWarning( "JPG %s is unsupported color depth (%d)",
864 filename, cinfo.output_components);
865 }
866 out = (byte *)R_StaticAlloc(cinfo.output_width*cinfo.output_height*4);
867
868 *pic = out;
869 *width = cinfo.output_width;
870 *height = cinfo.output_height;
871
872 /* Step 6: while (scan lines remain to be read) */
873 /* jpeg_read_scanlines(...); */
874
875 /* Here we use the library's state variable cinfo.output_scanline as the
876 * loop counter, so that we don't have to keep track ourselves.
877 */
878 while (cinfo.output_scanline < cinfo.output_height) {
879 /* jpeg_read_scanlines expects an array of pointers to scanlines.
880 * Here the array is only one element long, but you could ask for
881 * more than one scanline at a time if that's more convenient.
882 */
883 bbuf = ((out+(row_stride*cinfo.output_scanline)));
884 buffer = &bbuf;
885 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
886 }
887
888 // clear all the alphas to 255
889 {
890 int i, j;
891 byte *buf;
892
893 buf = *pic;
894
895 j = cinfo.output_width * cinfo.output_height * 4;
896 for ( i = 3 ; i < j ; i+=4 ) {
897 buf[i] = 255;
898 }
899 }
900
901 /* Step 7: Finish decompression */
902
903 (void) jpeg_finish_decompress(&cinfo);
904 /* We can ignore the return value since suspension is not possible
905 * with the stdio data source.
906 */
907
908 /* Step 8: Release JPEG decompression object */
909
910 /* This is an important step since it will release a good deal of memory. */
911 jpeg_destroy_decompress(&cinfo);
912
913 /* After finish_decompress, we can close the input file.
914 * Here we postpone it until after no more JPEG errors are possible,
915 * so as to simplify the setjmp error logic above. (Actually, I don't
916 * think that jpeg_destroy can do an error exit, but why assume anything...)
917 */
918 Mem_Free( fbuffer );
919
920 /* At this point you may want to check to see whether any corrupt-data
921 * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
922 */
923
924 /* And we're done! */
925 }
926
927 //===================================================================
928
929 /*
930 =================
931 R_LoadImage
932
933 Loads any of the supported image types into a cannonical
934 32 bit format.
935
936 Automatically attempts to load .jpg files if .tga files fail to load.
937
938 *pic will be NULL if the load failed.
939
940 Anything that is going to make this into a texture would use
941 makePowerOf2 = true, but something loading an image as a lookup
942 table of some sort would leave it in identity form.
943
944 It is important to do this at image load time instead of texture load
945 time for bump maps.
946
947 Timestamp may be NULL if the value is going to be ignored
948
949 If pic is NULL, the image won't actually be loaded, it will just find the
950 timestamp.
951 =================
952 */
R_LoadImage(const char * cname,byte ** pic,int * width,int * height,ID_TIME_T * timestamp,bool makePowerOf2)953 void R_LoadImage( const char *cname, byte **pic, int *width, int *height, ID_TIME_T *timestamp, bool makePowerOf2 ) {
954 idStr name = cname;
955
956 if ( pic ) {
957 *pic = NULL;
958 }
959 if ( timestamp ) {
960 *timestamp = FILE_NOT_FOUND_TIMESTAMP;
961 }
962 if ( width ) {
963 *width = 0;
964 }
965 if ( height ) {
966 *height = 0;
967 }
968
969 name.DefaultFileExtension( ".tga" );
970
971 if (name.Length()<5) {
972 return;
973 }
974
975 name.ToLower();
976 idStr ext;
977 name.ExtractFileExtension( ext );
978
979 if ( ext == "tga" ) {
980 LoadTGA( name.c_str(), pic, width, height, timestamp ); // try tga first
981 if ( ( pic && *pic == 0 ) || ( timestamp && *timestamp == FILE_NOT_FOUND_TIMESTAMP ) ) {
982 name.StripFileExtension();
983 name.DefaultFileExtension( ".jpg" );
984 LoadJPG( name.c_str(), pic, width, height, timestamp );
985 }
986 } else if ( ext == "pcx" ) {
987 LoadPCX32( name.c_str(), pic, width, height, timestamp );
988 } else if ( ext == "bmp" ) {
989 LoadBMP( name.c_str(), pic, width, height, timestamp );
990 } else if ( ext == "jpg" ) {
991 LoadJPG( name.c_str(), pic, width, height, timestamp );
992 }
993
994 if ( ( width && *width < 1 ) || ( height && *height < 1 ) ) {
995 if ( pic && *pic ) {
996 R_StaticFree( *pic );
997 *pic = 0;
998 }
999 }
1000
1001 //
1002 // convert to exact power of 2 sizes
1003 //
1004 if ( pic && *pic && makePowerOf2 ) {
1005 int w, h;
1006 int scaled_width, scaled_height;
1007 byte *resampledBuffer;
1008
1009 w = *width;
1010 h = *height;
1011
1012 for (scaled_width = 1 ; scaled_width < w ; scaled_width<<=1)
1013 ;
1014 for (scaled_height = 1 ; scaled_height < h ; scaled_height<<=1)
1015 ;
1016
1017 if ( scaled_width != w || scaled_height != h ) {
1018 if ( globalImages->image_roundDown.GetBool() && scaled_width > w ) {
1019 scaled_width >>= 1;
1020 }
1021 if ( globalImages->image_roundDown.GetBool() && scaled_height > h ) {
1022 scaled_height >>= 1;
1023 }
1024
1025 resampledBuffer = R_ResampleTexture( *pic, w, h, scaled_width, scaled_height );
1026 R_StaticFree( *pic );
1027 *pic = resampledBuffer;
1028 *width = scaled_width;
1029 *height = scaled_height;
1030 }
1031 }
1032 }
1033
1034
1035 /*
1036 =======================
1037 R_LoadCubeImages
1038
1039 Loads six files with proper extensions
1040 =======================
1041 */
R_LoadCubeImages(const char * imgName,cubeFiles_t extensions,byte * pics[6],int * outSize,ID_TIME_T * timestamp)1042 bool R_LoadCubeImages( const char *imgName, cubeFiles_t extensions, byte *pics[6], int *outSize, ID_TIME_T *timestamp ) {
1043 int i, j;
1044 const char *cameraSides[6] = { "_forward.tga", "_back.tga", "_left.tga", "_right.tga",
1045 "_up.tga", "_down.tga" };
1046 const char *axisSides[6] = { "_px.tga", "_nx.tga", "_py.tga", "_ny.tga",
1047 "_pz.tga", "_nz.tga" };
1048 const char **sides;
1049 char fullName[MAX_IMAGE_NAME];
1050 int width, height, size = 0;
1051
1052 if ( extensions == CF_CAMERA ) {
1053 sides = cameraSides;
1054 } else {
1055 sides = axisSides;
1056 }
1057
1058 // FIXME: precompressed cube map files
1059 if ( pics ) {
1060 memset( pics, 0, 6*sizeof(pics[0]) );
1061 }
1062 if ( timestamp ) {
1063 *timestamp = 0;
1064 }
1065
1066 for ( i = 0 ; i < 6 ; i++ ) {
1067 idStr::snPrintf( fullName, sizeof( fullName ), "%s%s", imgName, sides[i] );
1068
1069 ID_TIME_T thisTime;
1070 if ( !pics ) {
1071 // just checking timestamps
1072 R_LoadImageProgram( fullName, NULL, &width, &height, &thisTime );
1073 } else {
1074 R_LoadImageProgram( fullName, &pics[i], &width, &height, &thisTime );
1075 }
1076 if ( thisTime == FILE_NOT_FOUND_TIMESTAMP ) {
1077 break;
1078 }
1079 if ( i == 0 ) {
1080 size = width;
1081 }
1082 if ( width != size || height != size ) {
1083 common->Warning( "Mismatched sizes on cube map '%s'", imgName );
1084 break;
1085 }
1086 if ( timestamp ) {
1087 if ( thisTime > *timestamp ) {
1088 *timestamp = thisTime;
1089 }
1090 }
1091 if ( pics && extensions == CF_CAMERA ) {
1092 // convert from "camera" images to native cube map images
1093 switch( i ) {
1094 case 0: // forward
1095 R_RotatePic( pics[i], width);
1096 break;
1097 case 1: // back
1098 R_RotatePic( pics[i], width);
1099 R_HorizontalFlip( pics[i], width, height );
1100 R_VerticalFlip( pics[i], width, height );
1101 break;
1102 case 2: // left
1103 R_VerticalFlip( pics[i], width, height );
1104 break;
1105 case 3: // right
1106 R_HorizontalFlip( pics[i], width, height );
1107 break;
1108 case 4: // up
1109 R_RotatePic( pics[i], width);
1110 break;
1111 case 5: // down
1112 R_RotatePic( pics[i], width);
1113 break;
1114 }
1115 }
1116 }
1117
1118 if ( i != 6 ) {
1119 // we had an error, so free everything
1120 if ( pics ) {
1121 for ( j = 0 ; j < i ; j++ ) {
1122 R_StaticFree( pics[j] );
1123 }
1124 }
1125
1126 if ( timestamp ) {
1127 *timestamp = 0;
1128 }
1129 return false;
1130 }
1131
1132 if ( outSize ) {
1133 *outSize = size;
1134 }
1135 return true;
1136 }
1137