| 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 |