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