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 "SkCodec.h" | 8 #include "SkCodec.h" |
9 #include "SkJpegCodec.h" | 9 #include "SkJpegCodec.h" |
10 #include "SkJpegDecoderMgr.h" | 10 #include "SkJpegDecoderMgr.h" |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 jpeg_calc_output_dimensions(fDecoderMgr->dinfo()); | 295 jpeg_calc_output_dimensions(fDecoderMgr->dinfo()); |
296 } | 296 } |
297 return true; | 297 return true; |
298 } | 298 } |
299 | 299 |
300 /* | 300 /* |
301 * Performs the jpeg decode | 301 * Performs the jpeg decode |
302 */ | 302 */ |
303 SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, | 303 SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, |
304 void* dst, size_t dstRowBytes, | 304 void* dst, size_t dstRowBytes, |
305 const Options& options, SkPMColor*, int
*) { | 305 const Options& options, SkPMColor*, int
*, |
| 306 int* rowsDecoded) { |
306 if (options.fSubset) { | 307 if (options.fSubset) { |
307 // Subsets are not supported. | 308 // Subsets are not supported. |
308 return kUnimplemented; | 309 return kUnimplemented; |
309 } | 310 } |
310 | 311 |
311 // Get a pointer to the decompress info since we will use it quite frequentl
y | 312 // Get a pointer to the decompress info since we will use it quite frequentl
y |
312 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo(); | 313 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo(); |
313 | 314 |
314 // Set the jump location for libjpeg errors | 315 // Set the jump location for libjpeg errors |
315 if (setjmp(fDecoderMgr->getJmpBuf())) { | 316 if (setjmp(fDecoderMgr->getJmpBuf())) { |
(...skipping 17 matching lines...) Expand all Loading... |
333 | 334 |
334 // The recommended output buffer height should always be 1 in high quality m
odes. | 335 // The recommended output buffer height should always be 1 in high quality m
odes. |
335 // If it's not, we want to know because it means our strategy is not optimal
. | 336 // If it's not, we want to know because it means our strategy is not optimal
. |
336 SkASSERT(1 == dinfo->rec_outbuf_height); | 337 SkASSERT(1 == dinfo->rec_outbuf_height); |
337 | 338 |
338 // Perform the decode a single row at a time | 339 // Perform the decode a single row at a time |
339 uint32_t dstHeight = dstInfo.height(); | 340 uint32_t dstHeight = dstInfo.height(); |
340 JSAMPLE* dstRow = (JSAMPLE*) dst; | 341 JSAMPLE* dstRow = (JSAMPLE*) dst; |
341 for (uint32_t y = 0; y < dstHeight; y++) { | 342 for (uint32_t y = 0; y < dstHeight; y++) { |
342 // Read rows of the image | 343 // Read rows of the image |
343 uint32_t rowsDecoded = jpeg_read_scanlines(dinfo, &dstRow, 1); | 344 uint32_t lines = jpeg_read_scanlines(dinfo, &dstRow, 1); |
344 | 345 |
345 // If we cannot read enough rows, assume the input is incomplete | 346 // If we cannot read enough rows, assume the input is incomplete |
346 if (rowsDecoded != 1) { | 347 if (lines != 1) { |
347 // Fill the remainder of the image with black. This error handling | 348 *rowsDecoded = y; |
348 // behavior is unspecified but SkCodec consistently uses black as | |
349 // the fill color for opaque images. If the destination is kGray, | |
350 // the low 8 bits of SK_ColorBLACK will be used. Conveniently, | |
351 // these are zeros, which is the representation for black in kGray. | |
352 // If the destination is kRGB_565, the low 16 bits of SK_ColorBLACK | |
353 // will be used. Conveniently, these are zeros, which is the | |
354 // representation for black in kRGB_565. | |
355 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, dstHeight - y, | |
356 SK_ColorBLACK, nullptr, options.fZeroInitialized); | |
357 | 349 |
358 // Prevent libjpeg from failing on incomplete decode | 350 // Prevent libjpeg from failing on incomplete decode |
359 dinfo->output_scanline = dstHeight; | 351 dinfo->output_scanline = dstHeight; |
360 | 352 |
361 // Finish the decode and indicate that the input was incomplete. | 353 // Finish the decode and indicate that the input was incomplete. |
362 jpeg_finish_decompress(dinfo); | 354 jpeg_finish_decompress(dinfo); |
363 return fDecoderMgr->returnFailure("Incomplete image data", kIncomple
teInput); | 355 return fDecoderMgr->returnFailure("Incomplete image data", kIncomple
teInput); |
364 } | 356 } |
365 | 357 |
366 // Convert to RGBA if necessary | 358 // Convert to RGBA if necessary |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n"); | 446 SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n"); |
455 return; | 447 return; |
456 } | 448 } |
457 | 449 |
458 // We may not have decoded the entire image. Prevent libjpeg-turbo from fai
ling on a | 450 // We may not have decoded the entire image. Prevent libjpeg-turbo from fai
ling on a |
459 // partial decode. | 451 // partial decode. |
460 fDecoderMgr->dinfo()->output_scanline = this->getInfo().height(); | 452 fDecoderMgr->dinfo()->output_scanline = this->getInfo().height(); |
461 jpeg_finish_decompress(fDecoderMgr->dinfo()); | 453 jpeg_finish_decompress(fDecoderMgr->dinfo()); |
462 } | 454 } |
463 | 455 |
464 SkCodec::Result SkJpegCodec::onGetScanlines(void* dst, int count, size_t rowByte
s) { | 456 uint32_t SkJpegCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { |
465 // Set the jump location for libjpeg errors | 457 // Set the jump location for libjpeg errors |
466 if (setjmp(fDecoderMgr->getJmpBuf())) { | 458 if (setjmp(fDecoderMgr->getJmpBuf())) { |
467 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); | 459 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); |
468 } | 460 } |
469 // Read rows one at a time | 461 // Read rows one at a time |
470 JSAMPLE* dstRow; | 462 JSAMPLE* dstRow; |
471 if (fSwizzler) { | 463 if (fSwizzler) { |
472 // write data to storage row, then sample using swizzler | 464 // write data to storage row, then sample using swizzler |
473 dstRow = fSrcRow; | 465 dstRow = fSrcRow; |
474 } else { | 466 } else { |
475 // write data directly to dst | 467 // write data directly to dst |
476 dstRow = (JSAMPLE*) dst; | 468 dstRow = (JSAMPLE*) dst; |
477 } | 469 } |
478 | 470 |
479 for (int y = 0; y < count; y++) { | 471 for (int y = 0; y < count; y++) { |
480 // Read row of the image | 472 // Read row of the image |
481 uint32_t rowsDecoded = jpeg_read_scanlines(fDecoderMgr->dinfo(), &dstRow
, 1); | 473 uint32_t rowsDecoded = jpeg_read_scanlines(fDecoderMgr->dinfo(), &dstRow
, 1); |
482 if (rowsDecoded != 1) { | 474 if (rowsDecoded != 1) { |
483 SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes, count - y, | |
484 SK_ColorBLACK, nullptr, this->options().fZeroInitialized
); | |
485 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height(); | 475 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height(); |
486 return kIncompleteInput; | 476 return y; |
487 } | 477 } |
488 | 478 |
489 // Convert to RGBA if necessary | 479 // Convert to RGBA if necessary |
490 if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) { | 480 if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) { |
491 convert_CMYK_to_RGBA(dstRow, fDecoderMgr->dinfo()->output_width); | 481 convert_CMYK_to_RGBA(dstRow, fDecoderMgr->dinfo()->output_width); |
492 } | 482 } |
493 | 483 |
494 if(fSwizzler) { | 484 if(fSwizzler) { |
495 // use swizzler to sample row | 485 // use swizzler to sample row |
496 fSwizzler->swizzle(dst, dstRow); | 486 fSwizzler->swizzle(dst, dstRow); |
497 dst = SkTAddOffset<JSAMPLE>(dst, rowBytes); | 487 dst = SkTAddOffset<JSAMPLE>(dst, rowBytes); |
498 } else { | 488 } else { |
499 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes); | 489 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes); |
500 } | 490 } |
501 } | 491 } |
502 return kSuccess; | 492 return count; |
503 } | 493 } |
504 | 494 |
505 #ifndef TURBO_HAS_SKIP | 495 #ifndef TURBO_HAS_SKIP |
506 // TODO (msarett): Make this a member function and avoid reallocating the | 496 // TODO (msarett): Make this a member function and avoid reallocating the |
507 // memory buffer on each call to skip. | 497 // memory buffer on each call to skip. |
508 #define jpeg_skip_scanlines(dinfo, count) \ | 498 #define jpeg_skip_scanlines(dinfo, count) \ |
509 SkAutoMalloc storage(get_row_bytes(dinfo)); \ | 499 SkAutoMalloc storage(get_row_bytes(dinfo)); \ |
510 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \ | 500 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \ |
511 for (int y = 0; y < count; y++) { \ | 501 for (int y = 0; y < count; y++) { \ |
512 jpeg_read_scanlines(dinfo, &storagePtr, 1); \ | 502 jpeg_read_scanlines(dinfo, &storagePtr, 1); \ |
513 } | 503 } |
514 #endif | 504 #endif |
515 | 505 |
516 SkCodec::Result SkJpegCodec::onSkipScanlines(int count) { | 506 bool SkJpegCodec::onSkipScanlines(int count) { |
517 // Set the jump location for libjpeg errors | 507 // Set the jump location for libjpeg errors |
518 if (setjmp(fDecoderMgr->getJmpBuf())) { | 508 if (setjmp(fDecoderMgr->getJmpBuf())) { |
519 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); | 509 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); |
520 } | 510 } |
521 | 511 |
522 jpeg_skip_scanlines(fDecoderMgr->dinfo(), count); | 512 return count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count); |
523 | |
524 return kSuccess; | |
525 } | 513 } |
526 | |
OLD | NEW |