blob: 978e3745394dffe291ee662770e5fa903a531eee [file] [log] [blame]
halcanary@google.com29d4e632013-10-11 18:21:56 +00001/*
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
scroggo9d214292015-05-14 14:44:13 -07008#include "SkTypes.h"
9
halcanary@google.com29d4e632013-10-11 18:21:56 +000010// 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
scroggo9d214292015-05-14 14:44:13 -070016#include "Resources.h"
halcanary@google.com29d4e632013-10-11 18:21:56 +000017#include "SkBitmap.h"
18#include "SkData.h"
19#include "SkForceLinking.h"
halcanary@google.com29d4e632013-10-11 18:21:56 +000020#include "SkImage.h"
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +000021#include "SkImageDecoder.h"
halcanary@google.com29d4e632013-10-11 18:21:56 +000022#include "SkStream.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000023#include "Test.h"
halcanary@google.com29d4e632013-10-11 18:21:56 +000024
25__SK_FORCE_IMAGE_DECODER_LINKING;
26
tfarina@chromium.org58674812014-01-21 23:39:22 +000027static 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
37static 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
43static 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};
halcanary@google.com29d4e632013-10-11 18:21:56 +000053
54static void test_gif_data_no_colormap(skiatest::Reporter* r,
tfarina@chromium.org58674812014-01-21 23:39:22 +000055 void* data,
56 size_t size) {
halcanary@google.com29d4e632013-10-11 18:21:56 +000057 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}
68static 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}
88static 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
121static 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*/
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000146DEF_TEST(Gif, reporter) {
halcanary@google.com29d4e632013-10-11 18:21:56 +0000147 // test perfectly good images.
tfarina@chromium.org58674812014-01-21 23:39:22 +0000148 test_gif_data(reporter, static_cast<void *>(gGIFData), sizeof(gGIFData));
149 test_interlaced_gif_data(reporter, static_cast<void *>(gInterlacedGIF),
150 sizeof(gInterlacedGIF));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000151
tfarina@chromium.org58674812014-01-21 23:39:22 +0000152 unsigned char badData[sizeof(gGIFData)];
halcanary@google.com29d4e632013-10-11 18:21:56 +0000153
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
tfarina@chromium.org58674812014-01-21 23:39:22 +0000158 memcpy(badData, gGIFData, sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000159 badData[6] = 0x01; // image too wide
tfarina@chromium.org58674812014-01-21 23:39:22 +0000160 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000161 // "libgif warning [image too wide, expanding output to size]"
162
tfarina@chromium.org58674812014-01-21 23:39:22 +0000163 memcpy(badData, gGIFData, sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000164 badData[8] = 0x01; // image too tall
tfarina@chromium.org58674812014-01-21 23:39:22 +0000165 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000166 // "libgif warning [image too tall, expanding output to size]"
167
tfarina@chromium.org58674812014-01-21 23:39:22 +0000168 memcpy(badData, gGIFData, sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000169 badData[62] = 0x01; // image shifted right
tfarina@chromium.org58674812014-01-21 23:39:22 +0000170 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000171 // "libgif warning [shifting image left to fit]"
172
tfarina@chromium.org58674812014-01-21 23:39:22 +0000173 memcpy(badData, gGIFData, sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000174 badData[64] = 0x01; // image shifted down
tfarina@chromium.org58674812014-01-21 23:39:22 +0000175 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000176 // "libgif warning [shifting image up to fit]"
177
tfarina@chromium.org58674812014-01-21 23:39:22 +0000178 memcpy(badData, gGIFData, sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000179 badData[62] = 0xff; // image shifted left
180 badData[63] = 0xff; // 2's complement -1 short
tfarina@chromium.org58674812014-01-21 23:39:22 +0000181 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000182 // "libgif warning [shifting image left to fit]"
183
tfarina@chromium.org58674812014-01-21 23:39:22 +0000184 memcpy(badData, gGIFData, sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000185 badData[64] = 0xff; // image shifted up
186 badData[65] = 0xff; // 2's complement -1 short
tfarina@chromium.org58674812014-01-21 23:39:22 +0000187 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000188 // "libgif warning [shifting image up to fit]"
189
tfarina@chromium.org58674812014-01-21 23:39:22 +0000190 test_gif_data_no_colormap(reporter, static_cast<void *>(gGIFDataNoColormap),
191 sizeof(gGIFDataNoColormap));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000192 // "libgif warning [missing colormap]"
193
194 // test short Gif. 80 is missing a few bytes.
tfarina@chromium.org58674812014-01-21 23:39:22 +0000195 test_gif_data_short(reporter, static_cast<void *>(gGIFData), 80);
halcanary@google.com29d4e632013-10-11 18:21:56 +0000196 // "libgif warning [DGifGetLine]"
197
tfarina@chromium.org58674812014-01-21 23:39:22 +0000198 test_interlaced_gif_data(reporter, static_cast<void *>(gInterlacedGIF),
halcanary@google.com29d4e632013-10-11 18:21:56 +0000199 100); // 100 is missing a few bytes
200 // "libgif warning [interlace DGifGetLine]"
201}
202
scroggo9d214292015-05-14 14:44:13 -0700203// Regression test for decoding a gif image with sampleSize of 4, which was
204// previously crashing.
205DEF_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
halcanary@google.com29d4e632013-10-11 18:21:56 +0000224#endif // !(SK_BUILD_FOR_WIN32||SK_BUILD_FOR_IOS||SK_BUILD_FOR_MAC)