From b105152222f9dfb387efa6a70dedf3dd0ceb2cd5 Mon Sep 17 00:00:00 2001 From: Ryan Harrison Date: Tue, 6 Feb 2018 15:31:04 +0000 Subject: Move core/fxcodec/lbmp/ -> core/fxcodec/bmp/ BUG=chromium:808336 Change-Id: Id721787dd77d1bcac6daf6e3c149f79e8d1d9fe4 Reviewed-on: https://pdfium-review.googlesource.com/25610 Reviewed-by: dsinclair Commit-Queue: Ryan Harrison --- core/fxcodec/bmp/fx_bmp.cpp | 675 +++++++++++++++++++++++++++++++ core/fxcodec/bmp/fx_bmp.h | 136 +++++++ core/fxcodec/codec/ccodec_bmpmodule.cpp | 2 +- core/fxcodec/gif/cfx_lzwdecompressor.cpp | 2 +- core/fxcodec/lbmp/fx_bmp.cpp | 675 ------------------------------- core/fxcodec/lbmp/fx_bmp.h | 136 ------- 6 files changed, 813 insertions(+), 813 deletions(-) create mode 100644 core/fxcodec/bmp/fx_bmp.cpp create mode 100644 core/fxcodec/bmp/fx_bmp.h delete mode 100644 core/fxcodec/lbmp/fx_bmp.cpp delete mode 100644 core/fxcodec/lbmp/fx_bmp.h (limited to 'core') diff --git a/core/fxcodec/bmp/fx_bmp.cpp b/core/fxcodec/bmp/fx_bmp.cpp new file mode 100644 index 0000000000..31a93287f1 --- /dev/null +++ b/core/fxcodec/bmp/fx_bmp.cpp @@ -0,0 +1,675 @@ +// Copyright 2014 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/fx_bmp.h" + +#include +#include + +#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((value16 + 1) / 2); +} + +} // namespace + +BMPDecompressor::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) {} + +BMPDecompressor::~BMPDecompressor() {} + +void BMPDecompressor::Error() { + longjmp(jmpbuf_, 1); +} + +void BMPDecompressor::ReadScanline(uint32_t row_num_, + const std::vector& row_buf) { + auto* p = reinterpret_cast(context_ptr_); + p->m_pDelegate->BmpReadScanline(row_num_, row_buf); +} + +bool BMPDecompressor::GetDataPosition(uint32_t rcd_pos) { + auto* p = reinterpret_cast(context_ptr_); + return p->m_pDelegate->BmpInputImagePositionBuf(rcd_pos); +} + +int32_t BMPDecompressor::ReadHeader() { + uint32_t skip_size_org = skip_size_; + if (decode_status_ == BMP_D_STATUS_HEADER) { + BmpFileHeader* pBmp_header = nullptr; + if (!ReadData(reinterpret_cast(&pBmp_header), + sizeof(BmpFileHeader))) { + return 2; + } + + pBmp_header->bfType = + FXWORD_GET_LSBFIRST(reinterpret_cast(&pBmp_header->bfType)); + pBmp_header->bfOffBits = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_header->bfOffBits)); + data_size_ = + FXDWORD_GET_LSBFIRST(reinterpret_cast(&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(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(&pBmp_core_header), + img_ifh_size_)) { + skip_size_ = skip_size_org; + return 2; + } + width_ = FXWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_core_header->bcWidth)); + height_ = FXWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_core_header->bcHeight)); + bit_counts_ = FXWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_core_header->bcBitCount)); + compress_flag_ = BMP_RGB; + imgTB_flag_ = false; + } break; + case kBmpInfoHeaderSize: { + BmpInfoHeader* pBmp_info_header = nullptr; + if (!ReadData(reinterpret_cast(&pBmp_info_header), + img_ifh_size_)) { + skip_size_ = skip_size_org; + return 2; + } + width_ = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biWidth)); + int32_t signed_height = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biHeight)); + bit_counts_ = FXWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biBitCount)); + compress_flag_ = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biCompression)); + color_used_ = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biClrUsed)); + dpi_x_ = static_cast(FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biXPelsPerMeter))); + dpi_y_ = static_cast(FXDWORD_GET_LSBFIRST( + reinterpret_cast(&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(&pBmp_info_header), + img_ifh_size_)) { + skip_size_ = skip_size_org; + return 2; + } + uint16_t biPlanes; + width_ = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biWidth)); + int32_t signed_height = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biHeight)); + bit_counts_ = FXWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biBitCount)); + compress_flag_ = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biCompression)); + color_used_ = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biClrUsed)); + biPlanes = FXWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biPlanes)); + dpi_x_ = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biXPelsPerMeter)); + dpi_y_ = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&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(&mask), 3 * sizeof(uint32_t)) == + nullptr) { + skip_size_ = skip_size_org; + return 2; + } + mask_red_ = FXDWORD_GET_LSBFIRST(reinterpret_cast(&mask[0])); + mask_green_ = FXDWORD_GET_LSBFIRST(reinterpret_cast(&mask[1])); + mask_blue_ = FXDWORD_GET_LSBFIRST(reinterpret_cast(&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 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 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 BMPDecompressor::ValidateColorIndex(uint8_t val) { + if (val >= pal_num_) { + Error(); + NOTREACHED(); + } + return true; +} + +int32_t 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(buf)); + out_row_buffer_[idx++] = + static_cast((*buf & mask_blue_) << blue_bits); + out_row_buffer_[idx++] = + static_cast((*buf & mask_green_) >> green_bits); + out_row_buffer_[idx++] = + static_cast((*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 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(*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(*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 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(*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(*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* 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 BMPDecompressor::SaveDecodingStatus(int32_t status) { + decode_status_ = status; + next_in_ += skip_size_; + avail_in_ -= skip_size_; + skip_size_ = 0; +} + +void BMPDecompressor::SetInputBuffer(uint8_t* src_buf, uint32_t src_size) { + next_in_ = src_buf; + avail_in_ = src_size; + skip_size_ = 0; +} + +uint32_t BMPDecompressor::GetAvailInput(uint8_t** avail_buf) { + if (avail_buf) { + *avail_buf = nullptr; + if (avail_in_ > 0) + *avail_buf = next_in_; + } + return avail_in_; +} + +void BMPDecompressor::SetHeight(int32_t signed_height) { + if (signed_height >= 0) { + height_ = signed_height; + return; + } + if (signed_height == std::numeric_limits::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 new file mode 100644 index 0000000000..4033e510a6 --- /dev/null +++ b/core/fxcodec/bmp/fx_bmp.h @@ -0,0 +1,136 @@ +// Copyright 2014 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_FX_BMP_H_ +#define CORE_FXCODEC_BMP_FX_BMP_H_ + +#include + +#include +#include + +#include "core/fxcodec/codec/ccodec_bmpmodule.h" + +#define BMP_WIDTHBYTES(width, bitCount) ((width * bitCount) + 31) / 32 * 4 +#define BMP_PAL_ENCODE(a, r, g, b) \ + (((uint32_t)(a) << 24) | ((r) << 16) | ((g) << 8) | (b)) +#define BMP_D_STATUS_HEADER 0x01 +#define BMP_D_STATUS_PAL 0x02 +#define BMP_D_STATUS_DATA_PRE 0x03 +#define BMP_D_STATUS_DATA 0x04 +#define BMP_D_STATUS_TAIL 0x00 +#define BMP_SIGNATURE 0x4D42 +#define BMP_PAL_OLD 1 +#define RLE_MARKER 0 +#define RLE_EOL 0 +#define RLE_EOI 1 +#define RLE_DELTA 2 +#define BMP_RGB 0L +#define BMP_RLE8 1L +#define BMP_RLE4 2L +#define BMP_BITFIELDS 3L +// Limit width to (MAXINT32 - 31) / 32 +#define BMP_MAX_WIDTH 67108863 +#pragma pack(1) +typedef struct tagBmpFileHeader { + uint16_t bfType; + uint32_t bfSize; + uint16_t bfReserved1; + uint16_t bfReserved2; + uint32_t bfOffBits; +} BmpFileHeader; +typedef struct tagBmpCoreHeader { + uint32_t bcSize; + uint16_t bcWidth; + uint16_t bcHeight; + uint16_t bcPlanes; + uint16_t bcBitCount; +} BmpCoreHeader; +typedef struct tagBmpInfoHeader { + uint32_t biSize; + int32_t biWidth; + int32_t biHeight; + uint16_t biPlanes; + uint16_t biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + int32_t biXPelsPerMeter; + int32_t biYPelsPerMeter; + uint32_t biClrUsed; + uint32_t biClrImportant; +} BmpInfoHeader; +#pragma pack() + +class BMPDecompressor { + public: + BMPDecompressor(); + ~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 out_row_buffer_; + std::vector 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& 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 CBmpContext : public CCodec_BmpModule::Context { + public: + CBmpContext(CCodec_BmpModule* pModule, CCodec_BmpModule::Delegate* pDelegate); + ~CBmpContext() override; + + BMPDecompressor m_Bmp; + UnownedPtr const m_pModule; + UnownedPtr const m_pDelegate; +}; + +#endif // CORE_FXCODEC_BMP_FX_BMP_H_ diff --git a/core/fxcodec/codec/ccodec_bmpmodule.cpp b/core/fxcodec/codec/ccodec_bmpmodule.cpp index 46e2cf8f65..9fbb557008 100644 --- a/core/fxcodec/codec/ccodec_bmpmodule.cpp +++ b/core/fxcodec/codec/ccodec_bmpmodule.cpp @@ -6,9 +6,9 @@ #include "core/fxcodec/codec/ccodec_bmpmodule.h" +#include "core/fxcodec/bmp/fx_bmp.h" #include "core/fxcodec/codec/codec_int.h" #include "core/fxcodec/fx_codec.h" -#include "core/fxcodec/lbmp/fx_bmp.h" #include "core/fxcrt/unowned_ptr.h" #include "core/fxge/fx_dib.h" #include "third_party/base/ptr_util.h" diff --git a/core/fxcodec/gif/cfx_lzwdecompressor.cpp b/core/fxcodec/gif/cfx_lzwdecompressor.cpp index 1ee7b5a217..edff8c4f4b 100644 --- a/core/fxcodec/gif/cfx_lzwdecompressor.cpp +++ b/core/fxcodec/gif/cfx_lzwdecompressor.cpp @@ -10,7 +10,7 @@ #include #include -#include "core/fxcodec/lbmp/fx_bmp.h" +#include "core/fxcodec/bmp/fx_bmp.h" #include "third_party/base/numerics/safe_math.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" diff --git a/core/fxcodec/lbmp/fx_bmp.cpp b/core/fxcodec/lbmp/fx_bmp.cpp deleted file mode 100644 index 5e02c46ef8..0000000000 --- a/core/fxcodec/lbmp/fx_bmp.cpp +++ /dev/null @@ -1,675 +0,0 @@ -// Copyright 2014 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/lbmp/fx_bmp.h" - -#include -#include - -#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((value16 + 1) / 2); -} - -} // namespace - -BMPDecompressor::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) {} - -BMPDecompressor::~BMPDecompressor() {} - -void BMPDecompressor::Error() { - longjmp(jmpbuf_, 1); -} - -void BMPDecompressor::ReadScanline(uint32_t row_num_, - const std::vector& row_buf) { - auto* p = reinterpret_cast(context_ptr_); - p->m_pDelegate->BmpReadScanline(row_num_, row_buf); -} - -bool BMPDecompressor::GetDataPosition(uint32_t rcd_pos) { - auto* p = reinterpret_cast(context_ptr_); - return p->m_pDelegate->BmpInputImagePositionBuf(rcd_pos); -} - -int32_t BMPDecompressor::ReadHeader() { - uint32_t skip_size_org = skip_size_; - if (decode_status_ == BMP_D_STATUS_HEADER) { - BmpFileHeader* pBmp_header = nullptr; - if (!ReadData(reinterpret_cast(&pBmp_header), - sizeof(BmpFileHeader))) { - return 2; - } - - pBmp_header->bfType = - FXWORD_GET_LSBFIRST(reinterpret_cast(&pBmp_header->bfType)); - pBmp_header->bfOffBits = FXDWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_header->bfOffBits)); - data_size_ = - FXDWORD_GET_LSBFIRST(reinterpret_cast(&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(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(&pBmp_core_header), - img_ifh_size_)) { - skip_size_ = skip_size_org; - return 2; - } - width_ = FXWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_core_header->bcWidth)); - height_ = FXWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_core_header->bcHeight)); - bit_counts_ = FXWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_core_header->bcBitCount)); - compress_flag_ = BMP_RGB; - imgTB_flag_ = false; - } break; - case kBmpInfoHeaderSize: { - BmpInfoHeader* pBmp_info_header = nullptr; - if (!ReadData(reinterpret_cast(&pBmp_info_header), - img_ifh_size_)) { - skip_size_ = skip_size_org; - return 2; - } - width_ = FXDWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_info_header->biWidth)); - int32_t signed_height = FXDWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_info_header->biHeight)); - bit_counts_ = FXWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_info_header->biBitCount)); - compress_flag_ = FXDWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_info_header->biCompression)); - color_used_ = FXDWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_info_header->biClrUsed)); - dpi_x_ = static_cast(FXDWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_info_header->biXPelsPerMeter))); - dpi_y_ = static_cast(FXDWORD_GET_LSBFIRST( - reinterpret_cast(&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(&pBmp_info_header), - img_ifh_size_)) { - skip_size_ = skip_size_org; - return 2; - } - uint16_t biPlanes; - width_ = FXDWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_info_header->biWidth)); - int32_t signed_height = FXDWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_info_header->biHeight)); - bit_counts_ = FXWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_info_header->biBitCount)); - compress_flag_ = FXDWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_info_header->biCompression)); - color_used_ = FXDWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_info_header->biClrUsed)); - biPlanes = FXWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_info_header->biPlanes)); - dpi_x_ = FXDWORD_GET_LSBFIRST( - reinterpret_cast(&pBmp_info_header->biXPelsPerMeter)); - dpi_y_ = FXDWORD_GET_LSBFIRST( - reinterpret_cast(&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(&mask), 3 * sizeof(uint32_t)) == - nullptr) { - skip_size_ = skip_size_org; - return 2; - } - mask_red_ = FXDWORD_GET_LSBFIRST(reinterpret_cast(&mask[0])); - mask_green_ = FXDWORD_GET_LSBFIRST(reinterpret_cast(&mask[1])); - mask_blue_ = FXDWORD_GET_LSBFIRST(reinterpret_cast(&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 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 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 BMPDecompressor::ValidateColorIndex(uint8_t val) { - if (val >= pal_num_) { - Error(); - NOTREACHED(); - } - return true; -} - -int32_t 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(buf)); - out_row_buffer_[idx++] = - static_cast((*buf & mask_blue_) << blue_bits); - out_row_buffer_[idx++] = - static_cast((*buf & mask_green_) >> green_bits); - out_row_buffer_[idx++] = - static_cast((*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 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(*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(*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 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(*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(*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* 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 BMPDecompressor::SaveDecodingStatus(int32_t status) { - decode_status_ = status; - next_in_ += skip_size_; - avail_in_ -= skip_size_; - skip_size_ = 0; -} - -void BMPDecompressor::SetInputBuffer(uint8_t* src_buf, uint32_t src_size) { - next_in_ = src_buf; - avail_in_ = src_size; - skip_size_ = 0; -} - -uint32_t BMPDecompressor::GetAvailInput(uint8_t** avail_buf) { - if (avail_buf) { - *avail_buf = nullptr; - if (avail_in_ > 0) - *avail_buf = next_in_; - } - return avail_in_; -} - -void BMPDecompressor::SetHeight(int32_t signed_height) { - if (signed_height >= 0) { - height_ = signed_height; - return; - } - if (signed_height == std::numeric_limits::min()) { - Error(); - NOTREACHED(); - } - height_ = -signed_height; - imgTB_flag_ = true; -} diff --git a/core/fxcodec/lbmp/fx_bmp.h b/core/fxcodec/lbmp/fx_bmp.h deleted file mode 100644 index 5f970c458e..0000000000 --- a/core/fxcodec/lbmp/fx_bmp.h +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2014 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_LBMP_FX_BMP_H_ -#define CORE_FXCODEC_LBMP_FX_BMP_H_ - -#include - -#include -#include - -#include "core/fxcodec/codec/ccodec_bmpmodule.h" - -#define BMP_WIDTHBYTES(width, bitCount) ((width * bitCount) + 31) / 32 * 4 -#define BMP_PAL_ENCODE(a, r, g, b) \ - (((uint32_t)(a) << 24) | ((r) << 16) | ((g) << 8) | (b)) -#define BMP_D_STATUS_HEADER 0x01 -#define BMP_D_STATUS_PAL 0x02 -#define BMP_D_STATUS_DATA_PRE 0x03 -#define BMP_D_STATUS_DATA 0x04 -#define BMP_D_STATUS_TAIL 0x00 -#define BMP_SIGNATURE 0x4D42 -#define BMP_PAL_OLD 1 -#define RLE_MARKER 0 -#define RLE_EOL 0 -#define RLE_EOI 1 -#define RLE_DELTA 2 -#define BMP_RGB 0L -#define BMP_RLE8 1L -#define BMP_RLE4 2L -#define BMP_BITFIELDS 3L -// Limit width to (MAXINT32 - 31) / 32 -#define BMP_MAX_WIDTH 67108863 -#pragma pack(1) -typedef struct tagBmpFileHeader { - uint16_t bfType; - uint32_t bfSize; - uint16_t bfReserved1; - uint16_t bfReserved2; - uint32_t bfOffBits; -} BmpFileHeader; -typedef struct tagBmpCoreHeader { - uint32_t bcSize; - uint16_t bcWidth; - uint16_t bcHeight; - uint16_t bcPlanes; - uint16_t bcBitCount; -} BmpCoreHeader; -typedef struct tagBmpInfoHeader { - uint32_t biSize; - int32_t biWidth; - int32_t biHeight; - uint16_t biPlanes; - uint16_t biBitCount; - uint32_t biCompression; - uint32_t biSizeImage; - int32_t biXPelsPerMeter; - int32_t biYPelsPerMeter; - uint32_t biClrUsed; - uint32_t biClrImportant; -} BmpInfoHeader; -#pragma pack() - -class BMPDecompressor { - public: - BMPDecompressor(); - ~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 out_row_buffer_; - std::vector 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& 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 CBmpContext : public CCodec_BmpModule::Context { - public: - CBmpContext(CCodec_BmpModule* pModule, CCodec_BmpModule::Delegate* pDelegate); - ~CBmpContext() override; - - BMPDecompressor m_Bmp; - UnownedPtr const m_pModule; - UnownedPtr const m_pDelegate; -}; - -#endif // CORE_FXCODEC_LBMP_FX_BMP_H_ -- cgit v1.2.3