diff options
author | msarett <msarett@google.com> | 2015-08-28 07:36:55 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-28 07:36:55 -0700 |
commit | d02b99f106702bc739d3aa4e3c21f8a0618cbb51 (patch) | |
tree | ac1eb2b332d7154093c2f11fead50361ad58f9aa | |
parent | 761cf6186e291ee8e4761e1280634cfe9c42eccc (diff) |
Interlaced gifs without the iterator
BUG=skia:
Review URL: https://codereview.chromium.org/1315583003
-rw-r--r-- | gyp/codec.gyp | 1 | ||||
-rw-r--r-- | src/codec/SkCodec_libgif.cpp | 37 | ||||
-rw-r--r-- | src/codec/SkGifInterlaceIter.cpp | 48 | ||||
-rw-r--r-- | src/codec/SkGifInterlaceIter.h | 35 |
4 files changed, 29 insertions, 92 deletions
diff --git a/gyp/codec.gyp b/gyp/codec.gyp index b34c85e7d9..a9a55d5638 100644 --- a/gyp/codec.gyp +++ b/gyp/codec.gyp @@ -41,7 +41,6 @@ '../src/codec/SkCodec_libico.cpp', '../src/codec/SkCodec_libpng.cpp', '../src/codec/SkCodec_wbmp.cpp', - '../src/codec/SkGifInterlaceIter.cpp', '../src/codec/SkJpegCodec.cpp', '../src/codec/SkJpegDecoderMgr.cpp', '../src/codec/SkJpegUtility_codec.cpp', diff --git a/src/codec/SkCodec_libgif.cpp b/src/codec/SkCodec_libgif.cpp index 20a5572d14..3e78f23322 100644 --- a/src/codec/SkCodec_libgif.cpp +++ b/src/codec/SkCodec_libgif.cpp @@ -9,7 +9,6 @@ #include "SkCodecPriv.h" #include "SkColorPriv.h" #include "SkColorTable.h" -#include "SkGifInterlaceIter.h" #include "SkStream.h" #include "SkSwizzler.h" #include "SkUtils.h" @@ -116,6 +115,31 @@ static uint32_t find_trans_index(const SavedImage& image) { return SK_MaxU32; } +static inline uint32_t ceil_div(uint32_t a, uint32_t b) { + return (a + b - 1) / b; +} + +/* + * Gets the output row corresponding to the encoded row for interlaced gifs + */ +static uint32_t get_output_row_interlaced(uint32_t encodedRow, uint32_t height) { + SkASSERT(encodedRow < height); + // First pass + if (encodedRow * 8 < height) { + return encodedRow * 8; + } + // Second pass + if (encodedRow * 4 < height) { + return 4 + 8 * (encodedRow - ceil_div(height, 8)); + } + // Third pass + if (encodedRow * 2 < height) { + return 2 + 4 * (encodedRow - ceil_div(height, 4)); + } + // Fourth pass + return 1 + 2 * (encodedRow - ceil_div(height, 2)); +} + /* * Read enough of the stream to initialize the SkGifCodec. * Returns a bool representing success or failure. @@ -409,18 +433,14 @@ SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo, // Check the interlace flag and iterate over rows of the input if (fGif->Image.Interlace) { - // In interlace mode, the rows of input are rearranged in - // the output image. We use an iterator to take care of - // the rearranging. - SkGifInterlaceIter iter(innerHeight); for (int32_t y = 0; y < innerHeight; y++) { if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), innerWidth)) { // Recover from error by filling remainder of image if (!skipBackground) { memset(buffer.get(), fillIndex, innerWidth); for (; y < innerHeight; y++) { - void* dstRow = SkTAddOffset<void>(dst, - dstRowBytes * iter.nextY()); + void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * + get_output_row_interlaced(y, innerHeight)); swizzler->swizzle(dstRow, buffer.get()); } } @@ -428,7 +448,8 @@ SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo, "Could not decode line %d of %d.\n", y, height - 1).c_str(), kIncompleteInput); } - void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * iter.nextY()); + void* dstRow = SkTAddOffset<void>(dst, + dstRowBytes * get_output_row_interlaced(y, innerHeight)); swizzler->swizzle(dstRow, buffer.get()); } } else { diff --git a/src/codec/SkGifInterlaceIter.cpp b/src/codec/SkGifInterlaceIter.cpp deleted file mode 100644 index 3a87f6950d..0000000000 --- a/src/codec/SkGifInterlaceIter.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2015 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkGifInterlaceIter.h" - -static const uint8_t kStartingInterlaceYValues[] = { 0, 4, 2, 1 }; -static const uint8_t kDeltaInterlaceYValues[] = { 8, 8, 4, 2 }; - -SkGifInterlaceIter::SkGifInterlaceIter(int height) : fHeight(height) { - fStartYPtr = kStartingInterlaceYValues; - fDeltaYPtr = kDeltaInterlaceYValues; - - fCurrY = *fStartYPtr++; - fDeltaY = *fDeltaYPtr++; -} - -void SkGifInterlaceIter::prepareY() { - int32_t y = fCurrY + fDeltaY; - - // Iterate through fStartYPtr until a valid row is found. - // This ensures that we do not move past the height of the small images. - while (y >= fHeight) { - if (kStartingInterlaceYValues + - SK_ARRAY_COUNT(kStartingInterlaceYValues) == fStartYPtr) { - // Now we have iterated over the entire image. Forbid any - // subsequent calls to nextY(). - SkDEBUGCODE(fStartYPtr = nullptr;) - SkDEBUGCODE(fDeltaYPtr = nullptr;) - y = 0; - } else { - y = *fStartYPtr++; - fDeltaY = *fDeltaYPtr++; - } - } - fCurrY = y; -} - -int32_t SkGifInterlaceIter::nextY() { - SkASSERT(fStartYPtr); - SkASSERT(fDeltaYPtr); - int32_t y = fCurrY; - prepareY(); - return y; -} diff --git a/src/codec/SkGifInterlaceIter.h b/src/codec/SkGifInterlaceIter.h deleted file mode 100644 index 970cd4950f..0000000000 --- a/src/codec/SkGifInterlaceIter.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2015 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkTypes.h" - -/* - * Helper class to determine the destination y-values for interlaced gifs - */ -class SkGifInterlaceIter : SkNoncopyable { -public: - - explicit SkGifInterlaceIter(int32_t height); - - /* - * Get the next destination y-value - */ - int32_t nextY(); - -private: - - /* - * Updates the iterator to prepare the next y-value - */ - void prepareY(); - - const int32_t fHeight; - int32_t fCurrY; - int32_t fDeltaY; - const uint8_t* fStartYPtr; - const uint8_t* fDeltaYPtr; -}; |