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