2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
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.
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.
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/>.
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.
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.
26 ===========================================================================
29 #include "../idlib/precompiled.h"
36 This file only has a single entry point:
38 void R_LoadImage( const char *name, byte **pic, int *width, int *height, bool makePowerOf2 );
43 * Include file for users of JPEG library.
44 * You will need to have included system headers that define at least
45 * the typedefs FILE and size_t before you can include jpeglib.h.
46 * (stdio.h is sufficient on ANSI-conforming systems.)
47 * You may also wish to include "jerror.h".
51 #include "jpeg-6/jpeglib.h"
53 // hooks from jpeg lib to our system
55 void jpg_Error( const char *fmt, ... ) {
59 va_start (argptr,fmt);
60 vsprintf (msg,fmt,argptr);
63 common->FatalError( "%s", msg );
66 void jpg_Printf( const char *fmt, ... ) {
70 va_start (argptr,fmt);
71 vsprintf (msg,fmt,argptr);
74 common->Printf( "%s", msg );
85 void R_WriteTGA( const char *filename, const byte *data, int width, int height, bool flipVertical ) {
88 int bufferSize = width*height*4 + 18;
91 buffer = (byte *)Mem_Alloc( bufferSize );
92 memset( buffer, 0, 18 );
93 buffer[2] = 2; // uncompressed type
94 buffer[12] = width&255;
95 buffer[13] = width>>8;
96 buffer[14] = height&255;
97 buffer[15] = height>>8;
98 buffer[16] = 32; // pixel size
99 if ( !flipVertical ) {
100 buffer[17] = (1<<5); // flip bit, for normal top to bottom raster order
104 for ( i=imgStart ; i<bufferSize ; i+=4 ) {
105 buffer[i] = data[i-imgStart+2]; // blue
106 buffer[i+1] = data[i-imgStart+1]; // green
107 buffer[i+2] = data[i-imgStart+0]; // red
108 buffer[i+3] = data[i-imgStart+3]; // alpha
111 fileSystem->WriteFile( filename, buffer, bufferSize );
122 void R_WritePalTGA( const char *filename, const byte *data, const byte *palette, int width, int height, bool flipVertical ) {
125 int bufferSize = (width * height) + (256 * 3) + 18;
127 int imgStart = 18 + (256 * 3);
129 buffer = (byte *)Mem_Alloc( bufferSize );
130 memset( buffer, 0, 18 );
131 buffer[1] = 1; // color map type
132 buffer[2] = 1; // uncompressed color mapped image
133 buffer[5] = 0; // number of palette entries (lo)
134 buffer[6] = 1; // number of palette entries (hi)
135 buffer[7] = 24; // color map bpp
136 buffer[12] = width&255;
137 buffer[13] = width>>8;
138 buffer[14] = height&255;
139 buffer[15] = height>>8;
140 buffer[16] = 8; // pixel size
141 if ( !flipVertical ) {
142 buffer[17] = (1<<5); // flip bit, for normal top to bottom raster order
145 // store palette, swapping rgb to bgr
146 for ( i=palStart ; i<imgStart ; i+=3 ) {
147 buffer[i] = palette[i-palStart+2]; // blue
148 buffer[i+1] = palette[i-palStart+1]; // green
149 buffer[i+2] = palette[i-palStart+0]; // red
152 // store the image data
153 for ( i=imgStart ; i<bufferSize ; i++ ) {
154 buffer[i] = data[i-imgStart];
157 fileSystem->WriteFile( filename, buffer, bufferSize );
163 static void LoadBMP( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp );
164 static void LoadTGA( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp );
165 static void LoadJPG( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp );
169 ========================================================================
171 PCX files are used for 8 bit images
173 ========================================================================
181 unsigned short xmin,ymin,xmax,ymax;
182 unsigned short hres,vres;
183 unsigned char palette[48];
186 unsigned short bytes_per_line;
187 unsigned short palette_type;
189 unsigned char data; // unbounded
194 ========================================================================
196 TGA files are used for 24/32 bit images
198 ========================================================================
201 typedef struct _TargaHeader {
202 unsigned char id_length, colormap_type, image_type;
203 unsigned short colormap_index, colormap_length;
204 unsigned char colormap_size;
205 unsigned short x_origin, y_origin, width, height;
206 unsigned char pixel_size, attributes;
212 =========================================================
216 =========================================================
221 unsigned long fileSize;
222 unsigned long reserved0;
223 unsigned long bitmapDataOffset;
224 unsigned long bitmapHeaderSize;
226 unsigned long height;
227 unsigned short planes;
228 unsigned short bitsPerPixel;
229 unsigned long compression;
230 unsigned long bitmapDataSize;
233 unsigned long colors;
234 unsigned long importantColors;
235 unsigned char palette[256][4];
243 static void LoadBMP( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp )
245 int columns, rows, numPixels;
251 BMPHeader_t bmpHeader;
255 fileSystem->ReadFile ( name, NULL, timestamp );
256 return; // just getting timestamp
264 length = fileSystem->ReadFile( name, (void **)&buffer, timestamp );
271 bmpHeader.id[0] = *buf_p++;
272 bmpHeader.id[1] = *buf_p++;
273 bmpHeader.fileSize = LittleLong( * ( long * ) buf_p );
275 bmpHeader.reserved0 = LittleLong( * ( long * ) buf_p );
277 bmpHeader.bitmapDataOffset = LittleLong( * ( long * ) buf_p );
279 bmpHeader.bitmapHeaderSize = LittleLong( * ( long * ) buf_p );
281 bmpHeader.width = LittleLong( * ( long * ) buf_p );
283 bmpHeader.height = LittleLong( * ( long * ) buf_p );
285 bmpHeader.planes = LittleShort( * ( short * ) buf_p );
287 bmpHeader.bitsPerPixel = LittleShort( * ( short * ) buf_p );
289 bmpHeader.compression = LittleLong( * ( long * ) buf_p );
291 bmpHeader.bitmapDataSize = LittleLong( * ( long * ) buf_p );
293 bmpHeader.hRes = LittleLong( * ( long * ) buf_p );
295 bmpHeader.vRes = LittleLong( * ( long * ) buf_p );
297 bmpHeader.colors = LittleLong( * ( long * ) buf_p );
299 bmpHeader.importantColors = LittleLong( * ( long * ) buf_p );
302 memcpy( bmpHeader.palette, buf_p, sizeof( bmpHeader.palette ) );
304 if ( bmpHeader.bitsPerPixel == 8 )
307 if ( bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M' )
309 common->Error( "LoadBMP: only Windows-style BMP files supported (%s)\n", name );
311 if ( bmpHeader.fileSize != length )
313 common->Error( "LoadBMP: header size does not match file size (%lu vs. %d) (%s)\n", bmpHeader.fileSize, length, name );
315 if ( bmpHeader.compression != 0 )
317 common->Error( "LoadBMP: only uncompressed BMP files supported (%s)\n", name );
319 if ( bmpHeader.bitsPerPixel < 8 )
321 common->Error( "LoadBMP: monochrome and 4-bit BMP files not supported (%s)\n", name );
324 columns = bmpHeader.width;
325 rows = bmpHeader.height;
328 numPixels = columns * rows;
335 bmpRGBA = (byte *)R_StaticAlloc( numPixels * 4 );
339 for ( row = rows-1; row >= 0; row-- )
341 pixbuf = bmpRGBA + row*columns*4;
343 for ( column = 0; column < columns; column++ )
345 unsigned char red, green, blue, alpha;
347 unsigned short shortPixel;
349 switch ( bmpHeader.bitsPerPixel )
353 *pixbuf++ = bmpHeader.palette[palIndex][2];
354 *pixbuf++ = bmpHeader.palette[palIndex][1];
355 *pixbuf++ = bmpHeader.palette[palIndex][0];
359 shortPixel = * ( unsigned short * ) pixbuf;
361 *pixbuf++ = ( shortPixel & ( 31 << 10 ) ) >> 7;
362 *pixbuf++ = ( shortPixel & ( 31 << 5 ) ) >> 2;
363 *pixbuf++ = ( shortPixel & ( 31 ) ) << 3;
387 common->Error( "LoadBMP: illegal pixel_size '%d' in file '%s'\n", bmpHeader.bitsPerPixel, name );
393 fileSystem->FreeFile( buffer );
399 =================================================================
403 =================================================================
412 static void LoadPCX ( const char *filename, byte **pic, byte **palette, int *width, int *height,
413 ID_TIME_T *timestamp ) {
418 int dataByte, runLength;
423 fileSystem->ReadFile( filename, NULL, timestamp );
424 return; // just getting timestamp
433 len = fileSystem->ReadFile( filename, (void **)&raw, timestamp );
439 // parse the PCX file
444 xmax = LittleShort(pcx->xmax);
445 ymax = LittleShort(pcx->ymax);
447 if (pcx->manufacturer != 0x0a
449 || pcx->encoding != 1
450 || pcx->bits_per_pixel != 8
454 common->Printf( "Bad pcx file %s (%i x %i) (%i x %i)\n", filename, xmax+1, ymax+1, pcx->xmax, pcx->ymax);
458 out = (byte *)R_StaticAlloc( (ymax+1) * (xmax+1) );
466 *palette = (byte *)R_StaticAlloc(768);
467 memcpy (*palette, (byte *)pcx + len - 768, 768);
474 // FIXME: use bytes_per_line here?
476 for (y=0 ; y<=ymax ; y++, pix += xmax+1)
478 for (x=0 ; x<=xmax ; )
482 if((dataByte & 0xC0) == 0xC0)
484 runLength = dataByte & 0x3F;
490 while(runLength-- > 0)
496 if ( raw - (byte *)pcx > len)
498 common->Printf( "PCX file %s was malformed", filename );
503 fileSystem->FreeFile( pcx );
512 static void LoadPCX32 ( const char *filename, byte **pic, int *width, int *height, ID_TIME_T *timestamp) {
519 fileSystem->ReadFile( filename, NULL, timestamp );
520 return; // just getting timestamp
522 LoadPCX (filename, &pic8, &palette, width, height, timestamp);
528 c = (*width) * (*height);
529 pic32 = *pic = (byte *)R_StaticAlloc(4 * c );
530 for (i = 0 ; i < c ; i++) {
532 pic32[0] = palette[p*3];
533 pic32[1] = palette[p*3 + 1];
534 pic32[2] = palette[p*3 + 2];
539 R_StaticFree( pic8 );
540 R_StaticFree( palette );
544 =========================================================
548 =========================================================
556 static void LoadTGA( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp ) {
557 int columns, rows, numPixels, fileSize, numBytes;
562 TargaHeader targa_header;
566 fileSystem->ReadFile( name, NULL, timestamp );
567 return; // just getting timestamp
575 fileSize = fileSystem->ReadFile( name, (void **)&buffer, timestamp );
582 targa_header.id_length = *buf_p++;
583 targa_header.colormap_type = *buf_p++;
584 targa_header.image_type = *buf_p++;
586 targa_header.colormap_index = LittleShort ( *(short *)buf_p );
588 targa_header.colormap_length = LittleShort ( *(short *)buf_p );
590 targa_header.colormap_size = *buf_p++;
591 targa_header.x_origin = LittleShort ( *(short *)buf_p );
593 targa_header.y_origin = LittleShort ( *(short *)buf_p );
595 targa_header.width = LittleShort ( *(short *)buf_p );
597 targa_header.height = LittleShort ( *(short *)buf_p );
599 targa_header.pixel_size = *buf_p++;
600 targa_header.attributes = *buf_p++;
602 if ( targa_header.image_type != 2 && targa_header.image_type != 10 && targa_header.image_type != 3 ) {
603 common->Error( "LoadTGA( %s ): Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n", name );
606 if ( targa_header.colormap_type != 0 ) {
607 common->Error( "LoadTGA( %s ): colormaps not supported\n", name );
610 if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 ) {
611 common->Error( "LoadTGA( %s ): Only 32 or 24 bit images supported (no colormaps)\n", name );
614 if ( targa_header.image_type == 2 || targa_header.image_type == 3 ) {
615 numBytes = targa_header.width * targa_header.height * ( targa_header.pixel_size >> 3 );
616 if ( numBytes > fileSize - 18 - targa_header.id_length ) {
617 common->Error( "LoadTGA( %s ): incomplete file\n", name );
621 columns = targa_header.width;
622 rows = targa_header.height;
623 numPixels = columns * rows;
632 targa_rgba = (byte *)R_StaticAlloc(numPixels*4);
635 if ( targa_header.id_length != 0 ) {
636 buf_p += targa_header.id_length; // skip TARGA image comment
639 if ( targa_header.image_type == 2 || targa_header.image_type == 3 )
641 // Uncompressed RGB or gray scale image
642 for( row = rows - 1; row >= 0; row-- )
644 pixbuf = targa_rgba + row*columns*4;
645 for( column = 0; column < columns; column++)
647 unsigned char red,green,blue,alphabyte;
648 switch( targa_header.pixel_size )
674 alphabyte = *buf_p++;
678 *pixbuf++ = alphabyte;
681 common->Error( "LoadTGA( %s ): illegal pixel_size '%d'\n", name, targa_header.pixel_size );
687 else if ( targa_header.image_type == 10 ) { // Runlength encoded RGB images
688 unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
695 for( row = rows - 1; row >= 0; row-- ) {
696 pixbuf = targa_rgba + row*columns*4;
697 for( column = 0; column < columns; ) {
698 packetHeader= *buf_p++;
699 packetSize = 1 + (packetHeader & 0x7f);
700 if ( packetHeader & 0x80 ) { // run-length packet
701 switch( targa_header.pixel_size ) {
712 alphabyte = *buf_p++;
715 common->Error( "LoadTGA( %s ): illegal pixel_size '%d'\n", name, targa_header.pixel_size );
719 for( j = 0; j < packetSize; j++ ) {
725 if ( column == columns ) { // run spans across rows
733 pixbuf = targa_rgba + row*columns*4;
737 else { // non run-length packet
738 for( j = 0; j < packetSize; j++ ) {
739 switch( targa_header.pixel_size ) {
753 alphabyte = *buf_p++;
757 *pixbuf++ = alphabyte;
760 common->Error( "LoadTGA( %s ): illegal pixel_size '%d'\n", name, targa_header.pixel_size );
764 if ( column == columns ) { // pixel packet run spans across rows
772 pixbuf = targa_rgba + row*columns*4;
781 if ( (targa_header.attributes & (1<<5)) ) { // image flp bit
782 R_VerticalFlip( *pic, *width, *height );
785 fileSystem->FreeFile( buffer );
789 =========================================================
793 Interfaces with the huge libjpeg
794 =========================================================
802 static void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height, ID_TIME_T *timestamp ) {
803 /* This struct contains the JPEG decompression parameters and pointers to
804 * working space (which is allocated as needed by the JPEG library).
806 struct jpeg_decompress_struct cinfo;
807 /* We use our private extension JPEG error handler.
808 * Note that this struct must live as long as the main JPEG parameter
809 * struct, to avoid dangling-pointer problems.
811 /* This struct represents a JPEG error handler. It is declared separately
812 * because applications often want to supply a specialized error handler
813 * (see the second half of this file for an example). But here we just
814 * take the easy way out and use the standard error handler, which will
815 * print a message on stderr and call exit() if compression fails.
816 * Note that this struct must live as long as the main JPEG parameter
817 * struct, to avoid dangling-pointer problems.
819 struct jpeg_error_mgr jerr;
821 JSAMPARRAY buffer; /* Output row buffer */
822 int row_stride; /* physical row width in output buffer */
827 /* In this example we want to open the input file before doing anything else,
828 * so that the setjmp() error recovery below can assume the file is open.
829 * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
830 * requires it in order to read binary files.
833 // JDC: because fill_input_buffer() blindly copies INPUT_BUF_SIZE bytes,
834 // we need to make sure the file buffer is padded or it may crash
836 *pic = NULL; // until proven otherwise
842 f = fileSystem->OpenFileRead( filename );
848 *timestamp = f->Timestamp();
851 fileSystem->CloseFile( f );
852 return; // just getting timestamp
854 fbuffer = (byte *)Mem_ClearedAlloc( len + 4096 );
855 f->Read( fbuffer, len );
856 fileSystem->CloseFile( f );
860 /* Step 1: allocate and initialize JPEG decompression object */
862 /* We have to set up the error handler first, in case the initialization
863 * step fails. (Unlikely, but it could happen if you are out of memory.)
864 * This routine fills in the contents of struct jerr, and returns jerr's
865 * address which we place into the link field in cinfo.
867 cinfo.err = jpeg_std_error(&jerr);
869 /* Now we can initialize the JPEG decompression object. */
870 jpeg_create_decompress(&cinfo);
872 /* Step 2: specify data source (eg, a file) */
874 jpeg_stdio_src(&cinfo, fbuffer);
876 /* Step 3: read file parameters with jpeg_read_header() */
878 (void) jpeg_read_header(&cinfo, true );
879 /* We can ignore the return value from jpeg_read_header since
880 * (a) suspension is not possible with the stdio data source, and
881 * (b) we passed TRUE to reject a tables-only JPEG file as an error.
882 * See libjpeg.doc for more info.
885 /* Step 4: set parameters for decompression */
887 /* In this example, we don't need to change any of the defaults set by
888 * jpeg_read_header(), so we do nothing here.
891 /* Step 5: Start decompressor */
893 (void) jpeg_start_decompress(&cinfo);
894 /* We can ignore the return value since suspension is not possible
895 * with the stdio data source.
898 /* We may need to do some setup of our own at this point before reading
899 * the data. After jpeg_start_decompress() we have the correct scaled
900 * output image dimensions available, as well as the output colormap
901 * if we asked for color quantization.
902 * In this example, we need to make an output work buffer of the right size.
904 /* JSAMPLEs per row in output buffer */
905 row_stride = cinfo.output_width * cinfo.output_components;
907 if (cinfo.output_components!=4) {
908 common->DWarning( "JPG %s is unsupported color depth (%d)",
909 filename, cinfo.output_components);
911 out = (byte *)R_StaticAlloc(cinfo.output_width*cinfo.output_height*4);
914 *width = cinfo.output_width;
915 *height = cinfo.output_height;
917 /* Step 6: while (scan lines remain to be read) */
918 /* jpeg_read_scanlines(...); */
920 /* Here we use the library's state variable cinfo.output_scanline as the
921 * loop counter, so that we don't have to keep track ourselves.
923 while (cinfo.output_scanline < cinfo.output_height) {
924 /* jpeg_read_scanlines expects an array of pointers to scanlines.
925 * Here the array is only one element long, but you could ask for
926 * more than one scanline at a time if that's more convenient.
928 bbuf = ((out+(row_stride*cinfo.output_scanline)));
930 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
933 // clear all the alphas to 255
940 j = cinfo.output_width * cinfo.output_height * 4;
941 for ( i = 3 ; i < j ; i+=4 ) {
946 /* Step 7: Finish decompression */
948 (void) jpeg_finish_decompress(&cinfo);
949 /* We can ignore the return value since suspension is not possible
950 * with the stdio data source.
953 /* Step 8: Release JPEG decompression object */
955 /* This is an important step since it will release a good deal of memory. */
956 jpeg_destroy_decompress(&cinfo);
958 /* After finish_decompress, we can close the input file.
959 * Here we postpone it until after no more JPEG errors are possible,
960 * so as to simplify the setjmp error logic above. (Actually, I don't
961 * think that jpeg_destroy can do an error exit, but why assume anything...)
965 /* At this point you may want to check to see whether any corrupt-data
966 * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
969 /* And we're done! */
972 //===================================================================
978 Loads any of the supported image types into a cannonical
981 Automatically attempts to load .jpg files if .tga files fail to load.
983 *pic will be NULL if the load failed.
985 Anything that is going to make this into a texture would use
986 makePowerOf2 = true, but something loading an image as a lookup
987 table of some sort would leave it in identity form.
989 It is important to do this at image load time instead of texture load
992 Timestamp may be NULL if the value is going to be ignored
994 If pic is NULL, the image won't actually be loaded, it will just find the
998 void R_LoadImage( const char *cname, byte **pic, int *width, int *height, ID_TIME_T *timestamp, bool makePowerOf2 ) {
1005 *timestamp = 0xFFFFFFFF;
1014 name.DefaultFileExtension( ".tga" );
1016 if (name.Length()<5) {
1022 name.ExtractFileExtension( ext );
1024 if ( ext == "tga" ) {
1025 LoadTGA( name.c_str(), pic, width, height, timestamp ); // try tga first
1026 if ( ( pic && *pic == 0 ) || ( timestamp && *timestamp == -1 ) ) {
1027 name.StripFileExtension();
1028 name.DefaultFileExtension( ".jpg" );
1029 LoadJPG( name.c_str(), pic, width, height, timestamp );
1031 } else if ( ext == "pcx" ) {
1032 LoadPCX32( name.c_str(), pic, width, height, timestamp );
1033 } else if ( ext == "bmp" ) {
1034 LoadBMP( name.c_str(), pic, width, height, timestamp );
1035 } else if ( ext == "jpg" ) {
1036 LoadJPG( name.c_str(), pic, width, height, timestamp );
1039 if ( ( width && *width < 1 ) || ( height && *height < 1 ) ) {
1040 if ( pic && *pic ) {
1041 R_StaticFree( *pic );
1047 // convert to exact power of 2 sizes
1049 if ( pic && *pic && makePowerOf2 ) {
1051 int scaled_width, scaled_height;
1052 byte *resampledBuffer;
1057 for (scaled_width = 1 ; scaled_width < w ; scaled_width<<=1)
1059 for (scaled_height = 1 ; scaled_height < h ; scaled_height<<=1)
1062 if ( scaled_width != w || scaled_height != h ) {
1063 if ( globalImages->image_roundDown.GetBool() && scaled_width > w ) {
1066 if ( globalImages->image_roundDown.GetBool() && scaled_height > h ) {
1067 scaled_height >>= 1;
1070 resampledBuffer = R_ResampleTexture( *pic, w, h, scaled_width, scaled_height );
1071 R_StaticFree( *pic );
1072 *pic = resampledBuffer;
1073 *width = scaled_width;
1074 *height = scaled_height;
1081 =======================
1084 Loads six files with proper extensions
1085 =======================
1087 bool R_LoadCubeImages( const char *imgName, cubeFiles_t extensions, byte *pics[6], int *outSize, ID_TIME_T *timestamp ) {
1089 char *cameraSides[6] = { "_forward.tga", "_back.tga", "_left.tga", "_right.tga",
1090 "_up.tga", "_down.tga" };
1091 char *axisSides[6] = { "_px.tga", "_nx.tga", "_py.tga", "_ny.tga",
1092 "_pz.tga", "_nz.tga" };
1094 char fullName[MAX_IMAGE_NAME];
1095 int width, height, size = 0;
1097 if ( extensions == CF_CAMERA ) {
1098 sides = cameraSides;
1103 // FIXME: precompressed cube map files
1105 memset( pics, 0, 6*sizeof(pics[0]) );
1111 for ( i = 0 ; i < 6 ; i++ ) {
1112 idStr::snPrintf( fullName, sizeof( fullName ), "%s%s", imgName, sides[i] );
1116 // just checking timestamps
1117 R_LoadImageProgram( fullName, NULL, &width, &height, &thisTime );
1119 R_LoadImageProgram( fullName, &pics[i], &width, &height, &thisTime );
1121 if ( thisTime == FILE_NOT_FOUND_TIMESTAMP ) {
1127 if ( width != size || height != size ) {
1128 common->Warning( "Mismatched sizes on cube map '%s'", imgName );
1132 if ( thisTime > *timestamp ) {
1133 *timestamp = thisTime;
1136 if ( pics && extensions == CF_CAMERA ) {
1137 // convert from "camera" images to native cube map images
1140 R_RotatePic( pics[i], width);
1143 R_RotatePic( pics[i], width);
1144 R_HorizontalFlip( pics[i], width, height );
1145 R_VerticalFlip( pics[i], width, height );
1148 R_VerticalFlip( pics[i], width, height );
1151 R_HorizontalFlip( pics[i], width, height );
1154 R_RotatePic( pics[i], width);
1157 R_RotatePic( pics[i], width);
1164 // we had an error, so free everything
1166 for ( j = 0 ; j < i ; j++ ) {
1167 R_StaticFree( pics[j] );