diff options
author | msarett <msarett@google.com> | 2016-02-11 08:41:01 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-11 08:41:01 -0800 |
commit | 4946b9419f650ef7a2dc684ce98bb771e1ce8f40 (patch) | |
tree | f4508907bedb7f254ff02f29302675c2811fd4c0 /src/codec/SkBmpRLECodec.cpp | |
parent | c1eb311f4e98934476f1b2ad5d6de772cf140d60 (diff) |
Fix scanline decoding of rare RLE bmps
This also exposed a bug in rewinding RLE bmps, which I have also
fixed in this CL.
This should fix testcase7.bmp on Gold.
The image that I am adding to resources is in the
public domain.
BUG=skia:4730
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1689953002
Review URL: https://codereview.chromium.org/1689953002
Diffstat (limited to 'src/codec/SkBmpRLECodec.cpp')
-rw-r--r-- | src/codec/SkBmpRLECodec.cpp | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/src/codec/SkBmpRLECodec.cpp b/src/codec/SkBmpRLECodec.cpp index b01012644b..57707d60c9 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; } |