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