Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkColor.h" | 8 #include "SkColor.h" |
| 9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
| 10 #include "SkColorTable.h" | 10 #include "SkColorTable.h" |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 */ | 178 */ |
| 179 static bool skip_src_rows(GifFileType* gif, uint8_t* dst, int width, int rowsToS kip) { | 179 static bool skip_src_rows(GifFileType* gif, uint8_t* dst, int width, int rowsToS kip) { |
| 180 for (int i = 0; i < rowsToSkip; i++) { | 180 for (int i = 0; i < rowsToSkip; i++) { |
| 181 if (DGifGetLine(gif, dst, width) == GIF_ERROR) { | 181 if (DGifGetLine(gif, dst, width) == GIF_ERROR) { |
| 182 return false; | 182 return false; |
| 183 } | 183 } |
| 184 } | 184 } |
| 185 return true; | 185 return true; |
| 186 } | 186 } |
| 187 | 187 |
| 188 static void sanitize_indexed_bitmap(SkBitmap* bm) { | |
|
robertphillips
2013/12/19 20:30:38
// Indexed GIFs with fewer then 256 color entries
hal.canary
2013/12/19 20:50:11
Done.
| |
| 189 if ((SkBitmap::kIndex8_Config == bm->config()) && !(bm->empty())) { | |
| 190 SkAutoLockPixels alp(*bm); | |
| 191 if (NULL != bm->getPixels()) { | |
| 192 SkColorTable* ct = bm->getColorTable(); // Index8 must have it. | |
| 193 SkASSERT(ct != NULL); | |
| 194 uint32_t count = ct->count(); | |
| 195 SkASSERT(count > 0); | |
| 196 SkASSERT(count <= 0x100); | |
| 197 if (count != 0x100) { // Full colortables can't go wrong. | |
| 198 // Count is a power of 2; asserted elsewhere. | |
| 199 uint8_t byteMask = (~(count - 1)); | |
| 200 bool warning = false; | |
| 201 uint8_t* addr = static_cast<uint8_t*>(bm->getPixels()); | |
| 202 int height = bm->height(); | |
| 203 int width = bm->width(); | |
| 204 size_t rowBytes = bm->rowBytes(); | |
| 205 while (--height >= 0) { | |
| 206 uint8_t* ptr = addr; | |
| 207 int x = width; | |
| 208 while (--x >= 0) { | |
| 209 if (0 != ((*ptr) & byteMask)) { | |
| 210 warning = true; | |
| 211 *ptr = 0; | |
| 212 } | |
| 213 ++ptr; | |
| 214 } | |
| 215 addr += rowBytes; | |
| 216 } | |
| 217 if (warning) { | |
| 218 gif_warning(*bm, "Index out of bounds."); | |
| 219 } | |
| 220 } | |
| 221 } | |
| 222 } | |
| 223 } | |
| 224 | |
| 188 bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) { | 225 bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) { |
| 189 #if GIFLIB_MAJOR < 5 | 226 #if GIFLIB_MAJOR < 5 |
| 190 GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc); | 227 GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc); |
| 191 #else | 228 #else |
| 192 GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc, NULL); | 229 GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc, NULL); |
| 193 #endif | 230 #endif |
| 194 if (NULL == gif) { | 231 if (NULL == gif) { |
| 195 return error_return(*bm, "DGifOpen"); | 232 return error_return(*bm, "DGifOpen"); |
| 196 } | 233 } |
| 197 | 234 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 | 319 |
| 283 | 320 |
| 284 // now we decode the colortable | 321 // now we decode the colortable |
| 285 int colorCount = 0; | 322 int colorCount = 0; |
| 286 { | 323 { |
| 287 // Declare colorPtr here for scope. | 324 // Declare colorPtr here for scope. |
| 288 SkPMColor colorPtr[256]; // storage for worst-case | 325 SkPMColor colorPtr[256]; // storage for worst-case |
| 289 const ColorMapObject* cmap = find_colormap(gif); | 326 const ColorMapObject* cmap = find_colormap(gif); |
| 290 SkAlphaType alphaType = kOpaque_SkAlphaType; | 327 SkAlphaType alphaType = kOpaque_SkAlphaType; |
| 291 if (cmap != NULL) { | 328 if (cmap != NULL) { |
| 329 SkASSERT(cmap->ColorCount == (1 << (cmap->BitsPerPixel))); | |
| 292 colorCount = cmap->ColorCount; | 330 colorCount = cmap->ColorCount; |
| 293 if (colorCount > 256) { | 331 if (colorCount > 256) { |
| 294 colorCount = 256; // our kIndex8 can't support more | 332 colorCount = 256; // our kIndex8 can't support more |
| 295 } | 333 } |
| 296 for (int index = 0; index < colorCount; index++) { | 334 for (int index = 0; index < colorCount; index++) { |
| 297 colorPtr[index] = SkPackARGB32(0xFF, | 335 colorPtr[index] = SkPackARGB32(0xFF, |
| 298 cmap->Colors[index].Red, | 336 cmap->Colors[index].Red, |
| 299 cmap->Colors[index].Green , | 337 cmap->Colors[index].Green , |
| 300 cmap->Colors[index].Blue) ; | 338 cmap->Colors[index].Blue) ; |
| 301 } | 339 } |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 sampler.next(scanline); | 441 sampler.next(scanline); |
| 404 if (y < outHeight - 1) { | 442 if (y < outHeight - 1) { |
| 405 skip_src_rows(gif, scanline, innerWidth, sampler.srcDY() - 1); | 443 skip_src_rows(gif, scanline, innerWidth, sampler.srcDY() - 1); |
| 406 } | 444 } |
| 407 } | 445 } |
| 408 // skip the rest of the rows (if any) | 446 // skip the rest of the rows (if any) |
| 409 int read = (outHeight - 1) * sampler.srcDY() + sampler.srcY0() + 1; | 447 int read = (outHeight - 1) * sampler.srcDY() + sampler.srcY0() + 1; |
| 410 SkASSERT(read <= innerHeight); | 448 SkASSERT(read <= innerHeight); |
| 411 skip_src_rows(gif, scanline, innerWidth, innerHeight - read); | 449 skip_src_rows(gif, scanline, innerWidth, innerHeight - read); |
| 412 } | 450 } |
| 451 sanitize_indexed_bitmap(bm); | |
| 413 return true; | 452 return true; |
| 414 } break; | 453 } break; |
| 415 | 454 |
| 416 case EXTENSION_RECORD_TYPE: | 455 case EXTENSION_RECORD_TYPE: |
| 417 #if GIFLIB_MAJOR < 5 | 456 #if GIFLIB_MAJOR < 5 |
| 418 if (DGifGetExtension(gif, &temp_save.Function, | 457 if (DGifGetExtension(gif, &temp_save.Function, |
| 419 &extData) == GIF_ERROR) { | 458 &extData) == GIF_ERROR) { |
| 420 #else | 459 #else |
| 421 if (DGifGetExtension(gif, &extFunction, &extData) == GIF_ERROR) { | 460 if (DGifGetExtension(gif, &extFunction, &extData) == GIF_ERROR) { |
| 422 #endif | 461 #endif |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 447 break; | 486 break; |
| 448 | 487 |
| 449 case TERMINATE_RECORD_TYPE: | 488 case TERMINATE_RECORD_TYPE: |
| 450 break; | 489 break; |
| 451 | 490 |
| 452 default: /* Should be trapped by DGifGetRecordType */ | 491 default: /* Should be trapped by DGifGetRecordType */ |
| 453 break; | 492 break; |
| 454 } | 493 } |
| 455 } while (recType != TERMINATE_RECORD_TYPE); | 494 } while (recType != TERMINATE_RECORD_TYPE); |
| 456 | 495 |
| 496 sanitize_indexed_bitmap(bm); | |
| 457 return true; | 497 return true; |
| 458 } | 498 } |
| 459 | 499 |
| 460 /////////////////////////////////////////////////////////////////////////////// | 500 /////////////////////////////////////////////////////////////////////////////// |
| 461 DEFINE_DECODER_CREATOR(GIFImageDecoder); | 501 DEFINE_DECODER_CREATOR(GIFImageDecoder); |
| 462 /////////////////////////////////////////////////////////////////////////////// | 502 /////////////////////////////////////////////////////////////////////////////// |
| 463 | 503 |
| 464 static bool is_gif(SkStreamRewindable* stream) { | 504 static bool is_gif(SkStreamRewindable* stream) { |
| 465 char buf[GIF_STAMP_LEN]; | 505 char buf[GIF_STAMP_LEN]; |
| 466 if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) { | 506 if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 483 static SkImageDecoder_DecodeReg gReg(sk_libgif_dfactory); | 523 static SkImageDecoder_DecodeReg gReg(sk_libgif_dfactory); |
| 484 | 524 |
| 485 static SkImageDecoder::Format get_format_gif(SkStreamRewindable* stream) { | 525 static SkImageDecoder::Format get_format_gif(SkStreamRewindable* stream) { |
| 486 if (is_gif(stream)) { | 526 if (is_gif(stream)) { |
| 487 return SkImageDecoder::kGIF_Format; | 527 return SkImageDecoder::kGIF_Format; |
| 488 } | 528 } |
| 489 return SkImageDecoder::kUnknown_Format; | 529 return SkImageDecoder::kUnknown_Format; |
| 490 } | 530 } |
| 491 | 531 |
| 492 static SkImageDecoder_FormatReg gFormatReg(get_format_gif); | 532 static SkImageDecoder_FormatReg gFormatReg(get_format_gif); |
| OLD | NEW |