diff options
Diffstat (limited to 'src/images/bmpdecoderhelper.cpp')
-rw-r--r-- | src/images/bmpdecoderhelper.cpp | 369 |
1 files changed, 0 insertions, 369 deletions
diff --git a/src/images/bmpdecoderhelper.cpp b/src/images/bmpdecoderhelper.cpp deleted file mode 100644 index 9171b5d527..0000000000 --- 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 |