aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec/SkBmpRLECodec.cpp
diff options
context:
space:
mode:
authorGravatar msarett <msarett@google.com>2015-10-09 11:07:34 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-10-09 11:07:34 -0700
commite6dd004c1b8a81dc37a370570877b8b7d6dbe308 (patch)
tree16ecfdede3939dcd7f1b3db311371d974477e7c5 /src/codec/SkBmpRLECodec.cpp
parent79da63fa0bec40b560597c79c2e1231fa51aef36 (diff)
Fill incomplete images in SkCodec parent class
Rather than implementing some sort of "fill" in every SkCodec subclass for incomplete images, let's make the parent class handle this situation. This includes an API change to SkCodec.h SkCodec::getScanlines() now returns the number of lines it read successfully, rather than an SkCodec::Result enum. getScanlines() most often fails on an incomplete input, in which case it is useful to know how many lines were successfully decoded - this provides more information than kIncomplete vs kSuccess. We do lose information when the API is used improperly, as we are no longer able to return kInvalidParameter or kScanlineNotStarted. Known Issues: Does not work for incomplete fFrameIsSubset gifs. Does not work for incomplete icos. BUG=skia: Review URL: https://codereview.chromium.org/1332053002
Diffstat (limited to 'src/codec/SkBmpRLECodec.cpp')
-rw-r--r--src/codec/SkBmpRLECodec.cpp53
1 files changed, 32 insertions, 21 deletions
diff --git a/src/codec/SkBmpRLECodec.cpp b/src/codec/SkBmpRLECodec.cpp
index fe499c6a6d..37af47600b 100644
--- a/src/codec/SkBmpRLECodec.cpp
+++ b/src/codec/SkBmpRLECodec.cpp
@@ -38,7 +38,8 @@ SkCodec::Result SkBmpRLECodec::onGetPixels(const SkImageInfo& dstInfo,
void* dst, size_t dstRowBytes,
const Options& opts,
SkPMColor* inputColorPtr,
- int* inputColorCount) {
+ int* inputColorCount,
+ int* rowsDecoded) {
if (opts.fSubset) {
// Subsets are not supported.
return kUnimplemented;
@@ -54,7 +55,16 @@ SkCodec::Result SkBmpRLECodec::onGetPixels(const SkImageInfo& dstInfo,
}
// Perform the decode
- return this->decodeRows(dstInfo, dst, dstRowBytes, opts);
+ uint32_t rows = this->decodeRows(dstInfo, dst, dstRowBytes, opts);
+ if (rows != dstInfo.height()) {
+ // We set rowsDecoded equal to the height because the background has already
+ // been filled. RLE encodings sometimes skip pixels, so we always start by
+ // filling the background.
+ *rowsDecoded = dstInfo.height();
+ return kIncompleteInput;
+ }
+
+ return kSuccess;
}
/*
@@ -275,9 +285,8 @@ SkCodec::Result SkBmpRLECodec::prepareToDecode(const SkImageInfo& dstInfo,
* Performs the bitmap decoding for RLE input format
* RLE decoding is performed all at once, rather than a one row at a time
*/
-SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
- void* dst, size_t dstRowBytes,
- const Options& opts) {
+int SkBmpRLECodec::decodeRows(const SkImageInfo& info, void* dst, size_t dstRowBytes,
+ const Options& opts) {
// Set RLE flags
static const uint8_t RLE_ESCAPE = 0;
static const uint8_t RLE_EOL = 0;
@@ -300,24 +309,23 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
// Because of the need for transparent pixels, kN32 is the only color
// type that makes sense for the destination format.
SkASSERT(kN32_SkColorType == dstInfo.colorType());
- SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, SK_ColorTRANSPARENT,
- NULL, opts.fZeroInitialized);
+ SkSampler::Fill(dstInfo, dst, dstRowBytes, SK_ColorTRANSPARENT, opts.fZeroInitialized);
while (true) {
// If we have reached a row that is beyond the requested height, we have
// succeeded.
if (y >= height) {
- // It would be better to check for the EOF marker before returning
+ // It would be better to check for the EOF marker before indicating
// success, but we may be performing a scanline decode, which
- // may require us to stop before decoding the full height.
- return kSuccess;
+ // would require us to stop before decoding the full height.
+ return height;
}
// Every entry takes at least two bytes
if ((int) fRLEBytes - fCurrRLEByte < 2) {
SkCodecPrintf("Warning: might be incomplete RLE input.\n");
if (this->checkForMoreData() < 2) {
- return kIncompleteInput;
+ return y;
}
}
@@ -342,7 +350,7 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
if ((int) fRLEBytes - fCurrRLEByte < 2) {
SkCodecPrintf("Warning: might be incomplete RLE input.\n");
if (this->checkForMoreData() < 2) {
- return kIncompleteInput;
+ return y;
}
}
// Modify x and y
@@ -352,7 +360,7 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
y += dy;
if (x > width || y > height) {
SkCodecPrintf("Warning: invalid RLE input.\n");
- return kInvalidInput;
+ return y - dy;
}
break;
}
@@ -368,14 +376,14 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
// image.
if (x + numPixels > width) {
SkCodecPrintf("Warning: invalid RLE input.\n");
- return kInvalidInput;
+ return y;
}
// Also abort if there are not enough bytes
// remaining in the stream to set numPixels.
if ((int) fRLEBytes - fCurrRLEByte < SkAlign2(rowBytes)) {
SkCodecPrintf("Warning: might be incomplete RLE input.\n");
if (this->checkForMoreData() < SkAlign2(rowBytes)) {
- return kIncompleteInput;
+ return y;
}
}
// Set numPixels number of pixels
@@ -411,7 +419,7 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
}
default:
SkASSERT(false);
- return kInvalidInput;
+ return y;
}
}
// Skip a byte if necessary to maintain alignment
@@ -434,7 +442,7 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
if ((int) fRLEBytes - fCurrRLEByte < 2) {
SkCodecPrintf("Warning: might be incomplete RLE input.\n");
if (this->checkForMoreData() < 2) {
- return kIncompleteInput;
+ return y;
}
}
@@ -467,6 +475,9 @@ SkCodec::Result SkBmpRLECodec::decodeRows(const SkImageInfo& info,
}
}
+// FIXME: Make SkBmpRLECodec have no knowledge of sampling.
+// Or it should do all sampling natively.
+// It currently is a hybrid that needs to know what SkScaledCodec is doing.
class SkBmpRLESampler : public SkSampler {
public:
SkBmpRLESampler(SkBmpRLECodec* codec)
@@ -476,7 +487,7 @@ public:
}
private:
- int onSetSampleX(int sampleX) {
+ int onSetSampleX(int sampleX) override {
return fCodec->setSampleX(sampleX);
}
@@ -484,15 +495,15 @@ private:
SkBmpRLECodec* fCodec;
};
-SkSampler* SkBmpRLECodec::getSampler() {
- if (!fSampler) {
+SkSampler* SkBmpRLECodec::getSampler(bool createIfNecessary) {
+ if (!fSampler && createIfNecessary) {
fSampler.reset(new SkBmpRLESampler(this));
}
return fSampler;
}
-int SkBmpRLECodec::setSampleX(int sampleX) {
+int SkBmpRLECodec::setSampleX(int sampleX){
fSampleX = sampleX;
return get_scaled_dimension(this->getInfo().width(), sampleX);
}