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 /** |
| 189 * GIFs with fewer then 256 color entries will sometimes index out of |
| 190 * bounds of the color table (this is malformed, but libgif does not |
| 191 * check sicne it is rare). This function checks for this error and |
| 192 * fixes it. This makes the output image consistantly deterministic. |
| 193 */ |
| 194 static void sanitize_indexed_bitmap(SkBitmap* bm) { |
| 195 if ((SkBitmap::kIndex8_Config == bm->config()) && !(bm->empty())) { |
| 196 SkAutoLockPixels alp(*bm); |
| 197 if (NULL != bm->getPixels()) { |
| 198 SkColorTable* ct = bm->getColorTable(); // Index8 must have it. |
| 199 SkASSERT(ct != NULL); |
| 200 uint32_t count = ct->count(); |
| 201 SkASSERT(count > 0); |
| 202 SkASSERT(count <= 0x100); |
| 203 if (count != 0x100) { // Full colortables can't go wrong. |
| 204 // Count is a power of 2; asserted elsewhere. |
| 205 uint8_t byteMask = (~(count - 1)); |
| 206 bool warning = false; |
| 207 uint8_t* addr = static_cast<uint8_t*>(bm->getPixels()); |
| 208 int height = bm->height(); |
| 209 int width = bm->width(); |
| 210 size_t rowBytes = bm->rowBytes(); |
| 211 while (--height >= 0) { |
| 212 uint8_t* ptr = addr; |
| 213 int x = width; |
| 214 while (--x >= 0) { |
| 215 if (0 != ((*ptr) & byteMask)) { |
| 216 warning = true; |
| 217 *ptr = 0; |
| 218 } |
| 219 ++ptr; |
| 220 } |
| 221 addr += rowBytes; |
| 222 } |
| 223 if (warning) { |
| 224 gif_warning(*bm, "Index out of bounds."); |
| 225 } |
| 226 } |
| 227 } |
| 228 } |
| 229 } |
| 230 |
188 bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) { | 231 bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) { |
189 #if GIFLIB_MAJOR < 5 | 232 #if GIFLIB_MAJOR < 5 |
190 GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc); | 233 GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc); |
191 #else | 234 #else |
192 GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc, NULL); | 235 GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc, NULL); |
193 #endif | 236 #endif |
194 if (NULL == gif) { | 237 if (NULL == gif) { |
195 return error_return(*bm, "DGifOpen"); | 238 return error_return(*bm, "DGifOpen"); |
196 } | 239 } |
197 | 240 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 | 325 |
283 | 326 |
284 // now we decode the colortable | 327 // now we decode the colortable |
285 int colorCount = 0; | 328 int colorCount = 0; |
286 { | 329 { |
287 // Declare colorPtr here for scope. | 330 // Declare colorPtr here for scope. |
288 SkPMColor colorPtr[256]; // storage for worst-case | 331 SkPMColor colorPtr[256]; // storage for worst-case |
289 const ColorMapObject* cmap = find_colormap(gif); | 332 const ColorMapObject* cmap = find_colormap(gif); |
290 SkAlphaType alphaType = kOpaque_SkAlphaType; | 333 SkAlphaType alphaType = kOpaque_SkAlphaType; |
291 if (cmap != NULL) { | 334 if (cmap != NULL) { |
| 335 SkASSERT(cmap->ColorCount == (1 << (cmap->BitsPerPixel))); |
292 colorCount = cmap->ColorCount; | 336 colorCount = cmap->ColorCount; |
293 if (colorCount > 256) { | 337 if (colorCount > 256) { |
294 colorCount = 256; // our kIndex8 can't support more | 338 colorCount = 256; // our kIndex8 can't support more |
295 } | 339 } |
296 for (int index = 0; index < colorCount; index++) { | 340 for (int index = 0; index < colorCount; index++) { |
297 colorPtr[index] = SkPackARGB32(0xFF, | 341 colorPtr[index] = SkPackARGB32(0xFF, |
298 cmap->Colors[index].Red, | 342 cmap->Colors[index].Red, |
299 cmap->Colors[index].Green
, | 343 cmap->Colors[index].Green
, |
300 cmap->Colors[index].Blue)
; | 344 cmap->Colors[index].Blue)
; |
301 } | 345 } |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 sampler.next(scanline); | 447 sampler.next(scanline); |
404 if (y < outHeight - 1) { | 448 if (y < outHeight - 1) { |
405 skip_src_rows(gif, scanline, innerWidth, sampler.srcDY()
- 1); | 449 skip_src_rows(gif, scanline, innerWidth, sampler.srcDY()
- 1); |
406 } | 450 } |
407 } | 451 } |
408 // skip the rest of the rows (if any) | 452 // skip the rest of the rows (if any) |
409 int read = (outHeight - 1) * sampler.srcDY() + sampler.srcY0() +
1; | 453 int read = (outHeight - 1) * sampler.srcDY() + sampler.srcY0() +
1; |
410 SkASSERT(read <= innerHeight); | 454 SkASSERT(read <= innerHeight); |
411 skip_src_rows(gif, scanline, innerWidth, innerHeight - read); | 455 skip_src_rows(gif, scanline, innerWidth, innerHeight - read); |
412 } | 456 } |
| 457 sanitize_indexed_bitmap(bm); |
413 return true; | 458 return true; |
414 } break; | 459 } break; |
415 | 460 |
416 case EXTENSION_RECORD_TYPE: | 461 case EXTENSION_RECORD_TYPE: |
417 #if GIFLIB_MAJOR < 5 | 462 #if GIFLIB_MAJOR < 5 |
418 if (DGifGetExtension(gif, &temp_save.Function, | 463 if (DGifGetExtension(gif, &temp_save.Function, |
419 &extData) == GIF_ERROR) { | 464 &extData) == GIF_ERROR) { |
420 #else | 465 #else |
421 if (DGifGetExtension(gif, &extFunction, &extData) == GIF_ERROR) { | 466 if (DGifGetExtension(gif, &extFunction, &extData) == GIF_ERROR) { |
422 #endif | 467 #endif |
(...skipping 24 matching lines...) Expand all Loading... |
447 break; | 492 break; |
448 | 493 |
449 case TERMINATE_RECORD_TYPE: | 494 case TERMINATE_RECORD_TYPE: |
450 break; | 495 break; |
451 | 496 |
452 default: /* Should be trapped by DGifGetRecordType */ | 497 default: /* Should be trapped by DGifGetRecordType */ |
453 break; | 498 break; |
454 } | 499 } |
455 } while (recType != TERMINATE_RECORD_TYPE); | 500 } while (recType != TERMINATE_RECORD_TYPE); |
456 | 501 |
| 502 sanitize_indexed_bitmap(bm); |
457 return true; | 503 return true; |
458 } | 504 } |
459 | 505 |
460 /////////////////////////////////////////////////////////////////////////////// | 506 /////////////////////////////////////////////////////////////////////////////// |
461 DEFINE_DECODER_CREATOR(GIFImageDecoder); | 507 DEFINE_DECODER_CREATOR(GIFImageDecoder); |
462 /////////////////////////////////////////////////////////////////////////////// | 508 /////////////////////////////////////////////////////////////////////////////// |
463 | 509 |
464 static bool is_gif(SkStreamRewindable* stream) { | 510 static bool is_gif(SkStreamRewindable* stream) { |
465 char buf[GIF_STAMP_LEN]; | 511 char buf[GIF_STAMP_LEN]; |
466 if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) { | 512 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); | 529 static SkImageDecoder_DecodeReg gReg(sk_libgif_dfactory); |
484 | 530 |
485 static SkImageDecoder::Format get_format_gif(SkStreamRewindable* stream) { | 531 static SkImageDecoder::Format get_format_gif(SkStreamRewindable* stream) { |
486 if (is_gif(stream)) { | 532 if (is_gif(stream)) { |
487 return SkImageDecoder::kGIF_Format; | 533 return SkImageDecoder::kGIF_Format; |
488 } | 534 } |
489 return SkImageDecoder::kUnknown_Format; | 535 return SkImageDecoder::kUnknown_Format; |
490 } | 536 } |
491 | 537 |
492 static SkImageDecoder_FormatReg gFormatReg(get_format_gif); | 538 static SkImageDecoder_FormatReg gFormatReg(get_format_gif); |
OLD | NEW |