OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 "Test.h" | 8 #include "Test.h" |
9 #include "TestClassDef.h" | 9 #include "TestClassDef.h" |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
11 #include "SkCanvas.h" | 11 #include "SkCanvas.h" |
12 #include "SkColor.h" | 12 #include "SkColor.h" |
13 #include "SkColorPriv.h" | 13 #include "SkColorPriv.h" |
14 #include "SkData.h" | 14 #include "SkData.h" |
15 #include "SkDecodingImageGenerator.h" | 15 #include "SkDecodingImageGenerator.h" |
| 16 #include "SkDiscardableMemoryPool.h" |
16 #include "SkForceLinking.h" | 17 #include "SkForceLinking.h" |
17 #include "SkGradientShader.h" | 18 #include "SkGradientShader.h" |
18 #include "SkImageDecoder.h" | 19 #include "SkImageDecoder.h" |
19 #include "SkImageEncoder.h" | 20 #include "SkImageEncoder.h" |
| 21 #include "SkImageGenerator.h" |
| 22 #include "SkImagePriv.h" |
20 #include "SkOSFile.h" | 23 #include "SkOSFile.h" |
21 #include "SkPoint.h" | 24 #include "SkPoint.h" |
22 #include "SkShader.h" | 25 #include "SkShader.h" |
23 #include "SkStream.h" | 26 #include "SkStream.h" |
24 #include "SkString.h" | 27 #include "SkString.h" |
25 | 28 |
26 __SK_FORCE_IMAGE_DECODER_LINKING; | 29 __SK_FORCE_IMAGE_DECODER_LINKING; |
27 | 30 |
28 /** | 31 /** |
29 * Interprets c as an unpremultiplied color, and returns the | 32 * Interprets c as an unpremultiplied color, and returns the |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 SkString resourcePath = skiatest::Test::GetResourcePath(); | 149 SkString resourcePath = skiatest::Test::GetResourcePath(); |
147 if (resourcePath.isEmpty()) { | 150 if (resourcePath.isEmpty()) { |
148 SkDebugf("Could not run unpremul test because resourcePath not specified
."); | 151 SkDebugf("Could not run unpremul test because resourcePath not specified
."); |
149 return; | 152 return; |
150 } | 153 } |
151 SkOSFile::Iter iter(resourcePath.c_str()); | 154 SkOSFile::Iter iter(resourcePath.c_str()); |
152 SkString basename; | 155 SkString basename; |
153 if (iter.next(&basename)) { | 156 if (iter.next(&basename)) { |
154 do { | 157 do { |
155 SkString filename = SkOSPath::SkPathJoin(resourcePath.c_str(), basen
ame.c_str()); | 158 SkString filename = SkOSPath::SkPathJoin(resourcePath.c_str(), basen
ame.c_str()); |
156 //SkDebugf("about to decode \"%s\"\n", filename.c_str()); | 159 // SkDebugf("about to decode \"%s\"\n", filename.c_str()); |
157 compare_unpremul(reporter, filename); | 160 compare_unpremul(reporter, filename); |
158 } while (iter.next(&basename)); | 161 } while (iter.next(&basename)); |
159 } else { | 162 } else { |
160 SkDebugf("Failed to find any files :(\n"); | 163 SkDebugf("Failed to find any files :(\n"); |
161 } | 164 } |
162 } | 165 } |
163 | 166 |
164 #ifdef SK_DEBUG | 167 #ifdef SK_DEBUG |
165 // Create a stream containing a bitmap encoded to Type type. | 168 // Create a stream containing a bitmap encoded to Type type. |
166 static SkMemoryStream* create_image_stream(SkImageEncoder::Type type) { | 169 static SkMemoryStream* create_image_stream(SkImageEncoder::Type type) { |
(...skipping 27 matching lines...) Expand all Loading... |
194 // Only runs in debug mode since we are testing for a crash. | 197 // Only runs in debug mode since we are testing for a crash. |
195 static void test_stream_life() { | 198 static void test_stream_life() { |
196 const SkImageEncoder::Type gTypes[] = { | 199 const SkImageEncoder::Type gTypes[] = { |
197 #ifdef SK_BUILD_FOR_ANDROID | 200 #ifdef SK_BUILD_FOR_ANDROID |
198 SkImageEncoder::kJPEG_Type, | 201 SkImageEncoder::kJPEG_Type, |
199 SkImageEncoder::kPNG_Type, | 202 SkImageEncoder::kPNG_Type, |
200 #endif | 203 #endif |
201 SkImageEncoder::kWEBP_Type, | 204 SkImageEncoder::kWEBP_Type, |
202 }; | 205 }; |
203 for (size_t i = 0; i < SK_ARRAY_COUNT(gTypes); ++i) { | 206 for (size_t i = 0; i < SK_ARRAY_COUNT(gTypes); ++i) { |
204 //SkDebugf("encoding to %i\n", i); | 207 // SkDebugf("encoding to %i\n", i); |
205 SkAutoTUnref<SkMemoryStream> stream(create_image_stream(gTypes[i])); | 208 SkAutoTUnref<SkMemoryStream> stream(create_image_stream(gTypes[i])); |
206 if (NULL == stream.get()) { | 209 if (NULL == stream.get()) { |
207 SkDebugf("no stream\n"); | 210 SkDebugf("no stream\n"); |
208 continue; | 211 continue; |
209 } | 212 } |
210 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream)); | 213 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream)); |
211 if (NULL == decoder.get()) { | 214 if (NULL == decoder.get()) { |
212 SkDebugf("no decoder\n"); | 215 SkDebugf("no decoder\n"); |
213 continue; | 216 continue; |
214 } | 217 } |
215 int width, height; | 218 int width, height; |
216 if (!decoder->buildTileIndex(stream.get(), &width, &height)) { | 219 if (!decoder->buildTileIndex(stream.get(), &width, &height)) { |
217 SkDebugf("could not build a tile index\n"); | 220 SkDebugf("could not build a tile index\n"); |
218 continue; | 221 continue; |
219 } | 222 } |
220 // Now unref the stream to make sure it survives | 223 // Now unref the stream to make sure it survives |
221 stream.reset(NULL); | 224 stream.reset(NULL); |
222 SkBitmap bm; | 225 SkBitmap bm; |
223 decoder->decodeSubset(&bm, SkIRect::MakeWH(width, height), | 226 decoder->decodeSubset(&bm, SkIRect::MakeWH(width, height), |
224 SkBitmap::kARGB_8888_Config); | 227 SkBitmap::kARGB_8888_Config); |
225 } | 228 } |
226 } | 229 } |
227 | 230 |
228 // Test inside SkScaledBitmapSampler.cpp | 231 // Test inside SkScaledBitmapSampler.cpp |
229 extern void test_row_proc_choice(); | 232 extern void test_row_proc_choice(); |
230 | 233 |
231 #endif // SK_DEBUG | 234 #endif // SK_DEBUG |
232 | 235 |
233 DEF_TEST(ImageDecoding, reporter) { | 236 DEF_TEST(ImageDecoding, reporter) { |
234 test_unpremul(reporter); | 237 test_unpremul(reporter); |
235 #ifdef SK_DEBUG | 238 #ifdef SK_DEBUG |
236 test_stream_life(); | 239 test_stream_life(); |
237 test_row_proc_choice(); | 240 test_row_proc_choice(); |
238 #endif | 241 #endif |
239 } | 242 } |
240 | 243 |
241 //////////////////////////////////////////////////////////////////////////////// | 244 //////////////////////////////////////////////////////////////////////////////// |
| 245 namespace { |
| 246 // expected output for 8x8 bitmap |
| 247 const int kExpectedWidth = 8; |
| 248 const int kExpectedHeight = 8; |
| 249 const SkColor kExpectedPixels[] = { |
| 250 0xffbba570, 0xff395f5d, 0xffe25c39, 0xff197666, |
| 251 0xff3cba27, 0xffdefcb0, 0xffc13874, 0xfffa0093, |
| 252 0xffbda60e, 0xffc01db6, 0xff2bd688, 0xff9362d4, |
| 253 0xffc641b2, 0xffa5cede, 0xff606eba, 0xff8f4bf3, |
| 254 0xff3bf742, 0xff8f02a8, 0xff5509df, 0xffc7027e, |
| 255 0xff24aa8a, 0xff886c96, 0xff625481, 0xff403689, |
| 256 0xffc52152, 0xff78ccd6, 0xffdcb4ab, 0xff09d27d, |
| 257 0xffca00f3, 0xff605d47, 0xff446fb2, 0xff576e46, |
| 258 0xff273df9, 0xffb41a83, 0xfff812c3, 0xffccab67, |
| 259 0xff034218, 0xff7db9a7, 0xff821048, 0xfffe4ab4, |
| 260 0xff6fac98, 0xff941d27, 0xff5fe411, 0xfffbb283, |
| 261 0xffd86e99, 0xff169162, 0xff71128c, 0xff39cab4, |
| 262 0xffa7fe63, 0xff4c956b, 0xffbc22e0, 0xffb272e4, |
| 263 0xff129f4a, 0xffe34513, 0xff3d3742, 0xffbd190a, |
| 264 0xffb07222, 0xff2e23f8, 0xfff089d9, 0xffb35738, |
| 265 0xffa86022, 0xff3340fe, 0xff95fe71, 0xff6a71df |
| 266 }; |
| 267 SK_COMPILE_ASSERT((kExpectedWidth * kExpectedHeight) |
| 268 == SK_ARRAY_COUNT(kExpectedPixels), array_size_mismatch); |
| 269 } // namespace |
242 | 270 |
243 DEF_TEST(WebP, reporter) { | 271 DEF_TEST(WebP, reporter) { |
244 const unsigned char encodedWebP[] = { | 272 const unsigned char encodedWebP[] = { |
245 0x52, 0x49, 0x46, 0x46, 0x2c, 0x01, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, | 273 0x52, 0x49, 0x46, 0x46, 0x2c, 0x01, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, |
246 0x56, 0x50, 0x38, 0x4c, 0x20, 0x01, 0x00, 0x00, 0x2f, 0x07, 0xc0, 0x01, | 274 0x56, 0x50, 0x38, 0x4c, 0x20, 0x01, 0x00, 0x00, 0x2f, 0x07, 0xc0, 0x01, |
247 0x00, 0xff, 0x01, 0x45, 0x03, 0x00, 0xe2, 0xd5, 0xae, 0x60, 0x2b, 0xad, | 275 0x00, 0xff, 0x01, 0x45, 0x03, 0x00, 0xe2, 0xd5, 0xae, 0x60, 0x2b, 0xad, |
248 0xd9, 0x68, 0x76, 0xb6, 0x8d, 0x6a, 0x1d, 0xc0, 0xe6, 0x19, 0xd6, 0x16, | 276 0xd9, 0x68, 0x76, 0xb6, 0x8d, 0x6a, 0x1d, 0xc0, 0xe6, 0x19, 0xd6, 0x16, |
249 0xb7, 0xb4, 0xef, 0xcf, 0xc3, 0x15, 0x6c, 0xb3, 0xbd, 0x77, 0x0d, 0x85, | 277 0xb7, 0xb4, 0xef, 0xcf, 0xc3, 0x15, 0x6c, 0xb3, 0xbd, 0x77, 0x0d, 0x85, |
250 0x6d, 0x1b, 0xa9, 0xb1, 0x2b, 0xdc, 0x3d, 0x83, 0xdb, 0x00, 0x00, 0xc8, | 278 0x6d, 0x1b, 0xa9, 0xb1, 0x2b, 0xdc, 0x3d, 0x83, 0xdb, 0x00, 0x00, 0xc8, |
251 0x26, 0xe5, 0x01, 0x99, 0x8a, 0xd5, 0xdd, 0xfc, 0x82, 0xcd, 0xcd, 0x9a, | 279 0x26, 0xe5, 0x01, 0x99, 0x8a, 0xd5, 0xdd, 0xfc, 0x82, 0xcd, 0xcd, 0x9a, |
(...skipping 10 matching lines...) Expand all Loading... |
262 0x03, 0x45, 0x29, 0xe0, 0xe2, 0x4a, 0xc3, 0xa2, 0xe8, 0xe0, 0x25, 0x12, | 290 0x03, 0x45, 0x29, 0xe0, 0xe2, 0x4a, 0xc3, 0xa2, 0xe8, 0xe0, 0x25, 0x12, |
263 0x74, 0xc6, 0xe8, 0xfb, 0x93, 0x4f, 0x9f, 0x5e, 0xc0, 0xa6, 0x91, 0x1b, | 291 0x74, 0xc6, 0xe8, 0xfb, 0x93, 0x4f, 0x9f, 0x5e, 0xc0, 0xa6, 0x91, 0x1b, |
264 0xa4, 0x24, 0x82, 0xc3, 0x61, 0x07, 0x4c, 0x49, 0x4f, 0x53, 0xae, 0x5f, | 292 0xa4, 0x24, 0x82, 0xc3, 0x61, 0x07, 0x4c, 0x49, 0x4f, 0x53, 0xae, 0x5f, |
265 0x5d, 0x39, 0x36, 0xc0, 0x5b, 0x57, 0x54, 0x60, 0x10, 0x00, 0x00, 0xd1, | 293 0x5d, 0x39, 0x36, 0xc0, 0x5b, 0x57, 0x54, 0x60, 0x10, 0x00, 0x00, 0xd1, |
266 0x68, 0xb6, 0x6d, 0xdb, 0x36, 0x22, 0xfa, 0x1f, 0x35, 0x75, 0x22, 0xec, | 294 0x68, 0xb6, 0x6d, 0xdb, 0x36, 0x22, 0xfa, 0x1f, 0x35, 0x75, 0x22, 0xec, |
267 0x31, 0xbc, 0x5d, 0x8f, 0x87, 0x53, 0xa2, 0x05, 0x8c, 0x2f, 0xcd, 0xa8, | 295 0x31, 0xbc, 0x5d, 0x8f, 0x87, 0x53, 0xa2, 0x05, 0x8c, 0x2f, 0xcd, 0xa8, |
268 0xa7, 0xf3, 0xa3, 0xbd, 0x83, 0x8b, 0x2a, 0xc8, 0x58, 0xf5, 0xac, 0x80, | 296 0xa7, 0xf3, 0xa3, 0xbd, 0x83, 0x8b, 0x2a, 0xc8, 0x58, 0xf5, 0xac, 0x80, |
269 0xe3, 0xfe, 0x66, 0xa4, 0x7c, 0x1b, 0x6c, 0xd1, 0xa9, 0xd8, 0x14, 0xd0, | 297 0xe3, 0xfe, 0x66, 0xa4, 0x7c, 0x1b, 0x6c, 0xd1, 0xa9, 0xd8, 0x14, 0xd0, |
270 0xc5, 0xb5, 0x39, 0x71, 0x97, 0x19, 0x19, 0x1b | 298 0xc5, 0xb5, 0x39, 0x71, 0x97, 0x19, 0x19, 0x1b |
271 }; | 299 }; |
272 const SkColor thePixels[] = { | |
273 0xffbba570, 0xff395f5d, 0xffe25c39, 0xff197666, | |
274 0xff3cba27, 0xffdefcb0, 0xffc13874, 0xfffa0093, | |
275 0xffbda60e, 0xffc01db6, 0xff2bd688, 0xff9362d4, | |
276 0xffc641b2, 0xffa5cede, 0xff606eba, 0xff8f4bf3, | |
277 0xff3bf742, 0xff8f02a8, 0xff5509df, 0xffc7027e, | |
278 0xff24aa8a, 0xff886c96, 0xff625481, 0xff403689, | |
279 0xffc52152, 0xff78ccd6, 0xffdcb4ab, 0xff09d27d, | |
280 0xffca00f3, 0xff605d47, 0xff446fb2, 0xff576e46, | |
281 0xff273df9, 0xffb41a83, 0xfff812c3, 0xffccab67, | |
282 0xff034218, 0xff7db9a7, 0xff821048, 0xfffe4ab4, | |
283 0xff6fac98, 0xff941d27, 0xff5fe411, 0xfffbb283, | |
284 0xffd86e99, 0xff169162, 0xff71128c, 0xff39cab4, | |
285 0xffa7fe63, 0xff4c956b, 0xffbc22e0, 0xffb272e4, | |
286 0xff129f4a, 0xffe34513, 0xff3d3742, 0xffbd190a, | |
287 0xffb07222, 0xff2e23f8, 0xfff089d9, 0xffb35738, | |
288 0xffa86022, 0xff3340fe, 0xff95fe71, 0xff6a71df | |
289 }; | |
290 SkAutoDataUnref encoded(SkData::NewWithCopy(encodedWebP, | 300 SkAutoDataUnref encoded(SkData::NewWithCopy(encodedWebP, |
291 sizeof(encodedWebP))); | 301 sizeof(encodedWebP))); |
292 SkBitmap bm; | 302 SkBitmap bm; |
293 bool success = SkDecodingImageGenerator::Install(encoded, &bm, NULL); | 303 |
| 304 bool success = SkInstallDiscardablePixelRef( |
| 305 SkDecodingImageGenerator::Create(encoded, |
| 306 SkDecodingImageGenerator::Options()), &bm, NULL); |
| 307 |
294 REPORTER_ASSERT(reporter, success); | 308 REPORTER_ASSERT(reporter, success); |
295 if (!success) { | 309 if (!success) { |
296 return; | 310 return; |
297 } | 311 } |
298 SkAutoLockPixels alp(bm); | 312 SkAutoLockPixels alp(bm); |
299 bool rightSize = SK_ARRAY_COUNT(thePixels) == bm.width() * bm.height(); | 313 |
| 314 bool rightSize = ((kExpectedWidth == bm.width()) |
| 315 && (kExpectedHeight == bm.height())); |
300 REPORTER_ASSERT(reporter, rightSize); | 316 REPORTER_ASSERT(reporter, rightSize); |
301 if (rightSize) { | 317 if (rightSize) { |
302 bool error = false; | 318 bool error = false; |
303 const SkColor* correctPixel = thePixels; | 319 const SkColor* correctPixel = kExpectedPixels; |
304 for (int y = 0; y < bm.height(); ++y) { | 320 for (int y = 0; y < bm.height(); ++y) { |
305 for (int x = 0; x < bm.width(); ++x) { | 321 for (int x = 0; x < bm.width(); ++x) { |
306 error |= (*correctPixel != bm.getColor(x, y)); | 322 error |= (*correctPixel != bm.getColor(x, y)); |
307 ++correctPixel; | 323 ++correctPixel; |
308 } | 324 } |
309 } | 325 } |
310 REPORTER_ASSERT(reporter, !error); | 326 REPORTER_ASSERT(reporter, !error); |
311 } | 327 } |
312 } | 328 } |
| 329 |
| 330 //////////////////////////////////////////////////////////////////////////////// |
| 331 |
| 332 // example of how Android will do this inside their BitmapFactory |
| 333 static SkPixelRef* install_pixel_ref(SkBitmap* bitmap, |
| 334 SkStreamRewindable* stream, |
| 335 int sampleSize, bool ditherImage) { |
| 336 SkASSERT(bitmap != NULL); |
| 337 SkASSERT(stream != NULL); |
| 338 SkASSERT(stream->rewind()); |
| 339 SkASSERT(stream->unique()); |
| 340 SkColorType colorType; |
| 341 if (!SkBitmapConfigToColorType(bitmap->config(), &colorType)) { |
| 342 return NULL; |
| 343 } |
| 344 SkDecodingImageGenerator::Options opts(sampleSize, ditherImage, colorType); |
| 345 SkAutoTDelete<SkImageGenerator> gen( |
| 346 SkDecodingImageGenerator::Create(stream, opts)); |
| 347 SkImageInfo info; |
| 348 if ((NULL == gen.get()) || !gen->getInfo(&info)) { |
| 349 return NULL; |
| 350 } |
| 351 SkDiscardableMemory::Factory* factory = NULL; |
| 352 if (info.getSafeSize(info.minRowBytes()) < (32 * 1024)) { |
| 353 // only use ashmem for large images, since mmaps come at a price |
| 354 factory = SkGetGlobalDiscardableMemoryPool(); |
| 355 } |
| 356 if (SkInstallDiscardablePixelRef(gen.detach(), bitmap, factory)) { |
| 357 return bitmap->pixelRef(); |
| 358 } |
| 359 return NULL; |
| 360 } |
| 361 /** |
| 362 * A test for the SkDecodingImageGenerator::Create and |
| 363 * SkInstallDiscardablePixelRef functions. |
| 364 */ |
| 365 DEF_TEST(ImprovedBitmapFactory, reporter) { |
| 366 SkString resourcePath = skiatest::Test::GetResourcePath(); |
| 367 SkString directory = SkOSPath::SkPathJoin(resourcePath.c_str(), "encoding"); |
| 368 SkString path = SkOSPath::SkPathJoin(directory.c_str(), "randPixels.png"); |
| 369 SkAutoTUnref<SkStreamRewindable> stream( |
| 370 SkStream::NewFromFile(path.c_str())); |
| 371 if (sk_exists(path.c_str())) { |
| 372 SkBitmap bm; |
| 373 SkAssertResult(bm.setConfig(SkBitmap::kARGB_8888_Config, 1, 1)); |
| 374 REPORTER_ASSERT(reporter, |
| 375 NULL != install_pixel_ref(&bm, stream.detach(), 1, true)); |
| 376 SkAutoLockPixels alp(bm); |
| 377 REPORTER_ASSERT(reporter, NULL != bm.getPixels()); |
| 378 } |
| 379 } |
| 380 |
| 381 |
| 382 //////////////////////////////////////////////////////////////////////////////// |
| 383 |
| 384 #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX) |
| 385 static inline bool check_rounding(int value, int dividend, int divisor) { |
| 386 // returns true if (dividend/divisor) rounds up OR down to value |
| 387 return (((divisor * value) > (dividend - divisor)) |
| 388 && ((divisor * value) < (dividend + divisor))); |
| 389 } |
| 390 #endif // SK_BUILD_FOR_ANDROID || SK_BUILD_FOR_UNIX |
| 391 |
| 392 |
| 393 #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) |
| 394 #define kBackwards_SkColorType kRGBA_8888_SkColorType |
| 395 #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) |
| 396 #define kBackwards_SkColorType kBGRA_8888_SkColorType |
| 397 #else |
| 398 #error "SK_*32_SHFIT values must correspond to BGRA or RGBA byte order" |
| 399 #endif |
| 400 |
| 401 static inline const char* SkColorType_to_string(SkColorType colorType) { |
| 402 switch(colorType) { |
| 403 case kAlpha_8_SkColorType: return "Alpha_8"; |
| 404 case kRGB_565_SkColorType: return "RGB_565"; |
| 405 case kARGB_4444_SkColorType: return "ARGB_4444"; |
| 406 case kPMColor_SkColorType: return "PMColor"; |
| 407 case kBackwards_SkColorType: return "Backwards"; |
| 408 case kIndex_8_SkColorType: return "Index_8"; |
| 409 default: return "ERROR"; |
| 410 } |
| 411 } |
| 412 |
| 413 /** |
| 414 * Given either a SkStream or a SkData, try to decode the encoded |
| 415 * image using the specified options and report errors. |
| 416 */ |
| 417 static void test_options(skiatest::Reporter* reporter, |
| 418 const SkDecodingImageGenerator::Options& opts, |
| 419 SkStreamRewindable* encodedStream, |
| 420 SkData* encodedData, |
| 421 bool useData, |
| 422 const SkString& path) { |
| 423 SkBitmap bm; |
| 424 bool success = false; |
| 425 if (useData) { |
| 426 if (NULL == encodedData) { |
| 427 return; |
| 428 } |
| 429 success = SkInstallDiscardablePixelRef( |
| 430 SkDecodingImageGenerator::Create(encodedData, opts), &bm, NULL); |
| 431 } else { |
| 432 if (NULL == encodedStream) { |
| 433 return; |
| 434 } |
| 435 success = SkInstallDiscardablePixelRef( |
| 436 SkDecodingImageGenerator::Create(encodedStream->duplicate(), opts), |
| 437 &bm, NULL); |
| 438 } |
| 439 if (!success) { |
| 440 if (opts.fUseRequestedColorType |
| 441 && (kARGB_4444_SkColorType == opts.fRequestedColorType)) { |
| 442 return; // Ignore known conversion inabilities. |
| 443 } |
| 444 // If we get here, it's a failure and we will need more |
| 445 // information about why it failed. |
| 446 reporter->reportFailed(SkStringPrintf( |
| 447 "Bounds decode failed " |
| 448 "[sampleSize=%d dither=%s colorType=%s %s] %s:%d", |
| 449 opts.fSampleSize, (opts.fDitherImage ? "yes" : "no"), |
| 450 (opts.fUseRequestedColorType |
| 451 ? SkColorType_to_string(opts.fRequestedColorType) : "(none)"), |
| 452 path.c_str(), __FILE__, __LINE__)); |
| 453 return; |
| 454 } |
| 455 #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX) |
| 456 // Android is the only system that use Skia's image decoders in |
| 457 // production. For now, we'll only verify that samplesize works |
| 458 // on systems where it already is known to work. |
| 459 REPORTER_ASSERT(reporter, check_rounding(bm.height(), kExpectedHeight, |
| 460 opts.fSampleSize)); |
| 461 REPORTER_ASSERT(reporter, check_rounding(bm.width(), kExpectedWidth, |
| 462 opts.fSampleSize)); |
| 463 #endif // SK_BUILD_FOR_ANDROID || SK_BUILD_FOR_UNIX |
| 464 SkAutoLockPixels alp(bm); |
| 465 if (bm.getPixels() == NULL) { |
| 466 reporter->reportFailed(SkStringPrintf( |
| 467 "Pixel decode failed " |
| 468 "[sampleSize=%d dither=%s colorType=%s %s] %s:%d", |
| 469 opts.fSampleSize, (opts.fDitherImage ? "yes" : "no"), |
| 470 (opts.fUseRequestedColorType |
| 471 ? SkColorType_to_string(opts.fRequestedColorType) : "(none)"), |
| 472 path.c_str(), __FILE__, __LINE__)); |
| 473 return; |
| 474 } |
| 475 |
| 476 SkBitmap::Config requestedConfig |
| 477 = SkColorTypeToBitmapConfig(opts.fRequestedColorType); |
| 478 REPORTER_ASSERT(reporter, |
| 479 (!opts.fUseRequestedColorType) |
| 480 || (bm.config() == requestedConfig)); |
| 481 |
| 482 // Condition under which we should check the decoding results: |
| 483 if ((SkBitmap::kARGB_8888_Config == bm.config()) |
| 484 && (!path.endsWith(".jpg")) // lossy |
| 485 && (opts.fSampleSize == 1)) { // scaled |
| 486 const SkColor* correctPixels = kExpectedPixels; |
| 487 SkASSERT(bm.height() == kExpectedHeight); |
| 488 SkASSERT(bm.width() == kExpectedWidth); |
| 489 int pixelErrors = 0; |
| 490 for (int y = 0; y < bm.height(); ++y) { |
| 491 for (int x = 0; x < bm.width(); ++x) { |
| 492 if (*correctPixels != bm.getColor(x, y)) { |
| 493 ++pixelErrors; |
| 494 } |
| 495 ++correctPixels; |
| 496 } |
| 497 } |
| 498 if (pixelErrors != 0) { |
| 499 reporter->reportFailed(SkStringPrintf( |
| 500 "Pixel-level mismatch (%d of %d) [sampleSize=%d " |
| 501 "dither=%s colorType=%s %s] %s:%d", |
| 502 pixelErrors, kExpectedHeight * kExpectedWidth, |
| 503 opts.fSampleSize, (opts.fDitherImage ? "yes" : "no"), |
| 504 (opts.fUseRequestedColorType |
| 505 ? SkColorType_to_string(opts.fRequestedColorType) |
| 506 : "(none)"), path.c_str(), __FILE__, __LINE__)); |
| 507 } |
| 508 } |
| 509 } |
| 510 |
| 511 /** |
| 512 * SkDecodingImageGenerator has an Options struct which lets the |
| 513 * client of the generator set sample size, dithering, and bitmap |
| 514 * config. This test loops through many possible options and tries |
| 515 * them on a set of 5 small encoded images (each in a different |
| 516 * format). We test both SkData and SkStreamRewindable decoding. |
| 517 */ |
| 518 DEF_TEST(ImageDecoderOptions, reporter) { |
| 519 const char* files[] = { |
| 520 "randPixels.bmp", |
| 521 "randPixels.jpg", |
| 522 "randPixels.png", |
| 523 "randPixels.webp", |
| 524 #if !defined(SK_BUILD_FOR_WIN) |
| 525 // TODO(halcanary): Find out why this fails sometimes. |
| 526 "randPixels.gif", |
| 527 #endif |
| 528 }; |
| 529 |
| 530 SkString resourceDir = skiatest::Test::GetResourcePath(); |
| 531 SkString directory = SkOSPath::SkPathJoin(resourceDir.c_str(), "encoding"); |
| 532 if (!sk_exists(directory.c_str())) { |
| 533 return; |
| 534 } |
| 535 |
| 536 int scaleList[] = {1, 2, 3, 4}; |
| 537 bool ditherList[] = {true, false}; |
| 538 SkColorType colorList[] = { |
| 539 kAlpha_8_SkColorType, |
| 540 kRGB_565_SkColorType, |
| 541 kARGB_4444_SkColorType, // Most decoders will fail on 4444. |
| 542 kPMColor_SkColorType |
| 543 // Note that indexed color is left out of the list. Lazy |
| 544 // decoding doesn't do indexed color. |
| 545 }; |
| 546 const bool useDataList[] = {true, false}; |
| 547 |
| 548 for (size_t fidx = 0; fidx < SK_ARRAY_COUNT(files); ++fidx) { |
| 549 SkString path = SkOSPath::SkPathJoin(directory.c_str(), files[fidx]); |
| 550 if (!sk_exists(path.c_str())) { |
| 551 continue; |
| 552 } |
| 553 |
| 554 SkAutoDataUnref encodedData(SkData::NewFromFileName(path.c_str())); |
| 555 REPORTER_ASSERT(reporter, encodedData.get() != NULL); |
| 556 SkAutoTUnref<SkStreamRewindable> encodedStream( |
| 557 SkStream::NewFromFile(path.c_str())); |
| 558 REPORTER_ASSERT(reporter, encodedStream.get() != NULL); |
| 559 |
| 560 for (size_t i = 0; i < SK_ARRAY_COUNT(scaleList); ++i) { |
| 561 for (size_t j = 0; j < SK_ARRAY_COUNT(ditherList); ++j) { |
| 562 for (size_t m = 0; m < SK_ARRAY_COUNT(useDataList); ++m) { |
| 563 for (size_t k = 0; k < SK_ARRAY_COUNT(colorList); ++k) { |
| 564 SkDecodingImageGenerator::Options opts(scaleList[i], |
| 565 ditherList[j], |
| 566 colorList[k]); |
| 567 test_options(reporter, opts, encodedStream, encodedData, |
| 568 useDataList[m], path); |
| 569 |
| 570 } |
| 571 SkDecodingImageGenerator::Options options(scaleList[i], |
| 572 ditherList[j]); |
| 573 test_options(reporter, options, encodedStream, encodedData, |
| 574 useDataList[m], path); |
| 575 } |
| 576 } |
| 577 } |
| 578 } |
| 579 } |
| 580 //////////////////////////////////////////////////////////////////////////////// |
| 581 |
OLD | NEW |