TGAToDXT.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program 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. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : LevelEdit *
  23. * *
  24. * $Archive:: /Commando/Code/Tools/LevelEdit/TGAToDXT.cpp $*
  25. * *
  26. * Author:: Ian Leslie *
  27. * *
  28. * $Modtime:: 8/29/01 5:35p $*
  29. * *
  30. * $Revision:: 4 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "StdAfx.h"
  36. #include "NvDXTLib.h"
  37. #include "Targa.h"
  38. #include "TGAToDXT.H"
  39. #include <io.h>
  40. #include <stdlib.h>
  41. // Singletons.
  42. TGAToDXTClass _TGAToDXTConverter;
  43. ///////////////////////////////////////////////////////////////////////////////
  44. //
  45. // TGAToDXTClass
  46. //
  47. ///////////////////////////////////////////////////////////////////////////////
  48. TGAToDXTClass::TGAToDXTClass()
  49. : WriteTimePtr (NULL),
  50. BufferSize (1024),
  51. BufferCount (0)
  52. {
  53. Buffer = new unsigned char [BufferSize];
  54. ASSERT (Buffer != NULL);
  55. }
  56. ///////////////////////////////////////////////////////////////////////////////
  57. //
  58. // ~TGAToDXTClass
  59. //
  60. ///////////////////////////////////////////////////////////////////////////////
  61. TGAToDXTClass::~TGAToDXTClass()
  62. {
  63. // Clean-up.
  64. delete [] Buffer;
  65. }
  66. ///////////////////////////////////////////////////////////////////////////////
  67. //
  68. // Convert
  69. //
  70. ///////////////////////////////////////////////////////////////////////////////
  71. bool TGAToDXTClass::Convert (const char *inputpathname, const char *outputpathname, FILETIME *writetimeptr, bool &redundantalpha)
  72. {
  73. bool success;
  74. Targa targa;
  75. long error;
  76. WriteTimePtr = writetimeptr;
  77. redundantalpha = false;
  78. success = false;
  79. error = targa.Load (inputpathname, TGAF_IMAGE, false);
  80. if (error == 0) {
  81. bool validbitdepth, validsize, validaspect;
  82. // Check that the targa is in the right format.
  83. // In order to be valid it must adhere to the following:
  84. // 1. Pixel depth must be 24 or 32 (compressor has no support for lower bit depths).
  85. // 2. Dimensions >= 4 (DDS block size is 4x4).
  86. // 3. Aspect ratio <= 1:8 (some H/W will not render textures above this ratio).
  87. // 4. Dimensions must be power of 2 (see below).
  88. validbitdepth = ((targa.Header.PixelDepth == 24) || (targa.Header.PixelDepth == 32));
  89. validsize = (targa.Header.Width >= 4) && (targa.Header.Height >= 4);
  90. validaspect = ((float) MAX (targa.Header.Width, targa.Header.Height)) / ((float) MIN (targa.Header.Width, targa.Header.Height)) <= 8.0f;
  91. if (validbitdepth && validsize && validaspect) {
  92. unsigned char *byte;
  93. HRESULT errorcode;
  94. targa.YFlip();
  95. // If TGA has an alpha channel...
  96. if (targa.Header.PixelDepth == 32) {
  97. // Analyse the alpha channel and ignore it if it contains redundant data (ie. is either all black or all white).
  98. byte = (unsigned char*) targa.GetImage();
  99. if ((*(byte + 3) == 0x00) || (*(byte + 3) == 0xff)) {
  100. const unsigned char alpha = *(byte + 3);
  101. redundantalpha = true;
  102. for (unsigned p = 0; p < ((unsigned) targa.Header.Width) * ((unsigned) targa.Header.Height); p++) {
  103. redundantalpha &= (*(byte + 3) == alpha);
  104. byte += 4;
  105. }
  106. }
  107. if (!redundantalpha) {
  108. errorcode = ::nvDXTcompress ((unsigned char*) targa.GetImage(), targa.Header.Width, targa.Header.Height, TF_DXT5, true, false, 4);
  109. } else {
  110. unsigned char *nonalphaimage, *nonalphabyte;
  111. // Remove the alpha channel and swizel the pixel data.
  112. nonalphaimage = new unsigned char [3 * ((unsigned) targa.Header.Width) * ((unsigned) targa.Header.Height)];
  113. nonalphabyte = nonalphaimage;
  114. byte = (unsigned char*) targa.GetImage();
  115. for (unsigned p = 0; p < ((unsigned) targa.Header.Width) * ((unsigned) targa.Header.Height); p++) {
  116. *(nonalphabyte + 0) = *(byte + 0);
  117. *(nonalphabyte + 1) = *(byte + 1);
  118. *(nonalphabyte + 2) = *(byte + 2);
  119. nonalphabyte += 3;
  120. byte += 4;
  121. }
  122. errorcode = ::nvDXTcompress (nonalphaimage, targa.Header.Width, targa.Header.Height, TF_DXT1, true, false, 3);
  123. delete [] nonalphaimage;
  124. }
  125. } else {
  126. errorcode = ::nvDXTcompress ((unsigned char*) targa.GetImage(), targa.Header.Width, targa.Header.Height, TF_DXT1, true, false, 3);
  127. }
  128. // Was the image compressed successfully?
  129. // NOTE: Any image that does not have power of 2 dimensions will not be compressed.
  130. if (errorcode >= 0) {
  131. Write (outputpathname);
  132. success = true;
  133. }
  134. }
  135. }
  136. return (success);
  137. }
  138. ///////////////////////////////////////////////////////////////////////////////
  139. //
  140. // Write
  141. //
  142. ///////////////////////////////////////////////////////////////////////////////
  143. void TGAToDXTClass::Write (const char *outputpathname)
  144. {
  145. HANDLE hfile;
  146. DWORD bytecountwritten;
  147. hfile = ::CreateFile (outputpathname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0L, NULL);
  148. if (hfile != INVALID_HANDLE_VALUE) {
  149. LockFile (hfile, 0, 0, BufferCount, 0);
  150. WriteFile (hfile, Buffer, BufferCount, &bytecountwritten, NULL);
  151. UnlockFile (hfile, 0, 0, BufferCount, 0);
  152. // Stamp the write time (if one has been supplied).
  153. if (WriteTimePtr != NULL) {
  154. SetFileTime (hfile, NULL, NULL, WriteTimePtr);
  155. }
  156. CloseHandle (hfile);
  157. }
  158. // Reset buffer.
  159. BufferCount = 0;
  160. }
  161. ///////////////////////////////////////////////////////////////////////////////
  162. //
  163. // ReadDTXnFile
  164. //
  165. ///////////////////////////////////////////////////////////////////////////////
  166. void ReadDTXnFile (DWORD datacount, void *data)
  167. {
  168. // Not implemented.
  169. ASSERT (false);
  170. }
  171. ///////////////////////////////////////////////////////////////////////////////
  172. //
  173. // WriteDTXnFile
  174. //
  175. ///////////////////////////////////////////////////////////////////////////////
  176. void WriteDTXnFile (DWORD datacount, void *data)
  177. {
  178. // Ensure that the buffer is large enough.
  179. if (_TGAToDXTConverter.BufferSize < _TGAToDXTConverter.BufferCount + datacount) {
  180. unsigned newbuffersize;
  181. unsigned char *newbuffer;
  182. newbuffersize = MAX (_TGAToDXTConverter.BufferSize * 2, _TGAToDXTConverter.BufferCount + datacount);
  183. newbuffer = new unsigned char [newbuffersize];
  184. ASSERT (newbuffer != NULL);
  185. memcpy (newbuffer, _TGAToDXTConverter.Buffer, _TGAToDXTConverter.BufferCount);
  186. delete [] _TGAToDXTConverter.Buffer;
  187. _TGAToDXTConverter.Buffer = newbuffer;
  188. _TGAToDXTConverter.BufferSize = newbuffersize;
  189. }
  190. // Write new data to buffer.
  191. memcpy (_TGAToDXTConverter.Buffer + _TGAToDXTConverter.BufferCount, data, datacount);
  192. _TGAToDXTConverter.BufferCount += datacount;
  193. }