| 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 "SkMSAN.h" | 9 #include "SkMSAN.h" |
| 10 #include "SkJpegCodec.h" | 10 #include "SkJpegCodec.h" |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 , fSwizzleSrcRow(nullptr) | 271 , fSwizzleSrcRow(nullptr) |
| 272 , fColorXformSrcRow(nullptr) | 272 , fColorXformSrcRow(nullptr) |
| 273 , fSwizzlerSubset(SkIRect::MakeEmpty()) | 273 , fSwizzlerSubset(SkIRect::MakeEmpty()) |
| 274 , fICCData(std::move(iccData)) | 274 , fICCData(std::move(iccData)) |
| 275 {} | 275 {} |
| 276 | 276 |
| 277 /* | 277 /* |
| 278 * Return the row bytes of a particular image type and width | 278 * Return the row bytes of a particular image type and width |
| 279 */ | 279 */ |
| 280 static size_t get_row_bytes(const j_decompress_ptr dinfo) { | 280 static size_t get_row_bytes(const j_decompress_ptr dinfo) { |
| 281 #ifdef TURBO_HAS_565 | |
| 282 const size_t colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 : | 281 const size_t colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 : |
| 283 dinfo->out_color_components; | 282 dinfo->out_color_components; |
| 284 #else | |
| 285 const size_t colorBytes = dinfo->out_color_components; | |
| 286 #endif | |
| 287 return dinfo->output_width * colorBytes; | 283 return dinfo->output_width * colorBytes; |
| 288 | 284 |
| 289 } | 285 } |
| 290 | 286 |
| 291 /* | 287 /* |
| 292 * Calculate output dimensions based on the provided factors. | 288 * Calculate output dimensions based on the provided factors. |
| 293 * | 289 * |
| 294 * Not to be used on the actual jpeg_decompress_struct used for decoding, since
it will | 290 * Not to be used on the actual jpeg_decompress_struct used for decoding, since
it will |
| 295 * incorrectly modify num_components. | 291 * incorrectly modify num_components. |
| 296 */ | 292 */ |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 } | 342 } |
| 347 SkASSERT(nullptr != decoderMgr); | 343 SkASSERT(nullptr != decoderMgr); |
| 348 fDecoderMgr.reset(decoderMgr); | 344 fDecoderMgr.reset(decoderMgr); |
| 349 | 345 |
| 350 fSwizzler.reset(nullptr); | 346 fSwizzler.reset(nullptr); |
| 351 fSwizzleSrcRow = nullptr; | 347 fSwizzleSrcRow = nullptr; |
| 352 fColorXformSrcRow = nullptr; | 348 fColorXformSrcRow = nullptr; |
| 353 fStorage.reset(); | 349 fStorage.reset(); |
| 354 fColorXform.reset(nullptr); | 350 fColorXform.reset(nullptr); |
| 355 | 351 |
| 356 #if !defined(TURBO_HAS_SKIP) | |
| 357 fSkipStorage.reset(); | |
| 358 #endif | |
| 359 | |
| 360 return true; | 352 return true; |
| 361 } | 353 } |
| 362 | 354 |
| 363 /* | 355 /* |
| 364 * Checks if the conversion between the input image and the requested output | 356 * Checks if the conversion between the input image and the requested output |
| 365 * image has been implemented | 357 * image has been implemented |
| 366 * Sets the output color space | 358 * Sets the output color space |
| 367 */ | 359 */ |
| 368 bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dstInfo, bool needsColo
rXform) { | 360 bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dstInfo, bool needsColo
rXform) { |
| 369 if (kUnknown_SkAlphaType == dstInfo.alphaType()) { | 361 if (kUnknown_SkAlphaType == dstInfo.alphaType()) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 } | 393 } |
| 402 return true; | 394 return true; |
| 403 case kRGB_565_SkColorType: | 395 case kRGB_565_SkColorType: |
| 404 if (needsColorXform) { | 396 if (needsColorXform) { |
| 405 return false; | 397 return false; |
| 406 } | 398 } |
| 407 | 399 |
| 408 if (isCMYK) { | 400 if (isCMYK) { |
| 409 fDecoderMgr->dinfo()->out_color_space = JCS_CMYK; | 401 fDecoderMgr->dinfo()->out_color_space = JCS_CMYK; |
| 410 } else { | 402 } else { |
| 411 #ifdef TURBO_HAS_565 | |
| 412 fDecoderMgr->dinfo()->dither_mode = JDITHER_NONE; | 403 fDecoderMgr->dinfo()->dither_mode = JDITHER_NONE; |
| 413 fDecoderMgr->dinfo()->out_color_space = JCS_RGB565; | 404 fDecoderMgr->dinfo()->out_color_space = JCS_RGB565; |
| 414 #else | |
| 415 fDecoderMgr->dinfo()->out_color_space = JCS_RGB; | |
| 416 #endif | |
| 417 } | 405 } |
| 418 return true; | 406 return true; |
| 419 case kGray_8_SkColorType: | 407 case kGray_8_SkColorType: |
| 420 if (needsColorXform || JCS_GRAYSCALE != encodedColorType) { | 408 if (needsColorXform || JCS_GRAYSCALE != encodedColorType) { |
| 421 return false; | 409 return false; |
| 422 } | 410 } |
| 423 | 411 |
| 424 fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE; | 412 fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE; |
| 425 return true; | 413 return true; |
| 426 case kRGBA_F16_SkColorType: | 414 case kRGBA_F16_SkColorType: |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 | 557 |
| 570 if (!jpeg_start_decompress(dinfo)) { | 558 if (!jpeg_start_decompress(dinfo)) { |
| 571 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput); | 559 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput); |
| 572 } | 560 } |
| 573 | 561 |
| 574 // The recommended output buffer height should always be 1 in high quality m
odes. | 562 // The recommended output buffer height should always be 1 in high quality m
odes. |
| 575 // If it's not, we want to know because it means our strategy is not optimal
. | 563 // If it's not, we want to know because it means our strategy is not optimal
. |
| 576 SkASSERT(1 == dinfo->rec_outbuf_height); | 564 SkASSERT(1 == dinfo->rec_outbuf_height); |
| 577 | 565 |
| 578 J_COLOR_SPACE colorSpace = dinfo->out_color_space; | 566 J_COLOR_SPACE colorSpace = dinfo->out_color_space; |
| 579 if (JCS_CMYK == colorSpace || JCS_RGB == colorSpace) { | 567 if (JCS_CMYK == colorSpace) { |
| 580 this->initializeSwizzler(dstInfo, options); | 568 this->initializeSwizzler(dstInfo, options); |
| 581 } | 569 } |
| 582 | 570 |
| 583 this->allocateStorage(dstInfo); | 571 this->allocateStorage(dstInfo); |
| 584 | 572 |
| 585 int rows = this->readRows(dstInfo, dst, dstRowBytes, dstInfo.height()); | 573 int rows = this->readRows(dstInfo, dst, dstRowBytes, dstInfo.height()); |
| 586 if (rows < dstInfo.height()) { | 574 if (rows < dstInfo.height()) { |
| 587 *rowsDecoded = rows; | 575 *rowsDecoded = rows; |
| 588 return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteIn
put); | 576 return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteIn
put); |
| 589 } | 577 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 614 fColorXformSrcRow = (xformBytes > 0) ? | 602 fColorXformSrcRow = (xformBytes > 0) ? |
| 615 SkTAddOffset<uint32_t>(fStorage.get(), swizzleBytes) : nullptr; | 603 SkTAddOffset<uint32_t>(fStorage.get(), swizzleBytes) : nullptr; |
| 616 } | 604 } |
| 617 } | 605 } |
| 618 | 606 |
| 619 void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options&
options) { | 607 void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options&
options) { |
| 620 // libjpeg-turbo may have already performed color conversion. We must indic
ate the | 608 // libjpeg-turbo may have already performed color conversion. We must indic
ate the |
| 621 // appropriate format to the swizzler. | 609 // appropriate format to the swizzler. |
| 622 SkEncodedInfo swizzlerInfo = this->getEncodedInfo(); | 610 SkEncodedInfo swizzlerInfo = this->getEncodedInfo(); |
| 623 bool preSwizzled = true; | 611 bool preSwizzled = true; |
| 624 switch (fDecoderMgr->dinfo()->out_color_space) { | 612 if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) { |
| 625 case JCS_RGB: | 613 preSwizzled = false; |
| 626 preSwizzled = false; | 614 swizzlerInfo = SkEncodedInfo::Make(SkEncodedInfo::kInvertedCMYK_Color, |
| 627 swizzlerInfo = SkEncodedInfo::Make(SkEncodedInfo::kRGB_Color, | 615 swizzlerInfo.alpha(), |
| 628 swizzlerInfo.alpha(), | 616 swizzlerInfo.bitsPerComponent()); |
| 629 swizzlerInfo.bitsPerComponent()); | |
| 630 break; | |
| 631 case JCS_CMYK: | |
| 632 preSwizzled = false; | |
| 633 swizzlerInfo = SkEncodedInfo::Make(SkEncodedInfo::kInvertedCMYK_Colo
r, | |
| 634 swizzlerInfo.alpha(), | |
| 635 swizzlerInfo.bitsPerComponent()); | |
| 636 break; | |
| 637 default: | |
| 638 break; | |
| 639 } | 617 } |
| 640 | 618 |
| 641 Options swizzlerOptions = options; | 619 Options swizzlerOptions = options; |
| 642 if (options.fSubset) { | 620 if (options.fSubset) { |
| 643 // Use fSwizzlerSubset if this is a subset decode. This is necessary in
the case | 621 // Use fSwizzlerSubset if this is a subset decode. This is necessary in
the case |
| 644 // where libjpeg-turbo provides a subset and then we need to subset it f
urther. | 622 // where libjpeg-turbo provides a subset and then we need to subset it f
urther. |
| 645 // Also, verify that fSwizzlerSubset is initialized and valid. | 623 // Also, verify that fSwizzlerSubset is initialized and valid. |
| 646 SkASSERT(!fSwizzlerSubset.isEmpty() && fSwizzlerSubset.x() <= options.fS
ubset->x() && | 624 SkASSERT(!fSwizzlerSubset.isEmpty() && fSwizzlerSubset.x() <= options.fS
ubset->x() && |
| 647 fSwizzlerSubset.width() == options.fSubset->width()); | 625 fSwizzlerSubset.width() == options.fSubset->width()); |
| 648 swizzlerOptions.fSubset = &fSwizzlerSubset; | 626 swizzlerOptions.fSubset = &fSwizzlerSubset; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 | 669 |
| 692 if (!this->initializeColorXform(dstInfo, needsColorXform)) { | 670 if (!this->initializeColorXform(dstInfo, needsColorXform)) { |
| 693 return fDecoderMgr->returnFailure("initializeColorXform", kInvalidParame
ters); | 671 return fDecoderMgr->returnFailure("initializeColorXform", kInvalidParame
ters); |
| 694 } | 672 } |
| 695 | 673 |
| 696 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) { | 674 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) { |
| 697 SkCodecPrintf("start decompress failed\n"); | 675 SkCodecPrintf("start decompress failed\n"); |
| 698 return kInvalidInput; | 676 return kInvalidInput; |
| 699 } | 677 } |
| 700 | 678 |
| 701 #ifdef TURBO_HAS_CROP | |
| 702 if (options.fSubset) { | 679 if (options.fSubset) { |
| 703 uint32_t startX = options.fSubset->x(); | 680 uint32_t startX = options.fSubset->x(); |
| 704 uint32_t width = options.fSubset->width(); | 681 uint32_t width = options.fSubset->width(); |
| 705 | 682 |
| 706 // libjpeg-turbo may need to align startX to a multiple of the IDCT | 683 // libjpeg-turbo may need to align startX to a multiple of the IDCT |
| 707 // block size. If this is the case, it will decrease the value of | 684 // block size. If this is the case, it will decrease the value of |
| 708 // startX to the appropriate alignment and also increase the value | 685 // startX to the appropriate alignment and also increase the value |
| 709 // of width so that the right edge of the requested subset remains | 686 // of width so that the right edge of the requested subset remains |
| 710 // the same. | 687 // the same. |
| 711 jpeg_crop_scanline(fDecoderMgr->dinfo(), &startX, &width); | 688 jpeg_crop_scanline(fDecoderMgr->dinfo(), &startX, &width); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 733 if (startX != (uint32_t) options.fSubset->x() || | 710 if (startX != (uint32_t) options.fSubset->x() || |
| 734 width != (uint32_t) options.fSubset->width()) { | 711 width != (uint32_t) options.fSubset->width()) { |
| 735 this->initializeSwizzler(dstInfo, options); | 712 this->initializeSwizzler(dstInfo, options); |
| 736 } | 713 } |
| 737 } | 714 } |
| 738 | 715 |
| 739 // Make sure we have a swizzler if we are converting from CMYK. | 716 // Make sure we have a swizzler if we are converting from CMYK. |
| 740 if (!fSwizzler && JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) { | 717 if (!fSwizzler && JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) { |
| 741 this->initializeSwizzler(dstInfo, options); | 718 this->initializeSwizzler(dstInfo, options); |
| 742 } | 719 } |
| 743 #else | |
| 744 if (options.fSubset) { | |
| 745 fSwizzlerSubset = *options.fSubset; | |
| 746 } | |
| 747 | |
| 748 // We will need a swizzler if we are performing a subset decode or | |
| 749 // converting from CMYK. | |
| 750 J_COLOR_SPACE colorSpace = fDecoderMgr->dinfo()->out_color_space; | |
| 751 if (options.fSubset || JCS_CMYK == colorSpace || JCS_RGB == colorSpace) { | |
| 752 this->initializeSwizzler(dstInfo, options); | |
| 753 } | |
| 754 #endif | |
| 755 | 720 |
| 756 this->allocateStorage(dstInfo); | 721 this->allocateStorage(dstInfo); |
| 757 | 722 |
| 758 return kSuccess; | 723 return kSuccess; |
| 759 } | 724 } |
| 760 | 725 |
| 761 int SkJpegCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) { | 726 int SkJpegCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) { |
| 762 int rows = this->readRows(this->dstInfo(), dst, dstRowBytes, count); | 727 int rows = this->readRows(this->dstInfo(), dst, dstRowBytes, count); |
| 763 if (rows < count) { | 728 if (rows < count) { |
| 764 // This allows us to skip calling jpeg_finish_decompress(). | 729 // This allows us to skip calling jpeg_finish_decompress(). |
| 765 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height(); | 730 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height(); |
| 766 } | 731 } |
| 767 | 732 |
| 768 return rows; | 733 return rows; |
| 769 } | 734 } |
| 770 | 735 |
| 771 bool SkJpegCodec::onSkipScanlines(int count) { | 736 bool SkJpegCodec::onSkipScanlines(int count) { |
| 772 // Set the jump location for libjpeg errors | 737 // Set the jump location for libjpeg errors |
| 773 if (setjmp(fDecoderMgr->getJmpBuf())) { | 738 if (setjmp(fDecoderMgr->getJmpBuf())) { |
| 774 return fDecoderMgr->returnFalse("onSkipScanlines"); | 739 return fDecoderMgr->returnFalse("onSkipScanlines"); |
| 775 } | 740 } |
| 776 | 741 |
| 777 #ifdef TURBO_HAS_SKIP | |
| 778 return (uint32_t) count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count); | 742 return (uint32_t) count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count); |
| 779 #else | |
| 780 uint8_t* ptr = fSkipStorage.get(); | |
| 781 if (!ptr) { | |
| 782 fSkipStorage.reset(get_row_bytes(fDecoderMgr->dinfo())); | |
| 783 ptr = fSkipStorage.get(); | |
| 784 } | |
| 785 | |
| 786 for (int y = 0; y < count; y++) { | |
| 787 if (1 != jpeg_read_scanlines(fDecoderMgr->dinfo(), &ptr, 1)) { | |
| 788 return false; | |
| 789 } | |
| 790 } | |
| 791 return true; | |
| 792 #endif | |
| 793 } | 743 } |
| 794 | 744 |
| 795 static bool is_yuv_supported(jpeg_decompress_struct* dinfo) { | 745 static bool is_yuv_supported(jpeg_decompress_struct* dinfo) { |
| 796 // Scaling is not supported in raw data mode. | 746 // Scaling is not supported in raw data mode. |
| 797 SkASSERT(dinfo->scale_num == dinfo->scale_denom); | 747 SkASSERT(dinfo->scale_num == dinfo->scale_denom); |
| 798 | 748 |
| 799 // I can't imagine that this would ever change, but we do depend on it. | 749 // I can't imagine that this would ever change, but we do depend on it. |
| 800 static_assert(8 == DCTSIZE, "DCTSIZE (defined in jpeg library) should always
be 8."); | 750 static_assert(8 == DCTSIZE, "DCTSIZE (defined in jpeg library) should always
be 8."); |
| 801 | 751 |
| 802 if (JCS_YCbCr != dinfo->jpeg_color_space) { | 752 if (JCS_YCbCr != dinfo->jpeg_color_space) { |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 982 | 932 |
| 983 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock); | 933 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock); |
| 984 if (linesRead < remainingRows) { | 934 if (linesRead < remainingRows) { |
| 985 // FIXME: Handle incomplete YUV decodes without signalling an error. | 935 // FIXME: Handle incomplete YUV decodes without signalling an error. |
| 986 return kInvalidInput; | 936 return kInvalidInput; |
| 987 } | 937 } |
| 988 } | 938 } |
| 989 | 939 |
| 990 return kSuccess; | 940 return kSuccess; |
| 991 } | 941 } |
| OLD | NEW |