bitmaphandler.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /*
  2. ** Command & Conquer Generals(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. #if defined(_MSC_VER)
  19. #pragma once
  20. #endif
  21. #ifndef BITMAPHANDLER_H
  22. #define BITMAPHANDLER_H
  23. #include "always.h"
  24. #include "ww3dformat.h"
  25. void Bitmap_Assert(bool condition);
  26. class BitmapHandlerClass
  27. {
  28. public:
  29. WWINLINE static void Read_B8G8R8A8(
  30. unsigned char* argb,
  31. const unsigned char* src_ptr,
  32. WW3DFormat src_format,
  33. const unsigned char* palette,
  34. unsigned palette_bpp);
  35. WWINLINE static void Read_B8G8R8A8(
  36. unsigned& argb,
  37. const unsigned char* src_ptr,
  38. WW3DFormat src_format,
  39. const unsigned char* palette,
  40. unsigned palette_bpp);
  41. WWINLINE static void Write_B8G8R8A8(
  42. unsigned char* dest_ptr,
  43. WW3DFormat dest_format,
  44. const unsigned char* argb);
  45. WWINLINE static void Write_B8G8R8A8(
  46. unsigned char* dest_ptr,
  47. WW3DFormat dest_format,
  48. const unsigned& argb);
  49. WWINLINE static void Copy_Pixel(
  50. unsigned char* dest_ptr,
  51. WW3DFormat dest_format,
  52. const unsigned char* src_ptr,
  53. WW3DFormat src_format,
  54. const unsigned char* palette,
  55. unsigned palette_bpp);
  56. WWINLINE static unsigned Combine_A8R8G8B8(
  57. unsigned bgra1,
  58. unsigned bgra2,
  59. unsigned bgra3,
  60. unsigned bgra4);
  61. static void Create_Mipmap_B8G8R8A8(
  62. unsigned char* dest_surface,
  63. unsigned dest_surface_pitch,
  64. unsigned char* src_surface,
  65. unsigned src_surface_pitch,
  66. unsigned width,
  67. unsigned height);
  68. static void Copy_Image_Generate_Mipmap(
  69. unsigned width,
  70. unsigned height,
  71. unsigned char* dest_surface,
  72. unsigned dest_pitch,
  73. WW3DFormat dest_format,
  74. unsigned char* src_surface,
  75. unsigned src_pitch,
  76. WW3DFormat src_format,
  77. unsigned char* mip_surface,
  78. unsigned mip_pitch);
  79. static void Copy_Image(
  80. unsigned char* dest_surface,
  81. unsigned dest_surface_width,
  82. unsigned dest_surface_height,
  83. unsigned dest_surface_pitch,
  84. WW3DFormat dest_surface_format,
  85. unsigned char* src_surface,
  86. unsigned src_surface_width,
  87. unsigned src_surface_height,
  88. unsigned src_surface_pitch,
  89. WW3DFormat src_surface_format,
  90. const unsigned char* src_palette,
  91. unsigned src_palette_bpp,
  92. bool generate_mip_level);
  93. };
  94. // ----------------------------------------------------------------------------
  95. //
  96. // Read color value of given type in BGRA (D3D) byte order. Regarless
  97. // of the source format the color value is converted to 32-bit format.
  98. //
  99. // ----------------------------------------------------------------------------
  100. WWINLINE void BitmapHandlerClass::Read_B8G8R8A8(
  101. unsigned char* argb,
  102. const unsigned char* src_ptr,
  103. WW3DFormat src_format,
  104. const unsigned char* palette,
  105. unsigned palette_bpp)
  106. {
  107. switch (src_format) {
  108. case WW3D_FORMAT_A8R8G8B8:
  109. case WW3D_FORMAT_X8R8G8B8:
  110. *(unsigned*)argb=*(unsigned*)src_ptr;
  111. break;
  112. case WW3D_FORMAT_R8G8B8:
  113. *argb++=src_ptr[0];
  114. *argb++=src_ptr[1];
  115. *argb++=src_ptr[2];
  116. *argb++=0;
  117. break;
  118. case WW3D_FORMAT_A4R4G4B4:
  119. {
  120. unsigned short tmp;
  121. tmp=*(unsigned short*)src_ptr;
  122. *argb++=((tmp&0x000f)<<4);
  123. *argb++=((tmp&0x00f0));
  124. *argb++=((tmp&0x0f00)>>4);
  125. *argb++=((tmp&0xf000)>>8);
  126. }
  127. break;
  128. case WW3D_FORMAT_A1R5G5B5:
  129. {
  130. unsigned short tmp;
  131. tmp=*(unsigned short*)src_ptr;
  132. argb[3]=tmp&0x8000 ? 0xff : 0x0;
  133. argb[2]=(tmp>>7)&0xf8;
  134. argb[1]=(tmp>>2)&0xf8;
  135. argb[0]=(tmp<<3)&0xf8;
  136. }
  137. break;
  138. case WW3D_FORMAT_R5G6B5:
  139. {
  140. unsigned short tmp;
  141. tmp=*(unsigned short*)src_ptr;
  142. argb[3]=0;
  143. argb[2]=(tmp>>8)&0xf8;
  144. argb[1]=(tmp>>3)&0xfc;
  145. argb[0]=(tmp<<3)&0xf8;
  146. }
  147. break;
  148. case WW3D_FORMAT_L8:
  149. {
  150. unsigned char tmp=*src_ptr++;
  151. *argb++=tmp;
  152. *argb++=tmp;
  153. *argb++=tmp;
  154. *argb++=0x0;
  155. }
  156. break;
  157. case WW3D_FORMAT_A8:
  158. {
  159. *argb++=0;
  160. *argb++=0;
  161. *argb++=0;
  162. *argb++=*src_ptr++;
  163. }
  164. break;
  165. case WW3D_FORMAT_P8:
  166. {
  167. unsigned char index=*src_ptr++;
  168. switch (palette_bpp) {
  169. case 4:
  170. *argb++=palette[palette_bpp*index+3];
  171. *argb++=palette[palette_bpp*index+2];
  172. *argb++=palette[palette_bpp*index+1];
  173. *argb++=palette[palette_bpp*index+0];
  174. break;
  175. case 3:
  176. *argb++=palette[palette_bpp*index+2];
  177. *argb++=palette[palette_bpp*index+1];
  178. *argb++=palette[palette_bpp*index+0];
  179. *argb++=0x0;
  180. break;
  181. case 2:
  182. case 1:
  183. default:
  184. Bitmap_Assert(0);
  185. break;
  186. }
  187. }
  188. break;
  189. case WW3D_FORMAT_DXT1:
  190. case WW3D_FORMAT_DXT2:
  191. case WW3D_FORMAT_DXT3:
  192. case WW3D_FORMAT_DXT4:
  193. case WW3D_FORMAT_DXT5:
  194. default: Bitmap_Assert(0); break;
  195. }
  196. }
  197. WWINLINE void BitmapHandlerClass::Read_B8G8R8A8(
  198. unsigned& argb,
  199. const unsigned char* src_ptr,
  200. WW3DFormat src_format,
  201. const unsigned char* palette,
  202. unsigned palette_bpp)
  203. {
  204. Read_B8G8R8A8((unsigned char*)&argb,src_ptr,src_format,palette,palette_bpp);
  205. }
  206. // ----------------------------------------------------------------------------
  207. //
  208. // Write color value of given type in BGRA (D3D) byte order. The source value
  209. // is always 32 bit and it is converted to defined destination format.
  210. //
  211. // ----------------------------------------------------------------------------
  212. WWINLINE void BitmapHandlerClass::Write_B8G8R8A8(
  213. unsigned char* dest_ptr,
  214. WW3DFormat dest_format,
  215. const unsigned char* argb)
  216. {
  217. switch (dest_format) {
  218. case WW3D_FORMAT_A8R8G8B8:
  219. case WW3D_FORMAT_X8R8G8B8:
  220. *(unsigned*)dest_ptr=*(unsigned*)argb;
  221. break;
  222. case WW3D_FORMAT_R8G8B8:
  223. *dest_ptr++=*argb++;
  224. *dest_ptr++=*argb++;
  225. *dest_ptr++=*argb++;
  226. break;
  227. case WW3D_FORMAT_A4R4G4B4:
  228. {
  229. unsigned short tmp;
  230. tmp=((argb[3])&0xf0)<<8;
  231. tmp|=((argb[2])&0xf0)<<4;
  232. tmp|=((argb[1])&0xf0);
  233. tmp|=((argb[0])&0xf0)>>4;
  234. *(unsigned short*)dest_ptr=tmp;
  235. }
  236. break;
  237. case WW3D_FORMAT_A1R5G5B5:
  238. {
  239. unsigned short tmp;
  240. tmp=argb[3] ? 0x8000 : 0x0;
  241. tmp|=((argb[2])&0xf8)<<7;
  242. tmp|=((argb[1])&0xf8)<<2;
  243. tmp|=((argb[0])&0xf8)>>3;
  244. *(unsigned short*)dest_ptr=tmp;
  245. }
  246. break;
  247. case WW3D_FORMAT_R5G6B5:
  248. {
  249. unsigned short tmp;
  250. tmp=((argb[2])&0xf8)<<8;
  251. tmp|=((argb[1])&0xfc)<<3;
  252. tmp|=((argb[0])&0xf8)>>3;
  253. *(unsigned short*)dest_ptr=tmp;
  254. }
  255. break;
  256. case WW3D_FORMAT_L8:
  257. {
  258. // CIE Req. 709: Y709 = 0.2125R + 0.7154G + 0.0721B
  259. unsigned char tmp = (unsigned char) ( (
  260. ((unsigned int)argb[0] * (unsigned int)0x1275) + // 0.0721B
  261. ((unsigned int)argb[1] * (unsigned int)0xB725) + // 0.7154G (rounded up so FF, FF, FF becomes FF)
  262. ((unsigned int)argb[2] * (unsigned int)0x3666) // 0.2125R
  263. ) >> 16);
  264. *dest_ptr++=tmp;
  265. }
  266. break;
  267. case WW3D_FORMAT_A8:
  268. {
  269. *dest_ptr++=*argb++;
  270. }
  271. break;
  272. case WW3D_FORMAT_DXT1:
  273. case WW3D_FORMAT_DXT2:
  274. case WW3D_FORMAT_DXT3:
  275. case WW3D_FORMAT_DXT4:
  276. case WW3D_FORMAT_DXT5:
  277. case WW3D_FORMAT_P8: // Paletted destination not supported
  278. default: Bitmap_Assert(0); break;
  279. }
  280. }
  281. WWINLINE void BitmapHandlerClass::Write_B8G8R8A8(
  282. unsigned char* dest_ptr,
  283. WW3DFormat dest_format,
  284. const unsigned& argb)
  285. {
  286. Write_B8G8R8A8(dest_ptr,dest_format,(unsigned char*)&argb);
  287. }
  288. // ----------------------------------------------------------------------------
  289. //
  290. // Copy pixel. Perform color space conversion if needed. The source and
  291. // destination are always D3D-style BGRA.
  292. //
  293. // ----------------------------------------------------------------------------
  294. WWINLINE void BitmapHandlerClass::Copy_Pixel(
  295. unsigned char* dest_ptr,
  296. WW3DFormat dest_format,
  297. const unsigned char* src_ptr,
  298. WW3DFormat src_format,
  299. const unsigned char* palette,
  300. unsigned palette_bpp)
  301. {
  302. // Color space conversion needed?
  303. if (dest_format==src_format) {
  304. switch (dest_format) {
  305. case WW3D_FORMAT_A8R8G8B8:
  306. case WW3D_FORMAT_X8R8G8B8:
  307. *(unsigned*)dest_ptr=*(unsigned*)src_ptr;
  308. break;
  309. case WW3D_FORMAT_R8G8B8:
  310. *dest_ptr++=src_ptr[0];
  311. *dest_ptr++=src_ptr[1];
  312. *dest_ptr++=src_ptr[2];
  313. break;
  314. case WW3D_FORMAT_A4R4G4B4:
  315. {
  316. unsigned short tmp=*(unsigned short*)src_ptr;
  317. *(unsigned short*)dest_ptr=((tmp&0x000f)<<12)|((tmp&0x00f0)<<4)|((tmp&0x0f00)>>4)|((tmp&0xf000)>>12);
  318. }
  319. break;
  320. case WW3D_FORMAT_A1R5G5B5:
  321. {
  322. unsigned short tmp=*(unsigned short*)src_ptr;
  323. *(unsigned short*)dest_ptr=((tmp&0x001f)<<11)|((tmp&0x03e0)<<1)|((tmp&0x7c00)>>9)|((tmp&0x8000)>>15);
  324. }
  325. break;
  326. case WW3D_FORMAT_R5G6B5:
  327. {
  328. unsigned short tmp=*(unsigned short*)src_ptr;
  329. *(unsigned short*)dest_ptr=((tmp&0x001f)<<11)|(tmp&0x07e0)|((tmp&0xf800)>>11);
  330. }
  331. break;
  332. case WW3D_FORMAT_L8:
  333. case WW3D_FORMAT_A8: *dest_ptr++=*src_ptr++;
  334. break;
  335. case WW3D_FORMAT_P8: // Paletted destinations not supported
  336. default: Bitmap_Assert(0); break;
  337. }
  338. }
  339. else {
  340. unsigned b8g8r8a8;
  341. Read_B8G8R8A8(b8g8r8a8,src_ptr,src_format,palette,palette_bpp);
  342. Write_B8G8R8A8(dest_ptr,dest_format,b8g8r8a8);
  343. }
  344. }
  345. WWINLINE unsigned BitmapHandlerClass::Combine_A8R8G8B8(
  346. unsigned bgra1,
  347. unsigned bgra2,
  348. unsigned bgra3,
  349. unsigned bgra4)
  350. {
  351. bgra1&=0xfcfcfcfc;
  352. bgra2&=0xfcfcfcfc;
  353. bgra3&=0xfcfcfcfc;
  354. bgra4&=0xfcfcfcfc;
  355. bgra1>>=2;
  356. bgra2>>=2;
  357. bgra3>>=2;
  358. bgra4>>=2;
  359. bgra1+=bgra2;
  360. bgra3+=bgra4;
  361. bgra1+=bgra3;
  362. return bgra1;
  363. }
  364. #endif