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 18 FX_DWORD _GetDWord_LSBFirst(uint8_t* p) { 19 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 20 } 21 FX_WORD _GetWord_LSBFirst(uint8_t* p) { 22 return p[0] | (p[1] << 8); 23 } 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 } 30 void _SetWord_LSBFirst(uint8_t* p, FX_WORD v) { 31 p[0] = (uint8_t)v; 32 p[1] = (uint8_t)(v >> 8); 33 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 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 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 } 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 } 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 } 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 } 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 } 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