| Index: src/codec/SkJpegCodec.cpp
|
| diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp
|
| index 84e90d444249142d69a68cd52cab59cebb37c30a..9a91caffdd35ea235d7894ee1d14ec9c311da15b 100644
|
| --- a/src/codec/SkJpegCodec.cpp
|
| +++ b/src/codec/SkJpegCodec.cpp
|
| @@ -11,6 +11,7 @@
|
| #include "SkJpegUtility_codec.h"
|
| #include "SkCodecPriv.h"
|
| #include "SkColorPriv.h"
|
| +#include "SkScaledCodec.h"
|
| #include "SkScanlineDecoder.h"
|
| #include "SkStream.h"
|
| #include "SkTemplates.h"
|
| @@ -189,6 +190,43 @@ SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const {
|
| return SkISize::Make(dinfo.output_width, dinfo.output_height);
|
| }
|
|
|
| +// The swizzler is only used for sampling in the x direction
|
| +// when sampling a scanlineDecoder is used. The swizzler is not used in onGetPixels
|
| +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,
|
| + 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
|
| */
|
| @@ -272,10 +310,10 @@ bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dst) {
|
| }
|
|
|
| /*
|
| - * Checks if we can scale to the requested dimensions and scales the dimensions
|
| - * if possible
|
| + * Checks if we can natively scale to the requested dimensions and natively scales the
|
| + * dimensions if possible
|
| */
|
| -bool SkJpegCodec::scaleToDimensions(uint32_t dstWidth, uint32_t dstHeight) {
|
| +bool SkJpegCodec::nativelyScaleToDimensions(uint32_t dstWidth, uint32_t dstHeight) {
|
| // libjpeg-turbo can scale to 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1
|
| fDecoderMgr->dinfo()->scale_denom = 8;
|
| fDecoderMgr->dinfo()->scale_num = 8;
|
| @@ -287,7 +325,10 @@ 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) {
|
| - return fDecoderMgr->returnFalse("could not scale to requested dimensions");
|
| + // reset native scale settings on failure because this may be supported by the swizzler
|
| + this->fDecoderMgr->dinfo()->scale_num = 8;
|
| + turbo_jpeg_calc_output_dimensions(this->fDecoderMgr->dinfo());
|
| + return false;
|
| }
|
|
|
| // Try the next scale
|
| @@ -327,7 +368,7 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
|
| }
|
|
|
| // Perform the necessary scaling
|
| - if (!this->scaleToDimensions(dstInfo.width(), dstInfo.height())) {
|
| + if (!this->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) {
|
| return fDecoderMgr->returnFailure("cannot scale to requested dims", kInvalidScale);
|
| }
|
|
|
| @@ -394,7 +435,12 @@ public:
|
| : INHERITED(dstInfo)
|
| , fCodec(codec)
|
| , fOpts(opts)
|
| - {}
|
| + {
|
| + if(fCodec->fSwizzler) {
|
| + fStorage.reset(fCodec->getInfo().width() * dstInfo.minRowBytes());
|
| + fSrcRow = static_cast<uint8_t*>(fStorage.get());
|
| + }
|
| + }
|
|
|
| virtual ~SkJpegScanlineDecoder() {
|
| if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
|
| @@ -413,9 +459,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 =
|
| @@ -435,10 +488,14 @@ 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->swizzle(dst, dstRow);
|
| + dst = SkTAddOffset<JSAMPLE>(dst, rowBytes);
|
| + } else {
|
| + dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes);
|
| + }
|
| }
|
| -
|
| return SkCodec::kSuccess;
|
| }
|
|
|
| @@ -464,6 +521,8 @@ public:
|
|
|
| private:
|
| SkAutoTDelete<SkJpegCodec> fCodec;
|
| + SkAutoMalloc fStorage; // Only used if sampling is needed
|
| + uint8_t* fSrcRow; // Only used if sampling is needed
|
| const SkCodec::Options& fOpts;
|
|
|
| typedef SkScanlineDecoder INHERITED;
|
| @@ -500,9 +559,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;
|
| + if (!codec->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) {
|
| + // native scaling to dstInfo dimensions not supported
|
| +
|
| + if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) {
|
| + 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
|
|
|