Interlaced gifs without the iterator
BUG=skia: Review URL: https://codereview.chromium.org/1315583003
This commit is contained in:
parent
761cf6186e
commit
d02b99f106
@ -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',
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
};
|
Loading…
Reference in New Issue
Block a user