| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2007 The Android Open Source Project | 3 * Copyright 2007 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 // Author: cevans@google.com (Chris Evans) | 9 // Author: cevans@google.com (Chris Evans) |
| 10 | 10 |
| 11 #include "bmpdecoderhelper.h" | 11 #include "bmpdecoderhelper.h" |
| 12 | 12 |
| 13 namespace image_codec { | 13 namespace image_codec { |
| 14 | 14 |
| 15 static const int kBmpHeaderSize = 14; | 15 static const int kBmpHeaderSize = 14; |
| 16 static const int kBmpInfoSize = 40; | 16 static const int kBmpInfoSize = 40; |
| 17 static const int kBmpOS2InfoSize = 12; | 17 static const int kBmpOS2InfoSize = 12; |
| 18 static const int kMaxDim = SHRT_MAX / 2; | 18 static const int kMaxDim = SHRT_MAX / 2; |
| 19 | 19 |
| 20 bool BmpDecoderHelper::DecodeImage(const char* p, | 20 bool BmpDecoderHelper::DecodeImage(const char* p, |
| 21 int len, | 21 size_t len, |
| 22 int max_pixels, | 22 int max_pixels, |
| 23 BmpDecoderCallback* callback) { | 23 BmpDecoderCallback* callback) { |
| 24 data_ = reinterpret_cast<const uint8*>(p); | 24 data_ = reinterpret_cast<const uint8*>(p); |
| 25 pos_ = 0; | 25 pos_ = 0; |
| 26 len_ = len; | 26 len_ = len; |
| 27 inverted_ = true; | 27 inverted_ = true; |
| 28 // Parse the header structure. | 28 // Parse the header structure. |
| 29 if (len < kBmpHeaderSize + 4) { | 29 if (len < kBmpHeaderSize + 4) { |
| 30 return false; | 30 return false; |
| 31 } | 31 } |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 } | 146 } |
| 147 } else { | 147 } else { |
| 148 return false; | 148 return false; |
| 149 } | 149 } |
| 150 // Round the rowLen up to a multiple of 4. | 150 // Round the rowLen up to a multiple of 4. |
| 151 if (rowLen % 4 != 0) { | 151 if (rowLen % 4 != 0) { |
| 152 rowPad_ = 4 - (rowLen % 4); | 152 rowPad_ = 4 - (rowLen % 4); |
| 153 rowLen += rowPad_; | 153 rowLen += rowPad_; |
| 154 } | 154 } |
| 155 | 155 |
| 156 if (offset > 0 && offset > pos_ && offset < len_) { | 156 if (offset > 0 && (size_t)offset > pos_ && (size_t)offset < len_) { |
| 157 pos_ = offset; | 157 pos_ = offset; |
| 158 } | 158 } |
| 159 // Deliberately off-by-one; a load of BMPs seem to have their last byte | 159 // Deliberately off-by-one; a load of BMPs seem to have their last byte |
| 160 // missing. | 160 // missing. |
| 161 if (!rle && (pos_ + (rowLen * height_) > len_ + 1)) { | 161 if (!rle && (pos_ + (rowLen * height_) > len_ + 1)) { |
| 162 return false; | 162 return false; |
| 163 } | 163 } |
| 164 | 164 |
| 165 output_ = callback->SetSize(width_, height_); | 165 output_ = callback->SetSize(width_, height_); |
| 166 if (NULL == output_) { | 166 if (NULL == output_) { |
| 167 return true; // meaning we succeeded, but they want us to stop now | 167 return true; // meaning we succeeded, but they want us to stop now |
| 168 } | 168 } |
| 169 | 169 |
| 170 if (rle && (bpp_ == 4 || bpp_ == 8)) { | 170 if (rle && (bpp_ == 4 || bpp_ == 8)) { |
| 171 DoRLEDecode(); | 171 DoRLEDecode(); |
| 172 } else { | 172 } else { |
| 173 DoStandardDecode(); | 173 DoStandardDecode(); |
| 174 } | 174 } |
| 175 return true; | 175 return true; |
| 176 } | 176 } |
| 177 | 177 |
| 178 void BmpDecoderHelper::DoRLEDecode() { | 178 void BmpDecoderHelper::DoRLEDecode() { |
| 179 static const uint8 RLE_ESCAPE = 0; | 179 static const uint8 RLE_ESCAPE = 0; |
| 180 static const uint8 RLE_EOL = 0; | 180 static const uint8 RLE_EOL = 0; |
| 181 static const uint8 RLE_EOF = 1; | 181 static const uint8 RLE_EOF = 1; |
| 182 static const uint8 RLE_DELTA = 2; | 182 static const uint8 RLE_DELTA = 2; |
| 183 int x = 0; | 183 int x = 0; |
| 184 int y = height_ - 1; | 184 int y = height_ - 1; |
| 185 while (pos_ < len_ - 1) { | 185 while (pos_ + 1 < len_) { |
| 186 uint8 cmd = GetByte(); | 186 uint8 cmd = GetByte(); |
| 187 if (cmd != RLE_ESCAPE) { | 187 if (cmd != RLE_ESCAPE) { |
| 188 uint8 pixels = GetByte(); | 188 uint8 pixels = GetByte(); |
| 189 int num = 0; | 189 int num = 0; |
| 190 uint8 col = pixels; | 190 uint8 col = pixels; |
| 191 while (cmd-- && x < width_) { | 191 while (cmd-- && x < width_) { |
| 192 if (bpp_ == 4) { | 192 if (bpp_ == 4) { |
| 193 if (num & 1) { | 193 if (num & 1) { |
| 194 col = pixels & 0xf; | 194 col = pixels & 0xf; |
| 195 } else { | 195 } else { |
| 196 col = pixels >> 4; | 196 col = pixels >> 4; |
| 197 } | 197 } |
| 198 } | 198 } |
| 199 PutPixel(x++, y, col); | 199 PutPixel(x++, y, col); |
| 200 num++; | 200 num++; |
| 201 } | 201 } |
| 202 } else { | 202 } else { |
| 203 cmd = GetByte(); | 203 cmd = GetByte(); |
| 204 if (cmd == RLE_EOF) { | 204 if (cmd == RLE_EOF) { |
| 205 return; | 205 return; |
| 206 } else if (cmd == RLE_EOL) { | 206 } else if (cmd == RLE_EOL) { |
| 207 x = 0; | 207 x = 0; |
| 208 y--; | 208 y--; |
| 209 if (y < 0) { | 209 if (y < 0) { |
| 210 return; | 210 return; |
| 211 } | 211 } |
| 212 } else if (cmd == RLE_DELTA) { | 212 } else if (cmd == RLE_DELTA) { |
| 213 if (pos_ < len_ - 1) { | 213 if (pos_ + 1 < len_) { |
| 214 uint8 dx = GetByte(); | 214 uint8 dx = GetByte(); |
| 215 uint8 dy = GetByte(); | 215 uint8 dy = GetByte(); |
| 216 x += dx; | 216 x += dx; |
| 217 if (x > width_) { | 217 if (x > width_) { |
| 218 x = width_; | 218 x = width_; |
| 219 } | 219 } |
| 220 y -= dy; | 220 y -= dy; |
| 221 if (y < 0) { | 221 if (y < 0) { |
| 222 return; | 222 return; |
| 223 } | 223 } |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24); | 329 return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24); |
| 330 } | 330 } |
| 331 | 331 |
| 332 int BmpDecoderHelper::GetShort() { | 332 int BmpDecoderHelper::GetShort() { |
| 333 uint8 b1 = GetByte(); | 333 uint8 b1 = GetByte(); |
| 334 uint8 b2 = GetByte(); | 334 uint8 b2 = GetByte(); |
| 335 return b1 | (b2 << 8); | 335 return b1 | (b2 << 8); |
| 336 } | 336 } |
| 337 | 337 |
| 338 uint8 BmpDecoderHelper::GetByte() { | 338 uint8 BmpDecoderHelper::GetByte() { |
| 339 CHECK(pos_ >= 0 && pos_ <= len_); | 339 CHECK(pos_ <= len_); |
| 340 // We deliberately allow this off-by-one access to cater for BMPs with their | 340 // We deliberately allow this off-by-one access to cater for BMPs with their |
| 341 // last byte missing. | 341 // last byte missing. |
| 342 if (pos_ == len_) { | 342 if (pos_ == len_) { |
| 343 return 0; | 343 return 0; |
| 344 } | 344 } |
| 345 return data_[pos_++]; | 345 return data_[pos_++]; |
| 346 } | 346 } |
| 347 | 347 |
| 348 int BmpDecoderHelper::CalcShiftRight(uint32 mask) { | 348 int BmpDecoderHelper::CalcShiftRight(uint32 mask) { |
| 349 int ret = 0; | 349 int ret = 0; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 360 mask >>= 1; | 360 mask >>= 1; |
| 361 } | 361 } |
| 362 while (mask != 0 && !(mask & 0x80)) { | 362 while (mask != 0 && !(mask & 0x80)) { |
| 363 mask <<= 1; | 363 mask <<= 1; |
| 364 ret++; | 364 ret++; |
| 365 } | 365 } |
| 366 return ret; | 366 return ret; |
| 367 } | 367 } |
| 368 | 368 |
| 369 } // namespace image_codec | 369 } // namespace image_codec |
| OLD | NEW |