Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Unified Diff: src/codec/SkJpegCodec.cpp

Issue 1260673002: SkScaledCodec class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Move Jpeg Swizzler to ScanlineDecoder Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/codec/SkJpegCodec.cpp
diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp
index e160f0c4e29a124aa09b03fcb6fd8dea37f57b0e..758b6e7a79fc5d838db715305f59c6271fd1bf29 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"
@@ -149,6 +150,14 @@ SkJpegCodec::SkJpegCodec(const SkImageInfo& srcInfo, SkStream* stream,
{}
/*
+ * Return the row bytes of a particular image type and width
+ */
+static int get_row_bytes(const j_decompress_ptr dinfo) {
+ int colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 : dinfo->out_color_components;
+ return dinfo->output_width * colorBytes;
+
+}
+/*
* Return a valid set of output dimensions for this decoder, given an input scale
*/
SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const {
@@ -272,10 +281,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 +296,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 +339,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);
}
@@ -395,6 +407,47 @@ public:
, fOpts()
{}
+ /*
+ * Return a valid set of output dimensions for this decoder, given an input scale
+ */
+ SkISize onGetScaledDimensions(float desiredScale) override {
+ return fCodec->onGetScaledDimensions(desiredScale);
+ }
+
+ /*
+ * 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, NULL, info, options.fZeroInitialized,
+ this->getInfo().width()));
+ if (!fSwizzler) {
+ // FIXME: CreateSwizzler could fail for another reason.
+ return SkCodec::kUnimplemented;
+ }
+ return SkCodec::kSuccess;
+ }
+
SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options& options,
SkPMColor ctable[], int* ctableCount) override {
@@ -415,8 +468,19 @@ public:
}
// Perform the necessary scaling
- if (!fCodec->scaleToDimensions(dstInfo.width(), dstInfo.height())) {
- return SkCodec::kInvalidScale;
+ if (!fCodec->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
+ if (this->initializeSwizzler(dstInfo, options) != SkCodec::kSuccess) {
scroggo 2015/08/06 15:09:11 initializeSwizzler may return kUnimplemented, and
emmaleer 2015/08/06 18:59:52 I've changed this to check the result from initial
scroggo 2015/08/06 20:37:59 Your approach makes sense. My approach would have
emmaleer 2015/08/07 18:38:56 Acknowledged.
+ SkCodecPrintf("failed to initialize the swizzler.\n");
+ return SkCodec::kInvalidScale;
+ }
+ fStorage.reset(get_row_bytes(fCodec->fDecoderMgr->dinfo()));
+ fSrcRow = static_cast<uint8_t*>(fStorage.get());
}
scroggo 2015/08/06 15:09:10 Should we set fSrcRow to NULL otherwise? Same ques
emmaleer 2015/08/06 18:59:52 Acknowledged.
// Now, given valid output dimensions, we can start the decompress
@@ -447,9 +511,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 (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 =
@@ -466,22 +537,26 @@ public:
// Convert to RGBA if necessary
if (JCS_CMYK == fCodec->fDecoderMgr->dinfo()->out_color_space) {
- convert_CMYK_to_RGBA(dstRow, this->dstInfo().width());
+ convert_CMYK_to_RGBA(dstRow, fCodec->fDecoderMgr->dinfo()->output_width);
}
- // Move to the next row
- 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;
}
#ifndef TURBO_HAS_SKIP
-#define turbo_jpeg_skip_scanlines(dinfo, count) \
- SkAutoMalloc storage(dinfo->output_width * dinfo->out_color_components); \
- uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \
- for (int y = 0; y < count; y++) { \
- turbo_jpeg_read_scanlines(dinfo, &storagePtr, 1); \
+#define turbo_jpeg_skip_scanlines(dinfo, count) \
+ SkAutoMalloc storage(get_row_bytes(dinfo)); \
+ uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \
+ for (int y = 0; y < count; y++) { \
+ turbo_jpeg_read_scanlines(dinfo, &storagePtr, 1); \
}
#endif
@@ -496,9 +571,16 @@ public:
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;
};
@@ -510,6 +592,7 @@ SkScanlineDecoder* SkJpegCodec::NewSDFromStream(SkStream* stream) {
}
const SkImageInfo& srcInfo = codec->getInfo();
+
// Return the new scanline decoder
return SkNEW_ARGS(SkJpegScanlineDecoder, (srcInfo, codec.detach()));
}

Powered by Google App Engine
This is Rietveld 408576698