aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec/SkJpegCodec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec/SkJpegCodec.cpp')
-rw-r--r--src/codec/SkJpegCodec.cpp278
1 files changed, 114 insertions, 164 deletions
diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp
index 4557e45673..dac0c17b77 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;
}
+