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

Unified Diff: src/codec/SkJpegCodec.cpp

Issue 1372973002: Move all knowledge of X sampling into SkScaledCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@codecSDmerge
Patch Set: Attempt to fix RLE overflow Created 5 years, 2 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
« no previous file with comments | « src/codec/SkJpegCodec.h ('k') | src/codec/SkMaskSwizzler.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codec/SkJpegCodec.cpp
diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp
index b4c794c90623111d3835b0673d5ec88eb5c42d32..c9dee9a663b9a404ba5a7696b4a1df462944ea7f 100644
--- a/src/codec/SkJpegCodec.cpp
+++ b/src/codec/SkJpegCodec.cpp
@@ -155,14 +155,28 @@ static int get_row_bytes(const j_decompress_ptr dinfo) {
return dinfo->output_width * colorBytes;
}
+
+/*
+ * Calculate output dimensions based on the provided factors.
+ *
+ * Not to be used on the actual jpeg_decompress_struct used for decoding, since it will
+ * incorrectly modify num_components.
+ */
+void calc_output_dimensions(jpeg_decompress_struct* dinfo, unsigned int num, unsigned int denom) {
+ dinfo->num_components = 0;
+ dinfo->scale_num = num;
+ dinfo->scale_denom = denom;
+ jpeg_calc_output_dimensions(dinfo);
+}
+
/*
* Return a valid set of output dimensions for this decoder, given an input scale
*/
SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const {
// libjpeg-turbo supports scaling by 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1, so we will
// support these as well
- long num;
- long denom = 8;
+ unsigned int num;
+ unsigned int denom = 8;
if (desiredScale > 0.875f) {
num = 8;
} else if (desiredScale > 0.75f) {
@@ -187,10 +201,7 @@ SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const {
dinfo.image_width = this->getInfo().width();
dinfo.image_height = this->getInfo().height();
dinfo.global_state = fReadyState;
- dinfo.num_components = 0;
- dinfo.scale_num = num;
- dinfo.scale_denom = denom;
- jpeg_calc_output_dimensions(&dinfo);
+ calc_output_dimensions(&dinfo, num, denom);
// Return the calculated output dimensions for the given scale
return SkISize::Make(dinfo.output_width, dinfo.output_height);
@@ -272,28 +283,40 @@ bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dst) {
* Checks if we can natively scale to the requested dimensions and natively scales the
* dimensions if possible
*/
-bool SkJpegCodec::nativelyScaleToDimensions(uint32_t dstWidth, uint32_t dstHeight) {
+bool SkJpegCodec::onDimensionsSupported(const SkISize& size) {
+ if (setjmp(fDecoderMgr->getJmpBuf())) {
+ return fDecoderMgr->returnFalse("onDimensionsSupported/setjmp");
+ }
+
+ const unsigned int dstWidth = size.width();
+ const unsigned int dstHeight = size.height();
+
+ // Set up a fake decompress struct in order to use libjpeg to calculate output dimensions
+ // FIXME: Why is this necessary?
+ jpeg_decompress_struct dinfo;
+ sk_bzero(&dinfo, sizeof(dinfo));
+ dinfo.image_width = this->getInfo().width();
+ dinfo.image_height = this->getInfo().height();
+ dinfo.global_state = fReadyState;
+
// 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;
- jpeg_calc_output_dimensions(fDecoderMgr->dinfo());
- while (fDecoderMgr->dinfo()->output_width != dstWidth ||
- fDecoderMgr->dinfo()->output_height != dstHeight) {
+ unsigned int num = 8;
+ const unsigned int denom = 8;
+ calc_output_dimensions(&dinfo, num, denom);
+ while (dinfo.output_width != dstWidth || dinfo.output_height != dstHeight) {
// Return a failure if we have tried all of the possible scales
- if (1 == fDecoderMgr->dinfo()->scale_num ||
- dstWidth > fDecoderMgr->dinfo()->output_width ||
- dstHeight > fDecoderMgr->dinfo()->output_height) {
- // reset native scale settings on failure because this may be supported by the swizzler
- this->fDecoderMgr->dinfo()->scale_num = 8;
- jpeg_calc_output_dimensions(this->fDecoderMgr->dinfo());
+ if (1 == num || dstWidth > dinfo.output_width || dstHeight > dinfo.output_height) {
return false;
}
// Try the next scale
- fDecoderMgr->dinfo()->scale_num -= 1;
- jpeg_calc_output_dimensions(fDecoderMgr->dinfo());
+ num -= 1;
+ calc_output_dimensions(&dinfo, num, denom);
}
+
+ fDecoderMgr->dinfo()->scale_num = num;
+ fDecoderMgr->dinfo()->scale_denom = denom;
return true;
}
@@ -321,11 +344,6 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
return fDecoderMgr->returnFailure("conversion_possible", kInvalidConversion);
}
- // Perform the necessary scaling
- if (!this->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) {
- return fDecoderMgr->returnFailure("cannot scale to requested dims", kInvalidScale);
- }
-
// Now, given valid output dimensions, we can start the decompress
if (!jpeg_start_decompress(dinfo)) {
return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
@@ -376,7 +394,13 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
return kSuccess;
}
-SkCodec::Result SkJpegCodec::initializeSwizzler(const SkImageInfo& info, const Options& options) {
+SkSampler* SkJpegCodec::getSampler() {
+ if (fSwizzler) {
+ SkASSERT(fSrcRow && static_cast<uint8_t*>(fStorage.get()) == fSrcRow);
+ return fSwizzler;
+ }
+
+ const SkImageInfo& info = this->dstInfo();
SkSwizzler::SrcConfig srcConfig;
switch (info.colorType()) {
case kGray_8_SkColorType:
@@ -396,13 +420,15 @@ SkCodec::Result SkJpegCodec::initializeSwizzler(const SkImageInfo& info, const O
SkASSERT(false);
}
- fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, info, options.fZeroInitialized,
- this->getInfo()));
+ fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, info,
+ this->options().fZeroInitialized));
if (!fSwizzler) {
- return SkCodec::kUnimplemented;
+ return nullptr;
}
- return kSuccess;
+ fStorage.reset(get_row_bytes(fDecoderMgr->dinfo()));
+ fSrcRow = static_cast<uint8_t*>(fStorage.get());
+ return fSwizzler;
}
SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
@@ -418,25 +444,10 @@ SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
return kInvalidConversion;
}
- // 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 kInvalidScale;
- }
- // 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);
- }
+ // Remove objects used for sampling.
+ fSwizzler.reset(nullptr);
+ fSrcRow = nullptr;
+ fStorage.free();
// Now, given valid output dimensions, we can start the decompress
if (!jpeg_start_decompress(fDecoderMgr->dinfo())) {
« no previous file with comments | « src/codec/SkJpegCodec.h ('k') | src/codec/SkMaskSwizzler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698