blob: 452ba85fc4f9c32fe41967b1c0795d84a5118f39 [file] [log] [blame]
scroggo8e6c7ad2016-09-16 08:20:38 -07001/*
2 * Copyright 2016 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
Ben Wagnerb607a8f2018-03-12 13:46:21 -04008#include "FakeStreams.h"
9#include "Resources.h"
scroggo8e6c7ad2016-09-16 08:20:38 -070010#include "SkBitmap.h"
11#include "SkCodec.h"
12#include "SkData.h"
13#include "SkImageInfo.h"
Mike Reedede7bac2017-07-23 15:30:02 -040014#include "SkMakeUnique.h"
Ben Wagnerb607a8f2018-03-12 13:46:21 -040015#include "SkRefCnt.h"
16#include "SkStream.h"
17#include "SkTypes.h"
Ben Wagner501c17c2018-03-12 20:04:31 +000018#include "Test.h"
Ben Wagner1a462bd2018-03-12 13:46:21 -040019
Ben Wagnerb607a8f2018-03-12 13:46:21 -040020#include <cstring>
21#include <memory>
22#include <utility>
23#include <vector>
24
scroggo8e6c7ad2016-09-16 08:20:38 -070025static SkImageInfo standardize_info(SkCodec* codec) {
26 SkImageInfo defaultInfo = codec->getInfo();
27 // Note: This drops the SkColorSpace, allowing the equality check between two
28 // different codecs created from the same file to have the same SkImageInfo.
29 return SkImageInfo::MakeN32Premul(defaultInfo.width(), defaultInfo.height());
30}
31
32static bool create_truth(sk_sp<SkData> data, SkBitmap* dst) {
Mike Reedede7bac2017-07-23 15:30:02 -040033 std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(std::move(data)));
scroggo8e6c7ad2016-09-16 08:20:38 -070034 if (!codec) {
35 return false;
36 }
37
Ben Wagner145dbcd2016-11-03 14:40:50 -040038 const SkImageInfo info = standardize_info(codec.get());
scroggo8e6c7ad2016-09-16 08:20:38 -070039 dst->allocPixels(info);
40 return SkCodec::kSuccess == codec->getPixels(info, dst->getPixels(), dst->rowBytes());
41}
42
scroggo19b91532016-10-24 09:03:26 -070043static void compare_bitmaps(skiatest::Reporter* r, const SkBitmap& bm1, const SkBitmap& bm2) {
44 const SkImageInfo& info = bm1.info();
45 if (info != bm2.info()) {
46 ERRORF(r, "Bitmaps have different image infos!");
47 return;
48 }
49 const size_t rowBytes = info.minRowBytes();
50 for (int i = 0; i < info.height(); i++) {
nagarajan.n0ec0bf02017-10-11 10:41:27 +053051 if (memcmp(bm1.getAddr(0, i), bm2.getAddr(0, i), rowBytes)) {
52 ERRORF(r, "Bitmaps have different pixels, starting on line %i!", i);
53 return;
54 }
scroggo19b91532016-10-24 09:03:26 -070055 }
56}
57
Leon Scroggins III4993b952016-12-08 11:54:04 -050058static void test_partial(skiatest::Reporter* r, const char* name, size_t minBytes = 0) {
Leon Scroggins IIIe4ba1052017-01-30 13:55:14 -050059 sk_sp<SkData> file = GetResourceAsData(name);
scroggo8e6c7ad2016-09-16 08:20:38 -070060 if (!file) {
61 SkDebugf("missing resource %s\n", name);
62 return;
63 }
64
65 SkBitmap truth;
66 if (!create_truth(file, &truth)) {
67 ERRORF(r, "Failed to decode %s\n", name);
68 return;
69 }
70
scroggo8e6c7ad2016-09-16 08:20:38 -070071 // Now decode part of the file
Leon Scroggins III4993b952016-12-08 11:54:04 -050072 HaltingStream* stream = new HaltingStream(file, SkTMax(file->size() / 2, minBytes));
scroggo8e6c7ad2016-09-16 08:20:38 -070073
74 // Note that we cheat and hold on to a pointer to stream, though it is owned by
75 // partialCodec.
Mike Reedede7bac2017-07-23 15:30:02 -040076 std::unique_ptr<SkCodec> partialCodec(SkCodec::MakeFromStream(std::unique_ptr<SkStream>(stream)));
scroggo8e6c7ad2016-09-16 08:20:38 -070077 if (!partialCodec) {
78 // Technically, this could be a small file where half the file is not
79 // enough.
80 ERRORF(r, "Failed to create codec for %s", name);
81 return;
82 }
83
Ben Wagner145dbcd2016-11-03 14:40:50 -040084 const SkImageInfo info = standardize_info(partialCodec.get());
scroggo8e6c7ad2016-09-16 08:20:38 -070085 SkASSERT(info == truth.info());
86 SkBitmap incremental;
87 incremental.allocPixels(info);
88
scroggo19b91532016-10-24 09:03:26 -070089 while (true) {
90 const SkCodec::Result startResult = partialCodec->startIncrementalDecode(info,
91 incremental.getPixels(), incremental.rowBytes());
92 if (startResult == SkCodec::kSuccess) {
93 break;
94 }
95
96 if (stream->isAllDataReceived()) {
97 ERRORF(r, "Failed to start incremental decode\n");
98 return;
99 }
100
101 // Append some data. The size is arbitrary, but deliberately different from
102 // the buffer size used by SkPngCodec.
103 stream->addNewData(1000);
scroggo8e6c7ad2016-09-16 08:20:38 -0700104 }
105
106 while (true) {
107 const SkCodec::Result result = partialCodec->incrementalDecode();
108
scroggo19b91532016-10-24 09:03:26 -0700109 if (result == SkCodec::kSuccess) {
scroggo8e6c7ad2016-09-16 08:20:38 -0700110 break;
111 }
112
scroggo8e6c7ad2016-09-16 08:20:38 -0700113 REPORTER_ASSERT(r, result == SkCodec::kIncompleteInput);
114
scroggo19b91532016-10-24 09:03:26 -0700115 if (stream->isAllDataReceived()) {
116 ERRORF(r, "Failed to completely decode %s", name);
117 return;
118 }
119
120 // Append some data. The size is arbitrary, but deliberately different from
121 // the buffer size used by SkPngCodec.
122 stream->addNewData(1000);
scroggo8e6c7ad2016-09-16 08:20:38 -0700123 }
124
125 // compare to original
scroggo19b91532016-10-24 09:03:26 -0700126 compare_bitmaps(r, truth, incremental);
scroggo8e6c7ad2016-09-16 08:20:38 -0700127}
128
129DEF_TEST(Codec_partial, r) {
Leon Scroggins III83239652017-04-21 13:47:12 -0400130#if 0
131 // FIXME (scroggo): SkPngCodec needs to use SkStreamBuffer in order to
132 // support incremental decoding.
Hal Canaryc465d132017-12-08 10:21:31 -0500133 test_partial(r, "images/plane.png");
134 test_partial(r, "images/plane_interlaced.png");
135 test_partial(r, "images/yellow_rose.png");
136 test_partial(r, "images/index8.png");
137 test_partial(r, "images/color_wheel.png");
138 test_partial(r, "images/mandrill_256.png");
139 test_partial(r, "images/mandrill_32.png");
140 test_partial(r, "images/arrow.png");
141 test_partial(r, "images/randPixels.png");
142 test_partial(r, "images/baby_tux.png");
Leon Scroggins III83239652017-04-21 13:47:12 -0400143#endif
Hal Canaryc465d132017-12-08 10:21:31 -0500144 test_partial(r, "images/box.gif");
145 test_partial(r, "images/randPixels.gif", 215);
146 test_partial(r, "images/color_wheel.gif");
scroggo19b91532016-10-24 09:03:26 -0700147}
148
Leon Scroggins IIIe4ba1052017-01-30 13:55:14 -0500149// Verify that when decoding an animated gif byte by byte we report the correct
150// fRequiredFrame as soon as getFrameInfo reports the frame.
151DEF_TEST(Codec_requiredFrame, r) {
Hal Canaryc465d132017-12-08 10:21:31 -0500152 auto path = "images/colorTables.gif";
Leon Scroggins IIIe4ba1052017-01-30 13:55:14 -0500153 sk_sp<SkData> file = GetResourceAsData(path);
154 if (!file) {
155 return;
156 }
157
Mike Reedede7bac2017-07-23 15:30:02 -0400158 std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(file));
Leon Scroggins IIIe4ba1052017-01-30 13:55:14 -0500159 if (!codec) {
160 ERRORF(r, "Failed to create codec from %s", path);
161 return;
162 }
163
164 auto frameInfo = codec->getFrameInfo();
165 if (frameInfo.size() <= 1) {
166 ERRORF(r, "Test is uninteresting with 0 or 1 frames");
167 return;
168 }
169
170 HaltingStream* stream(nullptr);
171 std::unique_ptr<SkCodec> partialCodec(nullptr);
172 for (size_t i = 0; !partialCodec; i++) {
173 if (file->size() == i) {
174 ERRORF(r, "Should have created a partial codec for %s", path);
175 return;
176 }
177 stream = new HaltingStream(file, i);
Mike Reedede7bac2017-07-23 15:30:02 -0400178 partialCodec = SkCodec::MakeFromStream(std::unique_ptr<SkStream>(stream));
Leon Scroggins IIIe4ba1052017-01-30 13:55:14 -0500179 }
180
181 std::vector<SkCodec::FrameInfo> partialInfo;
182 size_t frameToCompare = 0;
Nigel Taoafea9c32018-08-01 15:00:32 +1000183 while (true) {
Leon Scroggins IIIe4ba1052017-01-30 13:55:14 -0500184 partialInfo = partialCodec->getFrameInfo();
185 for (; frameToCompare < partialInfo.size(); frameToCompare++) {
186 REPORTER_ASSERT(r, partialInfo[frameToCompare].fRequiredFrame
187 == frameInfo[frameToCompare].fRequiredFrame);
188 }
189
190 if (frameToCompare == frameInfo.size()) {
191 break;
192 }
Nigel Taoafea9c32018-08-01 15:00:32 +1000193
194 if (stream->getLength() == file->size()) {
195 ERRORF(r, "Should have found all frames for %s", path);
196 return;
197 }
198 stream->addNewData(1);
Leon Scroggins IIIe4ba1052017-01-30 13:55:14 -0500199 }
200}
201
scroggo19b91532016-10-24 09:03:26 -0700202DEF_TEST(Codec_partialAnim, r) {
Hal Canaryc465d132017-12-08 10:21:31 -0500203 auto path = "images/test640x479.gif";
Leon Scroggins IIIe4ba1052017-01-30 13:55:14 -0500204 sk_sp<SkData> file = GetResourceAsData(path);
scroggo19b91532016-10-24 09:03:26 -0700205 if (!file) {
206 return;
207 }
208
209 // This stream will be owned by fullCodec, but we hang on to the pointer
210 // to determine frame offsets.
Mike Reedede7bac2017-07-23 15:30:02 -0400211 std::unique_ptr<SkCodec> fullCodec(SkCodec::MakeFromStream(skstd::make_unique<SkMemoryStream>(file)));
scroggo19b91532016-10-24 09:03:26 -0700212 const auto info = standardize_info(fullCodec.get());
213
214 // frameByteCounts stores the number of bytes to decode a particular frame.
215 // - [0] is the number of bytes for the header
216 // - frames[i] requires frameByteCounts[i+1] bytes to decode
Leon Scroggins III1f6af6b2017-06-12 16:41:09 -0400217 const std::vector<size_t> frameByteCounts = { 455, 69350, 1344, 1346, 1327 };
scroggo19b91532016-10-24 09:03:26 -0700218 std::vector<SkBitmap> frames;
scroggo19b91532016-10-24 09:03:26 -0700219 for (size_t i = 0; true; i++) {
scroggo19b91532016-10-24 09:03:26 -0700220 SkBitmap frame;
221 frame.allocPixels(info);
222
223 SkCodec::Options opts;
224 opts.fFrameIndex = i;
225 const SkCodec::Result result = fullCodec->getPixels(info, frame.getPixels(),
Leon Scroggins571b30f2017-07-11 17:35:31 +0000226 frame.rowBytes(), &opts);
scroggo19b91532016-10-24 09:03:26 -0700227
Leon Scroggins III3fc97d72016-12-09 16:39:33 -0500228 if (result == SkCodec::kIncompleteInput || result == SkCodec::kInvalidInput) {
scroggo19b91532016-10-24 09:03:26 -0700229 // We need to distinguish between a partial frame and no more frames.
230 // getFrameInfo lets us do this, since it tells the number of frames
231 // not considering whether they are complete.
232 // FIXME: Should we use a different Result?
233 if (fullCodec->getFrameInfo().size() > i) {
234 // This is a partial frame.
235 frames.push_back(frame);
236 }
237 break;
238 }
239
240 if (result != SkCodec::kSuccess) {
241 ERRORF(r, "Failed to decode frame %i from %s", i, path);
242 return;
243 }
244
245 frames.push_back(frame);
246 }
247
248 // Now decode frames partially, then completely, and compare to the original.
249 HaltingStream* haltingStream = new HaltingStream(file, frameByteCounts[0]);
Mike Reedede7bac2017-07-23 15:30:02 -0400250 std::unique_ptr<SkCodec> partialCodec(SkCodec::MakeFromStream(
251 std::unique_ptr<SkStream>(haltingStream)));
scroggo19b91532016-10-24 09:03:26 -0700252 if (!partialCodec) {
253 ERRORF(r, "Failed to create a partial codec from %s with %i bytes out of %i",
254 path, frameByteCounts[0], file->size());
255 return;
256 }
257
258 SkASSERT(frameByteCounts.size() > frames.size());
259 for (size_t i = 0; i < frames.size(); i++) {
260 const size_t fullFrameBytes = frameByteCounts[i + 1];
261 const size_t firstHalf = fullFrameBytes / 2;
262 const size_t secondHalf = fullFrameBytes - firstHalf;
263
264 haltingStream->addNewData(firstHalf);
Leon Scroggins III3639faa2016-12-08 11:38:58 -0500265 auto frameInfo = partialCodec->getFrameInfo();
266 REPORTER_ASSERT(r, frameInfo.size() == i + 1);
267 REPORTER_ASSERT(r, !frameInfo[i].fFullyReceived);
scroggo19b91532016-10-24 09:03:26 -0700268
269 SkBitmap frame;
270 frame.allocPixels(info);
271
272 SkCodec::Options opts;
273 opts.fFrameIndex = i;
274 SkCodec::Result result = partialCodec->startIncrementalDecode(info,
275 frame.getPixels(), frame.rowBytes(), &opts);
276 if (result != SkCodec::kSuccess) {
277 ERRORF(r, "Failed to start incremental decode for %s on frame %i",
278 path, i);
279 return;
280 }
281
282 result = partialCodec->incrementalDecode();
283 REPORTER_ASSERT(r, SkCodec::kIncompleteInput == result);
284
285 haltingStream->addNewData(secondHalf);
286 result = partialCodec->incrementalDecode();
287 REPORTER_ASSERT(r, SkCodec::kSuccess == result);
288
Leon Scroggins III3639faa2016-12-08 11:38:58 -0500289 frameInfo = partialCodec->getFrameInfo();
290 REPORTER_ASSERT(r, frameInfo.size() == i + 1);
291 REPORTER_ASSERT(r, frameInfo[i].fFullyReceived);
scroggo19b91532016-10-24 09:03:26 -0700292 compare_bitmaps(r, frames[i], frame);
293 }
scroggo8e6c7ad2016-09-16 08:20:38 -0700294}
295
296// Test that calling getPixels when an incremental decode has been
297// started (but not finished) makes the next call to incrementalDecode
298// require a call to startIncrementalDecode.
299static void test_interleaved(skiatest::Reporter* r, const char* name) {
Leon Scroggins IIIe4ba1052017-01-30 13:55:14 -0500300 sk_sp<SkData> file = GetResourceAsData(name);
scroggo19b91532016-10-24 09:03:26 -0700301 if (!file) {
302 return;
303 }
304 const size_t halfSize = file->size() / 2;
Mike Reedede7bac2017-07-23 15:30:02 -0400305 std::unique_ptr<SkCodec> partialCodec(SkCodec::MakeFromStream(
306 skstd::make_unique<HaltingStream>(std::move(file), halfSize)));
scroggo8e6c7ad2016-09-16 08:20:38 -0700307 if (!partialCodec) {
308 ERRORF(r, "Failed to create codec for %s", name);
309 return;
310 }
311
Ben Wagner145dbcd2016-11-03 14:40:50 -0400312 const SkImageInfo info = standardize_info(partialCodec.get());
scroggo8e6c7ad2016-09-16 08:20:38 -0700313 SkBitmap incremental;
314 incremental.allocPixels(info);
315
316 const SkCodec::Result startResult = partialCodec->startIncrementalDecode(info,
317 incremental.getPixels(), incremental.rowBytes());
318 if (startResult != SkCodec::kSuccess) {
319 ERRORF(r, "Failed to start incremental decode\n");
320 return;
321 }
322
323 SkCodec::Result result = partialCodec->incrementalDecode();
324 REPORTER_ASSERT(r, result == SkCodec::kIncompleteInput);
325
326 SkBitmap full;
327 full.allocPixels(info);
328 result = partialCodec->getPixels(info, full.getPixels(), full.rowBytes());
329 REPORTER_ASSERT(r, result == SkCodec::kIncompleteInput);
330
331 // Now incremental decode will fail
332 result = partialCodec->incrementalDecode();
333 REPORTER_ASSERT(r, result == SkCodec::kInvalidParameters);
334}
335
336DEF_TEST(Codec_rewind, r) {
Hal Canaryc465d132017-12-08 10:21:31 -0500337 test_interleaved(r, "images/plane.png");
338 test_interleaved(r, "images/plane_interlaced.png");
339 test_interleaved(r, "images/box.gif");
scroggo8e6c7ad2016-09-16 08:20:38 -0700340}
Leon Scroggins III3fc97d72016-12-09 16:39:33 -0500341
342// Modified version of the giflib logo, from
343// http://giflib.sourceforge.net/whatsinagif/bits_and_bytes.html
344// The global color map has been replaced with a local color map.
345static unsigned char gNoGlobalColorMap[] = {
346 // Header
347 0x47, 0x49, 0x46, 0x38, 0x39, 0x61,
348
349 // Logical screen descriptor
350 0x0A, 0x00, 0x0A, 0x00, 0x11, 0x00, 0x00,
351
352 // Image descriptor
353 0x2C, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x81,
354
355 // Local color table
356 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
357
358 // Image data
359 0x02, 0x16, 0x8C, 0x2D, 0x99, 0x87, 0x2A, 0x1C, 0xDC, 0x33, 0xA0, 0x02, 0x75,
360 0xEC, 0x95, 0xFA, 0xA8, 0xDE, 0x60, 0x8C, 0x04, 0x91, 0x4C, 0x01, 0x00,
361
362 // Trailer
363 0x3B,
364};
365
366// Test that a gif file truncated before its local color map behaves as expected.
367DEF_TEST(Codec_GifPreMap, r) {
368 sk_sp<SkData> data = SkData::MakeWithoutCopy(gNoGlobalColorMap, sizeof(gNoGlobalColorMap));
Mike Reedede7bac2017-07-23 15:30:02 -0400369 std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(data));
Leon Scroggins III3fc97d72016-12-09 16:39:33 -0500370 if (!codec) {
371 ERRORF(r, "failed to create codec");
372 return;
373 }
374
375 SkBitmap truth;
376 auto info = standardize_info(codec.get());
377 truth.allocPixels(info);
378
379 auto result = codec->getPixels(info, truth.getPixels(), truth.rowBytes());
380 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
381
382 // Truncate to 23 bytes, just before the color map. This should fail to decode.
Leon Scroggins IIIe93ec682018-10-26 09:25:51 -0400383 //
384 // See also Codec_GifTruncated2 in GifTest.cpp for this magic 23.
Mike Reedede7bac2017-07-23 15:30:02 -0400385 codec = SkCodec::MakeFromData(SkData::MakeWithoutCopy(gNoGlobalColorMap, 23));
Leon Scroggins III3fc97d72016-12-09 16:39:33 -0500386 REPORTER_ASSERT(r, codec);
387 if (codec) {
388 SkBitmap bm;
389 bm.allocPixels(info);
390 result = codec->getPixels(info, bm.getPixels(), bm.rowBytes());
Leon Scroggins IIIe93ec682018-10-26 09:25:51 -0400391
392 // See the comments in Codec_GifTruncated2.
393#ifdef SK_HAS_WUFFS_LIBRARY
394 REPORTER_ASSERT(r, result == SkCodec::kIncompleteInput);
395#else
Leon Scroggins III3fc97d72016-12-09 16:39:33 -0500396 REPORTER_ASSERT(r, result == SkCodec::kInvalidInput);
Leon Scroggins IIIe93ec682018-10-26 09:25:51 -0400397#endif
Leon Scroggins III3fc97d72016-12-09 16:39:33 -0500398 }
399
400 // Again, truncate to 23 bytes, this time for an incremental decode. We
401 // cannot start an incremental decode until we have more data. If we did,
402 // we would be using the wrong color table.
403 HaltingStream* stream = new HaltingStream(data, 23);
Mike Reedede7bac2017-07-23 15:30:02 -0400404 codec = SkCodec::MakeFromStream(std::unique_ptr<SkStream>(stream));
Leon Scroggins III3fc97d72016-12-09 16:39:33 -0500405 REPORTER_ASSERT(r, codec);
406 if (codec) {
407 SkBitmap bm;
408 bm.allocPixels(info);
409 result = codec->startIncrementalDecode(info, bm.getPixels(), bm.rowBytes());
Leon Scroggins IIIe93ec682018-10-26 09:25:51 -0400410
411 // See the comments in Codec_GifTruncated2.
412#ifdef SK_HAS_WUFFS_LIBRARY
413 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
414
415 // Note that this is incrementalDecode, not startIncrementalDecode.
416 result = codec->incrementalDecode();
Leon Scroggins III3fc97d72016-12-09 16:39:33 -0500417 REPORTER_ASSERT(r, result == SkCodec::kIncompleteInput);
418
419 stream->addNewData(data->size());
Leon Scroggins IIIe93ec682018-10-26 09:25:51 -0400420#else
421 REPORTER_ASSERT(r, result == SkCodec::kIncompleteInput);
422
423 // Note that this is startIncrementalDecode, not incrementalDecode.
424 stream->addNewData(data->size());
Leon Scroggins III3fc97d72016-12-09 16:39:33 -0500425 result = codec->startIncrementalDecode(info, bm.getPixels(), bm.rowBytes());
426 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
Leon Scroggins IIIe93ec682018-10-26 09:25:51 -0400427#endif
Leon Scroggins III3fc97d72016-12-09 16:39:33 -0500428
429 result = codec->incrementalDecode();
430 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
431 compare_bitmaps(r, truth, bm);
432 }
433}
Leon Scroggins IIIb6446502017-04-24 09:32:50 -0400434
435DEF_TEST(Codec_emptyIDAT, r) {
Hal Canaryc465d132017-12-08 10:21:31 -0500436 const char* name = "images/baby_tux.png";
Leon Scroggins IIIb6446502017-04-24 09:32:50 -0400437 sk_sp<SkData> file = GetResourceAsData(name);
438 if (!file) {
Leon Scroggins IIIb6446502017-04-24 09:32:50 -0400439 return;
440 }
441
442 // Truncate to the beginning of the IDAT, immediately after the IDAT tag.
443 file = SkData::MakeSubset(file.get(), 0, 80);
444
Mike Reedede7bac2017-07-23 15:30:02 -0400445 std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(std::move(file)));
Leon Scroggins IIIb6446502017-04-24 09:32:50 -0400446 if (!codec) {
447 ERRORF(r, "Failed to create a codec for %s", name);
448 return;
449 }
450
451 SkBitmap bm;
452 const auto info = standardize_info(codec.get());
453 bm.allocPixels(info);
454
455 const auto result = codec->getPixels(info, bm.getPixels(), bm.rowBytes());
456 REPORTER_ASSERT(r, SkCodec::kIncompleteInput == result);
457}
Leon Scroggins III588fb042017-07-14 16:32:31 -0400458
459DEF_TEST(Codec_incomplete, r) {
Hal Canaryc465d132017-12-08 10:21:31 -0500460 for (const char* name : { "images/baby_tux.png",
461 "images/baby_tux.webp",
462 "images/CMYK.jpg",
463 "images/color_wheel.gif",
464 "images/google_chrome.ico",
465 "images/rle.bmp",
466 "images/mandrill.wbmp",
Leon Scroggins III588fb042017-07-14 16:32:31 -0400467 }) {
468 sk_sp<SkData> file = GetResourceAsData(name);
Bruce Wang61f36d32018-05-29 17:29:24 -0400469 if (!file) {
Leon Scroggins III588fb042017-07-14 16:32:31 -0400470 continue;
471 }
472
473 for (size_t len = 14; len <= file->size(); len += 5) {
474 SkCodec::Result result;
Mike Reedede7bac2017-07-23 15:30:02 -0400475 std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(
476 skstd::make_unique<SkMemoryStream>(file->data(), len), &result));
Leon Scroggins III588fb042017-07-14 16:32:31 -0400477 if (codec) {
478 if (result != SkCodec::kSuccess) {
479 ERRORF(r, "Created an SkCodec for %s with %lu bytes, but "
480 "reported an error %i", name, len, result);
481 }
482 break;
483 }
484
485 if (SkCodec::kIncompleteInput != result) {
486 ERRORF(r, "Reported error %i for %s with %lu bytes",
487 result, name, len);
488 break;
489 }
490 }
491 }
492}