tgatodxt.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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. #pragma message ("(gth) disabling TGAtoDXTClass temporarily so I can test the WW libs merge...")
  36. #if 0
  37. #include "always.h"
  38. #include "nvdxtlib.h"
  39. #include "targa.h"
  40. #include "tgatodxt.h"
  41. #include "wwdebug.h"
  42. #include <io.h>
  43. #include <stdlib.h>
  44. // Singletons.
  45. TGAToDXTClass _TGAToDXTConverter;
  46. ///////////////////////////////////////////////////////////////////////////////
  47. //
  48. // TGAToDXTClass
  49. //
  50. ///////////////////////////////////////////////////////////////////////////////
  51. TGAToDXTClass::TGAToDXTClass()
  52. : WriteTimePtr (NULL),
  53. BufferSize (1024),
  54. BufferCount (0)
  55. {
  56. Buffer = new unsigned char [BufferSize];
  57. WWASSERT (Buffer != NULL);
  58. }
  59. ///////////////////////////////////////////////////////////////////////////////
  60. //
  61. // ~TGAToDXTClass
  62. //
  63. ///////////////////////////////////////////////////////////////////////////////
  64. TGAToDXTClass::~TGAToDXTClass()
  65. {
  66. // Clean-up.
  67. delete [] Buffer;
  68. }
  69. ///////////////////////////////////////////////////////////////////////////////
  70. //
  71. // Convert
  72. //
  73. ///////////////////////////////////////////////////////////////////////////////
  74. TGAToDXTClass::ErrorCode TGAToDXTClass::Convert (const char *inputpathname, const char *outputpathname, FILETIME *writetimeptr, bool &redundantalpha, bool dontcheckalpha)
  75. {
  76. ErrorCode error_code;
  77. Targa targa;
  78. long error;
  79. WriteTimePtr = writetimeptr;
  80. redundantalpha = false;
  81. error_code=TGA_LOAD_ERROR;
  82. error = targa.Load (inputpathname, TGAF_IMAGE, false);
  83. if (error == 0) {
  84. bool validbitdepth, validsize, validaspect;
  85. // Check that the targa is in the right format.
  86. // In order to be valid it must adhere to the following:
  87. // 1. Pixel depth must be 24 or 32 (compressor has no support for lower bit depths) or 8-bit not paletted
  88. // 2. Dimensions >= 4 (DDS block size is 4x4).
  89. // 3. Aspect ratio <= 1:8 (some H/W will not render textures above this ratio).
  90. // 4. Dimensions must be power of 2 (see below).
  91. validbitdepth = ((targa.Header.PixelDepth == 24) || (targa.Header.PixelDepth == 32)
  92. || ( (targa.Header.PixelDepth == 8) && (targa.Header.ColorMapType != 1) ) );
  93. validsize = (targa.Header.Width >= 4) && (targa.Header.Height >= 4);
  94. validaspect = ((float) MAX (targa.Header.Width, targa.Header.Height)) / ((float) MIN (targa.Header.Width, targa.Header.Height)) <= 8.0f;
  95. if (validbitdepth && validsize && validaspect) {
  96. unsigned char *byte;
  97. HRESULT errorcode;
  98. targa.YFlip();
  99. // If TGA has an alpha channel...
  100. if (targa.Header.PixelDepth == 32) {
  101. // Analyse the alpha channel and ignore it if it contains redundant data (ie. is either all black or all white).
  102. if (!dontcheckalpha) {
  103. byte = (unsigned char*) targa.GetImage();
  104. if ((*(byte + 3) == 0x00) || (*(byte + 3) == 0xff)) {
  105. const unsigned char alpha = *(byte + 3);
  106. redundantalpha = true;
  107. for (unsigned p = 0; p < ((unsigned) targa.Header.Width) * ((unsigned) targa.Header.Height); p++) {
  108. redundantalpha &= (*(byte + 3) == alpha);
  109. byte += 4;
  110. }
  111. }
  112. }
  113. if (!redundantalpha) {
  114. errorcode = ::nvDXTcompress ((unsigned char*) targa.GetImage(), targa.Header.Width, targa.Header.Height, TF_DXT5, true, false, 4);
  115. } else {
  116. unsigned char *nonalphaimage, *nonalphabyte;
  117. // Remove the alpha channel and swizel the pixel data.
  118. nonalphaimage = new unsigned char [3 * ((unsigned) targa.Header.Width) * ((unsigned) targa.Header.Height)];
  119. nonalphabyte = nonalphaimage;
  120. byte = (unsigned char*) targa.GetImage();
  121. for (unsigned p = 0; p < ((unsigned) targa.Header.Width) * ((unsigned) targa.Header.Height); p++) {
  122. *(nonalphabyte + 0) = *(byte + 0);
  123. *(nonalphabyte + 1) = *(byte + 1);
  124. *(nonalphabyte + 2) = *(byte + 2);
  125. nonalphabyte += 3;
  126. byte += 4;
  127. }
  128. errorcode = ::nvDXTcompress (nonalphaimage, targa.Header.Width, targa.Header.Height, TF_DXT1, true, false, 3);
  129. delete [] nonalphaimage;
  130. }
  131. } else if (targa.Header.PixelDepth == 8) {
  132. // 8-bit luminance
  133. unsigned char *image;
  134. // convert to 24-bit monochrome
  135. image = new unsigned char [3 * ((unsigned) targa.Header.Width) * ((unsigned) targa.Header.Height)];
  136. byte = (unsigned char*) targa.GetImage();
  137. for (unsigned p = 0; p < ((unsigned) targa.Header.Width) * ((unsigned) targa.Header.Height); p++) {
  138. image[3*p]=image[3*p+1]=image[3*p+2]=byte[p];
  139. }
  140. errorcode = ::nvDXTcompress (image, targa.Header.Width, targa.Header.Height, TF_DXT1, true, false, 3);
  141. delete [] image;
  142. } else {
  143. // 24-bit color
  144. errorcode = ::nvDXTcompress ((unsigned char*) targa.GetImage(), targa.Header.Width, targa.Header.Height, TF_DXT1, true, false, 3);
  145. }
  146. // Was the image compressed successfully?
  147. // NOTE: Any image that does not have power of 2 dimensions will not be compressed.
  148. if (errorcode >= 0) {
  149. Write (outputpathname);
  150. error_code = OK;
  151. } else {
  152. error_code = COMPRESSION_ERROR;
  153. }
  154. } else {
  155. if (!validbitdepth) error_code = INVALID_BIT_DEPTH;
  156. if (!validsize) error_code = INVALID_SIZE;
  157. if (!validaspect) error_code = INVALID_ASPECT_RATIO;
  158. }
  159. } // error == 0
  160. return error_code;
  161. }
  162. ///////////////////////////////////////////////////////////////////////////////
  163. //
  164. // Write
  165. //
  166. ///////////////////////////////////////////////////////////////////////////////
  167. void TGAToDXTClass::Write (const char *outputpathname)
  168. {
  169. HANDLE hfile;
  170. DWORD bytecountwritten;
  171. hfile = ::CreateFile (outputpathname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0L, NULL);
  172. if (hfile != INVALID_HANDLE_VALUE) {
  173. LockFile (hfile, 0, 0, BufferCount, 0);
  174. WriteFile (hfile, Buffer, BufferCount, &bytecountwritten, NULL);
  175. UnlockFile (hfile, 0, 0, BufferCount, 0);
  176. // Stamp the write time (if one has been supplied).
  177. if (WriteTimePtr != NULL) {
  178. SetFileTime (hfile, NULL, NULL, WriteTimePtr);
  179. }
  180. CloseHandle (hfile);
  181. }
  182. // Reset buffer.
  183. BufferCount = 0;
  184. }
  185. ///////////////////////////////////////////////////////////////////////////////
  186. //
  187. // ReadDTXnFile
  188. //
  189. ///////////////////////////////////////////////////////////////////////////////
  190. void ReadDTXnFile (DWORD datacount, void *data)
  191. {
  192. // Not implemented.
  193. WWASSERT (false);
  194. }
  195. ///////////////////////////////////////////////////////////////////////////////
  196. //
  197. // WriteDTXnFile
  198. //
  199. ///////////////////////////////////////////////////////////////////////////////
  200. void WriteDTXnFile (DWORD datacount, void *data)
  201. {
  202. // Ensure that the buffer is large enough.
  203. if (_TGAToDXTConverter.BufferSize < _TGAToDXTConverter.BufferCount + datacount) {
  204. unsigned newbuffersize;
  205. unsigned char *newbuffer;
  206. newbuffersize = MAX (_TGAToDXTConverter.BufferSize * 2, _TGAToDXTConverter.BufferCount + datacount);
  207. newbuffer = new unsigned char [newbuffersize];
  208. WWASSERT (newbuffer != NULL);
  209. memcpy (newbuffer, _TGAToDXTConverter.Buffer, _TGAToDXTConverter.BufferCount);
  210. delete [] _TGAToDXTConverter.Buffer;
  211. _TGAToDXTConverter.Buffer = newbuffer;
  212. _TGAToDXTConverter.BufferSize = newbuffersize;
  213. }
  214. // Write new data to buffer.
  215. memcpy (_TGAToDXTConverter.Buffer + _TGAToDXTConverter.BufferCount, data, datacount);
  216. _TGAToDXTConverter.BufferCount += datacount;
  217. }
  218. #endif