| Index: src/images/bmpdecoderhelper.cpp
|
| diff --git a/src/images/bmpdecoderhelper.cpp b/src/images/bmpdecoderhelper.cpp
|
| deleted file mode 100644
|
| index 9171b5d5278410592db36c7e82d7170d9b90ca02..0000000000000000000000000000000000000000
|
| --- a/src/images/bmpdecoderhelper.cpp
|
| +++ /dev/null
|
| @@ -1,369 +0,0 @@
|
| -
|
| -/*
|
| - * Copyright 2007 The Android Open Source Project
|
| - *
|
| - * Use of this source code is governed by a BSD-style license that can be
|
| - * found in the LICENSE file.
|
| - */
|
| -
|
| -// Author: cevans@google.com (Chris Evans)
|
| -
|
| -#include "bmpdecoderhelper.h"
|
| -
|
| -namespace image_codec {
|
| -
|
| -static const int kBmpHeaderSize = 14;
|
| -static const int kBmpInfoSize = 40;
|
| -static const int kBmpOS2InfoSize = 12;
|
| -static const int kMaxDim = SHRT_MAX / 2;
|
| -
|
| -bool BmpDecoderHelper::DecodeImage(const char* p,
|
| - size_t len,
|
| - int max_pixels,
|
| - BmpDecoderCallback* callback) {
|
| - data_ = reinterpret_cast<const uint8*>(p);
|
| - pos_ = 0;
|
| - len_ = len;
|
| - inverted_ = true;
|
| - // Parse the header structure.
|
| - if (len < kBmpHeaderSize + 4) {
|
| - return false;
|
| - }
|
| - GetShort(); // Signature.
|
| - GetInt(); // Size.
|
| - GetInt(); // Reserved.
|
| - int offset = GetInt();
|
| - // Parse the info structure.
|
| - int infoSize = GetInt();
|
| - if (infoSize != kBmpOS2InfoSize && infoSize < kBmpInfoSize) {
|
| - return false;
|
| - }
|
| - int cols = 0;
|
| - int comp = 0;
|
| - int colLen = 4;
|
| - if (infoSize >= kBmpInfoSize) {
|
| - if (len < kBmpHeaderSize + kBmpInfoSize) {
|
| - return false;
|
| - }
|
| - width_ = GetInt();
|
| - height_ = GetInt();
|
| - GetShort(); // Planes.
|
| - bpp_ = GetShort();
|
| - comp = GetInt();
|
| - GetInt(); // Size.
|
| - GetInt(); // XPPM.
|
| - GetInt(); // YPPM.
|
| - cols = GetInt();
|
| - GetInt(); // Important colours.
|
| - } else {
|
| - if (len < kBmpHeaderSize + kBmpOS2InfoSize) {
|
| - return false;
|
| - }
|
| - colLen = 3;
|
| - width_ = GetShort();
|
| - height_ = GetShort();
|
| - GetShort(); // Planes.
|
| - bpp_ = GetShort();
|
| - }
|
| - if (height_ < 0) {
|
| - height_ = -height_;
|
| - inverted_ = false;
|
| - }
|
| - if (width_ <= 0 || width_ > kMaxDim || height_ <= 0 || height_ > kMaxDim) {
|
| - return false;
|
| - }
|
| - if (width_ * height_ > max_pixels) {
|
| - return false;
|
| - }
|
| - if (cols < 0 || cols > 256) {
|
| - return false;
|
| - }
|
| - // Allocate then read in the colour map.
|
| - if (cols == 0 && bpp_ <= 8) {
|
| - cols = 1 << bpp_;
|
| - }
|
| - if (bpp_ <= 8 || cols > 0) {
|
| - uint8* colBuf = new uint8[256 * 3];
|
| - memset(colBuf, '\0', 256 * 3);
|
| - colTab_.reset(colBuf);
|
| - }
|
| - if (cols > 0) {
|
| - if (pos_ + (cols * colLen) > len_) {
|
| - return false;
|
| - }
|
| - for (int i = 0; i < cols; ++i) {
|
| - int base = i * 3;
|
| - colTab_[base + 2] = GetByte();
|
| - colTab_[base + 1] = GetByte();
|
| - colTab_[base] = GetByte();
|
| - if (colLen == 4) {
|
| - GetByte();
|
| - }
|
| - }
|
| - }
|
| - // Read in the compression data if necessary.
|
| - redBits_ = 0x7c00;
|
| - greenBits_ = 0x03e0;
|
| - blueBits_ = 0x001f;
|
| - bool rle = false;
|
| - if (comp == 1 || comp == 2) {
|
| - rle = true;
|
| - } else if (comp == 3) {
|
| - if (pos_ + 12 > len_) {
|
| - return false;
|
| - }
|
| - redBits_ = GetInt() & 0xffff;
|
| - greenBits_ = GetInt() & 0xffff;
|
| - blueBits_ = GetInt() & 0xffff;
|
| - }
|
| - redShiftRight_ = CalcShiftRight(redBits_);
|
| - greenShiftRight_ = CalcShiftRight(greenBits_);
|
| - blueShiftRight_ = CalcShiftRight(blueBits_);
|
| - redShiftLeft_ = CalcShiftLeft(redBits_);
|
| - greenShiftLeft_ = CalcShiftLeft(greenBits_);
|
| - blueShiftLeft_ = CalcShiftLeft(blueBits_);
|
| - rowPad_ = 0;
|
| - pixelPad_ = 0;
|
| - int rowLen;
|
| - if (bpp_ == 32) {
|
| - rowLen = width_ * 4;
|
| - pixelPad_ = 1;
|
| - } else if (bpp_ == 24) {
|
| - rowLen = width_ * 3;
|
| - } else if (bpp_ == 16) {
|
| - rowLen = width_ * 2;
|
| - } else if (bpp_ == 8) {
|
| - rowLen = width_;
|
| - } else if (bpp_ == 4) {
|
| - rowLen = width_ / 2;
|
| - if (width_ & 1) {
|
| - rowLen++;
|
| - }
|
| - } else if (bpp_ == 1) {
|
| - rowLen = width_ / 8;
|
| - if (width_ & 7) {
|
| - rowLen++;
|
| - }
|
| - } else {
|
| - return false;
|
| - }
|
| - // Round the rowLen up to a multiple of 4.
|
| - if (rowLen % 4 != 0) {
|
| - rowPad_ = 4 - (rowLen % 4);
|
| - rowLen += rowPad_;
|
| - }
|
| -
|
| - if (offset > 0 && (size_t)offset > pos_ && (size_t)offset < len_) {
|
| - pos_ = offset;
|
| - }
|
| - // Deliberately off-by-one; a load of BMPs seem to have their last byte
|
| - // missing.
|
| - if (!rle && (pos_ + (rowLen * height_) > len_ + 1)) {
|
| - return false;
|
| - }
|
| -
|
| - output_ = callback->SetSize(width_, height_);
|
| - if (nullptr == output_) {
|
| - return true; // meaning we succeeded, but they want us to stop now
|
| - }
|
| -
|
| - if (rle && (bpp_ == 4 || bpp_ == 8)) {
|
| - DoRLEDecode();
|
| - } else {
|
| - DoStandardDecode();
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void BmpDecoderHelper::DoRLEDecode() {
|
| - static const uint8 RLE_ESCAPE = 0;
|
| - static const uint8 RLE_EOL = 0;
|
| - static const uint8 RLE_EOF = 1;
|
| - static const uint8 RLE_DELTA = 2;
|
| - int x = 0;
|
| - int y = height_ - 1;
|
| - while (pos_ + 1 < len_) {
|
| - uint8 cmd = GetByte();
|
| - if (cmd != RLE_ESCAPE) {
|
| - uint8 pixels = GetByte();
|
| - int num = 0;
|
| - uint8 col = pixels;
|
| - while (cmd-- && x < width_) {
|
| - if (bpp_ == 4) {
|
| - if (num & 1) {
|
| - col = pixels & 0xf;
|
| - } else {
|
| - col = pixels >> 4;
|
| - }
|
| - }
|
| - PutPixel(x++, y, col);
|
| - num++;
|
| - }
|
| - } else {
|
| - cmd = GetByte();
|
| - if (cmd == RLE_EOF) {
|
| - return;
|
| - } else if (cmd == RLE_EOL) {
|
| - x = 0;
|
| - y--;
|
| - if (y < 0) {
|
| - return;
|
| - }
|
| - } else if (cmd == RLE_DELTA) {
|
| - if (pos_ + 1 < len_) {
|
| - uint8 dx = GetByte();
|
| - uint8 dy = GetByte();
|
| - x += dx;
|
| - if (x > width_) {
|
| - x = width_;
|
| - }
|
| - y -= dy;
|
| - if (y < 0) {
|
| - return;
|
| - }
|
| - }
|
| - } else {
|
| - int num = 0;
|
| - int bytesRead = 0;
|
| - uint8 val = 0;
|
| - while (cmd-- && pos_ < len_) {
|
| - if (bpp_ == 8 || !(num & 1)) {
|
| - val = GetByte();
|
| - bytesRead++;
|
| - }
|
| - uint8 col = val;
|
| - if (bpp_ == 4) {
|
| - if (num & 1) {
|
| - col = col & 0xf;
|
| - } else {
|
| - col >>= 4;
|
| - }
|
| - }
|
| - if (x < width_) {
|
| - PutPixel(x++, y, col);
|
| - }
|
| - num++;
|
| - }
|
| - // All pixel runs must be an even number of bytes - skip a byte if we
|
| - // read an odd number.
|
| - if ((bytesRead & 1) && pos_ < len_) {
|
| - GetByte();
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void BmpDecoderHelper::PutPixel(int x, int y, uint8 col) {
|
| - CHECK(x >= 0 && x < width_);
|
| - CHECK(y >= 0 && y < height_);
|
| - if (!inverted_) {
|
| - y = height_ - (y + 1);
|
| - }
|
| -
|
| - int base = ((y * width_) + x) * 3;
|
| - int colBase = col * 3;
|
| - output_[base] = colTab_[colBase];
|
| - output_[base + 1] = colTab_[colBase + 1];
|
| - output_[base + 2] = colTab_[colBase + 2];
|
| -}
|
| -
|
| -void BmpDecoderHelper::DoStandardDecode() {
|
| - int row = 0;
|
| - uint8 currVal = 0;
|
| - for (int h = height_ - 1; h >= 0; h--, row++) {
|
| - int realH = h;
|
| - if (!inverted_) {
|
| - realH = height_ - (h + 1);
|
| - }
|
| - uint8* line = output_ + (3 * width_ * realH);
|
| - for (int w = 0; w < width_; w++) {
|
| - if (bpp_ >= 24) {
|
| - line[2] = GetByte();
|
| - line[1] = GetByte();
|
| - line[0] = GetByte();
|
| - } else if (bpp_ == 16) {
|
| - uint32 val = GetShort();
|
| - line[0] = ((val & redBits_) >> redShiftRight_) << redShiftLeft_;
|
| - line[1] = ((val & greenBits_) >> greenShiftRight_) << greenShiftLeft_;
|
| - line[2] = ((val & blueBits_) >> blueShiftRight_) << blueShiftLeft_;
|
| - } else if (bpp_ <= 8) {
|
| - uint8 col;
|
| - if (bpp_ == 8) {
|
| - col = GetByte();
|
| - } else if (bpp_ == 4) {
|
| - if ((w % 2) == 0) {
|
| - currVal = GetByte();
|
| - col = currVal >> 4;
|
| - } else {
|
| - col = currVal & 0xf;
|
| - }
|
| - } else {
|
| - if ((w % 8) == 0) {
|
| - currVal = GetByte();
|
| - }
|
| - int bit = w & 7;
|
| - col = ((currVal >> (7 - bit)) & 1);
|
| - }
|
| - int base = col * 3;
|
| - line[0] = colTab_[base];
|
| - line[1] = colTab_[base + 1];
|
| - line[2] = colTab_[base + 2];
|
| - }
|
| - line += 3;
|
| - for (int i = 0; i < pixelPad_; ++i) {
|
| - GetByte();
|
| - }
|
| - }
|
| - for (int i = 0; i < rowPad_; ++i) {
|
| - GetByte();
|
| - }
|
| - }
|
| -}
|
| -
|
| -int BmpDecoderHelper::GetInt() {
|
| - uint8 b1 = GetByte();
|
| - uint8 b2 = GetByte();
|
| - uint8 b3 = GetByte();
|
| - uint8 b4 = GetByte();
|
| - return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
|
| -}
|
| -
|
| -int BmpDecoderHelper::GetShort() {
|
| - uint8 b1 = GetByte();
|
| - uint8 b2 = GetByte();
|
| - return b1 | (b2 << 8);
|
| -}
|
| -
|
| -uint8 BmpDecoderHelper::GetByte() {
|
| - CHECK(pos_ <= len_);
|
| - // We deliberately allow this off-by-one access to cater for BMPs with their
|
| - // last byte missing.
|
| - if (pos_ == len_) {
|
| - return 0;
|
| - }
|
| - return data_[pos_++];
|
| -}
|
| -
|
| -int BmpDecoderHelper::CalcShiftRight(uint32 mask) {
|
| - int ret = 0;
|
| - while (mask != 0 && !(mask & 1)) {
|
| - mask >>= 1;
|
| - ret++;
|
| - }
|
| - return ret;
|
| -}
|
| -
|
| -int BmpDecoderHelper::CalcShiftLeft(uint32 mask) {
|
| - int ret = 0;
|
| - while (mask != 0 && !(mask & 1)) {
|
| - mask >>= 1;
|
| - }
|
| - while (mask != 0 && !(mask & 0x80)) {
|
| - mask <<= 1;
|
| - ret++;
|
| - }
|
| - return ret;
|
| -}
|
| -
|
| -} // namespace image_codec
|
|
|