Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cfx_bmpdecompressor.cpp
Go to the documentation of this file.
1// Copyright 2018 The PDFium Authors
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/bmp/cfx_bmpdecompressor.h"
8
9#include <stdint.h>
10
11#include <algorithm>
12#include <limits>
13#include <utility>
14
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"
23
24namespace fxcodec {
25
26namespace {
27
28#define BMP_PAL_ENCODE(a, r, g, b)
29 (((uint32_t)(a) << 24) | ((r) << 16) | ((g) << 8) | (b))
30
31constexpr size_t kBmpCoreHeaderSize = 12;
32constexpr size_t kBmpInfoHeaderSize = 40;
33
34static_assert(sizeof(BmpCoreHeader) == kBmpCoreHeaderSize,
35 "BmpCoreHeader has wrong size");
36static_assert(sizeof(BmpInfoHeader) == kBmpInfoHeaderSize,
37 "BmpInfoHeader has wrong size");
38
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;
48
49// Limit of image dimension. Use the same limit as the JBIG2 codecs.
50constexpr uint32_t kBmpMaxImageDimension = 65535;
51
52uint8_t HalfRoundUp(uint8_t value) {
53 uint16_t value16 = value;
54 return static_cast<uint8_t>((value16 + 1) / 2);
55}
56
57} // namespace
58
59CFX_BmpDecompressor::CFX_BmpDecompressor(const CFX_BmpContext* context)
60 : context_(context) {}
61
63
64void CFX_BmpDecompressor::ReadNextScanline() {
65 uint32_t row = img_tb_flag_ ? row_num_ : (height_ - 1 - row_num_);
66 context_->m_pDelegate->BmpReadScanline(row, out_row_buffer_);
67 ++row_num_;
68}
69
70bool CFX_BmpDecompressor::GetDataPosition(uint32_t rcd_pos) {
71 return context_->m_pDelegate->BmpInputImagePositionBuf(rcd_pos);
72}
73
75 if (decode_status_ == DecodeStatus::kHeader) {
76 BmpDecoder::Status status = ReadBmpHeader();
77 if (status != BmpDecoder::Status::kSuccess)
78 return status;
79 }
80
81 if (decode_status_ != DecodeStatus::kPal)
83
84 if (compress_flag_ == kBmpBitfields)
85 return ReadBmpBitfields();
86
87 return ReadBmpPalette();
88}
89
90BmpDecoder::Status CFX_BmpDecompressor::ReadBmpHeader() {
91 BmpFileHeader bmp_header;
92 if (!ReadAllOrNone(
93 pdfium::as_writable_bytes(pdfium::span_from_ref(bmp_header)))) {
95 }
96
97 bmp_header.bfType =
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));
101 data_size_ =
102 FXSYS_UINT32_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&bmp_header.bfSize));
103 if (bmp_header.bfType != kBmpSignature)
105
106 size_t pos = input_buffer_->GetPosition();
107 if (!ReadAllOrNone(
108 pdfium::as_writable_bytes(pdfium::span_from_ref(img_ifh_size_)))) {
110 }
111 if (!input_buffer_->Seek(pos))
113
114 img_ifh_size_ =
115 FXSYS_UINT32_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&img_ifh_size_));
116 pal_type_ = PalType::kNew;
117 BmpDecoder::Status status = ReadBmpHeaderIfh();
118 if (status != BmpDecoder::Status::kSuccess)
119 return status;
120
121 return ReadBmpHeaderDimensions();
122}
123
124BmpDecoder::Status CFX_BmpDecompressor::ReadBmpHeaderIfh() {
125 if (img_ifh_size_ == kBmpCoreHeaderSize) {
126 pal_type_ = PalType::kOld;
127 BmpCoreHeader bmp_core_header;
128 if (!ReadAllOrNone(pdfium::as_writable_bytes(
129 pdfium::span_from_ref(bmp_core_header)))) {
131 }
132
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;
142 }
143
144 if (img_ifh_size_ == kBmpInfoHeaderSize) {
145 BmpInfoHeader bmp_info_header;
146 if (!ReadAllOrNone(pdfium::as_writable_bytes(
147 pdfium::span_from_ref(bmp_info_header)))) {
149 }
150
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(
158 reinterpret_cast<uint8_t*>(&bmp_info_header.biCompression));
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(
162 reinterpret_cast<uint8_t*>(&bmp_info_header.biXPelsPerMeter)));
163 dpi_y_ = static_cast<int32_t>(FXSYS_UINT32_GET_LSBFIRST(
164 reinterpret_cast<uint8_t*>(&bmp_info_header.biYPelsPerMeter)));
165 if (!SetHeight(signed_height))
168 }
169
170 if (img_ifh_size_ <= sizeof(BmpInfoHeader))
172
173 FX_SAFE_SIZE_T new_pos = input_buffer_->GetPosition();
174 BmpInfoHeader bmp_info_header;
175 if (!ReadAllOrNone(
176 pdfium::as_writable_bytes(pdfium::span_from_ref(bmp_info_header)))) {
178 }
179
180 new_pos += img_ifh_size_;
181 if (!new_pos.IsValid())
183
184 if (!input_buffer_->Seek(new_pos.ValueOrDie()))
186
187 uint16_t bi_planes;
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(
195 reinterpret_cast<uint8_t*>(&bmp_info_header.biCompression));
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(
201 reinterpret_cast<uint8_t*>(&bmp_info_header.biXPelsPerMeter));
202 dpi_y_ = FXSYS_UINT32_GET_LSBFIRST(
203 reinterpret_cast<uint8_t*>(&bmp_info_header.biYPelsPerMeter));
204 if (!SetHeight(signed_height))
206 if (compress_flag_ != kBmpRgb || bi_planes != 1 || color_used_ != 0)
209}
210
211BmpDecoder::Status CFX_BmpDecompressor::ReadBmpHeaderDimensions() {
212 if (width_ > kBmpMaxImageDimension || height_ > kBmpMaxImageDimension ||
213 compress_flag_ > kBmpBitfields) {
215 }
216
217 switch (bit_counts_) {
218 case 1:
219 case 4:
220 case 8:
221 case 16:
222 case 24: {
223 if (color_used_ > 1U << bit_counts_)
225 break;
226 }
227 case 32:
228 break;
229 default:
231 }
232 absl::optional<uint32_t> stride = fxge::CalculatePitch32(bit_counts_, width_);
233 if (!stride.has_value())
235
236 src_row_bytes_ = stride.value();
237 switch (bit_counts_) {
238 case 1:
239 case 4:
240 case 8:
241 stride = fxge::CalculatePitch32(8, width_);
242 if (!stride.has_value())
244 out_row_bytes_ = stride.value();
245 components_ = 1;
246 break;
247 case 16:
248 case 24:
249 stride = fxge::CalculatePitch32(24, width_);
250 if (!stride.has_value())
252 out_row_bytes_ = stride.value();
253 components_ = 3;
254 break;
255 case 32:
256 out_row_bytes_ = src_row_bytes_;
257 components_ = 4;
258 break;
259 }
260 out_row_buffer_.clear();
261
262 if (out_row_bytes_ <= 0)
264
265 out_row_buffer_.resize(out_row_bytes_);
266 SaveDecodingStatus(DecodeStatus::kPal);
268}
269
270BmpDecoder::Status CFX_BmpDecompressor::ReadBmpBitfields() {
271 if (bit_counts_ != 16 && bit_counts_ != 32)
273
274 uint32_t masks[3];
275 if (!ReadAllOrNone(pdfium::as_writable_bytes(pdfium::make_span(masks))))
277
278 mask_red_ = FXSYS_UINT32_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&masks[0]));
279 mask_green_ =
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_) {
285 }
286 header_offset_ = std::max(header_offset_, 26 + img_ifh_size_);
287 SaveDecodingStatus(DecodeStatus::kDataPre);
289}
290
291BmpDecoder::Status CFX_BmpDecompressor::ReadBmpPalette() {
292 if (bit_counts_ == 16) {
293 mask_red_ = 0x7C00;
294 mask_green_ = 0x03E0;
295 mask_blue_ = 0x001F;
296 }
297 pal_num_ = 0;
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))
307
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_) {
312 palette_[src_pal_index++] = BMP_PAL_ENCODE(
313 0x00, src_pal_data[2], src_pal_data[1], src_pal_data[0]);
314 src_pal_data += 3;
315 }
316 } else {
317 while (src_pal_index < pal_num_) {
318 palette_[src_pal_index++] = BMP_PAL_ENCODE(
319 src_pal_data[3], src_pal_data[2], src_pal_data[1], src_pal_data[0]);
320 src_pal_data += 4;
321 }
322 }
323 }
324 header_offset_ = std::max(
325 header_offset_, 14 + img_ifh_size_ + pal_num_ * PaletteChannelCount());
326 SaveDecodingStatus(DecodeStatus::kDataPre);
328}
329
330bool CFX_BmpDecompressor::ValidateFlag() const {
331 switch (compress_flag_) {
332 case kBmpRgb:
333 case kBmpBitfields:
334 case kBmpRle8:
335 case kBmpRle4:
336 return true;
337 default:
338 return false;
339 }
340}
341
343 if (decode_status_ == DecodeStatus::kDataPre) {
344 // In order to tolerate certain corrupt BMP files, use the header offset if
345 // the data offset would point into the header.
346 data_offset_ = std::max(header_offset_, data_offset_);
347
348 input_buffer_->Seek(input_buffer_->GetSize());
349 if (!GetDataPosition(data_offset_)) {
350 decode_status_ = DecodeStatus::kTail;
352 }
353
354 row_num_ = 0;
355 SaveDecodingStatus(DecodeStatus::kData);
356 }
357 if (decode_status_ != DecodeStatus::kData || !ValidateFlag())
359
360 switch (compress_flag_) {
361 case kBmpRgb:
362 case kBmpBitfields:
363 return DecodeRGB();
364 case kBmpRle8:
365 return DecodeRLE8();
366 case kBmpRle4:
367 return DecodeRLE4();
368 default:
370 }
371}
372
373bool CFX_BmpDecompressor::ValidateColorIndex(uint8_t val) const {
374 return val < pal_num_;
375}
376
378 DataVector<uint8_t> dest_buf(src_row_bytes_);
379 while (row_num_ < height_) {
380 size_t idx = 0;
381 if (!ReadAllOrNone(dest_buf))
383
384 SaveDecodingStatus(DecodeStatus::kData);
385 switch (bit_counts_) {
386 case 1: {
387 for (uint32_t col = 0; col < width_; ++col) {
388 uint8_t index =
389 dest_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00;
390 if (!ValidateColorIndex(index))
392 out_row_buffer_[idx++] = index;
393 }
394 break;
395 }
396 case 4: {
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;
403 }
404 break;
405 }
406 case 8: {
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;
412 }
413 break;
414 }
415 case 16: {
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)
422 blue_bits++;
423 if ((mask_green_ >> i) & 0x01)
424 green_bits++;
425 if ((mask_red_ >> i) & 0x01)
426 red_bits++;
427 }
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;
433 green_bits -= 8;
434 red_bits -= 8;
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);
443 }
444 break;
445 }
446 case 24:
447 case 32:
448 // TODO(crbug.com/pdfium/1901): Apply bitfields.
449 fxcrt::spancpy(pdfium::make_span(out_row_buffer_),
450 pdfium::make_span(dest_buf).first(src_row_bytes_));
451 idx += src_row_bytes_;
452 break;
453 }
454 ReadNextScanline();
455 }
456 SaveDecodingStatus(DecodeStatus::kTail);
458}
459
461 uint8_t first_part;
462 col_num_ = 0;
463 while (true) {
464 if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
466 }
467
468 switch (first_part) {
469 case kRleMarker: {
470 if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
472 }
473
474 switch (first_part) {
475 case kRleEol: {
476 if (row_num_ >= height_) {
477 SaveDecodingStatus(DecodeStatus::kTail);
479 }
480
481 ReadNextScanline();
482 col_num_ = 0;
483 fxcrt::spanset(pdfium::make_span(out_row_buffer_), 0);
484 SaveDecodingStatus(DecodeStatus::kData);
485 continue;
486 }
487 case kRleEoi: {
488 if (row_num_ < height_)
489 ReadNextScanline();
490 SaveDecodingStatus(DecodeStatus::kTail);
492 }
493 case kRleDelta: {
494 uint8_t delta[2];
495 if (!ReadAllOrNone(delta))
497
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_)
502
503 while (row_num_ < bmp_row_num__next) {
504 fxcrt::spanset(pdfium::make_span(out_row_buffer_), 0);
505 ReadNextScanline();
506 }
507 break;
508 }
509 default: {
510 int32_t avail_size =
511 pdfium::base::checked_cast<int32_t>(out_row_bytes_ - col_num_);
512 if (!avail_size || static_cast<int32_t>(first_part) > avail_size)
514
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))
520
521 fxcrt::spancpy(pdfium::make_span(out_row_buffer_).subspan(col_num_),
522 pdfium::make_span(second_part).first(first_part));
523
524 for (size_t i = col_num_; i < col_num_ + first_part; ++i) {
525 if (!ValidateColorIndex(out_row_buffer_[i]))
527 }
528 col_num_ += first_part;
529 }
530 }
531 break;
532 }
533 default: {
534 int32_t avail_size =
535 pdfium::base::checked_cast<int32_t>(out_row_bytes_ - col_num_);
536 if (!avail_size || static_cast<int32_t>(first_part) > avail_size)
538
539 uint8_t second_part;
540 if (!ReadAllOrNone(pdfium::span_from_ref(second_part))) {
542 }
543
544 fxcrt::spanset(
545 pdfium::make_span(out_row_buffer_).subspan(col_num_, first_part),
546 second_part);
547
548 if (!ValidateColorIndex(out_row_buffer_[col_num_]))
550 col_num_ += first_part;
551 }
552 }
553 }
554}
555
557 uint8_t first_part;
558 col_num_ = 0;
559 while (true) {
560 if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
562 }
563
564 switch (first_part) {
565 case kRleMarker: {
566 if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
568 }
569
570 switch (first_part) {
571 case kRleEol: {
572 if (row_num_ >= height_) {
573 SaveDecodingStatus(DecodeStatus::kTail);
575 }
576
577 ReadNextScanline();
578 col_num_ = 0;
579 fxcrt::spanset(pdfium::make_span(out_row_buffer_), 0);
580 SaveDecodingStatus(DecodeStatus::kData);
581 continue;
582 }
583 case kRleEoi: {
584 if (row_num_ < height_)
585 ReadNextScanline();
586 SaveDecodingStatus(DecodeStatus::kTail);
588 }
589 case kRleDelta: {
590 uint8_t delta[2];
591 if (!ReadAllOrNone(delta))
593
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_)
598
599 while (row_num_ < bmp_row_num__next) {
600 fxcrt::spanset(pdfium::make_span(out_row_buffer_), 0);
601 ReadNextScanline();
602 }
603 break;
604 }
605 default: {
606 int32_t avail_size =
607 pdfium::base::checked_cast<int32_t>(out_row_bytes_ - col_num_);
608 if (!avail_size)
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_)
614
615 first_part = avail_size - 1;
616 }
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))
622
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))
628
629 out_row_buffer_[col_num_++] = color;
630 }
631 }
632 }
633 break;
634 }
635 default: {
636 int32_t avail_size =
637 pdfium::base::checked_cast<int32_t>(out_row_bytes_ - col_num_);
638 if (!avail_size)
640
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_)
645
646 first_part = avail_size - 1;
647 }
648 uint8_t second_part;
649 if (!ReadAllOrNone(pdfium::span_from_ref(second_part))) {
651 }
652
653 for (uint8_t i = 0; i < first_part; i++) {
654 uint8_t second_byte = second_part;
655 second_byte =
656 i & 0x01 ? (second_byte & 0x0F) : (second_byte & 0xF0) >> 4;
657 if (!ValidateColorIndex(second_byte))
659
660 out_row_buffer_[col_num_++] = second_byte;
661 }
662 }
663 }
664 }
665}
666
667bool CFX_BmpDecompressor::ReadAllOrNone(pdfium::span<uint8_t> buf) {
668 if (!input_buffer_)
669 return false;
670
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);
675 return false;
676 }
677
678 return true;
679}
680
681void CFX_BmpDecompressor::SaveDecodingStatus(DecodeStatus status) {
682 decode_status_ = status;
683}
684
686 RetainPtr<CFX_CodecMemory> codec_memory) {
687 input_buffer_ = std::move(codec_memory);
688}
689
691 if (!input_buffer_)
692 return 0;
693
694 return input_buffer_->GetSize() - input_buffer_->GetPosition();
695}
696
697bool CFX_BmpDecompressor::SetHeight(int32_t signed_height) {
698 if (signed_height >= 0) {
699 height_ = signed_height;
700 return true;
701 }
702 if (signed_height != std::numeric_limits<int>::min()) {
703 height_ = -signed_height;
704 img_tb_flag_ = true;
705 return true;
706 }
707 return false;
708}
709
710} // namespace fxcodec
#define BMP_PAL_ENCODE(a, r, g, b)
CFX_BmpDecompressor(const CFX_BmpContext *context)
void SetInputBuffer(RetainPtr< CFX_CodecMemory > codec_memory)
#define FX_FILESIZE
Definition fx_types.h:19
uint16_t bcBitCount
Definition fx_bmp.h:26
uint16_t bcWidth
Definition fx_bmp.h:23
uint16_t bcHeight
Definition fx_bmp.h:24
uint32_t bfSize
Definition fx_bmp.h:15
uint32_t bfOffBits
Definition fx_bmp.h:18
uint16_t bfType
Definition fx_bmp.h:14
uint32_t biClrUsed
Definition fx_bmp.h:39
int32_t biWidth
Definition fx_bmp.h:31
uint16_t biPlanes
Definition fx_bmp.h:33
int32_t biHeight
Definition fx_bmp.h:32
uint16_t biBitCount
Definition fx_bmp.h:34
uint32_t biCompression
Definition fx_bmp.h:35
int32_t biYPelsPerMeter
Definition fx_bmp.h:38
int32_t biXPelsPerMeter
Definition fx_bmp.h:37