summaryrefslogtreecommitdiff
path: root/core/fxcodec/bmp
diff options
context:
space:
mode:
Diffstat (limited to 'core/fxcodec/bmp')
-rw-r--r--core/fxcodec/bmp/cfx_bmpcontext.cpp13
-rw-r--r--core/fxcodec/bmp/cfx_bmpcontext.h24
-rw-r--r--core/fxcodec/bmp/cfx_bmpdecompressor.cpp674
-rw-r--r--core/fxcodec/bmp/cfx_bmpdecompressor.h76
-rw-r--r--core/fxcodec/bmp/fx_bmp.cpp664
-rw-r--r--core/fxcodec/bmp/fx_bmp.h75
6 files changed, 787 insertions, 739 deletions
diff --git a/core/fxcodec/bmp/cfx_bmpcontext.cpp b/core/fxcodec/bmp/cfx_bmpcontext.cpp
new file mode 100644
index 0000000000..87f5083193
--- /dev/null
+++ b/core/fxcodec/bmp/cfx_bmpcontext.cpp
@@ -0,0 +1,13 @@
+// Copyright 2018 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/bmp/cfx_bmpcontext.h"
+
+CFX_BmpContext::CFX_BmpContext(CCodec_BmpModule* pModule,
+ CCodec_BmpModule::Delegate* pDelegate)
+ : m_pModule(pModule), m_pDelegate(pDelegate) {}
+
+CFX_BmpContext::~CFX_BmpContext() {}
diff --git a/core/fxcodec/bmp/cfx_bmpcontext.h b/core/fxcodec/bmp/cfx_bmpcontext.h
new file mode 100644
index 0000000000..198d080fb8
--- /dev/null
+++ b/core/fxcodec/bmp/cfx_bmpcontext.h
@@ -0,0 +1,24 @@
+// Copyright 2018 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_BMP_CFX_BMPCONTEXT_H_
+#define CORE_FXCODEC_BMP_CFX_BMPCONTEXT_H_
+
+#include "core/fxcodec/bmp/cfx_bmpdecompressor.h"
+#include "core/fxcodec/bmp/fx_bmp.h"
+
+class CFX_BmpContext : public CCodec_BmpModule::Context {
+ public:
+ CFX_BmpContext(CCodec_BmpModule* pModule,
+ CCodec_BmpModule::Delegate* pDelegate);
+ ~CFX_BmpContext() override;
+
+ CFX_BmpDecompressor m_Bmp;
+ UnownedPtr<CCodec_BmpModule> const m_pModule;
+ UnownedPtr<CCodec_BmpModule::Delegate> const m_pDelegate;
+};
+
+#endif // CORE_FXCODEC_BMP_CFX_BMPCONTEXT_H_
diff --git a/core/fxcodec/bmp/cfx_bmpdecompressor.cpp b/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
new file mode 100644
index 0000000000..b97dab18ce
--- /dev/null
+++ b/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
@@ -0,0 +1,674 @@
+// Copyright 2018 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/bmp/cfx_bmpdecompressor.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "core/fxcodec/bmp/cfx_bmpcontext.h"
+#include "core/fxcrt/fx_system.h"
+#include "third_party/base/logging.h"
+#include "third_party/base/ptr_util.h"
+
+namespace {
+
+const size_t kBmpCoreHeaderSize = 12;
+const size_t kBmpInfoHeaderSize = 40;
+
+uint8_t HalfRoundUp(uint8_t value) {
+ uint16_t value16 = value;
+ return static_cast<uint8_t>((value16 + 1) / 2);
+}
+
+} // namespace
+
+CFX_BmpDecompressor::CFX_BmpDecompressor()
+ : context_ptr_(nullptr),
+ next_in_(nullptr),
+ header_offset_(0),
+ width_(0),
+ height_(0),
+ compress_flag_(0),
+ components_(0),
+ src_row_bytes_(0),
+ out_row_bytes_(0),
+ bit_counts_(0),
+ color_used_(0),
+ imgTB_flag_(false),
+ pal_num_(0),
+ pal_type_(0),
+ data_size_(0),
+ img_data_offset_(0),
+ img_ifh_size_(0),
+ row_num_(0),
+ col_num_(0),
+ dpi_x_(0),
+ dpi_y_(0),
+ mask_red_(0),
+ mask_green_(0),
+ mask_blue_(0),
+ avail_in_(0),
+ skip_size_(0),
+ decode_status_(BMP_D_STATUS_HEADER) {}
+
+CFX_BmpDecompressor::~CFX_BmpDecompressor() {}
+
+void CFX_BmpDecompressor::Error() {
+ longjmp(jmpbuf_, 1);
+}
+
+void CFX_BmpDecompressor::ReadScanline(uint32_t row_num_,
+ const std::vector<uint8_t>& row_buf) {
+ auto* p = reinterpret_cast<CFX_BmpContext*>(context_ptr_);
+ p->m_pDelegate->BmpReadScanline(row_num_, row_buf);
+}
+
+bool CFX_BmpDecompressor::GetDataPosition(uint32_t rcd_pos) {
+ auto* p = reinterpret_cast<CFX_BmpContext*>(context_ptr_);
+ return p->m_pDelegate->BmpInputImagePositionBuf(rcd_pos);
+}
+
+int32_t CFX_BmpDecompressor::ReadHeader() {
+ uint32_t skip_size_org = skip_size_;
+ if (decode_status_ == BMP_D_STATUS_HEADER) {
+ BmpFileHeader* pBmp_header = nullptr;
+ if (!ReadData(reinterpret_cast<uint8_t**>(&pBmp_header),
+ sizeof(BmpFileHeader))) {
+ return 2;
+ }
+
+ pBmp_header->bfType =
+ FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&pBmp_header->bfType));
+ pBmp_header->bfOffBits = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_header->bfOffBits));
+ data_size_ =
+ FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&pBmp_header->bfSize));
+ if (pBmp_header->bfType != BMP_SIGNATURE) {
+ Error();
+ NOTREACHED();
+ }
+ if (avail_in_ < sizeof(uint32_t)) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ img_ifh_size_ =
+ FXDWORD_GET_LSBFIRST(static_cast<uint8_t*>(next_in_ + skip_size_));
+ pal_type_ = 0;
+ static_assert(sizeof(BmpCoreHeader) == kBmpCoreHeaderSize,
+ "BmpCoreHeader has wrong size");
+ static_assert(sizeof(BmpInfoHeader) == kBmpInfoHeaderSize,
+ "BmpInfoHeader has wrong size");
+ switch (img_ifh_size_) {
+ case kBmpCoreHeaderSize: {
+ pal_type_ = 1;
+ BmpCoreHeader* pBmp_core_header = nullptr;
+ if (!ReadData(reinterpret_cast<uint8_t**>(&pBmp_core_header),
+ img_ifh_size_)) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ width_ = FXWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_core_header->bcWidth));
+ height_ = FXWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_core_header->bcHeight));
+ bit_counts_ = FXWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_core_header->bcBitCount));
+ compress_flag_ = BMP_RGB;
+ imgTB_flag_ = false;
+ } break;
+ case kBmpInfoHeaderSize: {
+ BmpInfoHeader* pBmp_info_header = nullptr;
+ if (!ReadData(reinterpret_cast<uint8_t**>(&pBmp_info_header),
+ img_ifh_size_)) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ width_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biWidth));
+ int32_t signed_height = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biHeight));
+ bit_counts_ = FXWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biBitCount));
+ compress_flag_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biCompression));
+ color_used_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biClrUsed));
+ dpi_x_ = static_cast<int32_t>(FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biXPelsPerMeter)));
+ dpi_y_ = static_cast<int32_t>(FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biYPelsPerMeter)));
+ SetHeight(signed_height);
+ } break;
+ default: {
+ if (img_ifh_size_ >
+ std::min(kBmpInfoHeaderSize,
+ static_cast<size_t>(sizeof(BmpInfoHeader)))) {
+ BmpInfoHeader* pBmp_info_header = nullptr;
+ if (!ReadData(reinterpret_cast<uint8_t**>(&pBmp_info_header),
+ img_ifh_size_)) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ uint16_t biPlanes;
+ width_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biWidth));
+ int32_t signed_height = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biHeight));
+ bit_counts_ = FXWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biBitCount));
+ compress_flag_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biCompression));
+ color_used_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biClrUsed));
+ biPlanes = FXWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biPlanes));
+ dpi_x_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biXPelsPerMeter));
+ dpi_y_ = FXDWORD_GET_LSBFIRST(
+ reinterpret_cast<uint8_t*>(&pBmp_info_header->biYPelsPerMeter));
+ SetHeight(signed_height);
+ if (compress_flag_ == BMP_RGB && biPlanes == 1 && color_used_ == 0)
+ break;
+ }
+ Error();
+ NOTREACHED();
+ }
+ }
+ if (width_ > BMP_MAX_WIDTH || compress_flag_ > BMP_BITFIELDS) {
+ Error();
+ NOTREACHED();
+ }
+ switch (bit_counts_) {
+ case 1:
+ case 4:
+ case 8:
+ case 16:
+ case 24: {
+ if (color_used_ > 1U << bit_counts_) {
+ Error();
+ NOTREACHED();
+ }
+ }
+ case 32:
+ break;
+ default:
+ Error();
+ NOTREACHED();
+ }
+ src_row_bytes_ = BMP_WIDTHBYTES(width_, bit_counts_);
+ switch (bit_counts_) {
+ case 1:
+ case 4:
+ case 8:
+ out_row_bytes_ = BMP_WIDTHBYTES(width_, 8);
+ components_ = 1;
+ break;
+ case 16:
+ case 24:
+ out_row_bytes_ = BMP_WIDTHBYTES(width_, 24);
+ components_ = 3;
+ break;
+ case 32:
+ out_row_bytes_ = src_row_bytes_;
+ components_ = 4;
+ break;
+ }
+ out_row_buffer_.clear();
+
+ if (out_row_bytes_ <= 0) {
+ Error();
+ NOTREACHED();
+ }
+
+ out_row_buffer_.resize(out_row_bytes_);
+ SaveDecodingStatus(BMP_D_STATUS_PAL);
+ }
+ if (decode_status_ == BMP_D_STATUS_PAL) {
+ skip_size_org = skip_size_;
+ if (compress_flag_ == BMP_BITFIELDS) {
+ if (bit_counts_ != 16 && bit_counts_ != 32) {
+ Error();
+ NOTREACHED();
+ }
+ uint32_t* mask;
+ if (ReadData(reinterpret_cast<uint8_t**>(&mask), 3 * sizeof(uint32_t)) ==
+ nullptr) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ mask_red_ = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&mask[0]));
+ mask_green_ = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&mask[1]));
+ mask_blue_ = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&mask[2]));
+ if (mask_red_ & mask_green_ || mask_red_ & mask_blue_ ||
+ mask_green_ & mask_blue_) {
+ Error();
+ NOTREACHED();
+ }
+ header_offset_ = std::max(header_offset_, 26 + img_ifh_size_);
+ SaveDecodingStatus(BMP_D_STATUS_DATA_PRE);
+ return 1;
+ } else if (bit_counts_ == 16) {
+ mask_red_ = 0x7C00;
+ mask_green_ = 0x03E0;
+ mask_blue_ = 0x001F;
+ }
+ pal_num_ = 0;
+ if (bit_counts_ < 16) {
+ pal_num_ = 1 << bit_counts_;
+ if (color_used_ != 0)
+ pal_num_ = color_used_;
+ uint8_t* src_pal_ptr = nullptr;
+ uint32_t src_pal_size = pal_num_ * (pal_type_ ? 3 : 4);
+ if (ReadData(&src_pal_ptr, src_pal_size) == nullptr) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ palette_.resize(pal_num_);
+ int32_t src_pal_index = 0;
+ if (pal_type_ == BMP_PAL_OLD) {
+ while (src_pal_index < pal_num_) {
+ palette_[src_pal_index++] = BMP_PAL_ENCODE(
+ 0x00, src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]);
+ src_pal_ptr += 3;
+ }
+ } else {
+ while (src_pal_index < pal_num_) {
+ palette_[src_pal_index++] = BMP_PAL_ENCODE(
+ src_pal_ptr[3], src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]);
+ src_pal_ptr += 4;
+ }
+ }
+ }
+ header_offset_ = std::max(
+ header_offset_, 14 + img_ifh_size_ + pal_num_ * (pal_type_ ? 3 : 4));
+ SaveDecodingStatus(BMP_D_STATUS_DATA_PRE);
+ }
+ return 1;
+}
+
+bool CFX_BmpDecompressor::ValidateFlag() const {
+ switch (compress_flag_) {
+ case BMP_RGB:
+ case BMP_BITFIELDS:
+ case BMP_RLE8:
+ case BMP_RLE4:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int32_t CFX_BmpDecompressor::DecodeImage() {
+ if (decode_status_ == BMP_D_STATUS_DATA_PRE) {
+ avail_in_ = 0;
+ if (!GetDataPosition(header_offset_)) {
+ decode_status_ = BMP_D_STATUS_TAIL;
+ Error();
+ NOTREACHED();
+ }
+ row_num_ = 0;
+ SaveDecodingStatus(BMP_D_STATUS_DATA);
+ }
+ if (decode_status_ != BMP_D_STATUS_DATA || !ValidateFlag()) {
+ Error();
+ NOTREACHED();
+ }
+ switch (compress_flag_) {
+ case BMP_RGB:
+ case BMP_BITFIELDS:
+ return DecodeRGB();
+ case BMP_RLE8:
+ return DecodeRLE8();
+ case BMP_RLE4:
+ return DecodeRLE4();
+ default:
+ return 0;
+ }
+}
+
+bool CFX_BmpDecompressor::ValidateColorIndex(uint8_t val) {
+ if (val >= pal_num_) {
+ Error();
+ NOTREACHED();
+ }
+ return true;
+}
+
+int32_t CFX_BmpDecompressor::DecodeRGB() {
+ uint8_t* des_buf = nullptr;
+ while (row_num_ < height_) {
+ size_t idx = 0;
+ if (!ReadData(&des_buf, src_row_bytes_))
+ return 2;
+
+ SaveDecodingStatus(BMP_D_STATUS_DATA);
+ switch (bit_counts_) {
+ case 1: {
+ for (uint32_t col = 0; col < width_; ++col)
+ out_row_buffer_[idx++] =
+ des_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00;
+ } break;
+ case 4: {
+ for (uint32_t col = 0; col < width_; ++col) {
+ out_row_buffer_[idx++] = (col & 0x01)
+ ? (des_buf[col >> 1] & 0x0F)
+ : ((des_buf[col >> 1] & 0xF0) >> 4);
+ }
+ } break;
+ case 16: {
+ uint16_t* buf = (uint16_t*)des_buf;
+ uint8_t blue_bits = 0;
+ uint8_t green_bits = 0;
+ uint8_t red_bits = 0;
+ for (int32_t i = 0; i < 16; i++) {
+ if ((mask_blue_ >> i) & 0x01)
+ blue_bits++;
+ if ((mask_green_ >> i) & 0x01)
+ green_bits++;
+ if ((mask_red_ >> i) & 0x01)
+ red_bits++;
+ }
+ green_bits += blue_bits;
+ red_bits += green_bits;
+ if (blue_bits > 8 || green_bits < 8 || red_bits < 8)
+ return 2;
+ blue_bits = 8 - blue_bits;
+ green_bits -= 8;
+ red_bits -= 8;
+ for (uint32_t col = 0; col < width_; ++col) {
+ *buf = FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(buf));
+ out_row_buffer_[idx++] =
+ static_cast<uint8_t>((*buf & mask_blue_) << blue_bits);
+ out_row_buffer_[idx++] =
+ static_cast<uint8_t>((*buf & mask_green_) >> green_bits);
+ out_row_buffer_[idx++] =
+ static_cast<uint8_t>((*buf++ & mask_red_) >> red_bits);
+ }
+ } break;
+ case 8:
+ case 24:
+ case 32:
+ std::copy(des_buf, des_buf + src_row_bytes_, out_row_buffer_.begin());
+ idx += src_row_bytes_;
+ break;
+ }
+ for (uint8_t byte : out_row_buffer_) {
+ if (!ValidateColorIndex(byte))
+ return 0;
+ }
+ ReadScanline(imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
+ out_row_buffer_);
+ }
+ SaveDecodingStatus(BMP_D_STATUS_TAIL);
+ return 1;
+}
+
+int32_t CFX_BmpDecompressor::DecodeRLE8() {
+ uint8_t* first_byte_ptr = nullptr;
+ uint8_t* second_byte_ptr = nullptr;
+ col_num_ = 0;
+ while (true) {
+ uint32_t skip_size_org = skip_size_;
+ if (!ReadData(&first_byte_ptr, 1))
+ return 2;
+
+ switch (*first_byte_ptr) {
+ case RLE_MARKER: {
+ if (!ReadData(&first_byte_ptr, 1)) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ switch (*first_byte_ptr) {
+ case RLE_EOL: {
+ if (row_num_ >= height_) {
+ SaveDecodingStatus(BMP_D_STATUS_TAIL);
+ Error();
+ NOTREACHED();
+ }
+ ReadScanline(imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
+ out_row_buffer_);
+ col_num_ = 0;
+ std::fill(out_row_buffer_.begin(), out_row_buffer_.end(), 0);
+ SaveDecodingStatus(BMP_D_STATUS_DATA);
+ continue;
+ }
+ case RLE_EOI: {
+ if (row_num_ < height_) {
+ ReadScanline(
+ imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
+ out_row_buffer_);
+ }
+ SaveDecodingStatus(BMP_D_STATUS_TAIL);
+ return 1;
+ }
+ case RLE_DELTA: {
+ uint8_t* delta_ptr;
+ if (!ReadData(&delta_ptr, 2)) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ col_num_ += delta_ptr[0];
+ size_t bmp_row_num__next = row_num_ + delta_ptr[1];
+ if (col_num_ >= out_row_bytes_ || bmp_row_num__next >= height_) {
+ Error();
+ NOTREACHED();
+ }
+ while (row_num_ < bmp_row_num__next) {
+ std::fill(out_row_buffer_.begin(), out_row_buffer_.end(), 0);
+ ReadScanline(
+ imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
+ out_row_buffer_);
+ }
+ } break;
+ default: {
+ int32_t avail_size = out_row_bytes_ - col_num_;
+ if (!avail_size ||
+ static_cast<int32_t>(*first_byte_ptr) > avail_size) {
+ Error();
+ NOTREACHED();
+ }
+ if (!ReadData(&second_byte_ptr, *first_byte_ptr & 1
+ ? *first_byte_ptr + 1
+ : *first_byte_ptr)) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ std::copy(second_byte_ptr, second_byte_ptr + *first_byte_ptr,
+ out_row_buffer_.begin() + col_num_);
+ for (size_t i = col_num_; i < col_num_ + *first_byte_ptr; ++i) {
+ if (!ValidateColorIndex(out_row_buffer_[i]))
+ return 0;
+ }
+ col_num_ += *first_byte_ptr;
+ }
+ }
+ } break;
+ default: {
+ int32_t avail_size = out_row_bytes_ - col_num_;
+ if (!avail_size || static_cast<int32_t>(*first_byte_ptr) > avail_size) {
+ Error();
+ NOTREACHED();
+ }
+ if (!ReadData(&second_byte_ptr, 1)) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ std::fill(out_row_buffer_.begin() + col_num_,
+ out_row_buffer_.begin() + col_num_ + *first_byte_ptr,
+ *second_byte_ptr);
+ if (!ValidateColorIndex(out_row_buffer_[col_num_]))
+ return 0;
+ col_num_ += *first_byte_ptr;
+ }
+ }
+ }
+ Error();
+ NOTREACHED();
+}
+
+int32_t CFX_BmpDecompressor::DecodeRLE4() {
+ uint8_t* first_byte_ptr = nullptr;
+ uint8_t* second_byte_ptr = nullptr;
+ col_num_ = 0;
+ while (true) {
+ uint32_t skip_size_org = skip_size_;
+ if (!ReadData(&first_byte_ptr, 1))
+ return 2;
+
+ switch (*first_byte_ptr) {
+ case RLE_MARKER: {
+ if (!ReadData(&first_byte_ptr, 1)) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ switch (*first_byte_ptr) {
+ case RLE_EOL: {
+ if (row_num_ >= height_) {
+ SaveDecodingStatus(BMP_D_STATUS_TAIL);
+ Error();
+ NOTREACHED();
+ }
+ ReadScanline(imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
+ out_row_buffer_);
+ col_num_ = 0;
+ std::fill(out_row_buffer_.begin(), out_row_buffer_.end(), 0);
+ SaveDecodingStatus(BMP_D_STATUS_DATA);
+ continue;
+ }
+ case RLE_EOI: {
+ if (row_num_ < height_) {
+ ReadScanline(
+ imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
+ out_row_buffer_);
+ }
+ SaveDecodingStatus(BMP_D_STATUS_TAIL);
+ return 1;
+ }
+ case RLE_DELTA: {
+ uint8_t* delta_ptr;
+ if (!ReadData(&delta_ptr, 2)) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ col_num_ += delta_ptr[0];
+ size_t bmp_row_num__next = row_num_ + delta_ptr[1];
+ if (col_num_ >= out_row_bytes_ || bmp_row_num__next >= height_) {
+ Error();
+ NOTREACHED();
+ }
+ while (row_num_ < bmp_row_num__next) {
+ std::fill(out_row_buffer_.begin(), out_row_buffer_.end(), 0);
+ ReadScanline(
+ imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
+ out_row_buffer_);
+ }
+ } break;
+ default: {
+ int32_t avail_size = out_row_bytes_ - col_num_;
+ if (!avail_size) {
+ Error();
+ NOTREACHED();
+ }
+ uint8_t size = HalfRoundUp(*first_byte_ptr);
+ if (static_cast<int32_t>(*first_byte_ptr) > avail_size) {
+ if (size + (col_num_ >> 1) > src_row_bytes_) {
+ Error();
+ NOTREACHED();
+ }
+ *first_byte_ptr = avail_size - 1;
+ }
+ if (!ReadData(&second_byte_ptr, size & 1 ? size + 1 : size)) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ for (uint8_t i = 0; i < *first_byte_ptr; i++) {
+ uint8_t color = (i & 0x01) ? (*second_byte_ptr++ & 0x0F)
+ : (*second_byte_ptr & 0xF0) >> 4;
+ if (!ValidateColorIndex(color))
+ return 0;
+
+ out_row_buffer_[col_num_++] = color;
+ }
+ }
+ }
+ } break;
+ default: {
+ int32_t avail_size = out_row_bytes_ - col_num_;
+ if (!avail_size) {
+ Error();
+ NOTREACHED();
+ }
+ if (static_cast<int32_t>(*first_byte_ptr) > avail_size) {
+ uint8_t size = HalfRoundUp(*first_byte_ptr);
+ if (size + (col_num_ >> 1) > src_row_bytes_) {
+ Error();
+ NOTREACHED();
+ }
+ *first_byte_ptr = avail_size - 1;
+ }
+ if (!ReadData(&second_byte_ptr, 1)) {
+ skip_size_ = skip_size_org;
+ return 2;
+ }
+ for (uint8_t i = 0; i < *first_byte_ptr; i++) {
+ uint8_t second_byte = *second_byte_ptr;
+ second_byte =
+ i & 0x01 ? (second_byte & 0x0F) : (second_byte & 0xF0) >> 4;
+ if (!ValidateColorIndex(second_byte))
+ return 0;
+ out_row_buffer_[col_num_++] = second_byte;
+ }
+ }
+ }
+ }
+ Error();
+ NOTREACHED();
+}
+
+uint8_t* CFX_BmpDecompressor::ReadData(uint8_t** des_buf, uint32_t data_size_) {
+ if (avail_in_ < skip_size_ + data_size_)
+ return nullptr;
+
+ *des_buf = next_in_ + skip_size_;
+ skip_size_ += data_size_;
+ return *des_buf;
+}
+
+void CFX_BmpDecompressor::SaveDecodingStatus(int32_t status) {
+ decode_status_ = status;
+ next_in_ += skip_size_;
+ avail_in_ -= skip_size_;
+ skip_size_ = 0;
+}
+
+void CFX_BmpDecompressor::SetInputBuffer(uint8_t* src_buf, uint32_t src_size) {
+ next_in_ = src_buf;
+ avail_in_ = src_size;
+ skip_size_ = 0;
+}
+
+uint32_t CFX_BmpDecompressor::GetAvailInput(uint8_t** avail_buf) {
+ if (avail_buf) {
+ *avail_buf = nullptr;
+ if (avail_in_ > 0)
+ *avail_buf = next_in_;
+ }
+ return avail_in_;
+}
+
+void CFX_BmpDecompressor::SetHeight(int32_t signed_height) {
+ if (signed_height >= 0) {
+ height_ = signed_height;
+ return;
+ }
+ if (signed_height == std::numeric_limits<int>::min()) {
+ Error();
+ NOTREACHED();
+ }
+ height_ = -signed_height;
+ imgTB_flag_ = true;
+}
diff --git a/core/fxcodec/bmp/cfx_bmpdecompressor.h b/core/fxcodec/bmp/cfx_bmpdecompressor.h
new file mode 100644
index 0000000000..499d559637
--- /dev/null
+++ b/core/fxcodec/bmp/cfx_bmpdecompressor.h
@@ -0,0 +1,76 @@
+// Copyright 2018 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_BMP_CFX_BMPDECOMPRESSOR_H_
+#define CORE_FXCODEC_BMP_CFX_BMPDECOMPRESSOR_H_
+
+#include "core/fxcodec/bmp/fx_bmp.h"
+
+#include <setjmp.h>
+
+#include <memory>
+#include <vector>
+
+class CFX_BmpDecompressor {
+ public:
+ CFX_BmpDecompressor();
+ ~CFX_BmpDecompressor();
+
+ void Error();
+ int32_t DecodeImage();
+ int32_t ReadHeader();
+ void SetInputBuffer(uint8_t* src_buf, uint32_t src_size);
+ uint32_t GetAvailInput(uint8_t** avail_buf);
+
+ jmp_buf jmpbuf_;
+
+ void* context_ptr_;
+
+ std::vector<uint8_t> out_row_buffer_;
+ std::vector<uint32_t> palette_;
+ uint8_t* next_in_;
+
+ uint32_t header_offset_;
+ uint32_t width_;
+ uint32_t height_;
+ uint32_t compress_flag_;
+ int32_t components_;
+ size_t src_row_bytes_;
+ size_t out_row_bytes_;
+ uint16_t bit_counts_;
+ uint32_t color_used_;
+ bool imgTB_flag_;
+ int32_t pal_num_;
+ int32_t pal_type_;
+ uint32_t data_size_;
+ uint32_t img_data_offset_;
+ uint32_t img_ifh_size_;
+ size_t row_num_;
+ size_t col_num_;
+ int32_t dpi_x_;
+ int32_t dpi_y_;
+ uint32_t mask_red_;
+ uint32_t mask_green_;
+ uint32_t mask_blue_;
+
+ uint32_t avail_in_;
+ uint32_t skip_size_;
+ int32_t decode_status_;
+
+ private:
+ bool GetDataPosition(uint32_t cur_pos);
+ void ReadScanline(uint32_t row_num, const std::vector<uint8_t>& row_buf);
+ int32_t DecodeRGB();
+ int32_t DecodeRLE8();
+ int32_t DecodeRLE4();
+ uint8_t* ReadData(uint8_t** des_buf, uint32_t data_size);
+ void SaveDecodingStatus(int32_t status);
+ bool ValidateColorIndex(uint8_t val);
+ bool ValidateFlag() const;
+ void SetHeight(int32_t signed_height);
+};
+
+#endif // CORE_FXCODEC_BMP_CFX_BMPDECOMPRESSOR_H_
diff --git a/core/fxcodec/bmp/fx_bmp.cpp b/core/fxcodec/bmp/fx_bmp.cpp
index 910e0a6c3d..aca456f42f 100644
--- a/core/fxcodec/bmp/fx_bmp.cpp
+++ b/core/fxcodec/bmp/fx_bmp.cpp
@@ -6,670 +6,6 @@
#include "core/fxcodec/bmp/fx_bmp.h"
-#include <algorithm>
-#include <limits>
-
-#include "core/fxcrt/fx_system.h"
-#include "third_party/base/logging.h"
-#include "third_party/base/ptr_util.h"
-
static_assert(sizeof(BmpFileHeader) == 14,
"BmpFileHeader should have a size of 14");
-namespace {
-
-const size_t kBmpCoreHeaderSize = 12;
-const size_t kBmpInfoHeaderSize = 40;
-
-uint8_t HalfRoundUp(uint8_t value) {
- uint16_t value16 = value;
- return static_cast<uint8_t>((value16 + 1) / 2);
-}
-
-} // namespace
-
-CFX_BmpDecompressor::CFX_BmpDecompressor()
- : context_ptr_(nullptr),
- next_in_(nullptr),
- header_offset_(0),
- width_(0),
- height_(0),
- compress_flag_(0),
- components_(0),
- src_row_bytes_(0),
- out_row_bytes_(0),
- bit_counts_(0),
- color_used_(0),
- imgTB_flag_(false),
- pal_num_(0),
- pal_type_(0),
- data_size_(0),
- img_data_offset_(0),
- img_ifh_size_(0),
- row_num_(0),
- col_num_(0),
- dpi_x_(0),
- dpi_y_(0),
- mask_red_(0),
- mask_green_(0),
- mask_blue_(0),
- avail_in_(0),
- skip_size_(0),
- decode_status_(BMP_D_STATUS_HEADER) {}
-
-CFX_BmpDecompressor::~CFX_BmpDecompressor() {}
-
-void CFX_BmpDecompressor::Error() {
- longjmp(jmpbuf_, 1);
-}
-
-void CFX_BmpDecompressor::ReadScanline(uint32_t row_num_,
- const std::vector<uint8_t>& row_buf) {
- auto* p = reinterpret_cast<CFX_BmpContext*>(context_ptr_);
- p->m_pDelegate->BmpReadScanline(row_num_, row_buf);
-}
-
-bool CFX_BmpDecompressor::GetDataPosition(uint32_t rcd_pos) {
- auto* p = reinterpret_cast<CFX_BmpContext*>(context_ptr_);
- return p->m_pDelegate->BmpInputImagePositionBuf(rcd_pos);
-}
-
-int32_t CFX_BmpDecompressor::ReadHeader() {
- uint32_t skip_size_org = skip_size_;
- if (decode_status_ == BMP_D_STATUS_HEADER) {
- BmpFileHeader* pBmp_header = nullptr;
- if (!ReadData(reinterpret_cast<uint8_t**>(&pBmp_header),
- sizeof(BmpFileHeader))) {
- return 2;
- }
-
- pBmp_header->bfType =
- FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&pBmp_header->bfType));
- pBmp_header->bfOffBits = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_header->bfOffBits));
- data_size_ =
- FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&pBmp_header->bfSize));
- if (pBmp_header->bfType != BMP_SIGNATURE) {
- Error();
- NOTREACHED();
- }
- if (avail_in_ < sizeof(uint32_t)) {
- skip_size_ = skip_size_org;
- return 2;
- }
- img_ifh_size_ =
- FXDWORD_GET_LSBFIRST(static_cast<uint8_t*>(next_in_ + skip_size_));
- pal_type_ = 0;
- static_assert(sizeof(BmpCoreHeader) == kBmpCoreHeaderSize,
- "BmpCoreHeader has wrong size");
- static_assert(sizeof(BmpInfoHeader) == kBmpInfoHeaderSize,
- "BmpInfoHeader has wrong size");
- switch (img_ifh_size_) {
- case kBmpCoreHeaderSize: {
- pal_type_ = 1;
- BmpCoreHeader* pBmp_core_header = nullptr;
- if (!ReadData(reinterpret_cast<uint8_t**>(&pBmp_core_header),
- img_ifh_size_)) {
- skip_size_ = skip_size_org;
- return 2;
- }
- width_ = FXWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_core_header->bcWidth));
- height_ = FXWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_core_header->bcHeight));
- bit_counts_ = FXWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_core_header->bcBitCount));
- compress_flag_ = BMP_RGB;
- imgTB_flag_ = false;
- } break;
- case kBmpInfoHeaderSize: {
- BmpInfoHeader* pBmp_info_header = nullptr;
- if (!ReadData(reinterpret_cast<uint8_t**>(&pBmp_info_header),
- img_ifh_size_)) {
- skip_size_ = skip_size_org;
- return 2;
- }
- width_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biWidth));
- int32_t signed_height = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biHeight));
- bit_counts_ = FXWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biBitCount));
- compress_flag_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biCompression));
- color_used_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biClrUsed));
- dpi_x_ = static_cast<int32_t>(FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biXPelsPerMeter)));
- dpi_y_ = static_cast<int32_t>(FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biYPelsPerMeter)));
- SetHeight(signed_height);
- } break;
- default: {
- if (img_ifh_size_ >
- std::min(kBmpInfoHeaderSize, sizeof(BmpInfoHeader))) {
- BmpInfoHeader* pBmp_info_header = nullptr;
- if (!ReadData(reinterpret_cast<uint8_t**>(&pBmp_info_header),
- img_ifh_size_)) {
- skip_size_ = skip_size_org;
- return 2;
- }
- uint16_t biPlanes;
- width_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biWidth));
- int32_t signed_height = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biHeight));
- bit_counts_ = FXWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biBitCount));
- compress_flag_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biCompression));
- color_used_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biClrUsed));
- biPlanes = FXWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biPlanes));
- dpi_x_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biXPelsPerMeter));
- dpi_y_ = FXDWORD_GET_LSBFIRST(
- reinterpret_cast<uint8_t*>(&pBmp_info_header->biYPelsPerMeter));
- SetHeight(signed_height);
- if (compress_flag_ == BMP_RGB && biPlanes == 1 && color_used_ == 0)
- break;
- }
- Error();
- NOTREACHED();
- }
- }
- if (width_ > BMP_MAX_WIDTH || compress_flag_ > BMP_BITFIELDS) {
- Error();
- NOTREACHED();
- }
- switch (bit_counts_) {
- case 1:
- case 4:
- case 8:
- case 16:
- case 24: {
- if (color_used_ > 1U << bit_counts_) {
- Error();
- NOTREACHED();
- }
- }
- case 32:
- break;
- default:
- Error();
- NOTREACHED();
- }
- src_row_bytes_ = BMP_WIDTHBYTES(width_, bit_counts_);
- switch (bit_counts_) {
- case 1:
- case 4:
- case 8:
- out_row_bytes_ = BMP_WIDTHBYTES(width_, 8);
- components_ = 1;
- break;
- case 16:
- case 24:
- out_row_bytes_ = BMP_WIDTHBYTES(width_, 24);
- components_ = 3;
- break;
- case 32:
- out_row_bytes_ = src_row_bytes_;
- components_ = 4;
- break;
- }
- out_row_buffer_.clear();
-
- if (out_row_bytes_ <= 0) {
- Error();
- NOTREACHED();
- }
-
- out_row_buffer_.resize(out_row_bytes_);
- SaveDecodingStatus(BMP_D_STATUS_PAL);
- }
- if (decode_status_ == BMP_D_STATUS_PAL) {
- skip_size_org = skip_size_;
- if (compress_flag_ == BMP_BITFIELDS) {
- if (bit_counts_ != 16 && bit_counts_ != 32) {
- Error();
- NOTREACHED();
- }
- uint32_t* mask;
- if (ReadData(reinterpret_cast<uint8_t**>(&mask), 3 * sizeof(uint32_t)) ==
- nullptr) {
- skip_size_ = skip_size_org;
- return 2;
- }
- mask_red_ = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&mask[0]));
- mask_green_ = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&mask[1]));
- mask_blue_ = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&mask[2]));
- if (mask_red_ & mask_green_ || mask_red_ & mask_blue_ ||
- mask_green_ & mask_blue_) {
- Error();
- NOTREACHED();
- }
- header_offset_ = std::max(header_offset_, 26 + img_ifh_size_);
- SaveDecodingStatus(BMP_D_STATUS_DATA_PRE);
- return 1;
- } else if (bit_counts_ == 16) {
- mask_red_ = 0x7C00;
- mask_green_ = 0x03E0;
- mask_blue_ = 0x001F;
- }
- pal_num_ = 0;
- if (bit_counts_ < 16) {
- pal_num_ = 1 << bit_counts_;
- if (color_used_ != 0)
- pal_num_ = color_used_;
- uint8_t* src_pal_ptr = nullptr;
- uint32_t src_pal_size = pal_num_ * (pal_type_ ? 3 : 4);
- if (ReadData(&src_pal_ptr, src_pal_size) == nullptr) {
- skip_size_ = skip_size_org;
- return 2;
- }
- palette_.resize(pal_num_);
- int32_t src_pal_index = 0;
- if (pal_type_ == BMP_PAL_OLD) {
- while (src_pal_index < pal_num_) {
- palette_[src_pal_index++] = BMP_PAL_ENCODE(
- 0x00, src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]);
- src_pal_ptr += 3;
- }
- } else {
- while (src_pal_index < pal_num_) {
- palette_[src_pal_index++] = BMP_PAL_ENCODE(
- src_pal_ptr[3], src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]);
- src_pal_ptr += 4;
- }
- }
- }
- header_offset_ = std::max(
- header_offset_, 14 + img_ifh_size_ + pal_num_ * (pal_type_ ? 3 : 4));
- SaveDecodingStatus(BMP_D_STATUS_DATA_PRE);
- }
- return 1;
-}
-
-bool CFX_BmpDecompressor::ValidateFlag() const {
- switch (compress_flag_) {
- case BMP_RGB:
- case BMP_BITFIELDS:
- case BMP_RLE8:
- case BMP_RLE4:
- return true;
- default:
- return false;
- }
-}
-
-int32_t CFX_BmpDecompressor::DecodeImage() {
- if (decode_status_ == BMP_D_STATUS_DATA_PRE) {
- avail_in_ = 0;
- if (!GetDataPosition(header_offset_)) {
- decode_status_ = BMP_D_STATUS_TAIL;
- Error();
- NOTREACHED();
- }
- row_num_ = 0;
- SaveDecodingStatus(BMP_D_STATUS_DATA);
- }
- if (decode_status_ != BMP_D_STATUS_DATA || !ValidateFlag()) {
- Error();
- NOTREACHED();
- }
- switch (compress_flag_) {
- case BMP_RGB:
- case BMP_BITFIELDS:
- return DecodeRGB();
- case BMP_RLE8:
- return DecodeRLE8();
- case BMP_RLE4:
- return DecodeRLE4();
- default:
- return 0;
- }
-}
-
-bool CFX_BmpDecompressor::ValidateColorIndex(uint8_t val) {
- if (val >= pal_num_) {
- Error();
- NOTREACHED();
- }
- return true;
-}
-
-int32_t CFX_BmpDecompressor::DecodeRGB() {
- uint8_t* des_buf = nullptr;
- while (row_num_ < height_) {
- size_t idx = 0;
- if (!ReadData(&des_buf, src_row_bytes_))
- return 2;
-
- SaveDecodingStatus(BMP_D_STATUS_DATA);
- switch (bit_counts_) {
- case 1: {
- for (uint32_t col = 0; col < width_; ++col)
- out_row_buffer_[idx++] =
- des_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00;
- } break;
- case 4: {
- for (uint32_t col = 0; col < width_; ++col) {
- out_row_buffer_[idx++] = (col & 0x01)
- ? (des_buf[col >> 1] & 0x0F)
- : ((des_buf[col >> 1] & 0xF0) >> 4);
- }
- } break;
- case 16: {
- uint16_t* buf = (uint16_t*)des_buf;
- uint8_t blue_bits = 0;
- uint8_t green_bits = 0;
- uint8_t red_bits = 0;
- for (int32_t i = 0; i < 16; i++) {
- if ((mask_blue_ >> i) & 0x01)
- blue_bits++;
- if ((mask_green_ >> i) & 0x01)
- green_bits++;
- if ((mask_red_ >> i) & 0x01)
- red_bits++;
- }
- green_bits += blue_bits;
- red_bits += green_bits;
- if (blue_bits > 8 || green_bits < 8 || red_bits < 8)
- return 2;
- blue_bits = 8 - blue_bits;
- green_bits -= 8;
- red_bits -= 8;
- for (uint32_t col = 0; col < width_; ++col) {
- *buf = FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(buf));
- out_row_buffer_[idx++] =
- static_cast<uint8_t>((*buf & mask_blue_) << blue_bits);
- out_row_buffer_[idx++] =
- static_cast<uint8_t>((*buf & mask_green_) >> green_bits);
- out_row_buffer_[idx++] =
- static_cast<uint8_t>((*buf++ & mask_red_) >> red_bits);
- }
- } break;
- case 8:
- case 24:
- case 32:
- std::copy(des_buf, des_buf + src_row_bytes_, out_row_buffer_.begin());
- idx += src_row_bytes_;
- break;
- }
- for (uint8_t byte : out_row_buffer_) {
- if (!ValidateColorIndex(byte))
- return 0;
- }
- ReadScanline(imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
- out_row_buffer_);
- }
- SaveDecodingStatus(BMP_D_STATUS_TAIL);
- return 1;
-}
-
-int32_t CFX_BmpDecompressor::DecodeRLE8() {
- uint8_t* first_byte_ptr = nullptr;
- uint8_t* second_byte_ptr = nullptr;
- col_num_ = 0;
- while (true) {
- uint32_t skip_size_org = skip_size_;
- if (!ReadData(&first_byte_ptr, 1))
- return 2;
-
- switch (*first_byte_ptr) {
- case RLE_MARKER: {
- if (!ReadData(&first_byte_ptr, 1)) {
- skip_size_ = skip_size_org;
- return 2;
- }
- switch (*first_byte_ptr) {
- case RLE_EOL: {
- if (row_num_ >= height_) {
- SaveDecodingStatus(BMP_D_STATUS_TAIL);
- Error();
- NOTREACHED();
- }
- ReadScanline(imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
- out_row_buffer_);
- col_num_ = 0;
- std::fill(out_row_buffer_.begin(), out_row_buffer_.end(), 0);
- SaveDecodingStatus(BMP_D_STATUS_DATA);
- continue;
- }
- case RLE_EOI: {
- if (row_num_ < height_) {
- ReadScanline(
- imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
- out_row_buffer_);
- }
- SaveDecodingStatus(BMP_D_STATUS_TAIL);
- return 1;
- }
- case RLE_DELTA: {
- uint8_t* delta_ptr;
- if (!ReadData(&delta_ptr, 2)) {
- skip_size_ = skip_size_org;
- return 2;
- }
- col_num_ += delta_ptr[0];
- size_t bmp_row_num__next = row_num_ + delta_ptr[1];
- if (col_num_ >= out_row_bytes_ || bmp_row_num__next >= height_) {
- Error();
- NOTREACHED();
- }
- while (row_num_ < bmp_row_num__next) {
- std::fill(out_row_buffer_.begin(), out_row_buffer_.end(), 0);
- ReadScanline(
- imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
- out_row_buffer_);
- }
- } break;
- default: {
- int32_t avail_size = out_row_bytes_ - col_num_;
- if (!avail_size ||
- static_cast<int32_t>(*first_byte_ptr) > avail_size) {
- Error();
- NOTREACHED();
- }
- if (!ReadData(&second_byte_ptr, *first_byte_ptr & 1
- ? *first_byte_ptr + 1
- : *first_byte_ptr)) {
- skip_size_ = skip_size_org;
- return 2;
- }
- std::copy(second_byte_ptr, second_byte_ptr + *first_byte_ptr,
- out_row_buffer_.begin() + col_num_);
- for (size_t i = col_num_; i < col_num_ + *first_byte_ptr; ++i) {
- if (!ValidateColorIndex(out_row_buffer_[i]))
- return 0;
- }
- col_num_ += *first_byte_ptr;
- }
- }
- } break;
- default: {
- int32_t avail_size = out_row_bytes_ - col_num_;
- if (!avail_size || static_cast<int32_t>(*first_byte_ptr) > avail_size) {
- Error();
- NOTREACHED();
- }
- if (!ReadData(&second_byte_ptr, 1)) {
- skip_size_ = skip_size_org;
- return 2;
- }
- std::fill(out_row_buffer_.begin() + col_num_,
- out_row_buffer_.begin() + col_num_ + *first_byte_ptr,
- *second_byte_ptr);
- if (!ValidateColorIndex(out_row_buffer_[col_num_]))
- return 0;
- col_num_ += *first_byte_ptr;
- }
- }
- }
- Error();
- NOTREACHED();
-}
-
-int32_t CFX_BmpDecompressor::DecodeRLE4() {
- uint8_t* first_byte_ptr = nullptr;
- uint8_t* second_byte_ptr = nullptr;
- col_num_ = 0;
- while (true) {
- uint32_t skip_size_org = skip_size_;
- if (!ReadData(&first_byte_ptr, 1))
- return 2;
-
- switch (*first_byte_ptr) {
- case RLE_MARKER: {
- if (!ReadData(&first_byte_ptr, 1)) {
- skip_size_ = skip_size_org;
- return 2;
- }
- switch (*first_byte_ptr) {
- case RLE_EOL: {
- if (row_num_ >= height_) {
- SaveDecodingStatus(BMP_D_STATUS_TAIL);
- Error();
- NOTREACHED();
- }
- ReadScanline(imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
- out_row_buffer_);
- col_num_ = 0;
- std::fill(out_row_buffer_.begin(), out_row_buffer_.end(), 0);
- SaveDecodingStatus(BMP_D_STATUS_DATA);
- continue;
- }
- case RLE_EOI: {
- if (row_num_ < height_) {
- ReadScanline(
- imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
- out_row_buffer_);
- }
- SaveDecodingStatus(BMP_D_STATUS_TAIL);
- return 1;
- }
- case RLE_DELTA: {
- uint8_t* delta_ptr;
- if (!ReadData(&delta_ptr, 2)) {
- skip_size_ = skip_size_org;
- return 2;
- }
- col_num_ += delta_ptr[0];
- size_t bmp_row_num__next = row_num_ + delta_ptr[1];
- if (col_num_ >= out_row_bytes_ || bmp_row_num__next >= height_) {
- Error();
- NOTREACHED();
- }
- while (row_num_ < bmp_row_num__next) {
- std::fill(out_row_buffer_.begin(), out_row_buffer_.end(), 0);
- ReadScanline(
- imgTB_flag_ ? row_num_++ : (height_ - 1 - row_num_++),
- out_row_buffer_);
- }
- } break;
- default: {
- int32_t avail_size = out_row_bytes_ - col_num_;
- if (!avail_size) {
- Error();
- NOTREACHED();
- }
- uint8_t size = HalfRoundUp(*first_byte_ptr);
- if (static_cast<int32_t>(*first_byte_ptr) > avail_size) {
- if (size + (col_num_ >> 1) > src_row_bytes_) {
- Error();
- NOTREACHED();
- }
- *first_byte_ptr = avail_size - 1;
- }
- if (!ReadData(&second_byte_ptr, size & 1 ? size + 1 : size)) {
- skip_size_ = skip_size_org;
- return 2;
- }
- for (uint8_t i = 0; i < *first_byte_ptr; i++) {
- uint8_t color = (i & 0x01) ? (*second_byte_ptr++ & 0x0F)
- : (*second_byte_ptr & 0xF0) >> 4;
- if (!ValidateColorIndex(color))
- return 0;
-
- out_row_buffer_[col_num_++] = color;
- }
- }
- }
- } break;
- default: {
- int32_t avail_size = out_row_bytes_ - col_num_;
- if (!avail_size) {
- Error();
- NOTREACHED();
- }
- if (static_cast<int32_t>(*first_byte_ptr) > avail_size) {
- uint8_t size = HalfRoundUp(*first_byte_ptr);
- if (size + (col_num_ >> 1) > src_row_bytes_) {
- Error();
- NOTREACHED();
- }
- *first_byte_ptr = avail_size - 1;
- }
- if (!ReadData(&second_byte_ptr, 1)) {
- skip_size_ = skip_size_org;
- return 2;
- }
- for (uint8_t i = 0; i < *first_byte_ptr; i++) {
- uint8_t second_byte = *second_byte_ptr;
- second_byte =
- i & 0x01 ? (second_byte & 0x0F) : (second_byte & 0xF0) >> 4;
- if (!ValidateColorIndex(second_byte))
- return 0;
- out_row_buffer_[col_num_++] = second_byte;
- }
- }
- }
- }
- Error();
- NOTREACHED();
-}
-
-uint8_t* CFX_BmpDecompressor::ReadData(uint8_t** des_buf, uint32_t data_size_) {
- if (avail_in_ < skip_size_ + data_size_)
- return nullptr;
-
- *des_buf = next_in_ + skip_size_;
- skip_size_ += data_size_;
- return *des_buf;
-}
-
-void CFX_BmpDecompressor::SaveDecodingStatus(int32_t status) {
- decode_status_ = status;
- next_in_ += skip_size_;
- avail_in_ -= skip_size_;
- skip_size_ = 0;
-}
-
-void CFX_BmpDecompressor::SetInputBuffer(uint8_t* src_buf, uint32_t src_size) {
- next_in_ = src_buf;
- avail_in_ = src_size;
- skip_size_ = 0;
-}
-
-uint32_t CFX_BmpDecompressor::GetAvailInput(uint8_t** avail_buf) {
- if (avail_buf) {
- *avail_buf = nullptr;
- if (avail_in_ > 0)
- *avail_buf = next_in_;
- }
- return avail_in_;
-}
-
-void CFX_BmpDecompressor::SetHeight(int32_t signed_height) {
- if (signed_height >= 0) {
- height_ = signed_height;
- return;
- }
- if (signed_height == std::numeric_limits<int>::min()) {
- Error();
- NOTREACHED();
- }
- height_ = -signed_height;
- imgTB_flag_ = true;
-}
diff --git a/core/fxcodec/bmp/fx_bmp.h b/core/fxcodec/bmp/fx_bmp.h
index d81b97ea7e..76177ff063 100644
--- a/core/fxcodec/bmp/fx_bmp.h
+++ b/core/fxcodec/bmp/fx_bmp.h
@@ -7,11 +7,6 @@
#ifndef CORE_FXCODEC_BMP_FX_BMP_H_
#define CORE_FXCODEC_BMP_FX_BMP_H_
-#include <setjmp.h>
-
-#include <memory>
-#include <vector>
-
#include "core/fxcodec/codec/ccodec_bmpmodule.h"
#define BMP_WIDTHBYTES(width, bitCount) ((width * bitCount) + 31) / 32 * 4
@@ -64,74 +59,4 @@ typedef struct tagBmpInfoHeader {
} BmpInfoHeader;
#pragma pack()
-class CFX_BmpDecompressor {
- public:
- CFX_BmpDecompressor();
- ~CFX_BmpDecompressor();
-
- void Error();
- int32_t DecodeImage();
- int32_t ReadHeader();
- void SetInputBuffer(uint8_t* src_buf, uint32_t src_size);
- uint32_t GetAvailInput(uint8_t** avail_buf);
-
- jmp_buf jmpbuf_;
-
- void* context_ptr_;
-
- std::vector<uint8_t> out_row_buffer_;
- std::vector<uint32_t> palette_;
- uint8_t* next_in_;
-
- uint32_t header_offset_;
- uint32_t width_;
- uint32_t height_;
- uint32_t compress_flag_;
- int32_t components_;
- size_t src_row_bytes_;
- size_t out_row_bytes_;
- uint16_t bit_counts_;
- uint32_t color_used_;
- bool imgTB_flag_;
- int32_t pal_num_;
- int32_t pal_type_;
- uint32_t data_size_;
- uint32_t img_data_offset_;
- uint32_t img_ifh_size_;
- size_t row_num_;
- size_t col_num_;
- int32_t dpi_x_;
- int32_t dpi_y_;
- uint32_t mask_red_;
- uint32_t mask_green_;
- uint32_t mask_blue_;
-
- uint32_t avail_in_;
- uint32_t skip_size_;
- int32_t decode_status_;
-
- private:
- bool GetDataPosition(uint32_t cur_pos);
- void ReadScanline(uint32_t row_num, const std::vector<uint8_t>& row_buf);
- int32_t DecodeRGB();
- int32_t DecodeRLE8();
- int32_t DecodeRLE4();
- uint8_t* ReadData(uint8_t** des_buf, uint32_t data_size);
- void SaveDecodingStatus(int32_t status);
- bool ValidateColorIndex(uint8_t val);
- bool ValidateFlag() const;
- void SetHeight(int32_t signed_height);
-};
-
-class CFX_BmpContext : public CCodec_BmpModule::Context {
- public:
- CFX_BmpContext(CCodec_BmpModule* pModule,
- CCodec_BmpModule::Delegate* pDelegate);
- ~CFX_BmpContext() override;
-
- CFX_BmpDecompressor m_Bmp;
- UnownedPtr<CCodec_BmpModule> const m_pModule;
- UnownedPtr<CCodec_BmpModule::Delegate> const m_pDelegate;
-};
-
#endif // CORE_FXCODEC_BMP_FX_BMP_H_