diff options
-rw-r--r-- | resources/rle.bmp | bin | 0 -> 40400 bytes | |||
-rw-r--r-- | src/codec/SkBmpRLECodec.cpp | 31 | ||||
-rw-r--r-- | src/codec/SkBmpRLECodec.h | 7 | ||||
-rw-r--r-- | tests/CodexTest.cpp | 1 |
4 files changed, 32 insertions, 7 deletions
diff --git a/resources/rle.bmp b/resources/rle.bmp Binary files differnew file mode 100644 index 0000000000..a08745fb2d --- /dev/null +++ b/resources/rle.bmp 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; } diff --git a/src/codec/SkBmpRLECodec.h b/src/codec/SkBmpRLECodec.h index df2a97d845..e319a71052 100644 --- a/src/codec/SkBmpRLECodec.h +++ b/src/codec/SkBmpRLECodec.h @@ -96,9 +96,16 @@ private: const uint32_t fOffset; SkAutoTDeleteArray<uint8_t> fStreamBuffer; size_t fRLEBytes; + const size_t fOrigRLEBytes; uint32_t fCurrRLEByte; int fSampleX; SkAutoTDelete<SkSampler> fSampler; + // Scanline decodes allow the client to ask for a single scanline at a time. + // This can be tricky when the RLE encoding instructs the decoder to jump down + // multiple lines. This field keeps track of lines that need to be skipped + // on subsequent calls to decodeRows(). + int fLinesToSkip; + typedef SkBmpCodec INHERITED; }; diff --git a/tests/CodexTest.cpp b/tests/CodexTest.cpp index 1261d2b556..1aa3cdc4dd 100644 --- a/tests/CodexTest.cpp +++ b/tests/CodexTest.cpp @@ -344,6 +344,7 @@ DEF_TEST(Codec, r) { // BMP check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false); + check(r, "rle.bmp", SkISize::Make(320, 240), true, false); // ICO // FIXME: We are not ready to test incomplete ICOs |