Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / images / SkImageDecoder_libgif.cpp
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "SkColor.h"
9 #include "SkColorPriv.h"
10 #include "SkColorTable.h"
11 #include "SkImageDecoder.h"
12 #include "SkRTConf.h"
13 #include "SkScaledBitmapSampler.h"
14 #include "SkStream.h"
15 #include "SkTemplates.h"
16 #include "SkUtils.h"
17
18 #include "gif_lib.h"
19
20 class SkGIFImageDecoder : public SkImageDecoder {
21 public:
22     virtual Format getFormat() const SK_OVERRIDE {
23         return kGIF_Format;
24     }
25
26 protected:
27     virtual Result onDecode(SkStream* stream, SkBitmap* bm, Mode mode) SK_OVERRIDE;
28
29 private:
30     typedef SkImageDecoder INHERITED;
31 };
32
33 static const uint8_t gStartingIterlaceYValue[] = {
34     0, 4, 2, 1
35 };
36 static const uint8_t gDeltaIterlaceYValue[] = {
37     8, 8, 4, 2
38 };
39
40 SK_CONF_DECLARE(bool, c_suppressGIFImageDecoderWarnings,
41                 "images.gif.suppressDecoderWarnings", true,
42                 "Suppress GIF warnings and errors when calling image decode "
43                 "functions.");
44
45
46 /*  Implement the GIF interlace algorithm in an iterator.
47     1) grab every 8th line beginning at 0
48     2) grab every 8th line beginning at 4
49     3) grab every 4th line beginning at 2
50     4) grab every 2nd line beginning at 1
51 */
52 class GifInterlaceIter {
53 public:
54     GifInterlaceIter(int height) : fHeight(height) {
55         fStartYPtr = gStartingIterlaceYValue;
56         fDeltaYPtr = gDeltaIterlaceYValue;
57
58         fCurrY = *fStartYPtr++;
59         fDeltaY = *fDeltaYPtr++;
60     }
61
62     int currY() const {
63         SkASSERT(fStartYPtr);
64         SkASSERT(fDeltaYPtr);
65         return fCurrY;
66     }
67
68     void next() {
69         SkASSERT(fStartYPtr);
70         SkASSERT(fDeltaYPtr);
71
72         int y = fCurrY + fDeltaY;
73         // We went from an if statement to a while loop so that we iterate
74         // through fStartYPtr until a valid row is found. This is so that images
75         // that are smaller than 5x5 will not trash memory.
76         while (y >= fHeight) {
77             if (gStartingIterlaceYValue +
78                     SK_ARRAY_COUNT(gStartingIterlaceYValue) == fStartYPtr) {
79                 // we done
80                 SkDEBUGCODE(fStartYPtr = NULL;)
81                 SkDEBUGCODE(fDeltaYPtr = NULL;)
82                 y = 0;
83             } else {
84                 y = *fStartYPtr++;
85                 fDeltaY = *fDeltaYPtr++;
86             }
87         }
88         fCurrY = y;
89     }
90
91 private:
92     const int fHeight;
93     int fCurrY;
94     int fDeltaY;
95     const uint8_t* fStartYPtr;
96     const uint8_t* fDeltaYPtr;
97 };
98
99 ///////////////////////////////////////////////////////////////////////////////
100
101 static int DecodeCallBackProc(GifFileType* fileType, GifByteType* out,
102                               int size) {
103     SkStream* stream = (SkStream*) fileType->UserData;
104     return (int) stream->read(out, size);
105 }
106
107 void CheckFreeExtension(SavedImage* Image) {
108     if (Image->ExtensionBlocks) {
109 #if GIFLIB_MAJOR < 5
110         FreeExtension(Image);
111 #else
112         GifFreeExtensions(&Image->ExtensionBlockCount, &Image->ExtensionBlocks);
113 #endif
114     }
115 }
116
117 // return NULL on failure
118 static const ColorMapObject* find_colormap(const GifFileType* gif) {
119     const ColorMapObject* cmap = gif->Image.ColorMap;
120     if (NULL == cmap) {
121         cmap = gif->SColorMap;
122     }
123
124     if (NULL == cmap) {
125         // no colormap found
126         return NULL;
127     }
128     // some sanity checks
129     if (cmap && ((unsigned)cmap->ColorCount > 256 ||
130                  cmap->ColorCount != (1 << cmap->BitsPerPixel))) {
131         cmap = NULL;
132     }
133     return cmap;
134 }
135
136 // return -1 if not found (i.e. we're completely opaque)
137 static int find_transpIndex(const SavedImage& image, int colorCount) {
138     int transpIndex = -1;
139     for (int i = 0; i < image.ExtensionBlockCount; ++i) {
140         const ExtensionBlock* eb = image.ExtensionBlocks + i;
141         if (eb->Function == 0xF9 && eb->ByteCount == 4) {
142             if (eb->Bytes[0] & 1) {
143                 transpIndex = (unsigned char)eb->Bytes[3];
144                 // check for valid transpIndex
145                 if (transpIndex >= colorCount) {
146                     transpIndex = -1;
147                 }
148                 break;
149             }
150         }
151     }
152     return transpIndex;
153 }
154
155 static SkImageDecoder::Result error_return(const SkBitmap& bm, const char msg[]) {
156     if (!c_suppressGIFImageDecoderWarnings) {
157         SkDebugf("libgif error [%s] bitmap [%d %d] pixels %p colortable %p\n",
158                  msg, bm.width(), bm.height(), bm.getPixels(),
159                  bm.getColorTable());
160     }
161     return SkImageDecoder::kFailure;
162 }
163
164 static void gif_warning(const SkBitmap& bm, const char msg[]) {
165     if (!c_suppressGIFImageDecoderWarnings) {
166         SkDebugf("libgif warning [%s] bitmap [%d %d] pixels %p colortable %p\n",
167                  msg, bm.width(), bm.height(), bm.getPixels(),
168                  bm.getColorTable());
169     }
170 }
171
172 /**
173  *  Skip rows in the source gif image.
174  *  @param gif Source image.
175  *  @param dst Scratch output needed by gif library call. Must be >= width bytes.
176  *  @param width Bytes per row in the source image.
177  *  @param rowsToSkip Number of rows to skip.
178  *  @return True on success, false on GIF_ERROR.
179  */
180 static bool skip_src_rows(GifFileType* gif, uint8_t* dst, int width, int rowsToSkip) {
181     for (int i = 0; i < rowsToSkip; i++) {
182         if (DGifGetLine(gif, dst, width) == GIF_ERROR) {
183             return false;
184         }
185     }
186     return true;
187 }
188
189 /**
190  *  GIFs with fewer then 256 color entries will sometimes index out of
191  *  bounds of the color table (this is malformed, but libgif does not
192  *  check sicne it is rare).  This function checks for this error and
193  *  fixes it.  This makes the output image consistantly deterministic.
194  */
195 static void sanitize_indexed_bitmap(SkBitmap* bm) {
196     if ((kIndex_8_SkColorType == bm->colorType()) && !(bm->empty())) {
197         SkAutoLockPixels alp(*bm);
198         if (bm->getPixels()) {
199             SkColorTable* ct = bm->getColorTable();  // Index8 must have it.
200             SkASSERT(ct != NULL);
201             uint32_t count = ct->count();
202             SkASSERT(count > 0);
203             SkASSERT(count <= 0x100);
204             if (count != 0x100) {  // Full colortables can't go wrong.
205                 // Count is a power of 2; asserted elsewhere.
206                 uint8_t byteMask = (~(count - 1));
207                 bool warning = false;
208                 uint8_t* addr = static_cast<uint8_t*>(bm->getPixels());
209                 int height = bm->height();
210                 int width = bm->width();
211                 size_t rowBytes = bm->rowBytes();
212                 while (--height >= 0) {
213                     uint8_t* ptr = addr;
214                     int x = width;
215                     while (--x >= 0) {
216                         if (0 != ((*ptr) & byteMask)) {
217                             warning = true;
218                             *ptr = 0;
219                         }
220                         ++ptr;
221                     }
222                     addr += rowBytes;
223                 }
224                 if (warning) {
225                     gif_warning(*bm, "Index out of bounds.");
226                 }
227             }
228         }
229     }
230 }
231
232 SkImageDecoder::Result SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
233 #if GIFLIB_MAJOR < 5
234     GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc);
235 #else
236     GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc, NULL);
237 #endif
238     if (NULL == gif) {
239         return error_return(*bm, "DGifOpen");
240     }
241
242     SkAutoTCallIProc<GifFileType, DGifCloseFile> acp(gif);
243
244     SavedImage temp_save;
245     temp_save.ExtensionBlocks=NULL;
246     temp_save.ExtensionBlockCount=0;
247     SkAutoTCallVProc<SavedImage, CheckFreeExtension> acp2(&temp_save);
248
249     int width, height;
250     GifRecordType recType;
251     GifByteType *extData;
252 #if GIFLIB_MAJOR >= 5
253     int extFunction;
254 #endif
255     int transpIndex = -1;   // -1 means we don't have it (yet)
256     int fillIndex = gif->SBackGroundColor;
257
258     do {
259         if (DGifGetRecordType(gif, &recType) == GIF_ERROR) {
260             return error_return(*bm, "DGifGetRecordType");
261         }
262
263         switch (recType) {
264         case IMAGE_DESC_RECORD_TYPE: {
265             if (DGifGetImageDesc(gif) == GIF_ERROR) {
266                 return error_return(*bm, "IMAGE_DESC_RECORD_TYPE");
267             }
268
269             if (gif->ImageCount < 1) {    // sanity check
270                 return error_return(*bm, "ImageCount < 1");
271             }
272
273             width = gif->SWidth;
274             height = gif->SHeight;
275
276             SavedImage* image = &gif->SavedImages[gif->ImageCount-1];
277             const GifImageDesc& desc = image->ImageDesc;
278
279             int imageLeft = desc.Left;
280             int imageTop = desc.Top;
281             const int innerWidth = desc.Width;
282             const int innerHeight = desc.Height;
283             if (innerWidth <= 0 || innerHeight <= 0) {
284                 return error_return(*bm, "invalid dimensions");
285             }
286
287             // check for valid descriptor
288             if (innerWidth > width) {
289                 gif_warning(*bm, "image too wide, expanding output to size");
290                 width = innerWidth;
291                 imageLeft = 0;
292             } else if (imageLeft + innerWidth > width) {
293                 gif_warning(*bm, "shifting image left to fit");
294                 imageLeft = width - innerWidth;
295             } else if (imageLeft < 0) {
296                 gif_warning(*bm, "shifting image right to fit");
297                 imageLeft = 0;
298             }
299
300
301             if (innerHeight > height) {
302                 gif_warning(*bm, "image too tall,  expanding output to size");
303                 height = innerHeight;
304                 imageTop = 0;
305             } else if (imageTop + innerHeight > height) {
306                 gif_warning(*bm, "shifting image up to fit");
307                 imageTop = height - innerHeight;
308             } else if (imageTop < 0) {
309                 gif_warning(*bm, "shifting image down to fit");
310                 imageTop = 0;
311             }
312
313 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
314             // FIXME: We could give the caller a choice of images or configs.
315             if (!this->chooseFromOneChoice(kIndex_8_SkColorType, width, height)) {
316                 return error_return(*bm, "chooseFromOneChoice");
317             }
318 #endif
319
320             SkScaledBitmapSampler sampler(width, height, this->getSampleSize());
321
322             bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
323                                           kIndex_8_SkColorType, kPremul_SkAlphaType));
324
325             if (SkImageDecoder::kDecodeBounds_Mode == mode) {
326                 return kSuccess;
327             }
328
329
330             // now we decode the colortable
331             int colorCount = 0;
332             {
333                 // Declare colorPtr here for scope.
334                 SkPMColor colorPtr[256]; // storage for worst-case
335                 const ColorMapObject* cmap = find_colormap(gif);
336                 if (cmap != NULL) {
337                     SkASSERT(cmap->ColorCount == (1 << (cmap->BitsPerPixel)));
338                     colorCount = cmap->ColorCount;
339                     if (colorCount > 256) {
340                         colorCount = 256;  // our kIndex8 can't support more
341                     }
342                     for (int index = 0; index < colorCount; index++) {
343                         colorPtr[index] = SkPackARGB32(0xFF,
344                                                        cmap->Colors[index].Red,
345                                                        cmap->Colors[index].Green,
346                                                        cmap->Colors[index].Blue);
347                     }
348                 } else {
349                     // find_colormap() returned NULL.  Some (rare, broken)
350                     // GIFs don't have a color table, so we force one.
351                     gif_warning(*bm, "missing colormap");
352                     colorCount = 256;
353                     sk_memset32(colorPtr, SK_ColorWHITE, colorCount);
354                 }
355                 transpIndex = find_transpIndex(temp_save, colorCount);
356                 if (transpIndex >= 0) {
357                     colorPtr[transpIndex] = SK_ColorTRANSPARENT; // ram in a transparent SkPMColor
358                     fillIndex = transpIndex;
359                 } else if (fillIndex >= colorCount) {
360                     // gif->SBackGroundColor should be less than colorCount.
361                     fillIndex = 0;  // If not, fix it.
362                 }
363
364                 SkAutoTUnref<SkColorTable> ctable(SkNEW_ARGS(SkColorTable, (colorPtr, colorCount)));
365                 if (!this->allocPixelRef(bm, ctable)) {
366                     return error_return(*bm, "allocPixelRef");
367                 }
368             }
369
370             // abort if either inner dimension is <= 0
371             if (innerWidth <= 0 || innerHeight <= 0) {
372                 return error_return(*bm, "non-pos inner width/height");
373             }
374
375             SkAutoLockPixels alp(*bm);
376
377             SkAutoMalloc storage(innerWidth);
378             uint8_t* scanline = (uint8_t*) storage.get();
379
380             // GIF has an option to store the scanlines of an image, plus a larger background,
381             // filled by a fill color. In this case, we will use a subset of the larger bitmap
382             // for sampling.
383             SkBitmap subset;
384             SkBitmap* workingBitmap;
385             // are we only a subset of the total bounds?
386             if ((imageTop | imageLeft) > 0 ||
387                  innerWidth < width || innerHeight < height) {
388                 // Fill the background.
389                 memset(bm->getPixels(), fillIndex, bm->getSize());
390
391                 // Create a subset of the bitmap.
392                 SkIRect subsetRect(SkIRect::MakeXYWH(imageLeft / sampler.srcDX(),
393                                                      imageTop / sampler.srcDY(),
394                                                      innerWidth / sampler.srcDX(),
395                                                      innerHeight / sampler.srcDY()));
396                 if (!bm->extractSubset(&subset, subsetRect)) {
397                     return error_return(*bm, "Extract failed.");
398                 }
399                 // Update the sampler. We'll now be only sampling into the subset.
400                 sampler = SkScaledBitmapSampler(innerWidth, innerHeight, this->getSampleSize());
401                 workingBitmap = &subset;
402             } else {
403                 workingBitmap = bm;
404             }
405
406             // bm is already locked, but if we had to take a subset, it must be locked also,
407             // so that getPixels() will point to its pixels.
408             SkAutoLockPixels alpWorking(*workingBitmap);
409
410             if (!sampler.begin(workingBitmap, SkScaledBitmapSampler::kIndex, *this)) {
411                 return error_return(*bm, "Sampler failed to begin.");
412             }
413
414             // now decode each scanline
415             if (gif->Image.Interlace) {
416                 // Iterate over the height of the source data. The sampler will
417                 // take care of skipping unneeded rows.
418                 GifInterlaceIter iter(innerHeight);
419                 for (int y = 0; y < innerHeight; y++) {
420                     if (DGifGetLine(gif, scanline, innerWidth) == GIF_ERROR) {
421                         gif_warning(*bm, "interlace DGifGetLine");
422                         memset(scanline, fillIndex, innerWidth);
423                         for (; y < innerHeight; y++) {
424                             sampler.sampleInterlaced(scanline, iter.currY());
425                             iter.next();
426                         }
427                         return kPartialSuccess;
428                     }
429                     sampler.sampleInterlaced(scanline, iter.currY());
430                     iter.next();
431                 }
432             } else {
433                 // easy, non-interlace case
434                 const int outHeight = workingBitmap->height();
435                 skip_src_rows(gif, scanline, innerWidth, sampler.srcY0());
436                 for (int y = 0; y < outHeight; y++) {
437                     if (DGifGetLine(gif, scanline, innerWidth) == GIF_ERROR) {
438                         gif_warning(*bm, "DGifGetLine");
439                         memset(scanline, fillIndex, innerWidth);
440                         for (; y < outHeight; y++) {
441                             sampler.next(scanline);
442                         }
443                         return kPartialSuccess;
444                     }
445                     // scanline now contains the raw data. Sample it.
446                     sampler.next(scanline);
447                     if (y < outHeight - 1) {
448                         skip_src_rows(gif, scanline, innerWidth, sampler.srcDY() - 1);
449                     }
450                 }
451                 // skip the rest of the rows (if any)
452                 int read = (outHeight - 1) * sampler.srcDY() + sampler.srcY0() + 1;
453                 SkASSERT(read <= innerHeight);
454                 skip_src_rows(gif, scanline, innerWidth, innerHeight - read);
455             }
456             sanitize_indexed_bitmap(bm);
457             return kSuccess;
458             } break;
459
460         case EXTENSION_RECORD_TYPE:
461 #if GIFLIB_MAJOR < 5
462             if (DGifGetExtension(gif, &temp_save.Function,
463                                  &extData) == GIF_ERROR) {
464 #else
465             if (DGifGetExtension(gif, &extFunction, &extData) == GIF_ERROR) {
466 #endif
467                 return error_return(*bm, "DGifGetExtension");
468             }
469
470             while (extData != NULL) {
471                 /* Create an extension block with our data */
472 #if GIFLIB_MAJOR < 5
473                 if (AddExtensionBlock(&temp_save, extData[0],
474                                       &extData[1]) == GIF_ERROR) {
475 #else
476                 if (GifAddExtensionBlock(&gif->ExtensionBlockCount,
477                                          &gif->ExtensionBlocks,
478                                          extFunction,
479                                          extData[0],
480                                          &extData[1]) == GIF_ERROR) {
481 #endif
482                     return error_return(*bm, "AddExtensionBlock");
483                 }
484                 if (DGifGetExtensionNext(gif, &extData) == GIF_ERROR) {
485                     return error_return(*bm, "DGifGetExtensionNext");
486                 }
487 #if GIFLIB_MAJOR < 5
488                 temp_save.Function = 0;
489 #endif
490             }
491             break;
492
493         case TERMINATE_RECORD_TYPE:
494             break;
495
496         default:    /* Should be trapped by DGifGetRecordType */
497             break;
498         }
499     } while (recType != TERMINATE_RECORD_TYPE);
500
501     sanitize_indexed_bitmap(bm);
502     return kSuccess;
503 }
504
505 ///////////////////////////////////////////////////////////////////////////////
506 DEFINE_DECODER_CREATOR(GIFImageDecoder);
507 ///////////////////////////////////////////////////////////////////////////////
508
509 static bool is_gif(SkStreamRewindable* stream) {
510     char buf[GIF_STAMP_LEN];
511     if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
512         if (memcmp(GIF_STAMP,   buf, GIF_STAMP_LEN) == 0 ||
513                 memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 ||
514                 memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0) {
515             return true;
516         }
517     }
518     return false;
519 }
520
521 static SkImageDecoder* sk_libgif_dfactory(SkStreamRewindable* stream) {
522     if (is_gif(stream)) {
523         return SkNEW(SkGIFImageDecoder);
524     }
525     return NULL;
526 }
527
528 static SkImageDecoder_DecodeReg gReg(sk_libgif_dfactory);
529
530 static SkImageDecoder::Format get_format_gif(SkStreamRewindable* stream) {
531     if (is_gif(stream)) {
532         return SkImageDecoder::kGIF_Format;
533     }
534     return SkImageDecoder::kUnknown_Format;
535 }
536
537 static SkImageDecoder_FormatReg gFormatReg(get_format_gif);