7#include "core/fxcodec/bmp/cfx_bmpdecompressor.h"
15#include "core/fxcodec/bmp/cfx_bmpcontext.h"
16#include "core/fxcodec/cfx_codec_memory.h"
17#include "core/fxcrt/data_vector.h"
18#include "core/fxcrt/fx_safe_types.h"
19#include "core/fxcrt/fx_system.h"
20#include "core/fxcrt/span_util.h"
21#include "core/fxge/calculate_pitch.h"
22#include "third_party/base/numerics/safe_math.h"
28#define BMP_PAL_ENCODE(a, r, g, b)
29 (((uint32_t)(a) << 24
) | ((r) << 16
) | ((g) << 8
) | (b))
31constexpr size_t kBmpCoreHeaderSize = 12;
32constexpr size_t kBmpInfoHeaderSize = 40;
35 "BmpCoreHeader has wrong size");
37 "BmpInfoHeader has wrong size");
39constexpr uint16_t kBmpSignature = 0x4D42;
40constexpr uint8_t kRleMarker = 0;
41constexpr uint8_t kRleEol = 0;
42constexpr uint8_t kRleEoi = 1;
43constexpr uint8_t kRleDelta = 2;
44constexpr uint32_t kBmpRgb = 0L;
45constexpr uint32_t kBmpRle8 = 1L;
46constexpr uint32_t kBmpRle4 = 2L;
47constexpr uint32_t kBmpBitfields = 3L;
50constexpr uint32_t kBmpMaxImageDimension = 65535;
52uint8_t HalfRoundUp(uint8_t value) {
53 uint16_t value16 = value;
54 return static_cast<uint8_t>((value16 + 1) / 2);
65 uint32_t row = img_tb_flag_ ? row_num_ : (height_ - 1 - row_num_);
66 context_->m_pDelegate->BmpReadScanline(row, out_row_buffer_);
71 return context_->m_pDelegate->BmpInputImagePositionBuf(rcd_pos);
75 if (decode_status_ == DecodeStatus::kHeader) {
81 if (decode_status_ != DecodeStatus::kPal)
84 if (compress_flag_ == kBmpBitfields)
85 return ReadBmpBitfields();
87 return ReadBmpPalette();
93 pdfium::as_writable_bytes(pdfium::span_from_ref(bmp_header)))) {
98 FXSYS_UINT16_GET_LSBFIRST(
reinterpret_cast<uint8_t*>(&bmp_header
.bfType));
99 data_offset_ = FXSYS_UINT32_GET_LSBFIRST(
100 reinterpret_cast<uint8_t*>(&bmp_header
.bfOffBits));
102 FXSYS_UINT32_GET_LSBFIRST(
reinterpret_cast<uint8_t*>(&bmp_header
.bfSize));
103 if (bmp_header
.bfType != kBmpSignature)
106 size_t pos = input_buffer_->GetPosition();
108 pdfium::as_writable_bytes(pdfium::span_from_ref(img_ifh_size_)))) {
111 if (!input_buffer_->Seek(pos))
115 FXSYS_UINT32_GET_LSBFIRST(
reinterpret_cast<uint8_t*>(&img_ifh_size_));
116 pal_type_ = PalType::kNew;
121 return ReadBmpHeaderDimensions();
125 if (img_ifh_size_ == kBmpCoreHeaderSize) {
126 pal_type_ = PalType::kOld;
128 if (!ReadAllOrNone(pdfium::as_writable_bytes(
129 pdfium::span_from_ref(bmp_core_header)))) {
133 width_ = FXSYS_UINT16_GET_LSBFIRST(
134 reinterpret_cast<uint8_t*>(&bmp_core_header
.bcWidth));
135 height_ = FXSYS_UINT16_GET_LSBFIRST(
136 reinterpret_cast<uint8_t*>(&bmp_core_header
.bcHeight));
137 bit_counts_ = FXSYS_UINT16_GET_LSBFIRST(
138 reinterpret_cast<uint8_t*>(&bmp_core_header
.bcBitCount));
139 compress_flag_ = kBmpRgb;
140 img_tb_flag_ =
false;
144 if (img_ifh_size_ == kBmpInfoHeaderSize) {
146 if (!ReadAllOrNone(pdfium::as_writable_bytes(
147 pdfium::span_from_ref(bmp_info_header)))) {
151 width_ = FXSYS_UINT32_GET_LSBFIRST(
152 reinterpret_cast<uint8_t*>(&bmp_info_header
.biWidth));
153 int32_t signed_height = FXSYS_UINT32_GET_LSBFIRST(
154 reinterpret_cast<uint8_t*>(&bmp_info_header
.biHeight));
155 bit_counts_ = FXSYS_UINT16_GET_LSBFIRST(
156 reinterpret_cast<uint8_t*>(&bmp_info_header
.biBitCount));
157 compress_flag_ = FXSYS_UINT32_GET_LSBFIRST(
159 color_used_ = FXSYS_UINT32_GET_LSBFIRST(
160 reinterpret_cast<uint8_t*>(&bmp_info_header
.biClrUsed));
161 dpi_x_ =
static_cast<int32_t>(FXSYS_UINT32_GET_LSBFIRST(
163 dpi_y_ =
static_cast<int32_t>(FXSYS_UINT32_GET_LSBFIRST(
165 if (!SetHeight(signed_height))
173 FX_SAFE_SIZE_T new_pos = input_buffer_->GetPosition();
176 pdfium::as_writable_bytes(pdfium::span_from_ref(bmp_info_header)))) {
180 new_pos += img_ifh_size_;
181 if (!new_pos.IsValid())
184 if (!input_buffer_->Seek(new_pos.ValueOrDie()))
188 width_ = FXSYS_UINT32_GET_LSBFIRST(
189 reinterpret_cast<uint8_t*>(&bmp_info_header
.biWidth));
190 int32_t signed_height = FXSYS_UINT32_GET_LSBFIRST(
191 reinterpret_cast<uint8_t*>(&bmp_info_header
.biHeight));
192 bit_counts_ = FXSYS_UINT16_GET_LSBFIRST(
193 reinterpret_cast<uint8_t*>(&bmp_info_header
.biBitCount));
194 compress_flag_ = FXSYS_UINT32_GET_LSBFIRST(
196 color_used_ = FXSYS_UINT32_GET_LSBFIRST(
197 reinterpret_cast<uint8_t*>(&bmp_info_header
.biClrUsed));
198 bi_planes = FXSYS_UINT16_GET_LSBFIRST(
199 reinterpret_cast<uint8_t*>(&bmp_info_header
.biPlanes));
200 dpi_x_ = FXSYS_UINT32_GET_LSBFIRST(
202 dpi_y_ = FXSYS_UINT32_GET_LSBFIRST(
204 if (!SetHeight(signed_height))
206 if (compress_flag_ != kBmpRgb || bi_planes != 1 || color_used_ != 0)
212 if (width_ > kBmpMaxImageDimension || height_ > kBmpMaxImageDimension ||
213 compress_flag_ > kBmpBitfields) {
217 switch (bit_counts_) {
223 if (color_used_ > 1U << bit_counts_)
232 absl::optional<uint32_t> stride = fxge::CalculatePitch32(bit_counts_, width_);
233 if (!stride.has_value())
236 src_row_bytes_ = stride.value();
237 switch (bit_counts_) {
241 stride = fxge::CalculatePitch32(8, width_);
242 if (!stride.has_value())
244 out_row_bytes_ = stride.value();
249 stride = fxge::CalculatePitch32(24, width_);
250 if (!stride.has_value())
252 out_row_bytes_ = stride.value();
256 out_row_bytes_ = src_row_bytes_;
260 out_row_buffer_.clear();
262 if (out_row_bytes_ <= 0)
265 out_row_buffer_.resize(out_row_bytes_);
266 SaveDecodingStatus(DecodeStatus::kPal);
271 if (bit_counts_ != 16 && bit_counts_ != 32)
275 if (!ReadAllOrNone(pdfium::as_writable_bytes(pdfium::make_span(masks))))
278 mask_red_ = FXSYS_UINT32_GET_LSBFIRST(
reinterpret_cast<uint8_t*>(&masks[0]));
280 FXSYS_UINT32_GET_LSBFIRST(
reinterpret_cast<uint8_t*>(&masks[1]));
281 mask_blue_ = FXSYS_UINT32_GET_LSBFIRST(
reinterpret_cast<uint8_t*>(&masks[2]));
282 if (mask_red_ & mask_green_ || mask_red_ & mask_blue_ ||
283 mask_green_ & mask_blue_) {
286 header_offset_ =
std::max(header_offset_, 26 + img_ifh_size_);
287 SaveDecodingStatus(DecodeStatus::kDataPre);
292 if (bit_counts_ == 16) {
294 mask_green_ = 0x03E0;
298 if (bit_counts_ < 16) {
299 pal_num_ = 1 << bit_counts_;
300 if (color_used_ != 0)
301 pal_num_ = color_used_;
302 size_t src_pal_size = pal_num_ * PaletteChannelCount();
303 DataVector<uint8_t> src_pal(src_pal_size);
304 uint8_t* src_pal_data = src_pal.data();
305 if (!ReadAllOrNone(src_pal))
308 palette_.resize(pal_num_);
309 int32_t src_pal_index = 0;
310 if (pal_type_ == PalType::kOld) {
311 while (src_pal_index < pal_num_) {
313 0x00, src_pal_data[2], src_pal_data[1], src_pal_data[0]);
317 while (src_pal_index < pal_num_) {
319 src_pal_data[3], src_pal_data[2], src_pal_data[1], src_pal_data[0]);
324 header_offset_ =
std::max(
325 header_offset_, 14 + img_ifh_size_ + pal_num_ * PaletteChannelCount());
326 SaveDecodingStatus(DecodeStatus::kDataPre);
331 switch (compress_flag_) {
343 if (decode_status_ == DecodeStatus::kDataPre) {
346 data_offset_ =
std::max(header_offset_, data_offset_);
348 input_buffer_->Seek(input_buffer_->GetSize());
349 if (!GetDataPosition(data_offset_)) {
350 decode_status_ = DecodeStatus::kTail;
355 SaveDecodingStatus(DecodeStatus::kData);
357 if (decode_status_ != DecodeStatus::kData || !ValidateFlag())
360 switch (compress_flag_) {
374 return val < pal_num_;
378 DataVector<uint8_t> dest_buf(src_row_bytes_);
379 while (row_num_ < height_) {
381 if (!ReadAllOrNone(dest_buf))
384 SaveDecodingStatus(DecodeStatus::kData);
385 switch (bit_counts_) {
387 for (uint32_t col = 0; col < width_; ++col) {
389 dest_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00;
390 if (!ValidateColorIndex(index))
392 out_row_buffer_[idx++] = index;
397 for (uint32_t col = 0; col < width_; ++col) {
398 uint8_t index = (col & 0x01) ? (dest_buf[col >> 1] & 0x0F)
399 : ((dest_buf[col >> 1] & 0xF0) >> 4);
400 if (!ValidateColorIndex(index))
402 out_row_buffer_[idx++] = index;
407 for (uint32_t col = 0; col < width_; ++col) {
408 uint8_t index = dest_buf[col];
409 if (!ValidateColorIndex(index))
411 out_row_buffer_[idx++] = index;
416 uint16_t* buf =
reinterpret_cast<uint16_t*>(dest_buf.data());
417 uint8_t blue_bits = 0;
418 uint8_t green_bits = 0;
419 uint8_t red_bits = 0;
420 for (int32_t i = 0; i < 16; i++) {
421 if ((mask_blue_ >> i) & 0x01)
423 if ((mask_green_ >> i) & 0x01)
425 if ((mask_red_ >> i) & 0x01)
428 green_bits += blue_bits;
429 red_bits += green_bits;
430 if (blue_bits > 8 || green_bits < 8 || red_bits < 8)
432 blue_bits = 8 - blue_bits;
435 for (uint32_t col = 0; col < width_; ++col) {
436 *buf = FXSYS_UINT16_GET_LSBFIRST(
reinterpret_cast<uint8_t*>(buf));
437 out_row_buffer_[idx++] =
438 static_cast<uint8_t>((*buf & mask_blue_) << blue_bits);
439 out_row_buffer_[idx++] =
440 static_cast<uint8_t>((*buf & mask_green_) >> green_bits);
441 out_row_buffer_[idx++] =
442 static_cast<uint8_t>((*buf++ & mask_red_) >> red_bits);
449 fxcrt::spancpy(pdfium::make_span(out_row_buffer_),
450 pdfium::make_span(dest_buf).first(src_row_bytes_));
451 idx += src_row_bytes_;
456 SaveDecodingStatus(DecodeStatus::kTail);
464 if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
468 switch (first_part) {
470 if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
474 switch (first_part) {
476 if (row_num_ >= height_) {
477 SaveDecodingStatus(DecodeStatus::kTail);
483 fxcrt::spanset(pdfium::make_span(out_row_buffer_), 0);
484 SaveDecodingStatus(DecodeStatus::kData);
488 if (row_num_ < height_)
490 SaveDecodingStatus(DecodeStatus::kTail);
495 if (!ReadAllOrNone(delta))
498 col_num_ += delta[0];
499 size_t bmp_row_num__next = row_num_ + delta[1];
500 if (col_num_ >= out_row_bytes_ || bmp_row_num__next >= height_)
503 while (row_num_ < bmp_row_num__next) {
504 fxcrt::spanset(pdfium::make_span(out_row_buffer_), 0);
511 pdfium::base::checked_cast<int32_t>(out_row_bytes_ - col_num_);
512 if (!avail_size ||
static_cast<int32_t>(first_part) > avail_size)
515 size_t second_part_size =
516 first_part & 1 ? first_part + 1 : first_part;
517 DataVector<uint8_t> second_part(second_part_size);
518 if (!ReadAllOrNone(second_part))
521 fxcrt::spancpy(pdfium::make_span(out_row_buffer_).subspan(col_num_),
522 pdfium::make_span(second_part).first(first_part));
524 for (size_t i = col_num_; i < col_num_ + first_part; ++i) {
525 if (!ValidateColorIndex(out_row_buffer_[i]))
528 col_num_ += first_part;
535 pdfium::base::checked_cast<int32_t>(out_row_bytes_ - col_num_);
536 if (!avail_size ||
static_cast<int32_t>(first_part) > avail_size)
540 if (!ReadAllOrNone(pdfium::span_from_ref(second_part))) {
545 pdfium::make_span(out_row_buffer_).subspan(col_num_, first_part),
548 if (!ValidateColorIndex(out_row_buffer_[col_num_]))
550 col_num_ += first_part;
560 if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
564 switch (first_part) {
566 if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
570 switch (first_part) {
572 if (row_num_ >= height_) {
573 SaveDecodingStatus(DecodeStatus::kTail);
579 fxcrt::spanset(pdfium::make_span(out_row_buffer_), 0);
580 SaveDecodingStatus(DecodeStatus::kData);
584 if (row_num_ < height_)
586 SaveDecodingStatus(DecodeStatus::kTail);
591 if (!ReadAllOrNone(delta))
594 col_num_ += delta[0];
595 size_t bmp_row_num__next = row_num_ + delta[1];
596 if (col_num_ >= out_row_bytes_ || bmp_row_num__next >= height_)
599 while (row_num_ < bmp_row_num__next) {
600 fxcrt::spanset(pdfium::make_span(out_row_buffer_), 0);
607 pdfium::base::checked_cast<int32_t>(out_row_bytes_ - col_num_);
610 uint8_t size = HalfRoundUp(first_part);
611 if (
static_cast<int32_t>(first_part) > avail_size) {
612 if (size + (col_num_ >> 1) > src_row_bytes_)
615 first_part = avail_size - 1;
617 size_t second_part_size = size & 1 ? size + 1 : size;
618 DataVector<uint8_t> second_part(second_part_size);
619 uint8_t* second_part_data = second_part.data();
620 if (!ReadAllOrNone(second_part))
623 for (uint8_t i = 0; i < first_part; i++) {
624 uint8_t color = (i & 0x01) ? (*second_part_data++ & 0x0F)
625 : (*second_part_data & 0xF0) >> 4;
626 if (!ValidateColorIndex(color))
629 out_row_buffer_[col_num_++] = color;
637 pdfium::base::checked_cast<int32_t>(out_row_bytes_ - col_num_);
641 if (
static_cast<int32_t>(first_part) > avail_size) {
642 uint8_t size = HalfRoundUp(first_part);
643 if (size + (col_num_ >> 1) > src_row_bytes_)
646 first_part = avail_size - 1;
649 if (!ReadAllOrNone(pdfium::span_from_ref(second_part))) {
653 for (uint8_t i = 0; i < first_part; i++) {
654 uint8_t second_byte = second_part;
656 i & 0x01 ? (second_byte & 0x0F) : (second_byte & 0xF0) >> 4;
657 if (!ValidateColorIndex(second_byte))
660 out_row_buffer_[col_num_++] = second_byte;
671 size_t original_position = input_buffer_->GetPosition();
672 size_t read = input_buffer_->ReadBlock(buf);
673 if (read < buf.size()) {
674 input_buffer_->Seek(original_position);
682 decode_status_ = status;
686 RetainPtr<CFX_CodecMemory> codec_memory) {
687 input_buffer_ = std::move(codec_memory);
694 return input_buffer_->GetSize() - input_buffer_->GetPosition();
698 if (signed_height >= 0) {
699 height_ = signed_height;
702 if (signed_height !=
std::numeric_limits<
int>::min()) {
703 height_ = -signed_height;
#define BMP_PAL_ENCODE(a, r, g, b)
FX_FILESIZE GetAvailInput() const
BmpDecoder::Status DecodeImage()
CFX_BmpDecompressor(const CFX_BmpContext *context)
BmpDecoder::Status ReadHeader()
void SetInputBuffer(RetainPtr< CFX_CodecMemory > codec_memory)