Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Unified Diff: src/codec/SkCodec_libgif.cpp

Issue 1055743003: Swizzler changes Index8 and 565 (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/codec/SkCodec_libgif.cpp
diff --git a/src/codec/SkCodec_libgif.cpp b/src/codec/SkCodec_libgif.cpp
index 2a1d81fc00f99a71f3453579ee1ba49ad764442b..aa06f0d94707c12e981754949ea172f8ca91d7b1 100644
--- a/src/codec/SkCodec_libgif.cpp
+++ b/src/codec/SkCodec_libgif.cpp
@@ -131,41 +131,58 @@ static uint32_t find_trans_index(const SavedImage& image) {
}
/*
- * Assumes IsGif was called and returned true
- * Creates a gif decoder
- * Reads enough of the stream to determine the image format
+ * Read enough of the stream to initialize the SkGifCodec.
+ * Returns a bool representing success or failure.
+ * If it returned true, and codecOut was not NULL,
+ * it will be set to a new SkGifCodec.
*/
-SkCodec* SkGifCodec::NewFromStream(SkStream* stream) {
+bool SkGifCodec::ReadHeader(SkStream* stream, SkCodec** codecOut) {
// Read gif header, logical screen descriptor, and global color table
SkAutoTCallIProc<GifFileType, CloseGif> gif(open_gif(stream));
if (NULL == gif) {
gif_error("DGifOpen failed.\n");
- return NULL;
+ return false;
}
- // Get fields from header
- const int32_t width = gif->SWidth;
- const int32_t height = gif->SHeight;
- if (width <= 0 || height <= 0) {
- gif_error("Invalid dimensions.\n");
- return NULL;
+ if (NULL != codecOut) {
+ // Get fields from header
+ const int32_t width = gif->SWidth;
+ const int32_t height = gif->SHeight;
+ if (width <= 0 || height <= 0) {
+ gif_error("Invalid dimensions.\n");
+ return false;
+ }
+
+ // Return the codec
+ // kIndex is the most natural color type for gifs, so we set this as
+ // the default.
+ // Many gifs specify a color table index for transparent pixels. Every
+ // other pixel is guaranteed to be opaque. Despite this, because of the
+ // possiblity of transparent pixels, we cannot assume that the image is
+ // opaque. We have the option to set the alpha type as kPremul or
+ // kUnpremul. Both are valid since the alpha component will always be
+ // 0xFF or the entire 32-bit pixel will be set to zero. We prefer
+ // kPremul because we support kPremul, and it is more efficient to
+ // use kPremul directly even when kUnpremul is supported.
+ const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
+ kIndex_8_SkColorType, kPremul_SkAlphaType);
+ *codecOut = SkNEW_ARGS(SkGifCodec, (imageInfo, stream, gif.detach()));
}
+ return true;
+}
- // Return the codec
- // kIndex is the most natural color type for gifs, so we set this as
- // the default.
- // Many gifs specify a color table index for transparent pixels. Every
- // other pixel is guaranteed to be opaque. Despite this, because of the
- // possiblity of transparent pixels, we cannot assume that the image is
- // opaque. We have the option to set the alpha type as kPremul or
- // kUnpremul. Both are valid since the alpha component will always be
- // 0xFF or the entire 32-bit pixel will be set to zero. We prefer
- // kPremul because we support kPremul, and it is more efficient to
- // use kPremul directly even when kUnpremul is supported.
- const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
- kIndex_8_SkColorType, kPremul_SkAlphaType);
- return SkNEW_ARGS(SkGifCodec, (imageInfo, stream, gif.detach()));
+/*
+ * Assumes IsGif was called and returned true
+ * Creates a gif decoder
+ * Reads enough of the stream to determine the image format
+ */
+SkCodec* SkGifCodec::NewFromStream(SkStream* stream) {
+ SkCodec* codec = NULL;
+ if (ReadHeader(stream, &codec)) {
+ return codec;
+ }
+ return NULL;
}
SkGifCodec::SkGifCodec(const SkImageInfo& srcInfo, SkStream* stream,
@@ -190,6 +207,9 @@ static bool conversion_possible(const SkImageInfo& dst,
case kN32_SkColorType:
return kPremul_SkAlphaType == dst.alphaType() ||
kUnpremul_SkAlphaType == dst.alphaType();
+ case kIndex_8_SkColorType:
+ return kPremul_SkAlphaType == dst.alphaType() ||
+ kUnpremul_SkAlphaType == dst.alphaType();
default:
return false;
}
@@ -200,11 +220,20 @@ static bool conversion_possible(const SkImageInfo& dst,
*/
SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
void* dst, size_t dstRowBytes,
- const Options& opts, SkPMColor*, int*) {
- // Check for valid input parameters
- if (!this->rewindIfNeeded()) {
+ const Options& opts,
+ SkPMColor* inputColorPtr,
+ int* inputColorCount) {
+ // Rewind if necessary
+ SkCodec::RewindState rewindState = this->rewindIfNeeded();
+ if (rewindState == kCouldNotRewind_RewindState) {
return kCouldNotRewind;
+ } else if (rewindState == kRewound_RewindState) {
+ if (!ReadHeader(this->stream(), NULL)) {
+ return kCouldNotRewind;
+ }
}
+
+ // Check for valid input parameters
if (dstInfo.dimensions() != this->getInfo().dimensions()) {
return gif_error("Scaling not supported.\n", kInvalidScale);
}
@@ -284,11 +313,15 @@ SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
imageTop = 0;
}
+ // Create a color table to store colors the giflib colorMap
+ SkPMColor alternateColorPtr[256];
+ SkPMColor* colorTable = get_color_table_ptr(dstInfo.colorType(),
+ inputColorPtr, inputColorCount, alternateColorPtr);
+
// Set up the color table
uint32_t colorCount = 0;
// Allocate maximum storage to deal with invalid indices safely
const uint32_t maxColors = 256;
- SkPMColor colorTable[maxColors];
ColorMapObject* colorMap = fGif->Image.ColorMap;
// If there is no local color table, use the global color table
if (NULL == colorMap) {
@@ -346,6 +379,7 @@ SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
// Check if image is only a subset of the image frame
SkAutoTDelete<SkSwizzler> swizzler(NULL);
+ SkColorType dstColorType = dstInfo.colorType();
if (innerWidth < width || innerHeight < height) {
// Modify the destination info
@@ -356,7 +390,6 @@ SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
// FIXME: This may not be the behavior that we want for
// animated gifs where we draw on top of the
// previous frame.
- SkColorType dstColorType = dstInfo.colorType();
if (fillBackground) {
switch (dstColorType) {
msarett 2015/04/02 17:26:29 I've been looking at factoring this into the swizz
scroggo 2015/04/02 19:20:31 That should be determined by the SrcConfig, correc
msarett 2015/04/03 18:01:32 I added a SkSwizzler::Fill() function. It turns o
case kN32_SkColorType:
@@ -365,6 +398,11 @@ SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
((int) dstRowBytes) * height
/ sizeof(SkPMColor));
break;
+ case kIndex_8_SkColorType:
+ memset((SkPMColor*) dst,
+ fillIndex,
+ ((int) dstRowBytes) * height);
scroggo 2015/04/02 19:20:31 Why did you cast to an int? (Sorry if this came up
msarett 2015/04/03 18:01:32 The cast was added for sk_memset32 which takes an
+ break;
default:
SkASSERT(false);
break;
@@ -421,11 +459,22 @@ SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
if (GIF_ERROR == DGifGetLine(fGif, buffer.get(),
innerWidth)) {
if (fillBackground) {
- SkPMColor* dstPtr = (SkPMColor*) SkTAddOffset
- <void*>(dst, y * dstRowBytes);
- sk_memset32(dstPtr, colorTable[fillIndex],
- (height - y) * ((int) dstRowBytes)
- / sizeof(SkPMColor));
+ switch (dstColorType) {
+ case kN32_SkColorType:
+ sk_memset32((SkPMColor*) dst,
+ colorTable[fillIndex],
+ (height - y) * ((int) dstRowBytes)
scroggo 2015/04/02 19:20:31 Again, for both of these, we need to be careful ab
msarett 2015/04/03 18:01:32 Acknowledged.
+ / sizeof(SkPMColor));
+ break;
+ case kIndex_8_SkColorType:
+ memset((SkPMColor*) dst,
+ fillIndex,
+ (height - y) * ((int) dstRowBytes));
+ break;
+ default:
+ SkASSERT(false);
+ break;
+ }
}
return gif_error(SkStringPrintf(
"Could not decode line %d of %d.\n",

Powered by Google App Engine
This is Rietveld 408576698