Chromium Code Reviews| Index: src/codec/SkJpegCodec.cpp |
| diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp |
| index 5acc0b396c54d34abb922f80687104b54f85990a..ea2834297ca77f3c484d9e0e263d1385549541a3 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().width())); |
| + 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,9 @@ 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) { |
| + // reset scale settings on failure |
| + 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 +423,12 @@ public: |
| SkJpegScanlineDecoder(const SkImageInfo& dstInfo, SkJpegCodec* codec) |
| : INHERITED(dstInfo) |
| , fCodec(codec) |
| - {} |
| + { |
| + if(fCodec->fSwizzler) { |
| + fStorage.reset(fCodec->getInfo().width() * dstInfo.minRowBytes()); |
| + fSrcRow = static_cast<uint8_t*>(fStorage.get()); |
| + } |
| + } |
| virtual ~SkJpegScanlineDecoder() { |
| if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { |
| @@ -404,9 +447,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) { |
| + // 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 +473,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 = SkTAddOffset<JSAMPLE>(dst, rowBytes); |
| + } else { |
| + dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes); |
| + } |
| } |
| - |
| return SkCodec::kSuccess; |
| } |
| @@ -452,6 +507,8 @@ public: |
| private: |
| SkAutoTDelete<SkJpegCodec> fCodec; |
| + SkAutoMalloc fStorage; |
|
scroggo
2015/07/31 13:35:33
This one is only needed for sampling, too, right?
emmaleer
2015/07/31 18:41:56
Yep! I've added a comment.
|
| + uint8_t* fSrcRow; // Only used if sampling is needed |
| typedef SkScanlineDecoder INHERITED; |
| }; |
| @@ -488,8 +545,22 @@ 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()) { |
|
scroggo
2015/07/31 13:35:33
This should call DimensionsSupportedForSampling
emmaleer
2015/07/31 18:41:56
Acknowledged.
|
| + // no non-native height sampling supported |
| + return NULL; |
| + } |
| + // only support down sampling, dstWidth cannot be larger that srcWidth |
| + if(dstInfo.width() > this->getInfo().width()) { |
| + 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 |