Image_files.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition 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 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. 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.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../idlib/precompiled.h"
  22. #include "tr_local.h"
  23. /*
  24. This file only has a single entry point:
  25. void R_LoadImage( const char *name, byte **pic, int *width, int *height, bool makePowerOf2 );
  26. */
  27. /*
  28. * Include file for users of JPEG library.
  29. * You will need to have included system headers that define at least
  30. * the typedefs FILE and size_t before you can include jpeglib.h.
  31. * (stdio.h is sufficient on ANSI-conforming systems.)
  32. * You may also wish to include "jerror.h".
  33. */
  34. #include "jpeg-6/jpeglib.h"
  35. // hooks from jpeg lib to our system
  36. void jpg_Error( const char *fmt, ... ) {
  37. va_list argptr;
  38. char msg[2048];
  39. va_start (argptr,fmt);
  40. vsprintf (msg,fmt,argptr);
  41. va_end (argptr);
  42. common->FatalError( "%s", msg );
  43. }
  44. void jpg_Printf( const char *fmt, ... ) {
  45. va_list argptr;
  46. char msg[2048];
  47. va_start (argptr,fmt);
  48. vsprintf (msg,fmt,argptr);
  49. va_end (argptr);
  50. common->Printf( "%s", msg );
  51. }
  52. /*
  53. ================
  54. R_WriteTGA
  55. ================
  56. */
  57. void R_WriteTGA( const char *filename, const byte *data, int width, int height, bool flipVertical, const char * basePath ) {
  58. byte *buffer;
  59. int i;
  60. int bufferSize = width*height*4 + 18;
  61. int imgStart = 18;
  62. idTempArray<byte> buf( bufferSize );
  63. buffer = (byte *)buf.Ptr();
  64. memset( buffer, 0, 18 );
  65. buffer[2] = 2; // uncompressed type
  66. buffer[12] = width&255;
  67. buffer[13] = width>>8;
  68. buffer[14] = height&255;
  69. buffer[15] = height>>8;
  70. buffer[16] = 32; // pixel size
  71. if ( !flipVertical ) {
  72. buffer[17] = (1<<5); // flip bit, for normal top to bottom raster order
  73. }
  74. // swap rgb to bgr
  75. for ( i=imgStart ; i<bufferSize ; i+=4 ) {
  76. buffer[i] = data[i-imgStart+2]; // blue
  77. buffer[i+1] = data[i-imgStart+1]; // green
  78. buffer[i+2] = data[i-imgStart+0]; // red
  79. buffer[i+3] = data[i-imgStart+3]; // alpha
  80. }
  81. fileSystem->WriteFile( filename, buffer, bufferSize, basePath );
  82. }
  83. static void LoadTGA( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp );
  84. static void LoadJPG( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp );
  85. /*
  86. ========================================================================
  87. TGA files are used for 24/32 bit images
  88. ========================================================================
  89. */
  90. typedef struct _TargaHeader {
  91. unsigned char id_length, colormap_type, image_type;
  92. unsigned short colormap_index, colormap_length;
  93. unsigned char colormap_size;
  94. unsigned short x_origin, y_origin, width, height;
  95. unsigned char pixel_size, attributes;
  96. } TargaHeader;
  97. /*
  98. =========================================================
  99. TARGA LOADING
  100. =========================================================
  101. */
  102. /*
  103. =============
  104. LoadTGA
  105. =============
  106. */
  107. static void LoadTGA( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp ) {
  108. int columns, rows, numPixels, fileSize, numBytes;
  109. byte *pixbuf;
  110. int row, column;
  111. byte *buf_p;
  112. byte *buffer;
  113. TargaHeader targa_header;
  114. byte *targa_rgba;
  115. if ( !pic ) {
  116. fileSystem->ReadFile( name, NULL, timestamp );
  117. return; // just getting timestamp
  118. }
  119. *pic = NULL;
  120. //
  121. // load the file
  122. //
  123. fileSize = fileSystem->ReadFile( name, (void **)&buffer, timestamp );
  124. if ( !buffer ) {
  125. return;
  126. }
  127. buf_p = buffer;
  128. targa_header.id_length = *buf_p++;
  129. targa_header.colormap_type = *buf_p++;
  130. targa_header.image_type = *buf_p++;
  131. targa_header.colormap_index = LittleShort ( *(short *)buf_p );
  132. buf_p += 2;
  133. targa_header.colormap_length = LittleShort ( *(short *)buf_p );
  134. buf_p += 2;
  135. targa_header.colormap_size = *buf_p++;
  136. targa_header.x_origin = LittleShort ( *(short *)buf_p );
  137. buf_p += 2;
  138. targa_header.y_origin = LittleShort ( *(short *)buf_p );
  139. buf_p += 2;
  140. targa_header.width = LittleShort ( *(short *)buf_p );
  141. buf_p += 2;
  142. targa_header.height = LittleShort ( *(short *)buf_p );
  143. buf_p += 2;
  144. targa_header.pixel_size = *buf_p++;
  145. targa_header.attributes = *buf_p++;
  146. if ( targa_header.image_type != 2 && targa_header.image_type != 10 && targa_header.image_type != 3 ) {
  147. common->Error( "LoadTGA( %s ): Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n", name );
  148. }
  149. if ( targa_header.colormap_type != 0 ) {
  150. common->Error( "LoadTGA( %s ): colormaps not supported\n", name );
  151. }
  152. if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 ) {
  153. common->Error( "LoadTGA( %s ): Only 32 or 24 bit images supported (no colormaps)\n", name );
  154. }
  155. if ( targa_header.image_type == 2 || targa_header.image_type == 3 ) {
  156. numBytes = targa_header.width * targa_header.height * ( targa_header.pixel_size >> 3 );
  157. if ( numBytes > fileSize - 18 - targa_header.id_length ) {
  158. common->Error( "LoadTGA( %s ): incomplete file\n", name );
  159. }
  160. }
  161. columns = targa_header.width;
  162. rows = targa_header.height;
  163. numPixels = columns * rows;
  164. if ( width ) {
  165. *width = columns;
  166. }
  167. if ( height ) {
  168. *height = rows;
  169. }
  170. targa_rgba = (byte *)R_StaticAlloc(numPixels*4, TAG_IMAGE);
  171. *pic = targa_rgba;
  172. if ( targa_header.id_length != 0 ) {
  173. buf_p += targa_header.id_length; // skip TARGA image comment
  174. }
  175. if ( targa_header.image_type == 2 || targa_header.image_type == 3 )
  176. {
  177. // Uncompressed RGB or gray scale image
  178. for( row = rows - 1; row >= 0; row-- )
  179. {
  180. pixbuf = targa_rgba + row*columns*4;
  181. for( column = 0; column < columns; column++)
  182. {
  183. unsigned char red,green,blue,alphabyte;
  184. switch( targa_header.pixel_size )
  185. {
  186. case 8:
  187. blue = *buf_p++;
  188. green = blue;
  189. red = blue;
  190. *pixbuf++ = red;
  191. *pixbuf++ = green;
  192. *pixbuf++ = blue;
  193. *pixbuf++ = 255;
  194. break;
  195. case 24:
  196. blue = *buf_p++;
  197. green = *buf_p++;
  198. red = *buf_p++;
  199. *pixbuf++ = red;
  200. *pixbuf++ = green;
  201. *pixbuf++ = blue;
  202. *pixbuf++ = 255;
  203. break;
  204. case 32:
  205. blue = *buf_p++;
  206. green = *buf_p++;
  207. red = *buf_p++;
  208. alphabyte = *buf_p++;
  209. *pixbuf++ = red;
  210. *pixbuf++ = green;
  211. *pixbuf++ = blue;
  212. *pixbuf++ = alphabyte;
  213. break;
  214. default:
  215. common->Error( "LoadTGA( %s ): illegal pixel_size '%d'\n", name, targa_header.pixel_size );
  216. break;
  217. }
  218. }
  219. }
  220. }
  221. else if ( targa_header.image_type == 10 ) { // Runlength encoded RGB images
  222. unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
  223. red = 0;
  224. green = 0;
  225. blue = 0;
  226. alphabyte = 0xff;
  227. for( row = rows - 1; row >= 0; row-- ) {
  228. pixbuf = targa_rgba + row*columns*4;
  229. for( column = 0; column < columns; ) {
  230. packetHeader= *buf_p++;
  231. packetSize = 1 + (packetHeader & 0x7f);
  232. if ( packetHeader & 0x80 ) { // run-length packet
  233. switch( targa_header.pixel_size ) {
  234. case 24:
  235. blue = *buf_p++;
  236. green = *buf_p++;
  237. red = *buf_p++;
  238. alphabyte = 255;
  239. break;
  240. case 32:
  241. blue = *buf_p++;
  242. green = *buf_p++;
  243. red = *buf_p++;
  244. alphabyte = *buf_p++;
  245. break;
  246. default:
  247. common->Error( "LoadTGA( %s ): illegal pixel_size '%d'\n", name, targa_header.pixel_size );
  248. break;
  249. }
  250. for( j = 0; j < packetSize; j++ ) {
  251. *pixbuf++=red;
  252. *pixbuf++=green;
  253. *pixbuf++=blue;
  254. *pixbuf++=alphabyte;
  255. column++;
  256. if ( column == columns ) { // run spans across rows
  257. column = 0;
  258. if ( row > 0) {
  259. row--;
  260. }
  261. else {
  262. goto breakOut;
  263. }
  264. pixbuf = targa_rgba + row*columns*4;
  265. }
  266. }
  267. }
  268. else { // non run-length packet
  269. for( j = 0; j < packetSize; j++ ) {
  270. switch( targa_header.pixel_size ) {
  271. case 24:
  272. blue = *buf_p++;
  273. green = *buf_p++;
  274. red = *buf_p++;
  275. *pixbuf++ = red;
  276. *pixbuf++ = green;
  277. *pixbuf++ = blue;
  278. *pixbuf++ = 255;
  279. break;
  280. case 32:
  281. blue = *buf_p++;
  282. green = *buf_p++;
  283. red = *buf_p++;
  284. alphabyte = *buf_p++;
  285. *pixbuf++ = red;
  286. *pixbuf++ = green;
  287. *pixbuf++ = blue;
  288. *pixbuf++ = alphabyte;
  289. break;
  290. default:
  291. common->Error( "LoadTGA( %s ): illegal pixel_size '%d'\n", name, targa_header.pixel_size );
  292. break;
  293. }
  294. column++;
  295. if ( column == columns ) { // pixel packet run spans across rows
  296. column = 0;
  297. if ( row > 0 ) {
  298. row--;
  299. }
  300. else {
  301. goto breakOut;
  302. }
  303. pixbuf = targa_rgba + row*columns*4;
  304. }
  305. }
  306. }
  307. }
  308. breakOut: ;
  309. }
  310. }
  311. if ( (targa_header.attributes & (1<<5)) ) { // image flp bit
  312. if ( width != NULL && height != NULL ) {
  313. R_VerticalFlip( *pic, *width, *height );
  314. }
  315. }
  316. fileSystem->FreeFile( buffer );
  317. }
  318. /*
  319. =========================================================
  320. JPG LOADING
  321. Interfaces with the huge libjpeg
  322. =========================================================
  323. */
  324. /*
  325. =============
  326. LoadJPG
  327. =============
  328. */
  329. static void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height, ID_TIME_T *timestamp ) {
  330. /* This struct contains the JPEG decompression parameters and pointers to
  331. * working space (which is allocated as needed by the JPEG library).
  332. */
  333. struct jpeg_decompress_struct cinfo;
  334. /* We use our private extension JPEG error handler.
  335. * Note that this struct must live as long as the main JPEG parameter
  336. * struct, to avoid dangling-pointer problems.
  337. */
  338. /* This struct represents a JPEG error handler. It is declared separately
  339. * because applications often want to supply a specialized error handler
  340. * (see the second half of this file for an example). But here we just
  341. * take the easy way out and use the standard error handler, which will
  342. * print a message on stderr and call exit() if compression fails.
  343. * Note that this struct must live as long as the main JPEG parameter
  344. * struct, to avoid dangling-pointer problems.
  345. */
  346. struct jpeg_error_mgr jerr;
  347. /* More stuff */
  348. JSAMPARRAY buffer; /* Output row buffer */
  349. int row_stride; /* physical row width in output buffer */
  350. unsigned char *out;
  351. byte *fbuffer;
  352. byte *bbuf;
  353. /* In this example we want to open the input file before doing anything else,
  354. * so that the setjmp() error recovery below can assume the file is open.
  355. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
  356. * requires it in order to read binary files.
  357. */
  358. // JDC: because fill_input_buffer() blindly copies INPUT_BUF_SIZE bytes,
  359. // we need to make sure the file buffer is padded or it may crash
  360. if ( pic ) {
  361. *pic = NULL; // until proven otherwise
  362. }
  363. {
  364. int len;
  365. idFile *f;
  366. f = fileSystem->OpenFileRead( filename );
  367. if ( !f ) {
  368. return;
  369. }
  370. len = f->Length();
  371. if ( timestamp ) {
  372. *timestamp = f->Timestamp();
  373. }
  374. if ( !pic ) {
  375. fileSystem->CloseFile( f );
  376. return; // just getting timestamp
  377. }
  378. fbuffer = (byte *)Mem_ClearedAlloc( len + 4096, TAG_JPG );
  379. f->Read( fbuffer, len );
  380. fileSystem->CloseFile( f );
  381. }
  382. /* Step 1: allocate and initialize JPEG decompression object */
  383. /* We have to set up the error handler first, in case the initialization
  384. * step fails. (Unlikely, but it could happen if you are out of memory.)
  385. * This routine fills in the contents of struct jerr, and returns jerr's
  386. * address which we place into the link field in cinfo.
  387. */
  388. cinfo.err = jpeg_std_error(&jerr);
  389. /* Now we can initialize the JPEG decompression object. */
  390. jpeg_create_decompress(&cinfo);
  391. /* Step 2: specify data source (eg, a file) */
  392. jpeg_stdio_src(&cinfo, fbuffer);
  393. /* Step 3: read file parameters with jpeg_read_header() */
  394. (void) jpeg_read_header(&cinfo, true );
  395. /* We can ignore the return value from jpeg_read_header since
  396. * (a) suspension is not possible with the stdio data source, and
  397. * (b) we passed TRUE to reject a tables-only JPEG file as an error.
  398. * See libjpeg.doc for more info.
  399. */
  400. /* Step 4: set parameters for decompression */
  401. /* In this example, we don't need to change any of the defaults set by
  402. * jpeg_read_header(), so we do nothing here.
  403. */
  404. /* Step 5: Start decompressor */
  405. (void) jpeg_start_decompress(&cinfo);
  406. /* We can ignore the return value since suspension is not possible
  407. * with the stdio data source.
  408. */
  409. /* We may need to do some setup of our own at this point before reading
  410. * the data. After jpeg_start_decompress() we have the correct scaled
  411. * output image dimensions available, as well as the output colormap
  412. * if we asked for color quantization.
  413. * In this example, we need to make an output work buffer of the right size.
  414. */
  415. /* JSAMPLEs per row in output buffer */
  416. row_stride = cinfo.output_width * cinfo.output_components;
  417. if (cinfo.output_components!=4) {
  418. common->DWarning( "JPG %s is unsupported color depth (%d)",
  419. filename, cinfo.output_components);
  420. }
  421. out = (byte *)R_StaticAlloc(cinfo.output_width*cinfo.output_height*4, TAG_IMAGE);
  422. *pic = out;
  423. *width = cinfo.output_width;
  424. *height = cinfo.output_height;
  425. /* Step 6: while (scan lines remain to be read) */
  426. /* jpeg_read_scanlines(...); */
  427. /* Here we use the library's state variable cinfo.output_scanline as the
  428. * loop counter, so that we don't have to keep track ourselves.
  429. */
  430. while (cinfo.output_scanline < cinfo.output_height) {
  431. /* jpeg_read_scanlines expects an array of pointers to scanlines.
  432. * Here the array is only one element long, but you could ask for
  433. * more than one scanline at a time if that's more convenient.
  434. */
  435. bbuf = ((out+(row_stride*cinfo.output_scanline)));
  436. buffer = &bbuf;
  437. (void) jpeg_read_scanlines(&cinfo, buffer, 1);
  438. }
  439. // clear all the alphas to 255
  440. {
  441. int i, j;
  442. byte *buf;
  443. buf = *pic;
  444. j = cinfo.output_width * cinfo.output_height * 4;
  445. for ( i = 3 ; i < j ; i+=4 ) {
  446. buf[i] = 255;
  447. }
  448. }
  449. /* Step 7: Finish decompression */
  450. (void) jpeg_finish_decompress(&cinfo);
  451. /* We can ignore the return value since suspension is not possible
  452. * with the stdio data source.
  453. */
  454. /* Step 8: Release JPEG decompression object */
  455. /* This is an important step since it will release a good deal of memory. */
  456. jpeg_destroy_decompress(&cinfo);
  457. /* After finish_decompress, we can close the input file.
  458. * Here we postpone it until after no more JPEG errors are possible,
  459. * so as to simplify the setjmp error logic above. (Actually, I don't
  460. * think that jpeg_destroy can do an error exit, but why assume anything...)
  461. */
  462. Mem_Free( fbuffer );
  463. /* At this point you may want to check to see whether any corrupt-data
  464. * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
  465. */
  466. /* And we're done! */
  467. }
  468. //===================================================================
  469. /*
  470. =================
  471. R_LoadImage
  472. Loads any of the supported image types into a cannonical
  473. 32 bit format.
  474. Automatically attempts to load .jpg files if .tga files fail to load.
  475. *pic will be NULL if the load failed.
  476. Anything that is going to make this into a texture would use
  477. makePowerOf2 = true, but something loading an image as a lookup
  478. table of some sort would leave it in identity form.
  479. It is important to do this at image load time instead of texture load
  480. time for bump maps.
  481. Timestamp may be NULL if the value is going to be ignored
  482. If pic is NULL, the image won't actually be loaded, it will just find the
  483. timestamp.
  484. =================
  485. */
  486. void R_LoadImage( const char *cname, byte **pic, int *width, int *height, ID_TIME_T *timestamp, bool makePowerOf2 ) {
  487. idStr name = cname;
  488. if ( pic ) {
  489. *pic = NULL;
  490. }
  491. if ( timestamp ) {
  492. *timestamp = FILE_NOT_FOUND_TIMESTAMP;
  493. }
  494. if ( width ) {
  495. *width = 0;
  496. }
  497. if ( height ) {
  498. *height = 0;
  499. }
  500. name.DefaultFileExtension( ".tga" );
  501. if (name.Length()<5) {
  502. return;
  503. }
  504. name.ToLower();
  505. idStr ext;
  506. name.ExtractFileExtension( ext );
  507. if ( ext == "tga" ) {
  508. LoadTGA( name.c_str(), pic, width, height, timestamp ); // try tga first
  509. if ( ( pic && *pic == 0 ) || ( timestamp && *timestamp == -1 ) ) { //-V595
  510. name.StripFileExtension();
  511. name.DefaultFileExtension( ".jpg" );
  512. LoadJPG( name.c_str(), pic, width, height, timestamp );
  513. }
  514. } else if ( ext == "jpg" ) {
  515. LoadJPG( name.c_str(), pic, width, height, timestamp );
  516. }
  517. if ( ( width && *width < 1 ) || ( height && *height < 1 ) ) {
  518. if ( pic && *pic ) {
  519. R_StaticFree( *pic );
  520. *pic = 0;
  521. }
  522. }
  523. //
  524. // convert to exact power of 2 sizes
  525. //
  526. /*
  527. if ( pic && *pic && makePowerOf2 ) {
  528. int w, h;
  529. int scaled_width, scaled_height;
  530. byte *resampledBuffer;
  531. w = *width;
  532. h = *height;
  533. for (scaled_width = 1 ; scaled_width < w ; scaled_width<<=1)
  534. ;
  535. for (scaled_height = 1 ; scaled_height < h ; scaled_height<<=1)
  536. ;
  537. if ( scaled_width != w || scaled_height != h ) {
  538. resampledBuffer = R_ResampleTexture( *pic, w, h, scaled_width, scaled_height );
  539. R_StaticFree( *pic );
  540. *pic = resampledBuffer;
  541. *width = scaled_width;
  542. *height = scaled_height;
  543. }
  544. }
  545. */
  546. }
  547. /*
  548. =======================
  549. R_LoadCubeImages
  550. Loads six files with proper extensions
  551. =======================
  552. */
  553. bool R_LoadCubeImages( const char *imgName, cubeFiles_t extensions, byte *pics[6], int *outSize, ID_TIME_T *timestamp ) {
  554. int i, j;
  555. char *cameraSides[6] = { "_forward.tga", "_back.tga", "_left.tga", "_right.tga",
  556. "_up.tga", "_down.tga" };
  557. char *axisSides[6] = { "_px.tga", "_nx.tga", "_py.tga", "_ny.tga",
  558. "_pz.tga", "_nz.tga" };
  559. char **sides;
  560. char fullName[MAX_IMAGE_NAME];
  561. int width, height, size = 0;
  562. if ( extensions == CF_CAMERA ) {
  563. sides = cameraSides;
  564. } else {
  565. sides = axisSides;
  566. }
  567. // FIXME: precompressed cube map files
  568. if ( pics ) {
  569. memset( pics, 0, 6*sizeof(pics[0]) );
  570. }
  571. if ( timestamp ) {
  572. *timestamp = 0;
  573. }
  574. for ( i = 0 ; i < 6 ; i++ ) {
  575. idStr::snPrintf( fullName, sizeof( fullName ), "%s%s", imgName, sides[i] );
  576. ID_TIME_T thisTime;
  577. if ( !pics ) {
  578. // just checking timestamps
  579. R_LoadImageProgram( fullName, NULL, &width, &height, &thisTime );
  580. } else {
  581. R_LoadImageProgram( fullName, &pics[i], &width, &height, &thisTime );
  582. }
  583. if ( thisTime == FILE_NOT_FOUND_TIMESTAMP ) {
  584. break;
  585. }
  586. if ( i == 0 ) {
  587. size = width;
  588. }
  589. if ( width != size || height != size ) {
  590. common->Warning( "Mismatched sizes on cube map '%s'", imgName );
  591. break;
  592. }
  593. if ( timestamp ) {
  594. if ( thisTime > *timestamp ) {
  595. *timestamp = thisTime;
  596. }
  597. }
  598. if ( pics && extensions == CF_CAMERA ) {
  599. // convert from "camera" images to native cube map images
  600. switch( i ) {
  601. case 0: // forward
  602. R_RotatePic( pics[i], width);
  603. break;
  604. case 1: // back
  605. R_RotatePic( pics[i], width);
  606. R_HorizontalFlip( pics[i], width, height );
  607. R_VerticalFlip( pics[i], width, height );
  608. break;
  609. case 2: // left
  610. R_VerticalFlip( pics[i], width, height );
  611. break;
  612. case 3: // right
  613. R_HorizontalFlip( pics[i], width, height );
  614. break;
  615. case 4: // up
  616. R_RotatePic( pics[i], width);
  617. break;
  618. case 5: // down
  619. R_RotatePic( pics[i], width);
  620. break;
  621. }
  622. }
  623. }
  624. if ( i != 6 ) {
  625. // we had an error, so free everything
  626. if ( pics ) {
  627. for ( j = 0 ; j < i ; j++ ) {
  628. R_StaticFree( pics[j] );
  629. }
  630. }
  631. if ( timestamp ) {
  632. *timestamp = 0;
  633. }
  634. return false;
  635. }
  636. if ( outSize ) {
  637. *outSize = size;
  638. }
  639. return true;
  640. }