1 /*
2 * Copyright 2013 Google Inc.
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 "SkTypes.h"
9
10 // This tests out GIF decoder (SkImageDecoder_libgif.cpp)
11 // It is not used on these platforms:
12 #if (!defined(SK_BUILD_FOR_WIN32)) && \
13 (!defined(SK_BUILD_FOR_IOS)) && \
14 (!defined(SK_BUILD_FOR_MAC))
15
16 #include "Resources.h"
17 #include "SkBitmap.h"
18 #include "SkData.h"
19 #include "SkForceLinking.h"
20 #include "SkImage.h"
21 #include "SkImageDecoder.h"
22 #include "SkStream.h"
23 #include "Test.h"
24
25 __SK_FORCE_IMAGE_DECODER_LINKING;
26
27 static unsigned char gGIFData[] = {
28 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x03, 0x00, 0x03, 0x00, 0xe3, 0x08,
29 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00,
30 0xff, 0x80, 0x80, 0x80, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
31 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
32 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
33 0xff, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x04,
34 0x07, 0x50, 0x1c, 0x43, 0x40, 0x41, 0x23, 0x44, 0x00, 0x3b
35 };
36
37 static unsigned char gGIFDataNoColormap[] = {
38 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
39 0x21, 0xf9, 0x04, 0x01, 0x0a, 0x00, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00,
40 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x4c, 0x01, 0x00, 0x3b
41 };
42
43 static unsigned char gInterlacedGIF[] = {
44 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x09, 0x00, 0x09, 0x00, 0xe3, 0x08, 0x00,
45 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x80,
46 0x80, 0x80, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff,
47 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
48 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00,
49 0x00, 0x09, 0x00, 0x09, 0x00, 0x40, 0x04, 0x1b, 0x50, 0x1c, 0x23, 0xe9, 0x44,
50 0x23, 0x60, 0x9d, 0x09, 0x28, 0x1e, 0xf8, 0x6d, 0x64, 0x56, 0x9d, 0x53, 0xa8,
51 0x7e, 0xa8, 0x65, 0x94, 0x5c, 0xb0, 0x8a, 0x45, 0x04, 0x00, 0x3b
52 };
53
test_gif_data_no_colormap(skiatest::Reporter * r,void * data,size_t size)54 static void test_gif_data_no_colormap(skiatest::Reporter* r,
55 void* data,
56 size_t size) {
57 SkBitmap bm;
58 bool imageDecodeSuccess = SkImageDecoder::DecodeMemory(
59 data, size, &bm);
60 REPORTER_ASSERT(r, imageDecodeSuccess);
61 REPORTER_ASSERT(r, bm.width() == 1);
62 REPORTER_ASSERT(r, bm.height() == 1);
63 REPORTER_ASSERT(r, !(bm.empty()));
64 if (!(bm.empty())) {
65 REPORTER_ASSERT(r, bm.getColor(0, 0) == 0x00000000);
66 }
67 }
test_gif_data(skiatest::Reporter * r,void * data,size_t size)68 static void test_gif_data(skiatest::Reporter* r, void* data, size_t size) {
69 SkBitmap bm;
70 bool imageDecodeSuccess = SkImageDecoder::DecodeMemory(
71 data, size, &bm);
72 REPORTER_ASSERT(r, imageDecodeSuccess);
73 REPORTER_ASSERT(r, bm.width() == 3);
74 REPORTER_ASSERT(r, bm.height() == 3);
75 REPORTER_ASSERT(r, !(bm.empty()));
76 if (!(bm.empty())) {
77 REPORTER_ASSERT(r, bm.getColor(0, 0) == 0xffff0000);
78 REPORTER_ASSERT(r, bm.getColor(1, 0) == 0xffffff00);
79 REPORTER_ASSERT(r, bm.getColor(2, 0) == 0xff00ffff);
80 REPORTER_ASSERT(r, bm.getColor(0, 1) == 0xff808080);
81 REPORTER_ASSERT(r, bm.getColor(1, 1) == 0xff000000);
82 REPORTER_ASSERT(r, bm.getColor(2, 1) == 0xff00ff00);
83 REPORTER_ASSERT(r, bm.getColor(0, 2) == 0xffffffff);
84 REPORTER_ASSERT(r, bm.getColor(1, 2) == 0xffff00ff);
85 REPORTER_ASSERT(r, bm.getColor(2, 2) == 0xff0000ff);
86 }
87 }
test_interlaced_gif_data(skiatest::Reporter * r,void * data,size_t size)88 static void test_interlaced_gif_data(skiatest::Reporter* r,
89 void* data,
90 size_t size) {
91 SkBitmap bm;
92 bool imageDecodeSuccess = SkImageDecoder::DecodeMemory(
93 data, size, &bm);
94 REPORTER_ASSERT(r, imageDecodeSuccess);
95 REPORTER_ASSERT(r, bm.width() == 9);
96 REPORTER_ASSERT(r, bm.height() == 9);
97 REPORTER_ASSERT(r, !(bm.empty()));
98 if (!(bm.empty())) {
99 REPORTER_ASSERT(r, bm.getColor(0, 0) == 0xffff0000);
100 REPORTER_ASSERT(r, bm.getColor(1, 0) == 0xffffff00);
101 REPORTER_ASSERT(r, bm.getColor(2, 0) == 0xff00ffff);
102
103 REPORTER_ASSERT(r, bm.getColor(0, 2) == 0xffffffff);
104 REPORTER_ASSERT(r, bm.getColor(1, 2) == 0xffff00ff);
105 REPORTER_ASSERT(r, bm.getColor(2, 2) == 0xff0000ff);
106
107 REPORTER_ASSERT(r, bm.getColor(0, 4) == 0xff808080);
108 REPORTER_ASSERT(r, bm.getColor(1, 4) == 0xff000000);
109 REPORTER_ASSERT(r, bm.getColor(2, 4) == 0xff00ff00);
110
111 REPORTER_ASSERT(r, bm.getColor(0, 6) == 0xffff0000);
112 REPORTER_ASSERT(r, bm.getColor(1, 6) == 0xffffff00);
113 REPORTER_ASSERT(r, bm.getColor(2, 6) == 0xff00ffff);
114
115 REPORTER_ASSERT(r, bm.getColor(0, 8) == 0xffffffff);
116 REPORTER_ASSERT(r, bm.getColor(1, 8) == 0xffff00ff);
117 REPORTER_ASSERT(r, bm.getColor(2, 8) == 0xff0000ff);
118 }
119 }
120
test_gif_data_short(skiatest::Reporter * r,void * data,size_t size)121 static void test_gif_data_short(skiatest::Reporter* r,
122 void* data,
123 size_t size) {
124 SkBitmap bm;
125 bool imageDecodeSuccess = SkImageDecoder::DecodeMemory(
126 data, size, &bm);
127 REPORTER_ASSERT(r, imageDecodeSuccess);
128 REPORTER_ASSERT(r, bm.width() == 3);
129 REPORTER_ASSERT(r, bm.height() == 3);
130 REPORTER_ASSERT(r, !(bm.empty()));
131 if (!(bm.empty())) {
132 REPORTER_ASSERT(r, bm.getColor(0, 0) == 0xffff0000);
133 REPORTER_ASSERT(r, bm.getColor(1, 0) == 0xffffff00);
134 REPORTER_ASSERT(r, bm.getColor(2, 0) == 0xff00ffff);
135 REPORTER_ASSERT(r, bm.getColor(0, 1) == 0xff808080);
136 REPORTER_ASSERT(r, bm.getColor(1, 1) == 0xff000000);
137 REPORTER_ASSERT(r, bm.getColor(2, 1) == 0xff00ff00);
138 }
139 }
140
141 /**
142 This test will test the ability of the SkImageDecoder to deal with
143 GIF files which have been mangled somehow. We want to display as
144 much of the GIF as possible.
145 */
DEF_TEST(Gif,reporter)146 DEF_TEST(Gif, reporter) {
147 // test perfectly good images.
148 test_gif_data(reporter, static_cast<void *>(gGIFData), sizeof(gGIFData));
149 test_interlaced_gif_data(reporter, static_cast<void *>(gInterlacedGIF),
150 sizeof(gInterlacedGIF));
151
152 unsigned char badData[sizeof(gGIFData)];
153
154 /* If you set the environment variable
155 skia_images_gif_suppressDecoderWarnings to 'false', you will
156 see warnings on stderr. This is a feature. */
157
158 memcpy(badData, gGIFData, sizeof(gGIFData));
159 badData[6] = 0x01; // image too wide
160 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
161 // "libgif warning [image too wide, expanding output to size]"
162
163 memcpy(badData, gGIFData, sizeof(gGIFData));
164 badData[8] = 0x01; // image too tall
165 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
166 // "libgif warning [image too tall, expanding output to size]"
167
168 memcpy(badData, gGIFData, sizeof(gGIFData));
169 badData[62] = 0x01; // image shifted right
170 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
171 // "libgif warning [shifting image left to fit]"
172
173 memcpy(badData, gGIFData, sizeof(gGIFData));
174 badData[64] = 0x01; // image shifted down
175 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
176 // "libgif warning [shifting image up to fit]"
177
178 memcpy(badData, gGIFData, sizeof(gGIFData));
179 badData[62] = 0xff; // image shifted left
180 badData[63] = 0xff; // 2's complement -1 short
181 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
182 // "libgif warning [shifting image left to fit]"
183
184 memcpy(badData, gGIFData, sizeof(gGIFData));
185 badData[64] = 0xff; // image shifted up
186 badData[65] = 0xff; // 2's complement -1 short
187 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
188 // "libgif warning [shifting image up to fit]"
189
190 test_gif_data_no_colormap(reporter, static_cast<void *>(gGIFDataNoColormap),
191 sizeof(gGIFDataNoColormap));
192 // "libgif warning [missing colormap]"
193
194 // test short Gif. 80 is missing a few bytes.
195 test_gif_data_short(reporter, static_cast<void *>(gGIFData), 80);
196 // "libgif warning [DGifGetLine]"
197
198 test_interlaced_gif_data(reporter, static_cast<void *>(gInterlacedGIF),
199 100); // 100 is missing a few bytes
200 // "libgif warning [interlace DGifGetLine]"
201 }
202
203 // Regression test for decoding a gif image with sampleSize of 4, which was
204 // previously crashing.
DEF_TEST(Gif_Sampled,r)205 DEF_TEST(Gif_Sampled, r) {
206 SkFILEStream fileStream(GetResourcePath("test640x479.gif").c_str());
207 REPORTER_ASSERT(r, fileStream.isValid());
208 if (!fileStream.isValid()) {
209 return;
210 }
211
212 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&fileStream));
213 REPORTER_ASSERT(r, decoder);
214 if (!decoder) {
215 return;
216 }
217 decoder->setSampleSize(4);
218 SkBitmap bm;
219 const SkImageDecoder::Result result = decoder->decode(&fileStream, &bm,
220 SkImageDecoder::kDecodePixels_Mode);
221 REPORTER_ASSERT(r, result == SkImageDecoder::kSuccess);
222 }
223
224 #endif // !(SK_BUILD_FOR_WIN32||SK_BUILD_FOR_IOS||SK_BUILD_FOR_MAC)
225