Interlaced gifs without the iterator

BUG=skia:

Review URL: https://codereview.chromium.org/1315583003
This commit is contained in:
msarett 2015-08-28 07:36:55 -07:00 committed by Commit bot
parent 761cf6186e
commit d02b99f106
4 changed files with 29 additions and 92 deletions

View File

@ -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',

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;
};