Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
bitmaphandler.h
Go to the documentation of this file.
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#if defined(_MSC_VER)
20#pragma once
21#endif
22
23#ifndef BITMAPHANDLER_H
24#define BITMAPHANDLER_H
25
26#include "always.h"
27#include "ww3dformat.h"
28#include "vector3.h"
29#include "colorspace.h"
30
31void Bitmap_Assert(bool condition);
32
34{
35public:
36 // Read pixel at given address
37 WWINLINE static void Read_B8G8R8A8(
38 unsigned char* argb,
39 const unsigned char* src_ptr,
40 WW3DFormat src_format,
41 const unsigned char* palette,
42 unsigned palette_bpp);
43
44 // Read pixel at given address
45 WWINLINE static void Read_B8G8R8A8(
46 unsigned& argb,
47 const unsigned char* src_ptr,
48 WW3DFormat src_format,
49 const unsigned char* palette,
50 unsigned palette_bpp);
51
52 // Read pixel from surface
53 WWINLINE static void Read_B8G8R8A8(
54 unsigned& argb,
55 const unsigned char* src_ptr,
56 WW3DFormat src_format,
57 int x,
58 int y,
59 int width,
60 int height,
61 const unsigned char* palette,
62 unsigned palette_bpp);
63
64 WWINLINE static void Write_B8G8R8A8(
65 unsigned char* dest_ptr,
66 WW3DFormat dest_format,
67 const unsigned char* argb);
68
69 WWINLINE static void Write_B8G8R8A8(
70 unsigned char* dest_ptr,
71 WW3DFormat dest_format,
72 const unsigned& argb);
73
74 WWINLINE static void Copy_Pixel(
75 unsigned char* dest_ptr,
76 WW3DFormat dest_format,
77 const unsigned char* src_ptr,
78 WW3DFormat src_format,
79 const unsigned char* palette,
80 unsigned palette_bpp);
81
82 WWINLINE static void Copy_Pixel(
83 unsigned char* dest_ptr,
84 WW3DFormat dest_format,
85 const unsigned char* src_ptr,
86 WW3DFormat src_format,
87 const unsigned char* palette,
88 unsigned palette_bpp,
89 const Vector3& hsv_shift);
90
91 WWINLINE static unsigned Combine_A8R8G8B8(
92 unsigned bgra1,
93 unsigned bgra2,
94 unsigned bgra3,
95 unsigned bgra4);
96
97 static void Create_Mipmap_B8G8R8A8(
98 unsigned char* dest_surface,
99 unsigned dest_surface_pitch,
100 unsigned char* src_surface,
101 unsigned src_surface_pitch,
102 unsigned width,
103 unsigned height);
104
105 static void Copy_Image_Generate_Mipmap(
106 unsigned width,
107 unsigned height,
108 unsigned char* dest_surface,
109 unsigned dest_pitch,
110 WW3DFormat dest_format,
111 unsigned char* src_surface,
112 unsigned src_pitch,
113 WW3DFormat src_format,
114 unsigned char* mip_surface,
115 unsigned mip_pitch,
116 const Vector3& hsv_shift=Vector3(0.0f,0.0f,0.0f));
117
118 static void Copy_Image(
119 unsigned char* dest_surface,
120 unsigned dest_surface_width,
121 unsigned dest_surface_height,
122 unsigned dest_surface_pitch,
123 WW3DFormat dest_surface_format,
124 unsigned char* src_surface,
125 unsigned src_surface_width,
126 unsigned src_surface_height,
127 unsigned src_surface_pitch,
128 WW3DFormat src_surface_format,
129 const unsigned char* src_palette,
130 unsigned src_palette_bpp,
131 bool generate_mip_level,
132 const Vector3& hsv_shift=Vector3(0.0f,0.0f,0.0f));
133
134};
135
136// ----------------------------------------------------------------------------
137//
138// Read color value of given type in BGRA (D3D) byte order. Regarless
139// of the source format the color value is converted to 32-bit format.
140//
141// ----------------------------------------------------------------------------
142
144 unsigned char* argb,
145 const unsigned char* src_ptr,
146 WW3DFormat src_format,
147 const unsigned char* palette,
148 unsigned palette_bpp)
149{
150 switch (src_format) {
153 *(unsigned*)argb=*(unsigned*)src_ptr;
154 break;
156 *argb++=src_ptr[0];
157 *argb++=src_ptr[1];
158 *argb++=src_ptr[2];
159 *argb++=0xff;
160 break;
162 {
163 unsigned short tmp;
164 tmp=*(unsigned short*)src_ptr;
165 *argb++=((tmp&0x000f)<<4);
166 *argb++=((tmp&0x00f0));
167 *argb++=((tmp&0x0f00)>>4);
168 *argb++=((tmp&0xf000)>>8);
169 }
170 break;
172 {
173 unsigned short tmp;
174 tmp=*(unsigned short*)src_ptr;
175 argb[3]=tmp&0x8000 ? 0xff : 0x0;
176 argb[2]=(tmp>>7)&0xf8;
177 argb[1]=(tmp>>2)&0xf8;
178 argb[0]=(tmp<<3)&0xf8;
179 }
180 break;
182 {
183 unsigned short tmp;
184 tmp=*(unsigned short*)src_ptr;
185 argb[3]=0xff;
186 argb[2]=(tmp>>8)&0xf8;
187 argb[1]=(tmp>>3)&0xfc;
188 argb[0]=(tmp<<3)&0xf8;
189 }
190 break;
192 {
193 unsigned char tmp=*src_ptr;
194 argb[3]=0xff;
195 argb[2]=tmp&0xe0;
196 argb[1]=(tmp<<3)&0xe0;
197 argb[0]=(tmp<<6)&0xc0;
198 }
199 break;
200 case WW3D_FORMAT_L8:
201 {
202 unsigned char tmp=*src_ptr++;
203 *argb++=tmp;
204 *argb++=tmp;
205 *argb++=tmp;
206 *argb++=0xff;
207 }
208 break;
209 case WW3D_FORMAT_A8:
210 {
211 *argb++=0;
212 *argb++=0;
213 *argb++=0;
214 *argb++=*src_ptr++;
215 }
216 break;
217 case WW3D_FORMAT_P8:
218 {
219 unsigned char index=*src_ptr++;
220 switch (palette_bpp) {
221 case 4:
222 *argb++=palette[palette_bpp*index+3];
223 *argb++=palette[palette_bpp*index+2];
224 *argb++=palette[palette_bpp*index+1];
225 *argb++=palette[palette_bpp*index+0];
226 break;
227 case 3:
228 *argb++=palette[palette_bpp*index+2];
229 *argb++=palette[palette_bpp*index+1];
230 *argb++=palette[palette_bpp*index+0];
231 *argb++=0xff;
232 break;
233 case 2:
234 case 1:
235 default:
236 Bitmap_Assert(0);
237 break;
238 }
239 }
240 break;
241 case WW3D_FORMAT_DXT1:
242 case WW3D_FORMAT_DXT2:
243 case WW3D_FORMAT_DXT3:
244 case WW3D_FORMAT_DXT4:
245 case WW3D_FORMAT_DXT5:
246 default: Bitmap_Assert(0); break;
247 }
248}
249
251 unsigned& argb,
252 const unsigned char* src_ptr,
253 WW3DFormat src_format,
254 const unsigned char* palette,
255 unsigned palette_bpp)
256{
257 Read_B8G8R8A8((unsigned char*)&argb,src_ptr,src_format,palette,palette_bpp);
258}
259
260// Read pixel from surface
262 unsigned& argb,
263 const unsigned char* src_ptr,
264 WW3DFormat src_format,
265 int x,
266 int y,
267 int width,
268 int height,
269 const unsigned char* palette,
270 unsigned palette_bpp)
271{
272 if (x<0 || y<0 || x>=width || y>=height) {
273 argb=0;
274 return;
275 }
276
277 unsigned bpp=Get_Bytes_Per_Pixel(src_format);
279 argb,
280 src_ptr+bpp*x+width*bpp*y,
281 src_format,
282 palette,
283 palette_bpp);
284}
285
286
287// ----------------------------------------------------------------------------
288//
289// Write color value of given type in BGRA (D3D) byte order. The source value
290// is always 32 bit and it is converted to defined destination format.
291//
292// ----------------------------------------------------------------------------
293
295 unsigned char* dest_ptr,
296 WW3DFormat dest_format,
297 const unsigned char* argb)
298{
299 switch (dest_format) {
302 *(unsigned*)dest_ptr=*(unsigned*)argb;
303 break;
305 *dest_ptr++=*argb++;
306 *dest_ptr++=*argb++;
307 *dest_ptr++=*argb++;
308 break;
310 {
311 unsigned short tmp;
312 tmp=((argb[3])&0xf0)<<8;
313 tmp|=((argb[2])&0xf0)<<4;
314 tmp|=((argb[1])&0xf0);
315 tmp|=((argb[0])&0xf0)>>4;
316 *(unsigned short*)dest_ptr=tmp;
317 }
318 break;
320 {
321 unsigned short tmp;
322 tmp=argb[3] ? 0x8000 : 0x0;
323 tmp|=((argb[2])&0xf8)<<7;
324 tmp|=((argb[1])&0xf8)<<2;
325 tmp|=((argb[0])&0xf8)>>3;
326 *(unsigned short*)dest_ptr=tmp;
327 }
328 break;
330 {
331 unsigned short tmp;
332 tmp=((argb[2])&0xf8)<<8;
333 tmp|=((argb[1])&0xfc)<<3;
334 tmp|=((argb[0])&0xf8)>>3;
335 *(unsigned short*)dest_ptr=tmp;
336 }
337 break;
339 {
340 unsigned char tmp;
341 tmp=((argb[2])&0xe0);
342 tmp|=((argb[1])&0xe0)>>3;
343 tmp|=((argb[0])&0xc0)>>6;
344 *(unsigned short*)dest_ptr=tmp;
345 }
346 break;
347 case WW3D_FORMAT_L8:
348 {
349 // CIE Req. 709: Y709 = 0.2125R + 0.7154G + 0.0721B
350 unsigned char tmp = (unsigned char) ( (
351 ((unsigned int)argb[0] * (unsigned int)0x1275) + // 0.0721B
352 ((unsigned int)argb[1] * (unsigned int)0xB725) + // 0.7154G (rounded up so FF, FF, FF becomes FF)
353 ((unsigned int)argb[2] * (unsigned int)0x3666) // 0.2125R
354 ) >> 16);
355 *dest_ptr++=tmp;
356 }
357 break;
358 case WW3D_FORMAT_A8:
359 {
360 *dest_ptr++=*argb++;
361 }
362 break;
363 case WW3D_FORMAT_DXT1:
364 case WW3D_FORMAT_DXT2:
365 case WW3D_FORMAT_DXT3:
366 case WW3D_FORMAT_DXT4:
367 case WW3D_FORMAT_DXT5:
368 case WW3D_FORMAT_P8: // Paletted destination not supported
369 default: Bitmap_Assert(0); break;
370 }
371}
372
374 unsigned char* dest_ptr,
375 WW3DFormat dest_format,
376 const unsigned& argb)
377{
378 Write_B8G8R8A8(dest_ptr,dest_format,(unsigned char*)&argb);
379}
380
381// ----------------------------------------------------------------------------
382//
383// Copy pixel. Perform color space conversion if needed. The source and
384// destination are always D3D-style BGRA.
385//
386// ----------------------------------------------------------------------------
387
389 unsigned char* dest_ptr,
390 WW3DFormat dest_format,
391 const unsigned char* src_ptr,
392 WW3DFormat src_format,
393 const unsigned char* palette,
394 unsigned palette_bpp)
395{
396 // Color space conversion needed?
397
398 if (dest_format==src_format) {
399 switch (dest_format) {
402 *(unsigned*)dest_ptr=*(unsigned*)src_ptr;
403 break;
405 *dest_ptr++=src_ptr[0];
406 *dest_ptr++=src_ptr[1];
407 *dest_ptr++=src_ptr[2];
408 break;
410 {
411 unsigned short tmp=*(unsigned short*)src_ptr;
412 *(unsigned short*)dest_ptr=((tmp&0x000f)<<12)|((tmp&0x00f0)<<4)|((tmp&0x0f00)>>4)|((tmp&0xf000)>>12);
413 }
414 break;
416 {
417 unsigned short tmp=*(unsigned short*)src_ptr;
418 *(unsigned short*)dest_ptr=((tmp&0x001f)<<11)|((tmp&0x03e0)<<1)|((tmp&0x7c00)>>9)|((tmp&0x8000)>>15);
419 }
420 break;
422 {
423 unsigned short tmp=*(unsigned short*)src_ptr;
424 *(unsigned short*)dest_ptr=((tmp&0x001f)<<11)|(tmp&0x07e0)|((tmp&0xf800)>>11);
425 }
426 break;
428 case WW3D_FORMAT_L8:
429 case WW3D_FORMAT_A8: *dest_ptr++=*src_ptr++;
430 break;
431 case WW3D_FORMAT_P8: // Paletted destinations not supported
432 default: Bitmap_Assert(0); break;
433 }
434 }
435 else {
436 unsigned b8g8r8a8;
437 Read_B8G8R8A8(b8g8r8a8,src_ptr,src_format,palette,palette_bpp);
438 Write_B8G8R8A8(dest_ptr,dest_format,b8g8r8a8);
439 }
440}
441
442// ----------------------------------------------------------------------------
443//
444// Copy pixel with HSV shift. The source and destination are always D3D-style BGRA.
445//
446// ----------------------------------------------------------------------------
447
449 unsigned char* dest_ptr,
450 WW3DFormat dest_format,
451 const unsigned char* src_ptr,
452 WW3DFormat src_format,
453 const unsigned char* palette,
454 unsigned palette_bpp,
455 const Vector3& hsv_shift)
456{
457 unsigned b8g8r8a8;
458 Read_B8G8R8A8(b8g8r8a8,src_ptr,src_format,palette,palette_bpp);
459 Recolor(b8g8r8a8,hsv_shift);
460 Write_B8G8R8A8(dest_ptr,dest_format,b8g8r8a8);
461}
462
464 unsigned bgra1,
465 unsigned bgra2,
466 unsigned bgra3,
467 unsigned bgra4)
468{
469 bgra1&=0xfcfcfcfc;
470 bgra2&=0xfcfcfcfc;
471 bgra3&=0xfcfcfcfc;
472 bgra4&=0xfcfcfcfc;
473 bgra1>>=2;
474 bgra2>>=2;
475 bgra3>>=2;
476 bgra4>>=2;
477 bgra1+=bgra2;
478 bgra3+=bgra4;
479 bgra1+=bgra3;
480 return bgra1;
481}
482
483
484#endif
#define WWINLINE
Definition always.h:172
void Bitmap_Assert(bool condition)
static WWINLINE void Copy_Pixel(unsigned char *dest_ptr, WW3DFormat dest_format, const unsigned char *src_ptr, WW3DFormat src_format, const unsigned char *palette, unsigned palette_bpp)
static WWINLINE void Read_B8G8R8A8(unsigned char *argb, const unsigned char *src_ptr, WW3DFormat src_format, const unsigned char *palette, unsigned palette_bpp)
static void Copy_Image_Generate_Mipmap(unsigned width, unsigned height, unsigned char *dest_surface, unsigned dest_pitch, WW3DFormat dest_format, unsigned char *src_surface, unsigned src_pitch, WW3DFormat src_format, unsigned char *mip_surface, unsigned mip_pitch, const Vector3 &hsv_shift=Vector3(0.0f, 0.0f, 0.0f))
static WWINLINE unsigned Combine_A8R8G8B8(unsigned bgra1, unsigned bgra2, unsigned bgra3, unsigned bgra4)
static void Create_Mipmap_B8G8R8A8(unsigned char *dest_surface, unsigned dest_surface_pitch, unsigned char *src_surface, unsigned src_surface_pitch, unsigned width, unsigned height)
static WWINLINE void Write_B8G8R8A8(unsigned char *dest_ptr, WW3DFormat dest_format, const unsigned char *argb)
static void Copy_Image(unsigned char *dest_surface, unsigned dest_surface_width, unsigned dest_surface_height, unsigned dest_surface_pitch, WW3DFormat dest_surface_format, unsigned char *src_surface, unsigned src_surface_width, unsigned src_surface_height, unsigned src_surface_pitch, WW3DFormat src_surface_format, const unsigned char *src_palette, unsigned src_palette_bpp, bool generate_mip_level, const Vector3 &hsv_shift=Vector3(0.0f, 0.0f, 0.0f))
void Recolor(Vector3 &rgb, const Vector3 &hsv_shift)
Definition colorspace.h:131
unsigned Get_Bytes_Per_Pixel(WW3DFormat format)
WW3DFormat
Definition ww3dformat.h:75
@ WW3D_FORMAT_R5G6B5
Definition ww3dformat.h:80
@ WW3D_FORMAT_DXT3
Definition ww3dformat.h:98
@ WW3D_FORMAT_R3G3B2
Definition ww3dformat.h:84
@ WW3D_FORMAT_L8
Definition ww3dformat.h:90
@ WW3D_FORMAT_DXT2
Definition ww3dformat.h:97
@ WW3D_FORMAT_P8
Definition ww3dformat.h:89
@ WW3D_FORMAT_X8R8G8B8
Definition ww3dformat.h:79
@ WW3D_FORMAT_A8
Definition ww3dformat.h:85
@ WW3D_FORMAT_DXT5
Definition ww3dformat.h:100
@ WW3D_FORMAT_DXT4
Definition ww3dformat.h:99
@ WW3D_FORMAT_R8G8B8
Definition ww3dformat.h:77
@ WW3D_FORMAT_DXT1
Definition ww3dformat.h:96
@ WW3D_FORMAT_A4R4G4B4
Definition ww3dformat.h:83
@ WW3D_FORMAT_A8R8G8B8
Definition ww3dformat.h:78
@ WW3D_FORMAT_A1R5G5B5
Definition ww3dformat.h:82