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 |