1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "fx_bmp.h"
8
9 #include <algorithm>
10
11 namespace {
12
13 const size_t kBmpCoreHeaderSize = 12;
14 const size_t kBmpInfoHeaderSize = 40;
15
16 } // namespace
17
_GetDWord_LSBFirst(uint8_t * p)18 FX_DWORD _GetDWord_LSBFirst(uint8_t* p) {
19 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
20 }
_GetWord_LSBFirst(uint8_t * p)21 FX_WORD _GetWord_LSBFirst(uint8_t* p) {
22 return p[0] | (p[1] << 8);
23 }
_SetDWord_LSBFirst(uint8_t * p,FX_DWORD v)24 void _SetDWord_LSBFirst(uint8_t* p, FX_DWORD v) {
25 p[0] = (uint8_t)v;
26 p[1] = (uint8_t)(v >> 8);
27 p[2] = (uint8_t)(v >> 16);
28 p[3] = (uint8_t)(v >> 24);
29 }
_SetWord_LSBFirst(uint8_t * p,FX_WORD v)30 void _SetWord_LSBFirst(uint8_t* p, FX_WORD v) {
31 p[0] = (uint8_t)v;
32 p[1] = (uint8_t)(v >> 8);
33 }
_bmp_error(bmp_decompress_struct_p bmp_ptr,const FX_CHAR * err_msg)34 void _bmp_error(bmp_decompress_struct_p bmp_ptr, const FX_CHAR* err_msg) {
35 if (bmp_ptr != NULL && bmp_ptr->_bmp_error_fn != NULL) {
36 bmp_ptr->_bmp_error_fn(bmp_ptr, err_msg);
37 }
38 }
_bmp_create_decompress()39 bmp_decompress_struct_p _bmp_create_decompress() {
40 bmp_decompress_struct_p bmp_ptr = FX_Alloc(bmp_decompress_struct, 1);
41 if (bmp_ptr == NULL) {
42 return NULL;
43 }
44 FXSYS_memset(bmp_ptr, 0, sizeof(bmp_decompress_struct));
45 bmp_ptr->decode_status = BMP_D_STATUS_HEADER;
46 bmp_ptr->bmp_header_ptr = FX_Alloc(BmpFileHeader, 1);
47 return bmp_ptr;
48 }
_bmp_destroy_decompress(bmp_decompress_struct_pp bmp_ptr_ptr)49 void _bmp_destroy_decompress(bmp_decompress_struct_pp bmp_ptr_ptr) {
50 if (bmp_ptr_ptr == NULL || *bmp_ptr_ptr == NULL) {
51 return;
52 }
53 bmp_decompress_struct_p bmp_ptr = *bmp_ptr_ptr;
54 *bmp_ptr_ptr = NULL;
55 if (bmp_ptr->out_row_buffer != NULL) {
56 FX_Free(bmp_ptr->out_row_buffer);
57 }
58 if (bmp_ptr->pal_ptr != NULL) {
59 FX_Free(bmp_ptr->pal_ptr);
60 }
61 if (bmp_ptr->bmp_header_ptr != NULL) {
62 FX_Free(bmp_ptr->bmp_header_ptr);
63 }
64 FX_Free(bmp_ptr);
65 }
_bmp_read_header(bmp_decompress_struct_p bmp_ptr)66 int32_t _bmp_read_header(bmp_decompress_struct_p bmp_ptr) {
67 if (bmp_ptr == NULL) {
68 return 0;
69 }
70 FX_DWORD skip_size_org = bmp_ptr->skip_size;
71 if (bmp_ptr->decode_status == BMP_D_STATUS_HEADER) {
72 ASSERT(sizeof(BmpFileHeader) == 14);
73 BmpFileHeader* bmp_header_ptr = NULL;
74 if (_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_header_ptr, 14) == NULL) {
75 return 2;
76 }
77 bmp_ptr->bmp_header_ptr->bfType =
78 _GetWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfType);
79 bmp_ptr->bmp_header_ptr->bfOffBits =
80 _GetDWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfOffBits);
81 bmp_ptr->data_size = _GetDWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfSize);
82 if (bmp_ptr->bmp_header_ptr->bfType != BMP_SIGNATURE) {
83 _bmp_error(bmp_ptr, "Not A Bmp Image");
84 return 0;
85 }
86 if (bmp_ptr->avail_in < sizeof(FX_DWORD)) {
87 bmp_ptr->skip_size = skip_size_org;
88 return 2;
89 }
90 bmp_ptr->img_ifh_size =
91 _GetDWord_LSBFirst(bmp_ptr->next_in + bmp_ptr->skip_size);
92 bmp_ptr->pal_type = 0;
93 static_assert(sizeof(BmpCoreHeader) == kBmpCoreHeaderSize,
94 "BmpCoreHeader has wrong size");
95 static_assert(sizeof(BmpInfoHeader) == kBmpInfoHeaderSize,
96 "BmpInfoHeader has wrong size");
97 switch (bmp_ptr->img_ifh_size) {
98 case kBmpCoreHeaderSize: {
99 bmp_ptr->pal_type = 1;
100 BmpCoreHeaderPtr bmp_core_header_ptr = NULL;
101 if (_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_core_header_ptr,
102 bmp_ptr->img_ifh_size) == NULL) {
103 bmp_ptr->skip_size = skip_size_org;
104 return 2;
105 }
106 bmp_ptr->width = (FX_DWORD)_GetWord_LSBFirst(
107 (uint8_t*)&bmp_core_header_ptr->bcWidth);
108 bmp_ptr->height = (FX_DWORD)_GetWord_LSBFirst(
109 (uint8_t*)&bmp_core_header_ptr->bcHeight);
110 bmp_ptr->bitCounts =
111 _GetWord_LSBFirst((uint8_t*)&bmp_core_header_ptr->bcBitCount);
112 bmp_ptr->compress_flag = BMP_RGB;
113 bmp_ptr->imgTB_flag = FALSE;
114 } break;
115 case kBmpInfoHeaderSize: {
116 BmpInfoHeaderPtr bmp_info_header_ptr = NULL;
117 if (_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_info_header_ptr,
118 bmp_ptr->img_ifh_size) == NULL) {
119 bmp_ptr->skip_size = skip_size_org;
120 return 2;
121 }
122 bmp_ptr->width =
123 _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth);
124 bmp_ptr->height =
125 _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight);
126 bmp_ptr->bitCounts =
127 _GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount);
128 bmp_ptr->compress_flag =
129 _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biCompression);
130 bmp_ptr->color_used =
131 _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biClrUsed);
132 bmp_ptr->dpi_x = (int32_t)_GetDWord_LSBFirst(
133 (uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter);
134 bmp_ptr->dpi_y = (int32_t)_GetDWord_LSBFirst(
135 (uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter);
136 if (bmp_ptr->height < 0) {
137 bmp_ptr->height = -bmp_ptr->height;
138 bmp_ptr->imgTB_flag = TRUE;
139 }
140 } break;
141 default: {
142 if (bmp_ptr->img_ifh_size >
143 std::min(kBmpInfoHeaderSize, sizeof(BmpInfoHeader))) {
144 BmpInfoHeaderPtr bmp_info_header_ptr = NULL;
145 if (_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_info_header_ptr,
146 bmp_ptr->img_ifh_size) == NULL) {
147 bmp_ptr->skip_size = skip_size_org;
148 return 2;
149 }
150 FX_WORD biPlanes;
151 bmp_ptr->width =
152 _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth);
153 bmp_ptr->height =
154 _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight);
155 bmp_ptr->bitCounts =
156 _GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount);
157 bmp_ptr->compress_flag =
158 _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biCompression);
159 bmp_ptr->color_used =
160 _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biClrUsed);
161 biPlanes =
162 _GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biPlanes);
163 bmp_ptr->dpi_x = _GetDWord_LSBFirst(
164 (uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter);
165 bmp_ptr->dpi_y = _GetDWord_LSBFirst(
166 (uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter);
167 if (bmp_ptr->height < 0) {
168 bmp_ptr->height = -bmp_ptr->height;
169 bmp_ptr->imgTB_flag = TRUE;
170 }
171 if (bmp_ptr->compress_flag == BMP_RGB && biPlanes == 1 &&
172 bmp_ptr->color_used == 0) {
173 break;
174 }
175 }
176 _bmp_error(bmp_ptr, "Unsupported Bmp File");
177 return 0;
178 }
179 }
180 ASSERT(bmp_ptr->width > 0);
181 ASSERT(bmp_ptr->compress_flag <= BMP_BITFIELDS);
182 switch (bmp_ptr->bitCounts) {
183 case 1:
184 case 4:
185 case 8:
186 case 16:
187 case 24: {
188 if (bmp_ptr->color_used > ((FX_DWORD)1) << bmp_ptr->bitCounts) {
189 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
190 return 0;
191 }
192 }
193 case 32: {
194 if (bmp_ptr->width <= 0 || bmp_ptr->compress_flag > BMP_BITFIELDS) {
195 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
196 return 0;
197 }
198 } break;
199 default:
200 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
201 return 0;
202 }
203 bmp_ptr->src_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, bmp_ptr->bitCounts);
204 switch (bmp_ptr->bitCounts) {
205 case 1:
206 case 4:
207 case 8:
208 bmp_ptr->out_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, 8);
209 bmp_ptr->components = 1;
210 break;
211 case 16:
212 case 24:
213 bmp_ptr->out_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, 24);
214 bmp_ptr->components = 3;
215 break;
216 case 32:
217 bmp_ptr->out_row_bytes = bmp_ptr->src_row_bytes;
218 bmp_ptr->components = 4;
219 break;
220 }
221 if (bmp_ptr->out_row_buffer != NULL) {
222 FX_Free(bmp_ptr->out_row_buffer);
223 bmp_ptr->out_row_buffer = NULL;
224 }
225 bmp_ptr->out_row_buffer = FX_Alloc(uint8_t, bmp_ptr->out_row_bytes);
226 BMP_PTR_NOT_NULL(bmp_ptr->out_row_buffer, bmp_ptr);
227 FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);
228 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_PAL);
229 }
230 if (bmp_ptr->decode_status == BMP_D_STATUS_PAL) {
231 skip_size_org = bmp_ptr->skip_size;
232 #ifdef BMP_SUPPORT_BITFIELD
233 if (bmp_ptr->compress_flag == BMP_BITFIELDS) {
234 if (bmp_ptr->bitCounts != 16 && bmp_ptr->bitCounts != 32) {
235 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
236 return 0;
237 }
238 FX_DWORD* mask;
239 if (_bmp_read_data(bmp_ptr, (uint8_t**)&mask, 3 * sizeof(FX_DWORD)) ==
240 NULL) {
241 bmp_ptr->skip_size = skip_size_org;
242 return 2;
243 }
244 bmp_ptr->mask_red = _GetDWord_LSBFirst((uint8_t*)&mask[0]);
245 bmp_ptr->mask_green = _GetDWord_LSBFirst((uint8_t*)&mask[1]);
246 bmp_ptr->mask_blue = _GetDWord_LSBFirst((uint8_t*)&mask[2]);
247 if (bmp_ptr->mask_red & bmp_ptr->mask_green ||
248 bmp_ptr->mask_red & bmp_ptr->mask_blue ||
249 bmp_ptr->mask_green & bmp_ptr->mask_blue) {
250 _bmp_error(bmp_ptr, "The Bitfield Bmp File Is Corrupt");
251 return 0;
252 }
253 if (bmp_ptr->bmp_header_ptr->bfOffBits < 26 + bmp_ptr->img_ifh_size) {
254 bmp_ptr->bmp_header_ptr->bfOffBits = 26 + bmp_ptr->img_ifh_size;
255 }
256 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA_PRE);
257 return 1;
258 } else if (bmp_ptr->bitCounts == 16) {
259 bmp_ptr->mask_red = 0x7C00;
260 bmp_ptr->mask_green = 0x03E0;
261 bmp_ptr->mask_blue = 0x001F;
262 }
263 #else
264 if (bmp_ptr->compress_flag == BMP_BITFIELDS || bmp_ptr->bitCounts == 16) {
265 _bmp_error(bmp_ptr, "Unsupported Bitfield Bmp File");
266 return 0;
267 }
268 #endif
269 bmp_ptr->pal_num = 0;
270 if (bmp_ptr->bitCounts < 16) {
271 bmp_ptr->pal_num = 1 << bmp_ptr->bitCounts;
272 if (bmp_ptr->color_used != 0) {
273 bmp_ptr->pal_num = bmp_ptr->color_used;
274 }
275 uint8_t* src_pal_ptr = NULL;
276 FX_DWORD src_pal_size = bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4);
277 if (_bmp_read_data(bmp_ptr, (uint8_t**)&src_pal_ptr, src_pal_size) ==
278 NULL) {
279 bmp_ptr->skip_size = skip_size_org;
280 return 2;
281 }
282 if (bmp_ptr->pal_ptr != NULL) {
283 FX_Free(bmp_ptr->pal_ptr);
284 bmp_ptr->pal_ptr = NULL;
285 }
286 bmp_ptr->pal_ptr = FX_Alloc(FX_DWORD, bmp_ptr->pal_num);
287 BMP_PTR_NOT_NULL(bmp_ptr->pal_ptr, bmp_ptr);
288 int32_t src_pal_index = 0;
289 if (bmp_ptr->pal_type == BMP_PAL_OLD) {
290 while (src_pal_index < bmp_ptr->pal_num) {
291 bmp_ptr->pal_ptr[src_pal_index++] = BMP_PAL_ENCODE(
292 0x00, src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]);
293 src_pal_ptr += 3;
294 }
295 } else {
296 while (src_pal_index < bmp_ptr->pal_num) {
297 bmp_ptr->pal_ptr[src_pal_index++] = BMP_PAL_ENCODE(
298 src_pal_ptr[3], src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]);
299 src_pal_ptr += 4;
300 }
301 }
302 }
303 if (bmp_ptr->bmp_header_ptr->bfOffBits <
304 14 + bmp_ptr->img_ifh_size +
305 bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4)) {
306 bmp_ptr->bmp_header_ptr->bfOffBits =
307 14 + bmp_ptr->img_ifh_size +
308 bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4);
309 }
310 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA_PRE);
311 }
312 return 1;
313 }
_bmp_decode_image(bmp_decompress_struct_p bmp_ptr)314 int32_t _bmp_decode_image(bmp_decompress_struct_p bmp_ptr) {
315 if (bmp_ptr->decode_status == BMP_D_STATUS_DATA_PRE) {
316 bmp_ptr->avail_in = 0;
317 if (!bmp_ptr->_bmp_get_data_position_fn(
318 bmp_ptr, bmp_ptr->bmp_header_ptr->bfOffBits)) {
319 bmp_ptr->decode_status = BMP_D_STATUS_TAIL;
320 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt, Unexpected Stream Offset");
321 return 0;
322 }
323 bmp_ptr->row_num = 0;
324 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA);
325 }
326 if (bmp_ptr->decode_status == BMP_D_STATUS_DATA) {
327 switch (bmp_ptr->compress_flag) {
328 case BMP_RGB:
329 case BMP_BITFIELDS:
330 return _bmp_decode_rgb(bmp_ptr);
331 case BMP_RLE8:
332 return _bmp_decode_rle8(bmp_ptr);
333 case BMP_RLE4:
334 return _bmp_decode_rle4(bmp_ptr);
335 }
336 }
337 _bmp_error(bmp_ptr, "Any Uncontrol Error");
338 return 0;
339 }
_bmp_decode_rgb(bmp_decompress_struct_p bmp_ptr)340 int32_t _bmp_decode_rgb(bmp_decompress_struct_p bmp_ptr) {
341 uint8_t* row_buf = bmp_ptr->out_row_buffer;
342 uint8_t* des_buf = NULL;
343 while (bmp_ptr->row_num < bmp_ptr->height) {
344 if (_bmp_read_data(bmp_ptr, &des_buf, bmp_ptr->src_row_bytes) == NULL) {
345 return 2;
346 }
347 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA);
348 switch (bmp_ptr->bitCounts) {
349 case 1: {
350 for (int32_t col = 0; col < bmp_ptr->width; col++) {
351 *row_buf++ = des_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00;
352 }
353 } break;
354 case 4: {
355 for (int32_t col = 0; col < bmp_ptr->width; col++) {
356 *row_buf++ = (col & 0x01) ? (des_buf[col >> 1] & 0x0F)
357 : ((des_buf[col >> 1] & 0xF0) >> 4);
358 }
359 } break;
360 #ifdef BMP_SUPPORT_BITFIELD
361 case 16: {
362 FX_WORD* buf = (FX_WORD*)des_buf;
363 uint8_t blue_bits = 0;
364 uint8_t green_bits = 0;
365 uint8_t red_bits = 0;
366 for (int32_t i = 0; i < 16; i++) {
367 if ((bmp_ptr->mask_blue >> i) & 0x01) {
368 blue_bits++;
369 }
370 if ((bmp_ptr->mask_green >> i) & 0x01) {
371 green_bits++;
372 }
373 if ((bmp_ptr->mask_red >> i) & 0x01) {
374 red_bits++;
375 }
376 }
377 green_bits += blue_bits;
378 red_bits += green_bits;
379 blue_bits = 8 - blue_bits;
380 green_bits -= 8;
381 red_bits -= 8;
382 for (int32_t col = 0; col < bmp_ptr->width; col++) {
383 *buf = _GetWord_LSBFirst((uint8_t*)buf);
384 *row_buf++ = (uint8_t)((*buf & bmp_ptr->mask_blue) << blue_bits);
385 *row_buf++ = (uint8_t)((*buf & bmp_ptr->mask_green) >> green_bits);
386 *row_buf++ = (uint8_t)((*buf++ & bmp_ptr->mask_red) >> red_bits);
387 }
388 } break;
389 #endif
390 case 8:
391 case 24:
392 case 32:
393 FXSYS_memcpy(bmp_ptr->out_row_buffer, des_buf, bmp_ptr->src_row_bytes);
394 break;
395 }
396 row_buf = bmp_ptr->out_row_buffer;
397 bmp_ptr->_bmp_get_row_fn(bmp_ptr,
398 bmp_ptr->imgTB_flag
399 ? bmp_ptr->row_num++
400 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
401 bmp_ptr->out_row_buffer);
402 }
403 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);
404 return 1;
405 }
_bmp_decode_rle8(bmp_decompress_struct_p bmp_ptr)406 int32_t _bmp_decode_rle8(bmp_decompress_struct_p bmp_ptr) {
407 uint8_t* first_byte_ptr = NULL;
408 uint8_t* second_byte_ptr = NULL;
409 bmp_ptr->col_num = 0;
410 while (TRUE) {
411 FX_DWORD skip_size_org = bmp_ptr->skip_size;
412 if (_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) {
413 return 2;
414 }
415 switch (*first_byte_ptr) {
416 case RLE_MARKER: {
417 if (_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) {
418 bmp_ptr->skip_size = skip_size_org;
419 return 2;
420 }
421 switch (*first_byte_ptr) {
422 case RLE_EOL: {
423 if (bmp_ptr->row_num >= bmp_ptr->height) {
424 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);
425 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
426 return 0;
427 }
428 bmp_ptr->_bmp_get_row_fn(
429 bmp_ptr, bmp_ptr->imgTB_flag
430 ? bmp_ptr->row_num++
431 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
432 bmp_ptr->out_row_buffer);
433 bmp_ptr->col_num = 0;
434 FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);
435 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA);
436 continue;
437 }
438 case RLE_EOI: {
439 if (bmp_ptr->row_num < bmp_ptr->height) {
440 bmp_ptr->_bmp_get_row_fn(
441 bmp_ptr, bmp_ptr->imgTB_flag
442 ? bmp_ptr->row_num++
443 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
444 bmp_ptr->out_row_buffer);
445 }
446 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);
447 return 1;
448 }
449 case RLE_DELTA: {
450 uint8_t* delta_ptr;
451 if (_bmp_read_data(bmp_ptr, &delta_ptr, 2) == NULL) {
452 bmp_ptr->skip_size = skip_size_org;
453 return 2;
454 }
455 bmp_ptr->col_num += (int32_t)delta_ptr[0];
456 int32_t bmp_row_num_next = bmp_ptr->row_num + (int32_t)delta_ptr[1];
457 if (bmp_ptr->col_num >= bmp_ptr->out_row_bytes ||
458 bmp_row_num_next >= bmp_ptr->height) {
459 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt Or Not Supported");
460 return 0;
461 }
462 while (bmp_ptr->row_num < bmp_row_num_next) {
463 FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);
464 bmp_ptr->_bmp_get_row_fn(
465 bmp_ptr, bmp_ptr->imgTB_flag
466 ? bmp_ptr->row_num++
467 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
468 bmp_ptr->out_row_buffer);
469 }
470 } break;
471 default: {
472 if ((int32_t)(*first_byte_ptr) >
473 bmp_ptr->src_row_bytes - bmp_ptr->col_num) {
474 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
475 return 0;
476 }
477 if (_bmp_read_data(bmp_ptr, &second_byte_ptr,
478 *first_byte_ptr & 1 ? *first_byte_ptr + 1
479 : *first_byte_ptr) == NULL) {
480 bmp_ptr->skip_size = skip_size_org;
481 return 2;
482 }
483 FXSYS_memcpy(bmp_ptr->out_row_buffer + bmp_ptr->col_num,
484 second_byte_ptr, *first_byte_ptr);
485 bmp_ptr->col_num += (int32_t)(*first_byte_ptr);
486 }
487 }
488 } break;
489 default: {
490 if (_bmp_read_data(bmp_ptr, &second_byte_ptr, 1) == NULL) {
491 bmp_ptr->skip_size = skip_size_org;
492 return 2;
493 }
494 if ((int32_t)(*first_byte_ptr) >
495 bmp_ptr->src_row_bytes - bmp_ptr->col_num) {
496 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
497 return 0;
498 }
499 FXSYS_memset(bmp_ptr->out_row_buffer + bmp_ptr->col_num,
500 *second_byte_ptr, *first_byte_ptr);
501 bmp_ptr->col_num += (int32_t)(*first_byte_ptr);
502 }
503 }
504 }
505 _bmp_error(bmp_ptr, "Any Uncontrol Error");
506 return 0;
507 }
_bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr)508 int32_t _bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr) {
509 uint8_t* first_byte_ptr = NULL;
510 uint8_t* second_byte_ptr = NULL;
511 bmp_ptr->col_num = 0;
512 while (TRUE) {
513 FX_DWORD skip_size_org = bmp_ptr->skip_size;
514 if (_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) {
515 return 2;
516 }
517 switch (*first_byte_ptr) {
518 case RLE_MARKER: {
519 if (_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) {
520 bmp_ptr->skip_size = skip_size_org;
521 return 2;
522 }
523 switch (*first_byte_ptr) {
524 case RLE_EOL: {
525 if (bmp_ptr->row_num >= bmp_ptr->height) {
526 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);
527 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
528 return 0;
529 }
530 bmp_ptr->_bmp_get_row_fn(
531 bmp_ptr, bmp_ptr->imgTB_flag
532 ? bmp_ptr->row_num++
533 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
534 bmp_ptr->out_row_buffer);
535 bmp_ptr->col_num = 0;
536 FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);
537 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA);
538 continue;
539 }
540 case RLE_EOI: {
541 if (bmp_ptr->row_num < bmp_ptr->height) {
542 bmp_ptr->_bmp_get_row_fn(
543 bmp_ptr, bmp_ptr->imgTB_flag
544 ? bmp_ptr->row_num++
545 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
546 bmp_ptr->out_row_buffer);
547 }
548 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);
549 return 1;
550 }
551 case RLE_DELTA: {
552 uint8_t* delta_ptr;
553 if (_bmp_read_data(bmp_ptr, &delta_ptr, 2) == NULL) {
554 bmp_ptr->skip_size = skip_size_org;
555 return 2;
556 }
557 bmp_ptr->col_num += (int32_t)delta_ptr[0];
558 int32_t bmp_row_num_next = bmp_ptr->row_num + (int32_t)delta_ptr[1];
559 if (bmp_ptr->col_num >= bmp_ptr->out_row_bytes ||
560 bmp_row_num_next >= bmp_ptr->height) {
561 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt Or Not Supported");
562 return 0;
563 }
564 while (bmp_ptr->row_num < bmp_row_num_next) {
565 FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);
566 bmp_ptr->_bmp_get_row_fn(
567 bmp_ptr, bmp_ptr->imgTB_flag
568 ? bmp_ptr->row_num++
569 : (bmp_ptr->height - 1 - bmp_ptr->row_num++),
570 bmp_ptr->out_row_buffer);
571 }
572 } break;
573 default: {
574 uint8_t size = (uint8_t)(((FX_WORD)(*first_byte_ptr) + 1) >> 1);
575 if ((int32_t)*first_byte_ptr >=
576 bmp_ptr->out_row_bytes - bmp_ptr->col_num) {
577 if (size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) {
578 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
579 return 0;
580 }
581 *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1;
582 }
583 if (_bmp_read_data(bmp_ptr, &second_byte_ptr,
584 size & 1 ? size + 1 : size) == NULL) {
585 bmp_ptr->skip_size = skip_size_org;
586 return 2;
587 }
588 for (uint8_t i = 0; i < *first_byte_ptr; i++) {
589 if (i & 0x01) {
590 *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) =
591 (*second_byte_ptr++ & 0x0F);
592 } else {
593 *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) =
594 ((*second_byte_ptr & 0xF0) >> 4);
595 }
596 }
597 }
598 }
599 } break;
600 default: {
601 if (_bmp_read_data(bmp_ptr, &second_byte_ptr, 1) == NULL) {
602 bmp_ptr->skip_size = skip_size_org;
603 return 2;
604 }
605 if ((int32_t)*first_byte_ptr >
606 bmp_ptr->out_row_bytes - bmp_ptr->col_num) {
607 uint8_t size = (uint8_t)(((FX_WORD)(*first_byte_ptr) + 1) >> 1);
608 if (size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) {
609 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");
610 return 0;
611 }
612 *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1;
613 }
614 for (uint8_t i = 0; i < *first_byte_ptr; i++) {
615 if (i & 0x01) {
616 *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) =
617 (*second_byte_ptr & 0x0F);
618 } else {
619 *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) =
620 ((*second_byte_ptr & 0xF0) >> 4);
621 }
622 }
623 }
624 }
625 }
626 _bmp_error(bmp_ptr, "Any Uncontrol Error");
627 return 0;
628 }
_bmp_read_data(bmp_decompress_struct_p bmp_ptr,uint8_t ** des_buf_pp,FX_DWORD data_size)629 uint8_t* _bmp_read_data(bmp_decompress_struct_p bmp_ptr,
630 uint8_t** des_buf_pp,
631 FX_DWORD data_size) {
632 if (bmp_ptr == NULL || bmp_ptr->avail_in < bmp_ptr->skip_size + data_size) {
633 return NULL;
634 }
635 *des_buf_pp = bmp_ptr->next_in + bmp_ptr->skip_size;
636 bmp_ptr->skip_size += data_size;
637 return *des_buf_pp;
638 }
_bmp_save_decoding_status(bmp_decompress_struct_p bmp_ptr,int32_t status)639 void _bmp_save_decoding_status(bmp_decompress_struct_p bmp_ptr,
640 int32_t status) {
641 bmp_ptr->decode_status = status;
642 bmp_ptr->next_in += bmp_ptr->skip_size;
643 bmp_ptr->avail_in -= bmp_ptr->skip_size;
644 bmp_ptr->skip_size = 0;
645 }
_bmp_input_buffer(bmp_decompress_struct_p bmp_ptr,uint8_t * src_buf,FX_DWORD src_size)646 void _bmp_input_buffer(bmp_decompress_struct_p bmp_ptr,
647 uint8_t* src_buf,
648 FX_DWORD src_size) {
649 bmp_ptr->next_in = src_buf;
650 bmp_ptr->avail_in = src_size;
651 bmp_ptr->skip_size = 0;
652 }
_bmp_get_avail_input(bmp_decompress_struct_p bmp_ptr,uint8_t ** avial_buf_ptr)653 FX_DWORD _bmp_get_avail_input(bmp_decompress_struct_p bmp_ptr,
654 uint8_t** avial_buf_ptr) {
655 if (avial_buf_ptr != NULL) {
656 *avial_buf_ptr = NULL;
657 if (bmp_ptr->avail_in > 0) {
658 *avial_buf_ptr = bmp_ptr->next_in;
659 }
660 }
661 return bmp_ptr->avail_in;
662 }
_bmp_create_compress()663 bmp_compress_struct_p _bmp_create_compress() {
664 bmp_compress_struct_p bmp_ptr;
665 bmp_ptr = FX_Alloc(bmp_compress_struct, 1);
666 if (bmp_ptr) {
667 FXSYS_memset(bmp_ptr, 0, sizeof(bmp_compress_struct));
668 }
669 return bmp_ptr;
670 }
_bmp_destroy_compress(bmp_compress_struct_p bmp_ptr)671 void _bmp_destroy_compress(bmp_compress_struct_p bmp_ptr) {
672 if (bmp_ptr) {
673 if (bmp_ptr->src_free && bmp_ptr->src_buf) {
674 FX_Free(bmp_ptr->src_buf);
675 }
676 FX_Free(bmp_ptr);
677 }
678 }
WriteFileHeader(BmpFileHeaderPtr head_ptr,uint8_t * dst_buf)679 static void WriteFileHeader(BmpFileHeaderPtr head_ptr, uint8_t* dst_buf) {
680 FX_DWORD offset;
681 offset = 0;
682 _SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfType);
683 offset += 2;
684 _SetDWord_LSBFirst(&dst_buf[offset], head_ptr->bfSize);
685 offset += 4;
686 _SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfReserved1);
687 offset += 2;
688 _SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfReserved2);
689 offset += 2;
690 _SetDWord_LSBFirst(&dst_buf[offset], head_ptr->bfOffBits);
691 offset += 4;
692 }
WriteInfoHeader(BmpInfoHeaderPtr info_head_ptr,uint8_t * dst_buf)693 static void WriteInfoHeader(BmpInfoHeaderPtr info_head_ptr, uint8_t* dst_buf) {
694 FX_DWORD offset;
695 offset = sizeof(BmpFileHeader);
696 _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biSize);
697 offset += 4;
698 _SetDWord_LSBFirst(&dst_buf[offset], (FX_DWORD)info_head_ptr->biWidth);
699 offset += 4;
700 _SetDWord_LSBFirst(&dst_buf[offset], (FX_DWORD)info_head_ptr->biHeight);
701 offset += 4;
702 _SetWord_LSBFirst(&dst_buf[offset], info_head_ptr->biPlanes);
703 offset += 2;
704 _SetWord_LSBFirst(&dst_buf[offset], info_head_ptr->biBitCount);
705 offset += 2;
706 _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biCompression);
707 offset += 4;
708 _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biSizeImage);
709 offset += 4;
710 _SetDWord_LSBFirst(&dst_buf[offset],
711 (FX_DWORD)info_head_ptr->biXPelsPerMeter);
712 offset += 4;
713 _SetDWord_LSBFirst(&dst_buf[offset],
714 (FX_DWORD)info_head_ptr->biYPelsPerMeter);
715 offset += 4;
716 _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biClrUsed);
717 offset += 4;
718 _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biClrImportant);
719 offset += 4;
720 }
721 #ifdef BMP_SUPPORT_BITFIELD
_bmp_encode_bitfields(bmp_compress_struct_p bmp_ptr,uint8_t * & dst_buf,FX_DWORD & dst_size)722 static void _bmp_encode_bitfields(bmp_compress_struct_p bmp_ptr,
723 uint8_t*& dst_buf,
724 FX_DWORD& dst_size) {
725 if (bmp_ptr->info_header.biBitCount != 16 &&
726 bmp_ptr->info_header.biBitCount != 32) {
727 return;
728 }
729 FX_DWORD size, dst_pos, i;
730 size = bmp_ptr->src_pitch * bmp_ptr->src_row *
731 bmp_ptr->info_header.biBitCount / 16;
732 dst_pos = bmp_ptr->file_header.bfOffBits;
733 dst_size += size;
734 dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size);
735 if (dst_buf == NULL) {
736 return;
737 }
738 FXSYS_memset(&dst_buf[dst_pos], 0, size);
739 FX_DWORD mask_red;
740 FX_DWORD mask_green;
741 FX_DWORD mask_blue;
742 mask_red = 0x7C00;
743 mask_green = 0x03E0;
744 mask_blue = 0x001F;
745 if (bmp_ptr->info_header.biCompression == BMP_BITFIELDS) {
746 if (bmp_ptr->bit_type == BMP_BIT_565) {
747 mask_red = 0xF800;
748 mask_green = 0x07E0;
749 mask_blue = 0x001F;
750 }
751 if (bmp_ptr->info_header.biBitCount == 32) {
752 mask_red = 0xFF0000;
753 mask_green = 0x00FF00;
754 mask_blue = 0x0000FF;
755 }
756 _SetDWord_LSBFirst(&dst_buf[dst_pos], mask_red);
757 dst_pos += 4;
758 _SetDWord_LSBFirst(&dst_buf[dst_pos], mask_green);
759 dst_pos += 4;
760 _SetDWord_LSBFirst(&dst_buf[dst_pos], mask_blue);
761 dst_pos += 4;
762 bmp_ptr->file_header.bfOffBits = dst_pos;
763 }
764 uint8_t blue_bits = 0;
765 uint8_t green_bits = 0;
766 uint8_t red_bits = 0;
767 for (i = 0; i < bmp_ptr->info_header.biBitCount; i++) {
768 if ((mask_blue >> i) & 0x01) {
769 blue_bits++;
770 }
771 if ((mask_green >> i) & 0x01) {
772 green_bits++;
773 }
774 if ((mask_red >> i) & 0x01) {
775 red_bits++;
776 }
777 }
778 green_bits += blue_bits;
779 red_bits += green_bits;
780 blue_bits = 8 - blue_bits;
781 green_bits -= 8;
782 red_bits -= 8;
783 i = 0;
784 for (int32_t row_num = bmp_ptr->src_row - 1; row_num > -1; row_num--, i = 0) {
785 while (i < bmp_ptr->src_width * bmp_ptr->src_bpp / 8) {
786 uint8_t b = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++];
787 uint8_t g = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++];
788 uint8_t r = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++];
789 if (bmp_ptr->src_bpp == 32) {
790 i++;
791 }
792 FX_DWORD pix_val = 0;
793 pix_val |= (b >> blue_bits) & mask_blue;
794 pix_val |= (g << green_bits) & mask_green;
795 pix_val |= (r << red_bits) & mask_red;
796 if (bmp_ptr->info_header.biBitCount == 16) {
797 _SetWord_LSBFirst(&dst_buf[dst_pos], (FX_WORD)pix_val);
798 dst_pos += 2;
799 } else {
800 _SetDWord_LSBFirst(&dst_buf[dst_pos], pix_val);
801 dst_pos += 4;
802 }
803 }
804 }
805 dst_size = dst_pos;
806 }
807 #endif
_bmp_encode_rgb(bmp_compress_struct_p bmp_ptr,uint8_t * & dst_buf,FX_DWORD & dst_size)808 static void _bmp_encode_rgb(bmp_compress_struct_p bmp_ptr,
809 uint8_t*& dst_buf,
810 FX_DWORD& dst_size) {
811 if (bmp_ptr->info_header.biBitCount == 16) {
812 #ifdef BMP_SUPPORT_BITFIELD
813 _bmp_encode_bitfields(bmp_ptr, dst_buf, dst_size);
814 #endif
815 return;
816 }
817 FX_DWORD size, dst_pos;
818 FX_DWORD dst_pitch =
819 (bmp_ptr->src_width * bmp_ptr->info_header.biBitCount + 31) / 32 * 4;
820 size = dst_pitch * bmp_ptr->src_row;
821 dst_pos = bmp_ptr->file_header.bfOffBits;
822 dst_size += size;
823 dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size);
824 if (dst_buf == NULL) {
825 return;
826 }
827 FXSYS_memset(&dst_buf[dst_pos], 0, size);
828 for (int32_t row_num = bmp_ptr->src_row - 1; row_num > -1; row_num--) {
829 FXSYS_memcpy(&dst_buf[dst_pos],
830 &bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch],
831 bmp_ptr->src_pitch);
832 dst_pos += dst_pitch;
833 }
834 dst_size = dst_pos;
835 }
_bmp_rle8_search(const uint8_t * buf,int32_t len)836 static uint8_t _bmp_rle8_search(const uint8_t* buf, int32_t len) {
837 uint8_t num;
838 num = 1;
839 while (num < len) {
840 if (buf[num - 1] != buf[num] || num == 0xFF) {
841 break;
842 }
843 num++;
844 }
845 return num;
846 }
_bmp_encode_rle8(bmp_compress_struct_p bmp_ptr,uint8_t * & dst_buf,FX_DWORD & dst_size)847 static void _bmp_encode_rle8(bmp_compress_struct_p bmp_ptr,
848 uint8_t*& dst_buf,
849 FX_DWORD& dst_size) {
850 FX_DWORD size, dst_pos, index;
851 uint8_t rle[2] = {0};
852 size = bmp_ptr->src_pitch * bmp_ptr->src_row * 2;
853 dst_pos = bmp_ptr->file_header.bfOffBits;
854 dst_size += size;
855 dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size);
856 if (dst_buf == NULL) {
857 return;
858 }
859 FXSYS_memset(&dst_buf[dst_pos], 0, size);
860 for (int32_t row_num = bmp_ptr->src_row - 1, i = 0; row_num > -1;) {
861 index = row_num * bmp_ptr->src_pitch;
862 rle[0] = _bmp_rle8_search(&bmp_ptr->src_buf[index + i], size - index - i);
863 rle[1] = bmp_ptr->src_buf[index + i];
864 if (i + rle[0] >= (int32_t)bmp_ptr->src_pitch) {
865 rle[0] = uint8_t(bmp_ptr->src_pitch - i);
866 if (rle[0]) {
867 dst_buf[dst_pos++] = rle[0];
868 dst_buf[dst_pos++] = rle[1];
869 }
870 dst_buf[dst_pos++] = RLE_MARKER;
871 dst_buf[dst_pos++] = RLE_EOL;
872 i = 0;
873 row_num--;
874 } else {
875 i += rle[0];
876 dst_buf[dst_pos++] = rle[0];
877 dst_buf[dst_pos++] = rle[1];
878 }
879 }
880 dst_buf[dst_pos++] = RLE_MARKER;
881 dst_buf[dst_pos++] = RLE_EOI;
882 dst_size = dst_pos;
883 }
_bmp_rle4_search(const uint8_t * buf,int32_t len)884 static uint8_t _bmp_rle4_search(const uint8_t* buf, int32_t len) {
885 uint8_t num;
886 num = 2;
887 while (num < len) {
888 if (buf[num - 2] != buf[num] || num == 0xFF) {
889 break;
890 }
891 num++;
892 }
893 return num;
894 }
_bmp_encode_rle4(bmp_compress_struct_p bmp_ptr,uint8_t * & dst_buf,FX_DWORD & dst_size)895 static void _bmp_encode_rle4(bmp_compress_struct_p bmp_ptr,
896 uint8_t*& dst_buf,
897 FX_DWORD& dst_size) {
898 FX_DWORD size, dst_pos, index;
899 uint8_t rle[2] = {0};
900 size = bmp_ptr->src_pitch * bmp_ptr->src_row;
901 dst_pos = bmp_ptr->file_header.bfOffBits;
902 dst_size += size;
903 dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size);
904 if (dst_buf == NULL) {
905 return;
906 }
907 FXSYS_memset(&dst_buf[dst_pos], 0, size);
908 for (int32_t row_num = bmp_ptr->src_row - 1, i = 0; row_num > -1;
909 rle[1] = 0) {
910 index = row_num * bmp_ptr->src_pitch;
911 rle[0] = _bmp_rle4_search(&bmp_ptr->src_buf[index + i], size - index - i);
912 rle[1] |= (bmp_ptr->src_buf[index + i] & 0x0f) << 4;
913 rle[1] |= bmp_ptr->src_buf[index + i + 1] & 0x0f;
914 if (i + rle[0] >= (int32_t)bmp_ptr->src_pitch) {
915 rle[0] = uint8_t(bmp_ptr->src_pitch - i);
916 if (rle[0]) {
917 dst_buf[dst_pos++] = rle[0];
918 dst_buf[dst_pos++] = rle[1];
919 }
920 dst_buf[dst_pos++] = RLE_MARKER;
921 dst_buf[dst_pos++] = RLE_EOL;
922 i = 0;
923 row_num--;
924 } else {
925 i += rle[0];
926 dst_buf[dst_pos++] = rle[0];
927 dst_buf[dst_pos++] = rle[1];
928 }
929 }
930 dst_buf[dst_pos++] = RLE_MARKER;
931 dst_buf[dst_pos++] = RLE_EOI;
932 dst_size = dst_pos;
933 }
_bmp_encode_image(bmp_compress_struct_p bmp_ptr,uint8_t * & dst_buf,FX_DWORD & dst_size)934 FX_BOOL _bmp_encode_image(bmp_compress_struct_p bmp_ptr,
935 uint8_t*& dst_buf,
936 FX_DWORD& dst_size) {
937 FX_DWORD head_size = sizeof(BmpFileHeader) + sizeof(BmpInfoHeader);
938 FX_DWORD pal_size = sizeof(FX_DWORD) * bmp_ptr->pal_num;
939 if (bmp_ptr->info_header.biClrUsed > 0 &&
940 bmp_ptr->info_header.biClrUsed < bmp_ptr->pal_num) {
941 pal_size = sizeof(FX_DWORD) * bmp_ptr->info_header.biClrUsed;
942 }
943 dst_size = head_size + sizeof(FX_DWORD) * bmp_ptr->pal_num;
944 dst_buf = FX_TryAlloc(uint8_t, dst_size);
945 if (dst_buf == NULL) {
946 return FALSE;
947 }
948 FXSYS_memset(dst_buf, 0, dst_size);
949 bmp_ptr->file_header.bfOffBits = head_size;
950 if (bmp_ptr->pal_ptr && pal_size) {
951 FXSYS_memcpy(&dst_buf[head_size], bmp_ptr->pal_ptr, pal_size);
952 bmp_ptr->file_header.bfOffBits += pal_size;
953 }
954 WriteInfoHeader(&bmp_ptr->info_header, dst_buf);
955 switch (bmp_ptr->info_header.biCompression) {
956 case BMP_RGB:
957 _bmp_encode_rgb(bmp_ptr, dst_buf, dst_size);
958 break;
959 case BMP_BITFIELDS:
960 #ifdef BMP_SUPPORT_BITFIELD
961 _bmp_encode_bitfields(bmp_ptr, dst_buf, dst_size);
962 #endif
963 break;
964 case BMP_RLE8:
965 _bmp_encode_rle8(bmp_ptr, dst_buf, dst_size);
966 break;
967 case BMP_RLE4:
968 _bmp_encode_rle4(bmp_ptr, dst_buf, dst_size);
969 break;
970 default:;
971 }
972 bmp_ptr->file_header.bfSize = dst_size;
973 WriteFileHeader(&bmp_ptr->file_header, dst_buf);
974 return TRUE;
975 }
976