Index: src/codec/SkJpegCodec.cpp |
diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp |
index 5acc0b396c54d34abb922f80687104b54f85990a..eeda35ac8509eb768d1a45e764f9a46bed00113c 100644 |
--- a/src/codec/SkJpegCodec.cpp |
+++ b/src/codec/SkJpegCodec.cpp |
@@ -189,6 +189,41 @@ SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const { |
return SkISize::Make(dinfo.output_width, dinfo.output_height); |
} |
+SkCodec::Result SkJpegCodec::initializeSwizzler(const SkImageInfo& requestedInfo, |
+ void* dst, size_t rowBytes, |
+ const Options& options, |
+ SkPMColor ctable[], |
+ int* ctableCount) { |
+ |
+ const SkColorType srcColorType = requestedInfo.colorType(); |
+ SkSwizzler::SrcConfig srcConfig; |
+ switch (srcColorType) { |
+ case kGray_8_SkColorType: |
+ srcConfig = SkSwizzler::kGray; |
+ break; |
+ case kRGBA_8888_SkColorType: |
+ srcConfig = SkSwizzler::kRGBX; |
+ break; |
+ case kBGRA_8888_SkColorType: |
+ srcConfig = SkSwizzler::kBGRX; |
+ break; |
+ case kRGB_565_SkColorType: |
+ srcConfig = SkSwizzler::kRGB_565; |
+ break; |
+ default: |
+ //would have exited before now if the colorType was supported by jpeg |
+ SkASSERT(false); |
+ } |
+ |
+ fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, NULL, requestedInfo, dst, rowBytes, |
+ options.fZeroInitialized, this->getInfo())); |
+ if (!fSwizzler) { |
+ // FIXME: CreateSwizzler could fail for another reason. |
+ return kUnimplemented; |
+ } |
+ return kSuccess; |
+} |
+ |
/* |
* Handles rewinding the input stream if it is necessary |
*/ |
@@ -287,6 +322,8 @@ bool SkJpegCodec::scaleToDimensions(uint32_t dstWidth, uint32_t dstHeight) { |
if (1 == fDecoderMgr->dinfo()->scale_num || |
dstWidth > fDecoderMgr->dinfo()->output_width || |
dstHeight > fDecoderMgr->dinfo()->output_height) { |
+ this->fDecoderMgr->dinfo()->scale_num = 8; |
+ turbo_jpeg_calc_output_dimensions(this->fDecoderMgr->dinfo()); |
return fDecoderMgr->returnFalse("could not scale to requested dimensions"); |
} |
@@ -385,7 +422,10 @@ public: |
SkJpegScanlineDecoder(const SkImageInfo& dstInfo, SkJpegCodec* codec) |
: INHERITED(dstInfo) |
, fCodec(codec) |
- {} |
+ { |
+ fStorage.reset(fCodec->getInfo().width() * dstInfo.minRowBytes()); |
scroggo
2015/07/30 18:28:23
We only need to do this if there is a swizzler, ri
emmaleer
2015/07/30 22:27:56
Yes, I've added an if statement to only do this if
|
+ fSrcRow = static_cast<uint8_t*>(fStorage.get()); |
+ } |
virtual ~SkJpegScanlineDecoder() { |
if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { |
@@ -404,9 +444,16 @@ public: |
if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { |
return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvalidInput); |
} |
- |
// Read rows one at a time |
- JSAMPLE* dstRow = (JSAMPLE*) dst; |
+ JSAMPLE* dstRow; |
+ if (fCodec->fSwizzler) { |
scroggo
2015/07/30 18:28:23
So it looks like these introduce a slight performa
emmaleer
2015/07/30 22:27:56
I think it's negligible. Also, I don't think this
msarett
2015/07/31 12:17:59
I think Leon's suggestion is a good one. We did r
emmaleer
2015/07/31 18:41:56
So I re-ran the performance tests, after changing
scroggo
2015/07/31 19:31:58
That's great! I'm a little surprised that it is fa
emmaleer
2015/07/31 20:43:09
Yes, it is comparing running nanobench on JPEG, wi
|
+ // write data to storage row, then sample using swizzler |
+ dstRow = fSrcRow; |
+ } else { |
+ // write data directly to dst |
+ dstRow = (JSAMPLE*) dst; |
+ } |
+ |
for (int y = 0; y < count; y++) { |
// Read row of the image |
uint32_t rowsDecoded = |
@@ -423,10 +470,15 @@ public: |
convert_CMYK_to_RGBA(dstRow, this->dstInfo().width()); |
} |
- // Move to the next row |
- dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes); |
+ if(fCodec->fSwizzler) { |
+ // use swizzler to sample row |
+ fCodec->fSwizzler->setDstRow(dst); |
+ fCodec->fSwizzler->next(dstRow); |
+ dst += rowBytes; |
scroggo
2015/07/30 18:28:23
Why not use SkTAddOffset?
emmaleer
2015/07/30 22:27:56
Changed to to SkTAddOffset.
|
+ } else { |
+ dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes); |
+ } |
} |
- |
return SkCodec::kSuccess; |
} |
@@ -452,6 +504,8 @@ public: |
private: |
SkAutoTDelete<SkJpegCodec> fCodec; |
+ SkAutoMalloc fStorage; |
scroggo
2015/07/30 18:28:23
// Only used if sampling is needed.
emmaleer
2015/07/30 22:27:56
Acknowledged.
|
+ uint8_t* fSrcRow; |
typedef SkScanlineDecoder INHERITED; |
}; |
@@ -488,8 +542,18 @@ SkScanlineDecoder* SkJpegCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, |
// Perform the necessary scaling |
if (!codec->scaleToDimensions(dstInfo.width(), dstInfo.height())) { |
- SkCodecPrintf("Cannot scale to output dimensions\n"); |
- return NULL; |
+ // native scaling to dstInfo dimensions not supported |
+ |
+ if (dstInfo.height() != this->getInfo().height()) { |
+ // no non-native height sampling supported |
+ return NULL; |
+ } |
+ // create swizzler for sampling |
+ if (codec->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), options, ctable, |
+ ctableCount) != kSuccess) { |
+ SkCodecPrintf("failed to initialize the swizzler.\n"); |
+ return NULL; |
+ } |
} |
// Now, given valid output dimensions, we can start the decompress |