Isle
Loading...
Searching...
No Matches
mxbitmap.cpp
Go to the documentation of this file.
1#include "mxbitmap.h"
2
3#include "decomp.h"
4#include "mxpalette.h"
5#include "mxutilities.h"
6
9
10// GLOBAL: LEGO1 0x10102184
11// GLOBAL: BETA10 0x10203030
13
14// FUNCTION: LEGO1 0x100bc980
15// FUNCTION: BETA10 0x1013cab0
17{
18 m_info = NULL;
19 m_bmiHeader = NULL;
20 m_paletteData = NULL;
21 m_data = NULL;
22 m_isHighColor = FALSE;
23 m_palette = NULL;
24}
25
26// FUNCTION: LEGO1 0x100bca10
27// FUNCTION: BETA10 0x1013cb58
29{
30 if (m_info) {
31 delete m_info;
32 }
33 if (m_data) {
34 delete m_data;
35 }
36 if (m_palette) {
37 delete m_palette;
38 }
39}
40
41// FUNCTION: LEGO1 0x100bcaa0
42// FUNCTION: BETA10 0x1013cc47
43MxResult MxBitmap::SetSize(MxS32 p_width, MxS32 p_height, MxPalette* p_palette, MxBool p_isHighColor)
44{
45 MxResult ret = FAILURE;
46 MxLong size = AlignToFourByte(p_width) * p_height;
47
48 m_info = (MxBITMAPINFO*) new MxU8[MxBitmapInfoSize()];
49 if (!m_info) {
50 goto done;
51 }
52
53 m_data = new MxU8[size];
54 if (!m_data) {
55 goto done;
56 }
57
58 m_bmiHeader = &m_info->m_bmiHeader;
59 m_paletteData = m_info->m_bmiColors;
60 memset(m_bmiHeader, 0, sizeof(m_info->m_bmiHeader));
61
62 m_bmiHeader->biSize = sizeof(*m_bmiHeader); // should be 40 bytes
63 m_bmiHeader->biWidth = p_width;
64 m_bmiHeader->biHeight = p_height;
65 m_bmiHeader->biPlanes = 1;
66 m_bmiHeader->biBitCount = 8;
67 m_bmiHeader->biCompression = 0;
68 m_bmiHeader->biSizeImage = size;
69
70 if (ImportColorsToPalette(m_paletteData, p_palette)) {
71 goto done;
72 }
73
74 if (SetBitDepth(p_isHighColor)) {
75 goto done;
76 }
77
78 ret = SUCCESS;
79
80done:
81 if (ret) {
82 if (m_info) {
83 delete[] m_info;
84 m_info = NULL;
85 }
86
87 if (m_data) {
88 delete[] m_data;
89 m_data = NULL;
90 }
91 }
92
93 return ret;
94}
95
96// FUNCTION: LEGO1 0x100bcba0
97// FUNCTION: BETA10 0x1013ce25
99{
100 MxResult result = FAILURE;
101 MxLong size = AlignToFourByte(p_info->m_bmiHeader.biWidth) * p_info->m_bmiHeader.biHeight;
102
103 m_info = (MxBITMAPINFO*) new MxU8[MxBitmapInfoSize()];
104 if (!m_info) {
105 goto done;
106 }
107
108 m_data = new MxU8[size];
109 if (!m_data) {
110 goto done;
111 }
112
113 memcpy(m_info, p_info, MxBitmapInfoSize());
114 m_bmiHeader = &m_info->m_bmiHeader;
115 m_paletteData = m_info->m_bmiColors;
116 result = SUCCESS;
117
118done:
119 if (result != SUCCESS) {
120 if (m_info) {
121 delete[] m_info;
122 m_info = NULL;
123 }
124
125 if (m_data) {
126 delete[] m_data;
127 m_data = NULL;
128 }
129 }
130
131 return result;
132}
133
134// FUNCTION: LEGO1 0x100bcc40
135// FUNCTION: BETA10 0x1013cf6d
137{
138 MxResult result = FAILURE;
139
140 m_info = (MxBITMAPINFO*) new MxU8[p_bitmap->MxBitmapInfoSize()];
141 if (!m_info) {
142 goto done;
143 }
144
145 m_data = new MxU8[p_bitmap->GetDataSize()];
146 if (!m_data) {
147 goto done;
148 }
149
150 memcpy(m_info, p_bitmap->GetBitmapInfo(), p_bitmap->MxBitmapInfoSize());
151 memcpy(m_data, p_bitmap->GetImage(), p_bitmap->GetDataSize());
152
153 m_bmiHeader = &m_info->m_bmiHeader;
154 m_paletteData = m_info->m_bmiColors;
155 result = SUCCESS;
156
157done:
158 if (result != SUCCESS) {
159 if (m_info) {
160 delete[] m_info;
161 m_info = NULL;
162 }
163
164 if (m_data) {
165 delete[] m_data;
166 m_data = NULL;
167 }
168 }
169
170 return result;
171}
172
173// FUNCTION: LEGO1 0x100bcd10
174// FUNCTION: BETA10 0x1013d0c7
175MxLong MxBitmap::Read(const char* p_filename)
176{
177 MxResult result = FAILURE;
178 HANDLE handle = 0;
179
180 handle = CreateFileA(p_filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
181
182 if (handle == INVALID_HANDLE_VALUE) {
183 goto done;
184 }
185
186 if (LoadFile(handle)) {
187 goto done;
188 }
189
190 result = SUCCESS;
191
192done:
193 if (handle) {
194 CloseHandle(handle);
195 }
196
197 return result;
198}
199
200// FUNCTION: LEGO1 0x100bcd60
201// FUNCTION: BETA10 0x1013d169
203{
204 MxResult result = FAILURE;
205 MxLong unused = 0;
206
207 MxLong size;
208 DWORD bytesRead;
209 BITMAPFILEHEADER hdr;
210 if (!ReadFile(p_handle, &hdr, sizeof(hdr), &bytesRead, NULL)) {
211 goto done;
212 }
213
214 if (hdr.bfType != g_bitmapSignature) {
215 goto done;
216 }
217
218 m_info = (MxBITMAPINFO*) new MxU8[MxBitmapInfoSize()];
219 if (!m_info) {
220 goto done;
221 }
222
223 if (!ReadFile(p_handle, m_info, MxBitmapInfoSize(), &bytesRead, NULL)) {
224 goto done;
225 }
226
227 if (m_info->m_bmiHeader.biBitCount != 8) {
228 goto done;
229 }
230
231 size = hdr.bfSize - sizeof(BITMAPFILEHEADER) - MxBitmapInfoSize();
232 m_data = new MxU8[size];
233 if (!m_data) {
234 goto done;
235 }
236
237 if (!ReadFile(p_handle, m_data, size, &bytesRead, NULL)) {
238 goto done;
239 }
240
241 m_bmiHeader = &m_info->m_bmiHeader;
242 m_paletteData = m_info->m_bmiColors;
243 if (m_info->m_bmiHeader.biSizeImage == 0) {
244 m_info->m_bmiHeader.biSizeImage = GetDataSize();
245 }
246
247 result = SUCCESS;
248
249done:
250 if (result != SUCCESS) {
251 if (m_info) {
252 delete[] m_info;
253 m_info = NULL;
254 }
255
256 if (m_data) {
257 delete[] m_data;
258 m_data = NULL;
259 }
260 }
261
262 return result;
263}
264
265// FUNCTION: LEGO1 0x100bce70
266// FUNCTION: BETA10 0x1013d399
268 MxBitmap* p_src,
269 MxS32 p_srcLeft,
270 MxS32 p_srcTop,
271 MxS32 p_dstLeft,
272 MxS32 p_dstTop,
273 MxS32 p_width,
274 MxS32 p_height
275)
276{
278 p_src->GetBmiWidth(),
279 p_src->GetBmiHeightAbs(),
280 GetBmiWidth(),
282 &p_srcLeft,
283 &p_srcTop,
284 &p_dstLeft,
285 &p_dstTop,
286 &p_width,
287 &p_height
288 )) {
289 return;
290 }
291
292 MxU8* srcStart = p_src->GetStart(p_srcLeft, p_srcTop);
293 MxU8* dstStart = GetStart(p_dstLeft, p_dstTop);
294 MxLong srcStride = GetAdjustedStride(p_src);
295 MxLong dstStride = GetAdjustedStride(this);
296
297 while (p_height--) {
298 memcpy(dstStart, srcStart, p_width);
299 dstStart += dstStride;
300 srcStart += srcStride;
301 }
302}
303
304// FUNCTION: LEGO1 0x100bd020
305// FUNCTION: BETA10 0x1013d4ea
307 MxBitmap* p_src,
308 MxS32 p_srcLeft,
309 MxS32 p_srcTop,
310 MxS32 p_dstLeft,
311 MxS32 p_dstTop,
312 MxS32 p_width,
313 MxS32 p_height
314)
315{
317 p_src->GetBmiWidth(),
318 p_src->GetBmiHeightAbs(),
319 GetBmiWidth(),
321 &p_srcLeft,
322 &p_srcTop,
323 &p_dstLeft,
324 &p_dstTop,
325 &p_width,
326 &p_height
327 )) {
328 return;
329 }
330
331 MxU8* srcStart = p_src->GetStart(p_srcLeft, p_srcTop);
332 MxU8* dstStart = GetStart(p_dstLeft, p_dstTop);
333 MxLong srcStride = -p_width + GetAdjustedStride(p_src);
334 MxLong dstStride = -p_width + GetAdjustedStride(this);
335
336 for (MxS32 h = 0; h < p_height; h++) {
337 for (MxS32 w = 0; w < p_width; w++) {
338 if (*srcStart) {
339 *dstStart = *srcStart;
340 }
341 srcStart++;
342 dstStart++;
343 }
344
345 srcStart += srcStride;
346 dstStart += dstStride;
347 }
348}
349
350// FUNCTION: LEGO1 0x100bd1c0
351// FUNCTION: BETA10 0x1013d684
353{
354 MxBool success = FALSE;
355 MxPalette* palette = NULL;
356
357 switch (m_isHighColor) {
358 case FALSE:
359 if (!(palette = new MxPalette(m_paletteData))) {
360 goto done;
361 }
362
363 break;
364 case TRUE:
365 if (!(palette = m_palette->Clone())) {
366 goto done;
367 }
368
369 break;
370 default:
371 goto done;
372 }
373
374 success = TRUE;
375
376done:
377 if (!success && palette) {
378 delete palette;
379 palette = NULL;
380 }
381
382 return palette;
383}
384
385// FUNCTION: LEGO1 0x100bd280
386// FUNCTION: BETA10 0x1013d80e
388{
389 // Odd to use a switch on a boolean, but it matches.
390 switch (m_isHighColor) {
391 case FALSE:
392 ImportColorsToPalette(m_paletteData, p_palette);
393 break;
394
395 case TRUE:
396 delete m_palette;
397 m_palette = p_palette->Clone();
398 break;
399 }
400}
401
402// FUNCTION: LEGO1 0x100bd2d0
403// FUNCTION: BETA10 0x1013d8a9
405{
406 MxResult ret = FAILURE;
407 MxPalette* pal = NULL;
408
409 if (m_isHighColor == p_isHighColor) {
410 // no change: do nothing.
411 ret = SUCCESS;
412 goto done;
413 }
414
415 switch (p_isHighColor) {
416 case FALSE:
417 ImportColorsToPalette(m_paletteData, m_palette);
418 delete m_palette;
419 m_palette = NULL;
420 break;
421 case TRUE: {
422 if (!(pal = new MxPalette(m_paletteData))) {
423 goto done;
424 }
425
426 m_palette = pal;
427
428 // TODO: what is this? zeroing out top half of palette?
429 MxU16* buf = (MxU16*) m_paletteData;
430 for (MxU16 i = 0; i < 256; i++) {
431 buf[i] = i;
432 }
433 break;
434 }
435 default:
436 goto done;
437 }
438
439 m_isHighColor = p_isHighColor;
440 ret = SUCCESS;
441
442done:
443 // If we were unsuccessful overall but did manage to alloc
444 // the MxPalette, free it.
445 if (ret && pal) {
446 delete pal;
447 }
448
449 return ret;
450}
451
452// FUNCTION: LEGO1 0x100bd3e0
453// FUNCTION: BETA10 0x1013dad2
455 HDC p_hdc,
456 MxS32 p_xSrc,
457 MxS32 p_ySrc,
458 MxS32 p_xDest,
459 MxS32 p_yDest,
460 MxS32 p_destWidth,
461 MxS32 p_destHeight
462)
463{
464 // Compression fix?
465 if (IsBottomUp()) {
466 p_ySrc = GetBmiHeightAbs() - p_ySrc - p_destHeight;
467 }
468
469 return StretchDIBits(
470 p_hdc,
471 p_xDest,
472 p_yDest,
473 p_destWidth,
474 p_destHeight,
475 p_xSrc,
476 p_ySrc,
477 p_destWidth,
478 p_destHeight,
479 m_data,
480 (BITMAPINFO*) m_info,
481 m_isHighColor,
482 SRCCOPY
483 );
484}
485
486// FUNCTION: LEGO1 0x100bd450
487// FUNCTION: BETA10 0x1013db55
488MxResult MxBitmap::ImportColorsToPalette(RGBQUAD* p_rgbquad, MxPalette* p_palette)
489{
490 MxResult ret = FAILURE;
491 PALETTEENTRY entries[256];
492
493 if (p_palette) {
494 if (p_palette->GetEntries(entries)) {
495 goto done;
496 }
497 }
498 else {
499 MxPalette palette;
500 if (palette.GetEntries(entries)) {
501 goto done;
502 }
503 }
504
505 MxS32 i;
506 for (i = 0; i < 256; i++) {
507 p_rgbquad[i].rgbRed = entries[i].peRed;
508 p_rgbquad[i].rgbGreen = entries[i].peGreen;
509 p_rgbquad[i].rgbBlue = entries[i].peBlue;
510 p_rgbquad[i].rgbReserved = 0;
511 }
512
513 ret = SUCCESS;
514
515done:
516 return ret;
517}
[AI] Represents an 8bpp or high color device-independent bitmap (DIB) and provides operations for bit...
Definition: mxbitmap.h:55
virtual MxResult StretchBits(HDC p_hdc, MxS32 p_xSrc, MxS32 p_ySrc, MxS32 p_xDest, MxS32 p_yDest, MxS32 p_destWidth, MxS32 p_destHeight)
[AI] Draws (blits) a scaled region of the bitmap to a Windows device context.
Definition: mxbitmap.cpp:454
MxBITMAPINFO * GetBitmapInfo() const
[AI] Retrieves the pointer to the underlying MxBITMAPINFO struct (header and palette).
Definition: mxbitmap.h:254
virtual MxResult SetBitDepth(MxBool)
[AI] Changes the bit depth mode for the bitmap (palettized or high color).
Definition: mxbitmap.cpp:404
virtual MxPalette * CreatePalette()
[AI] Allocates or clones the current palette for the bitmap.
Definition: mxbitmap.cpp:352
MxLong AlignToFourByte(MxLong p_value) const
[AI] Aligns a value up to the nearest multiple of four (stride alignment for DIBs).
Definition: mxbitmap.h:204
MxBitmap()
[AI] Constructs an empty MxBitmap instance, initializing all data pointers to NULL.
Definition: mxbitmap.cpp:16
virtual MxResult ImportBitmap(MxBitmap *p_bitmap)
[AI] Imports the contents of another bitmap into this bitmap, allocating new storage and copying meta...
Definition: mxbitmap.cpp:136
MxLong GetBmiHeightAbs() const
[AI] Returns the absolute value of the bitmap's height.
Definition: mxbitmap.h:242
virtual void BitBltTransparent(MxBitmap *p_src, MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom, MxS32 p_width, MxS32 p_height)
[AI] Copies a rectangular region from a source bitmap to this bitmap, but skips "transparent" (index ...
Definition: mxbitmap.cpp:306
~MxBitmap() override
[AI] Frees allocated memory for bitmap info, pixel data, and palette.
Definition: mxbitmap.cpp:28
virtual MxResult SetSize(MxS32 p_width, MxS32 p_height, MxPalette *p_palette, MxBool)
[AI] Allocates the bitmap to a specified width and height, attaches a palette, and configures bit dep...
Definition: mxbitmap.cpp:43
virtual MxLong Read(const char *p_filename)
[AI] Loads a bitmap from a file given its filename.
Definition: mxbitmap.cpp:175
virtual MxResult LoadFile(HANDLE p_handle)
[AI] Loads a bitmap from a file handle, populating header, palette data and pixel data.
Definition: mxbitmap.cpp:202
MxU8 * GetStart(MxS32 p_left, MxS32 p_top) const
[AI] Returns a pointer to the starting address of the pixel data at the specified coordinates.
Definition: mxbitmap.h:288
virtual void ImportPalette(MxPalette *p_palette)
[AI] Attaches or clones a palette for the bitmap and updates color data as needed.
Definition: mxbitmap.cpp:387
MxLong GetDataSize() const
[AI] Computes the total size in bytes for the bitmap's pixel data buffer.
Definition: mxbitmap.h:260
virtual void BitBlt(MxBitmap *p_src, MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom, MxS32 p_width, MxS32 p_height)
[AI] Copies a rectangular area from a source bitmap into this bitmap (BitBlt).
Definition: mxbitmap.cpp:267
MxLong GetBmiWidth() const
[AI] Fetches the width (in pixels) encoded in this bitmap's header.
Definition: mxbitmap.h:224
virtual MxResult ImportBitmapInfo(MxBITMAPINFO *p_info)
[AI] Imports bitmap header/palette info (but not pixel data) from the given info block.
Definition: mxbitmap.cpp:98
MxU8 * GetImage() const
[AI] Retrieves the pointer to the image pixel data.
Definition: mxbitmap.h:248
[AI] Encapsulates a DirectDraw 8-bit (256 color) palette for use with DirectX rendering.
Definition: mxpalette.h:17
MxPalette * Clone()
[AI] Creates a duplicate of this palette object with the same palette data and override flag.
Definition: mxpalette.cpp:160
MxResult GetEntries(LPPALETTEENTRY p_entries)
[AI] Copies all palette entries to external buffer.
Definition: mxpalette.cpp:170
#define TRUE
Definition: d3drmdef.h:28
#define FALSE
Definition: d3drmdef.h:27
typedef DWORD(FAR PASCAL *LPCLIPPERCALLBACK)(LPDIRECTDRAWCLIPPER lpDDClipper
#define DECOMP_SIZE_ASSERT(T, S)
Definition: decomp.h:19
#define NULL
[AI] Null pointer value (C/C++ semantics).
Definition: legotypes.h:26
#define FAILURE
[AI] Used to indicate a failed operation in result codes.
Definition: legotypes.h:34
#define SUCCESS
[AI] Used to indicate a successful operation in result codes.
Definition: legotypes.h:30
MxU16 g_bitmapSignature
Definition: mxbitmap.cpp:12
#define GetAdjustedStride(p_bitmap)
Definition: mxbitmap.h:277
MxU8 MxBool
[AI]
Definition: mxtypes.h:124
MxLong MxResult
[AI]
Definition: mxtypes.h:106
#define TWOCC(a, b)
[AI] Macro to compose a 16-bit code from two 8-bit characters (e.g., for type IDs).
Definition: mxtypes.h:151
int MxLong
[AI]
Definition: mxtypes.h:83
unsigned char MxU8
[AI]
Definition: mxtypes.h:8
signed int MxS32
[AI]
Definition: mxtypes.h:38
unsigned short MxU16
[AI]
Definition: mxtypes.h:20
MxBool GetRectIntersection(MxS32 p_rect1Width, MxS32 p_rect1Height, MxS32 p_rect2Width, MxS32 p_rect2Height, MxS32 *p_rect1Left, MxS32 *p_rect1Top, MxS32 *p_rect2Left, MxS32 *p_rect2Top, MxS32 *p_width, MxS32 *p_height)
Computes intersection of two rectangles and modifies their positions and dimensions to the intersecti...
Definition: mxutilities.cpp:19
[AI] Represents a bitmap information header plus a 256-color palette, matching the layout for 8-bit D...
Definition: mxbitmap.h:25
RGBQUAD m_bmiColors[256]
[AI] 256-entry color palette for 8bpp images.
Definition: mxbitmap.h:27
BITMAPINFOHEADER m_bmiHeader
[AI] Standard DIB bitmap header (size 0x28 bytes).
Definition: mxbitmap.h:26