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 |