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