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 || JCS_RGB == colorSpace) { |
msarett
2016/08/23 18:13:48
Remove " || JCS_RGB == colorSpace". We will never
| |
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 25 matching lines...) Expand all Loading... | |
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 switch (fDecoderMgr->dinfo()->out_color_space) { |
625 case JCS_RGB: | 613 case JCS_RGB: |
msarett
2016/08/23 18:13:47
Remove this case. Also probably makes sense to ma
| |
626 preSwizzled = false; | 614 preSwizzled = false; |
627 swizzlerInfo = SkEncodedInfo::Make(SkEncodedInfo::kRGB_Color, | 615 swizzlerInfo = SkEncodedInfo::Make(SkEncodedInfo::kRGB_Color, |
628 swizzlerInfo.alpha(), | 616 swizzlerInfo.alpha(), |
629 swizzlerInfo.bitsPerComponent()); | 617 swizzlerInfo.bitsPerComponent()); |
630 break; | 618 break; |
631 case JCS_CMYK: | 619 case JCS_CMYK: |
632 preSwizzled = false; | 620 preSwizzled = false; |
633 swizzlerInfo = SkEncodedInfo::Make(SkEncodedInfo::kInvertedCMYK_Colo r, | 621 swizzlerInfo = SkEncodedInfo::Make(SkEncodedInfo::kInvertedCMYK_Colo r, |
634 swizzlerInfo.alpha(), | 622 swizzlerInfo.alpha(), |
635 swizzlerInfo.bitsPerComponent()); | 623 swizzlerInfo.bitsPerComponent()); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
691 | 679 |
692 if (!this->initializeColorXform(dstInfo, needsColorXform)) { | 680 if (!this->initializeColorXform(dstInfo, needsColorXform)) { |
693 return fDecoderMgr->returnFailure("initializeColorXform", kInvalidParame ters); | 681 return fDecoderMgr->returnFailure("initializeColorXform", kInvalidParame ters); |
694 } | 682 } |
695 | 683 |
696 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) { | 684 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) { |
697 SkCodecPrintf("start decompress failed\n"); | 685 SkCodecPrintf("start decompress failed\n"); |
698 return kInvalidInput; | 686 return kInvalidInput; |
699 } | 687 } |
700 | 688 |
701 #ifdef TURBO_HAS_CROP | |
702 if (options.fSubset) { | 689 if (options.fSubset) { |
703 uint32_t startX = options.fSubset->x(); | 690 uint32_t startX = options.fSubset->x(); |
704 uint32_t width = options.fSubset->width(); | 691 uint32_t width = options.fSubset->width(); |
705 | 692 |
706 // libjpeg-turbo may need to align startX to a multiple of the IDCT | 693 // 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 | 694 // block size. If this is the case, it will decrease the value of |
708 // startX to the appropriate alignment and also increase the value | 695 // startX to the appropriate alignment and also increase the value |
709 // of width so that the right edge of the requested subset remains | 696 // of width so that the right edge of the requested subset remains |
710 // the same. | 697 // the same. |
711 jpeg_crop_scanline(fDecoderMgr->dinfo(), &startX, &width); | 698 jpeg_crop_scanline(fDecoderMgr->dinfo(), &startX, &width); |
(...skipping 21 matching lines...) Expand all Loading... | |
733 if (startX != (uint32_t) options.fSubset->x() || | 720 if (startX != (uint32_t) options.fSubset->x() || |
734 width != (uint32_t) options.fSubset->width()) { | 721 width != (uint32_t) options.fSubset->width()) { |
735 this->initializeSwizzler(dstInfo, options); | 722 this->initializeSwizzler(dstInfo, options); |
736 } | 723 } |
737 } | 724 } |
738 | 725 |
739 // Make sure we have a swizzler if we are converting from CMYK. | 726 // Make sure we have a swizzler if we are converting from CMYK. |
740 if (!fSwizzler && JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) { | 727 if (!fSwizzler && JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) { |
741 this->initializeSwizzler(dstInfo, options); | 728 this->initializeSwizzler(dstInfo, options); |
742 } | 729 } |
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 | 730 |
756 this->allocateStorage(dstInfo); | 731 this->allocateStorage(dstInfo); |
757 | 732 |
758 return kSuccess; | 733 return kSuccess; |
759 } | 734 } |
760 | 735 |
761 int SkJpegCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) { | 736 int SkJpegCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) { |
762 int rows = this->readRows(this->dstInfo(), dst, dstRowBytes, count); | 737 int rows = this->readRows(this->dstInfo(), dst, dstRowBytes, count); |
763 if (rows < count) { | 738 if (rows < count) { |
764 // This allows us to skip calling jpeg_finish_decompress(). | 739 // This allows us to skip calling jpeg_finish_decompress(). |
765 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height(); | 740 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height(); |
766 } | 741 } |
767 | 742 |
768 return rows; | 743 return rows; |
769 } | 744 } |
770 | 745 |
771 bool SkJpegCodec::onSkipScanlines(int count) { | 746 bool SkJpegCodec::onSkipScanlines(int count) { |
772 // Set the jump location for libjpeg errors | 747 // Set the jump location for libjpeg errors |
773 if (setjmp(fDecoderMgr->getJmpBuf())) { | 748 if (setjmp(fDecoderMgr->getJmpBuf())) { |
774 return fDecoderMgr->returnFalse("onSkipScanlines"); | 749 return fDecoderMgr->returnFalse("onSkipScanlines"); |
775 } | 750 } |
776 | 751 |
777 #ifdef TURBO_HAS_SKIP | |
778 return (uint32_t) count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count); | 752 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 } | 753 } |
794 | 754 |
795 static bool is_yuv_supported(jpeg_decompress_struct* dinfo) { | 755 static bool is_yuv_supported(jpeg_decompress_struct* dinfo) { |
796 // Scaling is not supported in raw data mode. | 756 // Scaling is not supported in raw data mode. |
797 SkASSERT(dinfo->scale_num == dinfo->scale_denom); | 757 SkASSERT(dinfo->scale_num == dinfo->scale_denom); |
798 | 758 |
799 // I can't imagine that this would ever change, but we do depend on it. | 759 // 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."); | 760 static_assert(8 == DCTSIZE, "DCTSIZE (defined in jpeg library) should always be 8."); |
801 | 761 |
802 if (JCS_YCbCr != dinfo->jpeg_color_space) { | 762 if (JCS_YCbCr != dinfo->jpeg_color_space) { |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
982 | 942 |
983 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock); | 943 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock); |
984 if (linesRead < remainingRows) { | 944 if (linesRead < remainingRows) { |
985 // FIXME: Handle incomplete YUV decodes without signalling an error. | 945 // FIXME: Handle incomplete YUV decodes without signalling an error. |
986 return kInvalidInput; | 946 return kInvalidInput; |
987 } | 947 } |
988 } | 948 } |
989 | 949 |
990 return kSuccess; | 950 return kSuccess; |
991 } | 951 } |
OLD | NEW |