Index: src/codec/SkJpegCodec.cpp |
diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp |
index e1440af5c3b6c79651361e1e20e61660258c7f1c..b54871b9a6d83f05a3c1385d2bd0ab96decf43ae 100644 |
--- a/src/codec/SkJpegCodec.cpp |
+++ b/src/codec/SkJpegCodec.cpp |
@@ -371,7 +371,13 @@ void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& |
srcConfig = SkSwizzler::kRGB; |
} |
- fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, dstInfo, options)); |
+ Options swizzlerOptions = options; |
+ if (options.fSubset) { |
+ // Use fSwizzlerSubset if this is a subset decode. This is necessary in the case |
+ // where libjpeg-turbo provides a subset and then we need to subset it further. |
+ swizzlerOptions.fSubset = &fSwizzlerSubset; |
scroggo
2016/02/22 15:55:03
Should we assert here that fSwizzlerSubset is init
msarett
2016/02/22 17:38:16
Yes that is a bit confusing. I'll add an assert.
|
+ } |
+ fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, dstInfo, swizzlerOptions)); |
SkASSERT(fSwizzler); |
fStorage.reset(get_row_bytes(fDecoderMgr->dinfo())); |
fSrcRow = fStorage.get(); |
@@ -411,12 +417,51 @@ SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, |
return kInvalidInput; |
} |
+ if (options.fSubset) { |
+ fSwizzlerSubset = *options.fSubset; |
+ } |
+ |
+#ifdef TURBO_HAS_CROP |
+ if (options.fSubset) { |
+ uint32_t startX = options.fSubset->x(); |
+ uint32_t width = options.fSubset->width(); |
+ |
+ // libjpeg-turbo may need to align startX to a multiple of the IDCT |
+ // block size. If this is the case, it will decrease the value of |
+ // startX to the appropriate alignment and also increase the value |
+ // of width so that the right edge of the requested subset remains |
+ // the same. |
+ jpeg_crop_scanline(fDecoderMgr->dinfo(), &startX, &width); |
+ |
+ SkASSERT(startX <= (uint32_t) options.fSubset->x()); |
+ SkASSERT(width >= (uint32_t) options.fSubset->width()); |
+ SkASSERT(startX + width >= (uint32_t) options.fSubset->right()); |
+ |
+ // Instruct the swizzler (if it is necessary) to further subset the |
+ // output provided by libjpeg-turbo |
+ fSwizzlerSubset.setXYWH(options.fSubset->x() - startX, 0, |
scroggo
2016/02/22 15:55:03
So if I understand correctly, this is set here (ra
msarett
2016/02/22 17:38:16
Yes that's correct.
scroggo
2016/02/22 18:46:47
Maybe add a comment?
msarett
2016/02/22 19:07:43
Done.
|
+ options.fSubset->width(), options.fSubset->height()); |
scroggo
2016/02/22 15:55:03
It seems odd that we ever care about the startY an
msarett
2016/02/22 17:38:16
No they don't. They are ignored by SkSwizzler. T
scroggo
2016/02/22 18:46:47
Maybe add a comment?
msarett
2016/02/22 19:07:43
Done.
|
+ |
+ // We will need a swizzler if libjpeg-turbo cannot provide the exact |
+ // subset that we request. Or if we are converting from CMYK. |
scroggo
2016/02/22 15:55:03
This part of the comment seems unnecessary here. I
msarett
2016/02/22 17:38:16
Done.
|
+ if (startX != (uint32_t) options.fSubset->x() || |
+ width != (uint32_t) options.fSubset->width()) { |
+ this->initializeSwizzler(dstInfo, options); |
+ } |
+ } |
+ |
+ // Make sure we have a swizzler if we are converting from CMYK. |
+ if (!fSwizzler && JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) { |
+ this->initializeSwizzler(dstInfo, options); |
+ } |
+#else |
// We will need a swizzler if we are performing a subset decode or |
// converting from CMYK. |
J_COLOR_SPACE colorSpace = fDecoderMgr->dinfo()->out_color_space; |
if (options.fSubset || JCS_CMYK == colorSpace || JCS_RGB == colorSpace) { |
this->initializeSwizzler(dstInfo, options); |
} |
+#endif |
return kSuccess; |
} |