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 11namespace { 12 13const size_t kBmpCoreHeaderSize = 12; 14const size_t kBmpInfoHeaderSize = 40; 15 16// TODO(thestig): Replace with FXDWORD_GET_LSBFIRST? 17uint32_t GetDWord_LSBFirst(uint8_t* p) { 18 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 19} 20 21void 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 29uint16_t GetWord_LSBFirst(uint8_t* p) { 30 return p[0] | (p[1] << 8); 31} 32void SetWord_LSBFirst(uint8_t* p, uint16_t v) { 33 p[0] = (uint8_t)v; 34 p[1] = (uint8_t)(v >> 8); 35} 36void 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} 41bmp_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} 48void 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} 61int32_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} 297int32_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} 323int32_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} 389int32_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} 491int32_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} 612uint8_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} 622void 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} 628void 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} 635uint32_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} 645bmp_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} 653void 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} 661static 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} 675static 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} 701static 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 784static 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} 807static 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} 818static 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} 852static 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} 863static 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} 899bool 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