Index: src/codec/SkBmpRLECodec.cpp |
diff --git a/src/codec/SkBmpRLECodec.cpp b/src/codec/SkBmpRLECodec.cpp |
index b01012644bfded083a27c95deb41bff5be0f96be..57707d60c9c33c452292b483b5c7b043edb36758 100644 |
--- a/src/codec/SkBmpRLECodec.cpp |
+++ b/src/codec/SkBmpRLECodec.cpp |
@@ -26,6 +26,7 @@ SkBmpRLECodec::SkBmpRLECodec(const SkImageInfo& info, SkStream* stream, |
, fOffset(offset) |
, fStreamBuffer(new uint8_t[RLEBytes]) |
, fRLEBytes(RLEBytes) |
+ , fOrigRLEBytes(RLEBytes) |
, fCurrRLEByte(0) |
, fSampleX(1) |
{} |
@@ -270,6 +271,8 @@ SkCodec::Result SkBmpRLECodec::prepareToDecode(const SkImageInfo& dstInfo, |
// Reset fSampleX. If it needs to be a value other than 1, it will get modified by |
// the sampler. |
fSampleX = 1; |
+ fLinesToSkip = 0; |
+ |
// Create the color table if necessary and prepare the stream for decode |
// Note that if it is non-NULL, inputColorCount will be modified |
if (!this->createColorTable(inputColorCount)) { |
@@ -281,6 +284,7 @@ SkCodec::Result SkBmpRLECodec::prepareToDecode(const SkImageInfo& dstInfo, |
copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount); |
// Initialize a buffer for encoded RLE data |
+ fRLEBytes = fOrigRLEBytes; |
if (!this->initializeStreamBuffer()) { |
SkCodecPrintf("Error: cannot initialize stream buffer.\n"); |
return SkCodec::kInvalidConversion; |
@@ -301,17 +305,12 @@ int SkBmpRLECodec::decodeRows(const SkImageInfo& info, void* dst, size_t dstRowB |
static const uint8_t RLE_EOF = 1; |
static const uint8_t RLE_DELTA = 2; |
- // Set constant values |
const int width = this->getInfo().width(); |
- const int height = info.height(); |
+ int height = info.height(); |
// Account for sampling. |
SkImageInfo dstInfo = info.makeWH(get_scaled_dimension(width, fSampleX), height); |
- // Destination parameters |
- int x = 0; |
- int y = 0; |
- |
// Set the background as transparent. Then, if the RLE code skips pixels, |
// the skipped pixels will be transparent. |
// Because of the need for transparent pixels, kN32 is the only color |
@@ -319,6 +318,21 @@ int SkBmpRLECodec::decodeRows(const SkImageInfo& info, void* dst, size_t dstRowB |
SkASSERT(kN32_SkColorType == dstInfo.colorType()); |
SkSampler::Fill(dstInfo, dst, dstRowBytes, SK_ColorTRANSPARENT, opts.fZeroInitialized); |
+ // Adjust the height and the dst if the previous call to decodeRows() left us |
+ // with lines that need to be skipped. |
+ if (height > fLinesToSkip) { |
+ height -= fLinesToSkip; |
+ dst = SkTAddOffset<void>(dst, fLinesToSkip * dstRowBytes); |
+ fLinesToSkip = 0; |
+ } else { |
+ fLinesToSkip -= height; |
+ return height; |
+ } |
+ |
+ // Destination parameters |
+ int x = 0; |
+ int y = 0; |
+ |
while (true) { |
// If we have reached a row that is beyond the requested height, we have |
// succeeded. |
@@ -366,9 +380,12 @@ int SkBmpRLECodec::decodeRows(const SkImageInfo& info, void* dst, size_t dstRowB |
const uint8_t dy = fStreamBuffer.get()[fCurrRLEByte++]; |
x += dx; |
y += dy; |
- if (x > width || y > height) { |
+ if (x > width) { |
SkCodecPrintf("Warning: invalid RLE input.\n"); |
return y - dy; |
+ } else if (y > height) { |
+ fLinesToSkip = y - height; |
+ return height; |
} |
break; |
} |