blob: 51cd85d1384250cf9aecf4406a1931124c897064 [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
msarett7f7ec202016-03-01 12:12:27 -08008#include "CodecPriv.h"
scroggo9d214292015-05-14 14:44:13 -07009#include "Resources.h"
msarett7f7ec202016-03-01 12:12:27 -080010#include "SkAndroidCodec.h"
halcanary@google.com29d4e632013-10-11 18:21:56 +000011#include "SkBitmap.h"
12#include "SkData.h"
halcanary@google.com29d4e632013-10-11 18:21:56 +000013#include "SkImage.h"
14#include "SkStream.h"
msarett7f7ec202016-03-01 12:12:27 -080015#include "SkTypes.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000016#include "Test.h"
halcanary@google.com29d4e632013-10-11 18:21:56 +000017
tfarina@chromium.org58674812014-01-21 23:39:22 +000018static 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
28static 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
34static 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};
halcanary@google.com29d4e632013-10-11 18:21:56 +000044
45static void test_gif_data_no_colormap(skiatest::Reporter* r,
tfarina@chromium.org58674812014-01-21 23:39:22 +000046 void* data,
47 size_t size) {
halcanary@google.com29d4e632013-10-11 18:21:56 +000048 SkBitmap bm;
msarett7f7ec202016-03-01 12:12:27 -080049 bool imageDecodeSuccess = decode_memory(data, size, &bm);
halcanary@google.com29d4e632013-10-11 18:21:56 +000050 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())) {
scroggo19b91532016-10-24 09:03:26 -070055 REPORTER_ASSERT(r, bm.getColor(0, 0) == 0x00000000);
halcanary@google.com29d4e632013-10-11 18:21:56 +000056 }
57}
58static void test_gif_data(skiatest::Reporter* r, void* data, size_t size) {
59 SkBitmap bm;
msarett7f7ec202016-03-01 12:12:27 -080060 bool imageDecodeSuccess = decode_memory(data, size, &bm);
halcanary@google.com29d4e632013-10-11 18:21:56 +000061 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}
msarett7f7ec202016-03-01 12:12:27 -080077static 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}
halcanary@google.com29d4e632013-10-11 18:21:56 +000086static void test_interlaced_gif_data(skiatest::Reporter* r,
87 void* data,
88 size_t size) {
89 SkBitmap bm;
msarett7f7ec202016-03-01 12:12:27 -080090 bool imageDecodeSuccess = decode_memory(data, size, &bm);
halcanary@google.com29d4e632013-10-11 18:21:56 +000091 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
118static void test_gif_data_short(skiatest::Reporter* r,
119 void* data,
120 size_t size) {
121 SkBitmap bm;
msarett7f7ec202016-03-01 12:12:27 -0800122 bool imageDecodeSuccess = decode_memory(data, size, &bm);
halcanary@google.com29d4e632013-10-11 18:21:56 +0000123 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/**
msarett7f7ec202016-03-01 12:12:27 -0800138 This test will test the ability of the SkCodec to deal with
halcanary@google.com29d4e632013-10-11 18:21:56 +0000139 GIF files which have been mangled somehow. We want to display as
140 much of the GIF as possible.
141*/
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000142DEF_TEST(Gif, reporter) {
halcanary@google.com29d4e632013-10-11 18:21:56 +0000143 // test perfectly good images.
tfarina@chromium.org58674812014-01-21 23:39:22 +0000144 test_gif_data(reporter, static_cast<void *>(gGIFData), sizeof(gGIFData));
145 test_interlaced_gif_data(reporter, static_cast<void *>(gInterlacedGIF),
146 sizeof(gInterlacedGIF));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000147
tfarina@chromium.org58674812014-01-21 23:39:22 +0000148 unsigned char badData[sizeof(gGIFData)];
halcanary@google.com29d4e632013-10-11 18:21:56 +0000149
tfarina@chromium.org58674812014-01-21 23:39:22 +0000150 memcpy(badData, gGIFData, sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000151 badData[6] = 0x01; // image too wide
tfarina@chromium.org58674812014-01-21 23:39:22 +0000152 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000153 // "libgif warning [image too wide, expanding output to size]"
154
tfarina@chromium.org58674812014-01-21 23:39:22 +0000155 memcpy(badData, gGIFData, sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000156 badData[8] = 0x01; // image too tall
tfarina@chromium.org58674812014-01-21 23:39:22 +0000157 test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000158 // "libgif warning [image too tall, expanding output to size]"
159
tfarina@chromium.org58674812014-01-21 23:39:22 +0000160 memcpy(badData, gGIFData, sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000161 badData[62] = 0x01; // image shifted right
msarett7f7ec202016-03-01 12:12:27 -0800162 test_gif_data_dims(reporter, static_cast<void *>(badData), sizeof(gGIFData), 4, 3);
halcanary@google.com29d4e632013-10-11 18:21:56 +0000163
tfarina@chromium.org58674812014-01-21 23:39:22 +0000164 memcpy(badData, gGIFData, sizeof(gGIFData));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000165 badData[64] = 0x01; // image shifted down
msarett7f7ec202016-03-01 12:12:27 -0800166 test_gif_data_dims(reporter, static_cast<void *>(badData), sizeof(gGIFData), 3, 4);
halcanary@google.com29d4e632013-10-11 18:21:56 +0000167
tfarina@chromium.org58674812014-01-21 23:39:22 +0000168 memcpy(badData, gGIFData, sizeof(gGIFData));
msarett7f7ec202016-03-01 12:12:27 -0800169 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);
halcanary@google.com29d4e632013-10-11 18:21:56 +0000172
tfarina@chromium.org58674812014-01-21 23:39:22 +0000173 memcpy(badData, gGIFData, sizeof(gGIFData));
msarett7f7ec202016-03-01 12:12:27 -0800174 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);
halcanary@google.com29d4e632013-10-11 18:21:56 +0000177
tfarina@chromium.org58674812014-01-21 23:39:22 +0000178 test_gif_data_no_colormap(reporter, static_cast<void *>(gGIFDataNoColormap),
179 sizeof(gGIFDataNoColormap));
halcanary@google.com29d4e632013-10-11 18:21:56 +0000180 // "libgif warning [missing colormap]"
181
182 // test short Gif. 80 is missing a few bytes.
tfarina@chromium.org58674812014-01-21 23:39:22 +0000183 test_gif_data_short(reporter, static_cast<void *>(gGIFData), 80);
halcanary@google.com29d4e632013-10-11 18:21:56 +0000184 // "libgif warning [DGifGetLine]"
185
tfarina@chromium.org58674812014-01-21 23:39:22 +0000186 test_interlaced_gif_data(reporter, static_cast<void *>(gInterlacedGIF),
halcanary@google.com29d4e632013-10-11 18:21:56 +0000187 100); // 100 is missing a few bytes
188 // "libgif warning [interlace DGifGetLine]"
189}
190
scroggo9d214292015-05-14 14:44:13 -0700191// Regression test for decoding a gif image with sampleSize of 4, which was
192// previously crashing.
193DEF_TEST(Gif_Sampled, r) {
msarett7f7ec202016-03-01 12:12:27 -0800194 SkAutoTDelete<SkFILEStream> stream(
195 new SkFILEStream(GetResourcePath("test640x479.gif").c_str()));
196 REPORTER_ASSERT(r, stream->isValid());
197 if (!stream->isValid()) {
scroggo9d214292015-05-14 14:44:13 -0700198 return;
199 }
200
mtklein18300a32016-03-16 13:53:35 -0700201 SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(stream.release()));
msarett7f7ec202016-03-01 12:12:27 -0800202 REPORTER_ASSERT(r, codec);
203 if (!codec) {
scroggo9d214292015-05-14 14:44:13 -0700204 return;
205 }
msarett7f7ec202016-03-01 12:12:27 -0800206
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
scroggo9d214292015-05-14 14:44:13 -0700224 SkBitmap bm;
msarett7f7ec202016-03-01 12:12:27 -0800225 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);
scroggo9d214292015-05-14 14:44:13 -0700229}