Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: tests/CodexTest.cpp

Issue 1332053002: Fill incomplete images in SkCodec parent class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Response to comments in Patch Set 5 Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "Resources.h" 8 #include "Resources.h"
9 #include "SkBitmap.h" 9 #include "SkBitmap.h"
10 #include "SkCodec.h" 10 #include "SkCodec.h"
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 rect.sort(); 72 rect.sort();
73 } while (rect.isEmpty()); 73 } while (rect.isEmpty());
74 return rect; 74 return rect;
75 } 75 }
76 76
77 static void check(skiatest::Reporter* r, 77 static void check(skiatest::Reporter* r,
78 const char path[], 78 const char path[],
79 SkISize size, 79 SkISize size,
80 bool supportsScanlineDecoding, 80 bool supportsScanlineDecoding,
81 bool supportsSubsetDecoding, 81 bool supportsSubsetDecoding,
82 bool supports565 = true) { 82 bool supports565 = true,
83 bool isIncomplete = false) {
83 SkAutoTDelete<SkStream> stream(resource(path)); 84 SkAutoTDelete<SkStream> stream(resource(path));
84 if (!stream) { 85 if (!stream) {
85 SkDebugf("Missing resource '%s'\n", path); 86 SkDebugf("Missing resource '%s'\n", path);
86 return; 87 return;
87 } 88 }
88 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach())); 89 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach()));
89 if (!codec) { 90 if (!codec) {
90 ERRORF(r, "Unable to decode '%s'", path); 91 ERRORF(r, "Unable to decode '%s'", path);
91 return; 92 return;
92 } 93 }
93 94
94 // This test is used primarily to verify rewinding works properly. Using kN 32 allows 95 // This test is used primarily to verify rewinding works properly. Using kN 32 allows
95 // us to test this without the added overhead of creating different bitmaps depending 96 // us to test this without the added overhead of creating different bitmaps depending
96 // on the color type (ex: building a color table for kIndex8). DM is where we test 97 // on the color type (ex: building a color table for kIndex8). DM is where we test
97 // decodes to all possible destination color types. 98 // decodes to all possible destination color types.
98 SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); 99 SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
99 REPORTER_ASSERT(r, info.dimensions() == size); 100 REPORTER_ASSERT(r, info.dimensions() == size);
100 101
101 SkBitmap bm; 102 SkBitmap bm;
102 bm.allocPixels(info); 103 bm.allocPixels(info);
103 SkAutoLockPixels autoLockPixels(bm); 104 SkAutoLockPixels autoLockPixels(bm);
104 SkCodec::Result result = 105 SkCodec::Result result =
105 codec->getPixels(info, bm.getPixels(), bm.rowBytes(), nullptr, nullptr, nullptr); 106 codec->getPixels(info, bm.getPixels(), bm.rowBytes(), nullptr, nullptr, nullptr);
106 REPORTER_ASSERT(r, result == SkCodec::kSuccess); 107 SkCodec::Result expected = isIncomplete ? SkCodec::kIncompleteInput : SkCode c::kSuccess;
108 REPORTER_ASSERT(r, result == expected);
107 109
108 SkMD5::Digest digest; 110 SkMD5::Digest digest;
109 md5(bm, &digest); 111 md5(bm, &digest);
110 112
111 { 113 {
112 // Test decoding to 565 114 // Test decoding to 565
113 SkImageInfo info565 = info.makeColorType(kRGB_565_SkColorType); 115 SkImageInfo info565 = info.makeColorType(kRGB_565_SkColorType);
114 SkCodec::Result expected = (supports565 && info.alphaType() == kOpaque_S kAlphaType) ? 116 SkCodec::Result expected565 = (supports565 && info.alphaType() == kOpaqu e_SkAlphaType) ?
115 SkCodec::kSuccess : SkCodec::kInvalidConversion; 117 SkCodec::kSuccess : SkCodec::kInvalidConversion;
116 test_info(r, codec, info565, expected, nullptr); 118 test_info(r, codec, info565, expected565, nullptr);
117 } 119 }
118 120
119 // Verify that re-decoding gives the same result. It is interesting to chec k this after 121 // Verify that re-decoding gives the same result. It is interesting to chec k this after
120 // a decode to 565, since choosing to decode to 565 may result in some of th e decode 122 // a decode to 565, since choosing to decode to 565 may result in some of th e decode
121 // options being modified. These options should return to their defaults on another 123 // options being modified. These options should return to their defaults on another
122 // decode to kN32, so the new digest should match the old digest. 124 // decode to kN32, so the new digest should match the old digest.
123 test_info(r, codec, info, SkCodec::kSuccess, &digest); 125 test_info(r, codec, info, expected, &digest);
124 126
125 { 127 {
126 // Check alpha type conversions 128 // Check alpha type conversions
127 if (info.alphaType() == kOpaque_SkAlphaType) { 129 if (info.alphaType() == kOpaque_SkAlphaType) {
128 test_info(r, codec, info.makeAlphaType(kUnpremul_SkAlphaType), 130 test_info(r, codec, info.makeAlphaType(kUnpremul_SkAlphaType),
129 SkCodec::kInvalidConversion, nullptr); 131 SkCodec::kInvalidConversion, nullptr);
130 test_info(r, codec, info.makeAlphaType(kPremul_SkAlphaType), 132 test_info(r, codec, info.makeAlphaType(kPremul_SkAlphaType),
131 SkCodec::kInvalidConversion, nullptr); 133 SkCodec::kInvalidConversion, nullptr);
132 } else { 134 } else {
133 // Decoding to opaque should fail 135 // Decoding to opaque should fail
134 test_info(r, codec, info.makeAlphaType(kOpaque_SkAlphaType), 136 test_info(r, codec, info.makeAlphaType(kOpaque_SkAlphaType),
135 SkCodec::kInvalidConversion, nullptr); 137 SkCodec::kInvalidConversion, nullptr);
136 SkAlphaType otherAt = info.alphaType(); 138 SkAlphaType otherAt = info.alphaType();
137 if (kPremul_SkAlphaType == otherAt) { 139 if (kPremul_SkAlphaType == otherAt) {
138 otherAt = kUnpremul_SkAlphaType; 140 otherAt = kUnpremul_SkAlphaType;
139 } else { 141 } else {
140 otherAt = kPremul_SkAlphaType; 142 otherAt = kPremul_SkAlphaType;
141 } 143 }
142 // The other non-opaque alpha type should always succeed, but not ma tch. 144 // The other non-opaque alpha type should always succeed, but not ma tch.
143 test_info(r, codec, info.makeAlphaType(otherAt), SkCodec::kSuccess, nullptr); 145 test_info(r, codec, info.makeAlphaType(otherAt), expected, nullptr);
144 } 146 }
145 } 147 }
146 148
147 // Scanline decoding follows. 149 // Scanline decoding follows.
148 150
149 // Need to call start() first. 151 // Need to call startScanlineDecode() first.
150 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) 152 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) == 0);
151 == SkCodec::kScanlineDecodingNotStarted); 153 REPORTER_ASSERT(r, codec->skipScanlines(1) == 0);
152 REPORTER_ASSERT(r, codec->skipScanlines(1)
153 == SkCodec::kScanlineDecodingNotStarted);
154 154
155 const SkCodec::Result startResult = codec->startScanlineDecode(info); 155 const SkCodec::Result startResult = codec->startScanlineDecode(info);
156 if (supportsScanlineDecoding) { 156 if (supportsScanlineDecoding) {
157 bm.eraseColor(SK_ColorYELLOW); 157 bm.eraseColor(SK_ColorYELLOW);
158 158
159 REPORTER_ASSERT(r, startResult == SkCodec::kSuccess); 159 REPORTER_ASSERT(r, startResult == SkCodec::kSuccess);
160 160
161 for (int y = 0; y < info.height(); y++) { 161 for (int y = 0; y < info.height(); y++) {
162 result = codec->getScanlines(bm.getAddr(0, y), 1, 0); 162 const uint32_t lines = codec->getScanlines(bm.getAddr(0, y), 1, 0);
163 REPORTER_ASSERT(r, result == SkCodec::kSuccess); 163 if (!isIncomplete) {
164 REPORTER_ASSERT(r, 1 == lines);
165 }
164 } 166 }
165 // verify that scanline decoding gives the same result. 167 // verify that scanline decoding gives the same result.
166 if (SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder()) { 168 if (SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder()) {
167 compare_to_good_digest(r, digest, bm); 169 compare_to_good_digest(r, digest, bm);
168 } 170 }
169 171
170 // Cannot continue to decode scanlines beyond the end 172 // Cannot continue to decode scanlines beyond the end
171 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) 173 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0)
172 == SkCodec::kInvalidParameters); 174 == 0);
173 175
174 // Interrupting a scanline decode with a full decode starts from 176 // Interrupting a scanline decode with a full decode starts from
175 // scratch 177 // scratch
176 REPORTER_ASSERT(r, codec->startScanlineDecode(info) == SkCodec::kSuccess ); 178 REPORTER_ASSERT(r, codec->startScanlineDecode(info) == SkCodec::kSuccess );
177 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) 179 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0)
178 == SkCodec::kSuccess); 180 == 1);
179 REPORTER_ASSERT(r, codec->getPixels(bm.info(), bm.getPixels(), bm.rowByt es()) 181 REPORTER_ASSERT(r, codec->getPixels(bm.info(), bm.getPixels(), bm.rowByt es())
180 == SkCodec::kSuccess); 182 == expected);
181 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) 183 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0)
182 == SkCodec::kScanlineDecodingNotStarted); 184 == 0);
183 REPORTER_ASSERT(r, codec->skipScanlines(1) 185 REPORTER_ASSERT(r, codec->skipScanlines(1)
184 == SkCodec::kScanlineDecodingNotStarted); 186 == 0);
185 } else { 187 } else {
186 REPORTER_ASSERT(r, startResult == SkCodec::kUnimplemented); 188 REPORTER_ASSERT(r, startResult == SkCodec::kUnimplemented);
187 } 189 }
188 190
189 // The rest of this function tests decoding subsets, and will decode an arbi trary number of 191 // The rest of this function tests decoding subsets, and will decode an arbi trary number of
190 // random subsets. 192 // random subsets.
191 // Do not attempt to decode subsets of an image of only once pixel, since th ere is no 193 // Do not attempt to decode subsets of an image of only once pixel, since th ere is no
192 // meaningful subset. 194 // meaningful subset.
193 if (size.width() * size.height() == 1) { 195 if (size.width() * size.height() == 1) {
194 return; 196 return;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false); 263 check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false);
262 check(r, "mandrill_16.png", SkISize::Make(16, 16), true, false); 264 check(r, "mandrill_16.png", SkISize::Make(16, 16), true, false);
263 check(r, "mandrill_256.png", SkISize::Make(256, 256), true, false); 265 check(r, "mandrill_256.png", SkISize::Make(256, 256), true, false);
264 check(r, "mandrill_32.png", SkISize::Make(32, 32), true, false); 266 check(r, "mandrill_32.png", SkISize::Make(32, 32), true, false);
265 check(r, "mandrill_512.png", SkISize::Make(512, 512), true, false); 267 check(r, "mandrill_512.png", SkISize::Make(512, 512), true, false);
266 check(r, "mandrill_64.png", SkISize::Make(64, 64), true, false); 268 check(r, "mandrill_64.png", SkISize::Make(64, 64), true, false);
267 check(r, "plane.png", SkISize::Make(250, 126), true, false); 269 check(r, "plane.png", SkISize::Make(250, 126), true, false);
268 check(r, "plane_interlaced.png", SkISize::Make(250, 126), true, false); 270 check(r, "plane_interlaced.png", SkISize::Make(250, 126), true, false);
269 check(r, "randPixels.png", SkISize::Make(8, 8), true, false); 271 check(r, "randPixels.png", SkISize::Make(8, 8), true, false);
270 check(r, "yellow_rose.png", SkISize::Make(400, 301), true, false); 272 check(r, "yellow_rose.png", SkISize::Make(400, 301), true, false);
273 // Incomplete Image
274 check(r, "incomplete_images/android.png", SkISize::Make(1024, 1218), true, f alse, true, true);
271 } 275 }
272 276
273 // Test interlaced PNG in stripes, similar to DM's kStripe_Mode 277 // Test interlaced PNG in stripes, similar to DM's kStripe_Mode
274 DEF_TEST(Codec_stripes, r) { 278 DEF_TEST(Codec_stripes, r) {
275 const char * path = "plane_interlaced.png"; 279 const char * path = "plane_interlaced.png";
276 SkAutoTDelete<SkStream> stream(resource(path)); 280 SkAutoTDelete<SkStream> stream(resource(path));
277 if (!stream) { 281 if (!stream) {
278 SkDebugf("Missing resource '%s'\n", path); 282 SkDebugf("Missing resource '%s'\n", path);
279 } 283 }
280 284
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 SkTDivMod(height, numStripes, &stripeHeight, &remainingLines); 318 SkTDivMod(height, numStripes, &stripeHeight, &remainingLines);
315 319
316 bm.eraseColor(SK_ColorYELLOW); 320 bm.eraseColor(SK_ColorYELLOW);
317 321
318 result = codec->startScanlineDecode(info); 322 result = codec->startScanlineDecode(info);
319 REPORTER_ASSERT(r, result == SkCodec::kSuccess); 323 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
320 324
321 // Odd stripes 325 // Odd stripes
322 for (int i = 1; i < numStripes; i += 2) { 326 for (int i = 1; i < numStripes; i += 2) {
323 // Skip the even stripes 327 // Skip the even stripes
324 result = codec->skipScanlines(stripeHeight); 328 bool skipResult = codec->skipScanlines(stripeHeight);
325 REPORTER_ASSERT(r, result == SkCodec::kSuccess); 329 REPORTER_ASSERT(r, skipResult);
326 330
327 result = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeig ht, 331 int linesDecoded = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight,
328 bm.rowBytes()); 332 bm.rowBytes());
329 REPORTER_ASSERT(r, result == SkCodec::kSuccess); 333 REPORTER_ASSERT(r, linesDecoded == stripeHeight);
330 } 334 }
331 335
332 // Even stripes 336 // Even stripes
333 result = codec->startScanlineDecode(info); 337 result = codec->startScanlineDecode(info);
334 REPORTER_ASSERT(r, result == SkCodec::kSuccess); 338 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
335 339
336 for (int i = 0; i < numStripes; i += 2) { 340 for (int i = 0; i < numStripes; i += 2) {
337 result = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeig ht, 341 int linesDecoded = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight,
338 bm.rowBytes()); 342 bm.rowBytes());
339 REPORTER_ASSERT(r, result == SkCodec::kSuccess); 343 REPORTER_ASSERT(r, linesDecoded == stripeHeight);
340 344
341 // Skip the odd stripes 345 // Skip the odd stripes
342 if (i + 1 < numStripes) { 346 if (i + 1 < numStripes) {
343 result = codec->skipScanlines(stripeHeight); 347 bool skipResult = codec->skipScanlines(stripeHeight);
344 REPORTER_ASSERT(r, result == SkCodec::kSuccess); 348 REPORTER_ASSERT(r, skipResult);
345 } 349 }
346 } 350 }
347 351
348 // Remainder at the end 352 // Remainder at the end
349 if (remainingLines > 0) { 353 if (remainingLines > 0) {
350 result = codec->startScanlineDecode(info); 354 result = codec->startScanlineDecode(info);
351 REPORTER_ASSERT(r, result == SkCodec::kSuccess); 355 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
352 356
353 result = codec->skipScanlines(height - remainingLines); 357 bool skipResult = codec->skipScanlines(height - remainingLines);
354 REPORTER_ASSERT(r, result == SkCodec::kSuccess); 358 REPORTER_ASSERT(r, skipResult);
355 359
356 result = codec->getScanlines(bm.getAddr(0, height - remainingLines), 360 int linesDecoded = codec->getScanlines(bm.getAddr(0, height - remainingL ines),
357 remainingLines, bm.rowBytes()); 361 remainingLines, bm.rowBytes());
358 REPORTER_ASSERT(r, result == SkCodec::kSuccess); 362 REPORTER_ASSERT(r, linesDecoded == remainingLines);
359 } 363 }
360 364
361 compare_to_good_digest(r, digest, bm); 365 compare_to_good_digest(r, digest, bm);
362 } 366 }
363 367
364 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_ t len) { 368 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_ t len) {
365 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals e)); 369 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals e));
366 // We should not have gotten a codec. Bots should catch us if we leaked anyt hing. 370 // We should not have gotten a codec. Bots should catch us if we leaked anyt hing.
367 REPORTER_ASSERT(r, !codec); 371 REPORTER_ASSERT(r, !codec);
368 } 372 }
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result); 503 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
500 result = decoder->startScanlineDecode( 504 result = decoder->startScanlineDecode(
501 decoder->getInfo().makeColorType(kIndex_8_SkColorType)); 505 decoder->getInfo().makeColorType(kIndex_8_SkColorType));
502 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result); 506 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
503 } 507 }
504 508
505 DEF_TEST(Codec_Params, r) { 509 DEF_TEST(Codec_Params, r) {
506 test_invalid_parameters(r, "index8.png"); 510 test_invalid_parameters(r, "index8.png");
507 test_invalid_parameters(r, "mandrill.wbmp"); 511 test_invalid_parameters(r, "mandrill.wbmp");
508 } 512 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698