| Index: src/codec/SkJpegCodec.cpp
|
| diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp
|
| index 4557e45673eb124a4ae346467b77a21cc955f8fa..dac0c17b77f290dd8e0c92448cf71ef8314c60e5 100644
|
| --- a/src/codec/SkJpegCodec.cpp
|
| +++ b/src/codec/SkJpegCodec.cpp
|
| @@ -12,7 +12,6 @@
|
| #include "SkCodecPriv.h"
|
| #include "SkColorPriv.h"
|
| #include "SkScaledCodec.h"
|
| -#include "SkScanlineDecoder.h"
|
| #include "SkStream.h"
|
| #include "SkTemplates.h"
|
| #include "SkTypes.h"
|
| @@ -382,160 +381,136 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
|
| return kSuccess;
|
| }
|
|
|
| -/*
|
| - * Enable scanline decoding for jpegs
|
| - */
|
| -class SkJpegScanlineDecoder : public SkScanlineDecoder {
|
| -public:
|
| - SkJpegScanlineDecoder(const SkImageInfo& srcInfo, SkJpegCodec* codec)
|
| - : INHERITED(srcInfo)
|
| - , fCodec(codec)
|
| - , fOpts()
|
| - {}
|
| -
|
| - /*
|
| - * Return a valid set of output dimensions for this decoder, given an input scale
|
| - */
|
| - SkISize onGetScaledDimensions(float desiredScale) override {
|
| - return fCodec->onGetScaledDimensions(desiredScale);
|
| +SkCodec::Result SkJpegCodec::initializeSwizzler(const SkImageInfo& info, const Options& options) {
|
| + SkSwizzler::SrcConfig srcConfig;
|
| + switch (info.colorType()) {
|
| + 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:
|
| + // This function should only be called if the colorType is supported by jpeg
|
| + SkASSERT(false);
|
| }
|
|
|
| - /*
|
| - * Create the swizzler based on the encoded format.
|
| - * The swizzler is only used for sampling in the x direction.
|
| - */
|
| -
|
| - SkCodec::Result initializeSwizzler(const SkImageInfo& info, const SkCodec::Options& options) {
|
| - SkSwizzler::SrcConfig srcConfig;
|
| - switch (info.colorType()) {
|
| - 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, nullptr, info, options.fZeroInitialized,
|
| - this->getInfo()));
|
| - if (!fSwizzler) {
|
| - // FIXME: CreateSwizzler could fail for another reason.
|
| - return SkCodec::kUnimplemented;
|
| - }
|
| - return SkCodec::kSuccess;
|
| + fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, info, options.fZeroInitialized,
|
| + this->getInfo()));
|
| + if (!fSwizzler) {
|
| + return SkCodec::kUnimplemented;
|
| }
|
|
|
| - SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options& options,
|
| - SkPMColor ctable[], int* ctableCount) override {
|
| + return kSuccess;
|
| +}
|
|
|
| - // Rewind the stream if needed
|
| - if (!fCodec->rewindIfNeeded()) {
|
| - return SkCodec::kCouldNotRewind;
|
| - }
|
| +SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
|
| + const Options& options, SkPMColor ctable[], int* ctableCount) {
|
| + // Rewind the stream if needed
|
| + if (!this->rewindIfNeeded()) {
|
| + return kCouldNotRewind;
|
| + }
|
|
|
| - // Set the jump location for libjpeg errors
|
| - if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
|
| - SkCodecPrintf("setjmp: Error from libjpeg\n");
|
| - return SkCodec::kInvalidInput;
|
| - }
|
| + // Set the jump location for libjpeg errors
|
| + if (setjmp(fDecoderMgr->getJmpBuf())) {
|
| + SkCodecPrintf("setjmp: Error from libjpeg\n");
|
| + return kInvalidInput;
|
| + }
|
|
|
| - // Check if we can decode to the requested destination and set the output color space
|
| - if (!fCodec->setOutputColorSpace(dstInfo)) {
|
| - return SkCodec::kInvalidConversion;
|
| - }
|
| + // Check if we can decode to the requested destination and set the output color space
|
| + if (!this->setOutputColorSpace(dstInfo)) {
|
| + return kInvalidConversion;
|
| + }
|
|
|
| - // Perform the necessary scaling
|
| - if (!fCodec->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) {
|
| - // full native scaling to dstInfo dimensions not supported
|
| + // Perform the necessary scaling
|
| + if (!this->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) {
|
| + // full native scaling to dstInfo dimensions not supported
|
|
|
| - if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) {
|
| - return SkCodec::kInvalidScale;
|
| - }
|
| - // create swizzler for sampling
|
| - SkCodec::Result result = this->initializeSwizzler(dstInfo, options);
|
| - if (SkCodec::kSuccess != result) {
|
| - SkCodecPrintf("failed to initialize the swizzler.\n");
|
| - return result;
|
| - }
|
| - fStorage.reset(get_row_bytes(fCodec->fDecoderMgr->dinfo()));
|
| - fSrcRow = static_cast<uint8_t*>(fStorage.get());
|
| - } else {
|
| - fSrcRow = nullptr;
|
| - fSwizzler.reset(nullptr);
|
| + if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) {
|
| + return kInvalidScale;
|
| }
|
| -
|
| - // Now, given valid output dimensions, we can start the decompress
|
| - if (!jpeg_start_decompress(fCodec->fDecoderMgr->dinfo())) {
|
| - SkCodecPrintf("start decompress failed\n");
|
| - return SkCodec::kInvalidInput;
|
| + // create swizzler for sampling
|
| + Result result = this->initializeSwizzler(dstInfo, options);
|
| + if (kSuccess != result) {
|
| + SkCodecPrintf("failed to initialize the swizzler.\n");
|
| + return result;
|
| }
|
| + fStorage.reset(get_row_bytes(fDecoderMgr->dinfo()));
|
| + fSrcRow = static_cast<uint8_t*>(fStorage.get());
|
| + } else {
|
| + fSrcRow = nullptr;
|
| + fSwizzler.reset(nullptr);
|
| + }
|
| +
|
| + // Now, given valid output dimensions, we can start the decompress
|
| + if (!jpeg_start_decompress(fDecoderMgr->dinfo())) {
|
| + SkCodecPrintf("start decompress failed\n");
|
| + return kInvalidInput;
|
| + }
|
|
|
| - fOpts = options;
|
| + return kSuccess;
|
| +}
|
|
|
| - return SkCodec::kSuccess;
|
| +SkJpegCodec::~SkJpegCodec() {
|
| + // FIXME: This probably does not need to be called after a full decode
|
| + // FIXME: Is it safe to call when it doesn't need to be called?
|
| + if (setjmp(fDecoderMgr->getJmpBuf())) {
|
| + SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n");
|
| + return;
|
| }
|
|
|
| - virtual ~SkJpegScanlineDecoder() {
|
| - if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
|
| - SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n");
|
| - return;
|
| - }
|
| + // We may not have decoded the entire image. Prevent libjpeg-turbo from failing on a
|
| + // partial decode.
|
| + fDecoderMgr->dinfo()->output_scanline = this->getInfo().height();
|
| + jpeg_finish_decompress(fDecoderMgr->dinfo());
|
| +}
|
|
|
| - // We may not have decoded the entire image. Prevent libjpeg-turbo from failing on a
|
| - // partial decode.
|
| - fCodec->fDecoderMgr->dinfo()->output_scanline = fCodec->getInfo().height();
|
| - jpeg_finish_decompress(fCodec->fDecoderMgr->dinfo());
|
| +SkCodec::Result SkJpegCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
|
| + // Set the jump location for libjpeg errors
|
| + if (setjmp(fDecoderMgr->getJmpBuf())) {
|
| + return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
|
| + }
|
| + // Read rows one at a time
|
| + JSAMPLE* dstRow;
|
| + if (fSwizzler) {
|
| + // write data to storage row, then sample using swizzler
|
| + dstRow = fSrcRow;
|
| + } else {
|
| + // write data directly to dst
|
| + dstRow = (JSAMPLE*) dst;
|
| }
|
|
|
| - SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) override {
|
| - // Set the jump location for libjpeg errors
|
| - if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
|
| - return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvalidInput);
|
| - }
|
| - // Read rows one at a time
|
| - JSAMPLE* dstRow;
|
| - if (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 = jpeg_read_scanlines(fDecoderMgr->dinfo(), &dstRow, 1);
|
| + if (rowsDecoded != 1) {
|
| + SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes, count - y,
|
| + SK_ColorBLACK, nullptr, this->options().fZeroInitialized);
|
| + fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height();
|
| + return kIncompleteInput;
|
| }
|
|
|
| - for (int y = 0; y < count; y++) {
|
| - // Read row of the image
|
| - uint32_t rowsDecoded = jpeg_read_scanlines(fCodec->fDecoderMgr->dinfo(), &dstRow, 1);
|
| - if (rowsDecoded != 1) {
|
| - SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes, count - y,
|
| - SK_ColorBLACK, nullptr, fOpts.fZeroInitialized);
|
| - fCodec->fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height();
|
| - return SkCodec::kIncompleteInput;
|
| - }
|
| -
|
| - // Convert to RGBA if necessary
|
| - if (JCS_CMYK == fCodec->fDecoderMgr->dinfo()->out_color_space) {
|
| - convert_CMYK_to_RGBA(dstRow, fCodec->fDecoderMgr->dinfo()->output_width);
|
| - }
|
| + // Convert to RGBA if necessary
|
| + if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) {
|
| + convert_CMYK_to_RGBA(dstRow, fDecoderMgr->dinfo()->output_width);
|
| + }
|
|
|
| - if(fSwizzler) {
|
| - // use swizzler to sample row
|
| - fSwizzler->swizzle(dst, dstRow);
|
| - dst = SkTAddOffset<JSAMPLE>(dst, rowBytes);
|
| - } else {
|
| - dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes);
|
| - }
|
| + if(fSwizzler) {
|
| + // use swizzler to sample row
|
| + fSwizzler->swizzle(dst, dstRow);
|
| + dst = SkTAddOffset<JSAMPLE>(dst, rowBytes);
|
| + } else {
|
| + dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes);
|
| }
|
| - return SkCodec::kSuccess;
|
| }
|
| + return kSuccess;
|
| +}
|
|
|
| #ifndef TURBO_HAS_SKIP
|
| // TODO (msarett): Make this a member function and avoid reallocating the
|
| @@ -548,39 +523,14 @@ public:
|
| }
|
| #endif
|
|
|
| - SkCodec::Result onSkipScanlines(int count) override {
|
| - // Set the jump location for libjpeg errors
|
| - if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
|
| - return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvalidInput);
|
| - }
|
| -
|
| - jpeg_skip_scanlines(fCodec->fDecoderMgr->dinfo(), count);
|
| -
|
| - return SkCodec::kSuccess;
|
| - }
|
| -
|
| - SkEncodedFormat onGetEncodedFormat() const override {
|
| - return kJPEG_SkEncodedFormat;
|
| - }
|
| -
|
| -private:
|
| - SkAutoTDelete<SkJpegCodec> fCodec;
|
| - SkAutoMalloc fStorage; // Only used if sampling is needed
|
| - uint8_t* fSrcRow; // Only used if sampling is needed
|
| - SkCodec::Options fOpts;
|
| - SkAutoTDelete<SkSwizzler> fSwizzler;
|
| -
|
| - typedef SkScanlineDecoder INHERITED;
|
| -};
|
| -
|
| -SkScanlineDecoder* SkJpegCodec::NewSDFromStream(SkStream* stream) {
|
| - SkAutoTDelete<SkJpegCodec> codec(static_cast<SkJpegCodec*>(SkJpegCodec::NewFromStream(stream)));
|
| - if (!codec) {
|
| - return nullptr;
|
| +SkCodec::Result SkJpegCodec::onSkipScanlines(int count) {
|
| + // Set the jump location for libjpeg errors
|
| + if (setjmp(fDecoderMgr->getJmpBuf())) {
|
| + return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
|
| }
|
|
|
| - const SkImageInfo& srcInfo = codec->getInfo();
|
| + jpeg_skip_scanlines(fDecoderMgr->dinfo(), count);
|
|
|
| - // Return the new scanline decoder
|
| - return new SkJpegScanlineDecoder(srcInfo, codec.detach());
|
| + return kSuccess;
|
| }
|
| +
|
|
|