OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBmpRLECodec.h" | 8 #include "SkBmpRLECodec.h" |
9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 SkCodecPrintf("Warning: incomplete RLE file.\n"); | 176 SkCodecPrintf("Warning: incomplete RLE file.\n"); |
177 } | 177 } |
178 if (fRLEBytes == 0) { | 178 if (fRLEBytes == 0) { |
179 SkCodecPrintf("Error: could not read RLE image data.\n"); | 179 SkCodecPrintf("Error: could not read RLE image data.\n"); |
180 return false; | 180 return false; |
181 } | 181 } |
182 return true; | 182 return true; |
183 } | 183 } |
184 | 184 |
185 /* | 185 /* |
| 186 * Before signalling kIncompleteInput, we should attempt to load the |
| 187 * stream buffer with additional data. |
| 188 * |
| 189 * @return the number of bytes remaining in the stream buffer after |
| 190 * attempting to read more bytes from the stream |
| 191 */ |
| 192 size_t SkBmpRLECodec::checkForMoreData() { |
| 193 const size_t remainingBytes = fRLEBytes - fCurrRLEByte; |
| 194 uint8_t* buffer = fStreamBuffer.get(); |
| 195 |
| 196 // We will be reusing the same buffer, starting over from the beginning. |
| 197 // Move any remaining bytes to the start of the buffer. |
| 198 // We use memmove() instead of memcpy() because there is risk that the dst |
| 199 // and src memory will overlap in corrupt images. |
| 200 memmove(buffer, SkTAddOffset<uint8_t>(buffer, fCurrRLEByte), remainingBytes)
; |
| 201 |
| 202 // Adjust the buffer ptr to the start of the unfilled data. |
| 203 buffer += remainingBytes; |
| 204 |
| 205 // Try to read additional bytes from the stream. There are fCurrRLEByte |
| 206 // bytes of additional space remaining in the buffer, assuming that we |
| 207 // have already copied remainingBytes to the start of the buffer. |
| 208 size_t additionalBytes = this->stream()->read(buffer, fCurrRLEByte); |
| 209 |
| 210 // Update counters and return the number of bytes we currently have |
| 211 // available. We are at the start of the buffer again. |
| 212 fCurrRLEByte = 0; |
| 213 // If we were unable to fill the buffer, fRLEBytes is no longer equal to |
| 214 // the size of the buffer. There will be unused space at the end. This |
| 215 // should be fine, given that there are no more bytes in the stream. |
| 216 fRLEBytes = remainingBytes + additionalBytes; |
| 217 return fRLEBytes; |
| 218 } |
| 219 |
| 220 /* |
186 * Set an RLE pixel using the color table | 221 * Set an RLE pixel using the color table |
187 */ | 222 */ |
188 void SkBmpRLECodec::setPixel(void* dst, size_t dstRowBytes, | 223 void SkBmpRLECodec::setPixel(void* dst, size_t dstRowBytes, |
189 const SkImageInfo& dstInfo, uint32_t x, uint32_t y, | 224 const SkImageInfo& dstInfo, uint32_t x, uint32_t y, |
190 uint8_t index) { | 225 uint8_t index) { |
191 // Set the row | 226 // Set the row |
192 int height = dstInfo.height(); | 227 int height = dstInfo.height(); |
193 int row; | 228 int row; |
194 if (SkBmpCodec::kBottomUp_RowOrder == this->rowOrder()) { | 229 if (SkBmpCodec::kBottomUp_RowOrder == this->rowOrder()) { |
195 row = height - y - 1; | 230 row = height - y - 1; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 // succeeded. | 315 // succeeded. |
281 if (y >= height) { | 316 if (y >= height) { |
282 // It would be better to check for the EOF marker before returning | 317 // It would be better to check for the EOF marker before returning |
283 // success, but we may be performing a scanline decode, which | 318 // success, but we may be performing a scanline decode, which |
284 // may require us to stop before decoding the full height. | 319 // may require us to stop before decoding the full height. |
285 return kSuccess; | 320 return kSuccess; |
286 } | 321 } |
287 | 322 |
288 // Every entry takes at least two bytes | 323 // Every entry takes at least two bytes |
289 if ((int) fRLEBytes - fCurrRLEByte < 2) { | 324 if ((int) fRLEBytes - fCurrRLEByte < 2) { |
290 SkCodecPrintf("Warning: incomplete RLE input.\n"); | 325 SkCodecPrintf("Warning: might be incomplete RLE input.\n"); |
291 return kIncompleteInput; | 326 if (this->checkForMoreData() < 2) { |
| 327 return kIncompleteInput; |
| 328 } |
292 } | 329 } |
293 | 330 |
294 // Read the next two bytes. These bytes have different meanings | 331 // Read the next two bytes. These bytes have different meanings |
295 // depending on their values. In the first interpretation, the first | 332 // depending on their values. In the first interpretation, the first |
296 // byte is an escape flag and the second byte indicates what special | 333 // byte is an escape flag and the second byte indicates what special |
297 // task to perform. | 334 // task to perform. |
298 const uint8_t flag = fStreamBuffer.get()[fCurrRLEByte++]; | 335 const uint8_t flag = fStreamBuffer.get()[fCurrRLEByte++]; |
299 const uint8_t task = fStreamBuffer.get()[fCurrRLEByte++]; | 336 const uint8_t task = fStreamBuffer.get()[fCurrRLEByte++]; |
300 | 337 |
301 // Perform decoding | 338 // Perform decoding |
302 if (RLE_ESCAPE == flag) { | 339 if (RLE_ESCAPE == flag) { |
303 switch (task) { | 340 switch (task) { |
304 case RLE_EOL: | 341 case RLE_EOL: |
305 x = 0; | 342 x = 0; |
306 y++; | 343 y++; |
307 break; | 344 break; |
308 case RLE_EOF: | 345 case RLE_EOF: |
309 return kSuccess; | 346 return kSuccess; |
310 case RLE_DELTA: { | 347 case RLE_DELTA: { |
311 // Two bytes are needed to specify delta | 348 // Two bytes are needed to specify delta |
312 if ((int) fRLEBytes - fCurrRLEByte < 2) { | 349 if ((int) fRLEBytes - fCurrRLEByte < 2) { |
313 SkCodecPrintf("Warning: incomplete RLE input\n"); | 350 SkCodecPrintf("Warning: might be incomplete RLE input.\n
"); |
314 return kIncompleteInput; | 351 if (this->checkForMoreData() < 2) { |
| 352 return kIncompleteInput; |
| 353 } |
315 } | 354 } |
316 // Modify x and y | 355 // Modify x and y |
317 const uint8_t dx = fStreamBuffer.get()[fCurrRLEByte++]; | 356 const uint8_t dx = fStreamBuffer.get()[fCurrRLEByte++]; |
318 const uint8_t dy = fStreamBuffer.get()[fCurrRLEByte++]; | 357 const uint8_t dy = fStreamBuffer.get()[fCurrRLEByte++]; |
319 x += dx; | 358 x += dx; |
320 y += dy; | 359 y += dy; |
321 if (x > width || y > height) { | 360 if (x > width || y > height) { |
322 SkCodecPrintf("Warning: invalid RLE input 1.\n"); | 361 SkCodecPrintf("Warning: invalid RLE input.\n"); |
323 return kIncompleteInput; | 362 return kInvalidInput; |
324 } | 363 } |
325 break; | 364 break; |
326 } | 365 } |
327 default: { | 366 default: { |
328 // If task does not match any of the above signals, it | 367 // If task does not match any of the above signals, it |
329 // indicates that we have a sequence of non-RLE pixels. | 368 // indicates that we have a sequence of non-RLE pixels. |
330 // Furthermore, the value of task is equal to the number | 369 // Furthermore, the value of task is equal to the number |
331 // of pixels to interpret. | 370 // of pixels to interpret. |
332 uint8_t numPixels = task; | 371 uint8_t numPixels = task; |
333 const size_t rowBytes = compute_row_bytes(numPixels, | 372 const size_t rowBytes = compute_row_bytes(numPixels, |
334 this->bitsPerPixel()); | 373 this->bitsPerPixel()); |
335 // Abort if setting numPixels moves us off the edge of the | 374 // Abort if setting numPixels moves us off the edge of the |
336 // image. Also abort if there are not enough bytes | 375 // image. |
| 376 if (x + numPixels > width) { |
| 377 SkCodecPrintf("Warning: invalid RLE input.\n"); |
| 378 return kInvalidInput; |
| 379 } |
| 380 // Also abort if there are not enough bytes |
337 // remaining in the stream to set numPixels. | 381 // remaining in the stream to set numPixels. |
338 if (x + numPixels > width || | 382 if ((int) fRLEBytes - fCurrRLEByte < SkAlign2(rowBytes)) { |
339 (int) fRLEBytes - fCurrRLEByte < SkAlign2(rowBytes))
{ | 383 SkCodecPrintf("Warning: might be incomplete RLE input.\n
"); |
340 SkCodecPrintf("Warning: invalid RLE input 2.\n"); | 384 if (this->checkForMoreData() < SkAlign2(rowBytes)) { |
341 return kIncompleteInput; | 385 return kIncompleteInput; |
| 386 } |
342 } | 387 } |
343 // Set numPixels number of pixels | 388 // Set numPixels number of pixels |
344 while (numPixels > 0) { | 389 while (numPixels > 0) { |
345 switch(this->bitsPerPixel()) { | 390 switch(this->bitsPerPixel()) { |
346 case 4: { | 391 case 4: { |
347 SkASSERT(fCurrRLEByte < fRLEBytes); | 392 SkASSERT(fCurrRLEByte < fRLEBytes); |
348 uint8_t val = fStreamBuffer.get()[fCurrRLEByte++
]; | 393 uint8_t val = fStreamBuffer.get()[fCurrRLEByte++
]; |
349 setPixel(dst, dstRowBytes, dstInfo, x++, | 394 setPixel(dst, dstRowBytes, dstInfo, x++, |
350 y, val >> 4); | 395 y, val >> 4); |
351 numPixels--; | 396 numPixels--; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 // If the first byte read is not a flag, it indicates the number of | 432 // If the first byte read is not a flag, it indicates the number of |
388 // pixels to set in RLE mode. | 433 // pixels to set in RLE mode. |
389 const uint8_t numPixels = flag; | 434 const uint8_t numPixels = flag; |
390 const int endX = SkTMin<int>(x + numPixels, width); | 435 const int endX = SkTMin<int>(x + numPixels, width); |
391 | 436 |
392 if (24 == this->bitsPerPixel()) { | 437 if (24 == this->bitsPerPixel()) { |
393 // In RLE24, the second byte read is part of the pixel color. | 438 // In RLE24, the second byte read is part of the pixel color. |
394 // There are two more required bytes to finish encoding the | 439 // There are two more required bytes to finish encoding the |
395 // color. | 440 // color. |
396 if ((int) fRLEBytes - fCurrRLEByte < 2) { | 441 if ((int) fRLEBytes - fCurrRLEByte < 2) { |
397 SkCodecPrintf("Warning: incomplete RLE input\n"); | 442 SkCodecPrintf("Warning: might be incomplete RLE input.\n"); |
398 return kIncompleteInput; | 443 if (this->checkForMoreData() < 2) { |
| 444 return kIncompleteInput; |
| 445 } |
399 } | 446 } |
400 | 447 |
401 // Fill the pixels up to endX with the specified color | 448 // Fill the pixels up to endX with the specified color |
402 uint8_t blue = task; | 449 uint8_t blue = task; |
403 uint8_t green = fStreamBuffer.get()[fCurrRLEByte++]; | 450 uint8_t green = fStreamBuffer.get()[fCurrRLEByte++]; |
404 uint8_t red = fStreamBuffer.get()[fCurrRLEByte++]; | 451 uint8_t red = fStreamBuffer.get()[fCurrRLEByte++]; |
405 while (x < endX) { | 452 while (x < endX) { |
406 setRGBPixel(dst, dstRowBytes, dstInfo, x++, y, red, | 453 setRGBPixel(dst, dstRowBytes, dstInfo, x++, y, red, |
407 green, blue); | 454 green, blue); |
408 } | 455 } |
(...skipping 12 matching lines...) Expand all Loading... |
421 // Set the indicated number of pixels | 468 // Set the indicated number of pixels |
422 for (int which = 0; x < endX; x++) { | 469 for (int which = 0; x < endX; x++) { |
423 setPixel(dst, dstRowBytes, dstInfo, x, y, | 470 setPixel(dst, dstRowBytes, dstInfo, x, y, |
424 indices[which]); | 471 indices[which]); |
425 which = !which; | 472 which = !which; |
426 } | 473 } |
427 } | 474 } |
428 } | 475 } |
429 } | 476 } |
430 } | 477 } |
OLD | NEW |