OLD | NEW |
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 "SkAndroidCodec.h" | 9 #include "SkAndroidCodec.h" |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
11 #include "SkCodec.h" | 11 #include "SkCodec.h" |
12 #include "SkCodecImageGenerator.h" | 12 #include "SkCodecImageGenerator.h" |
13 #include "SkData.h" | 13 #include "SkData.h" |
14 #include "SkImageEncoder.h" | 14 #include "SkImageEncoder.h" |
15 #include "SkFrontBufferedStream.h" | 15 #include "SkFrontBufferedStream.h" |
16 #include "SkMD5.h" | 16 #include "SkMD5.h" |
17 #include "SkRandom.h" | 17 #include "SkRandom.h" |
18 #include "SkStream.h" | 18 #include "SkStream.h" |
19 #include "SkStreamPriv.h" | 19 #include "SkStreamPriv.h" |
20 #include "SkPngChunkReader.h" | 20 #include "SkPngChunkReader.h" |
21 #include "Test.h" | 21 #include "Test.h" |
22 | 22 |
23 #include "png.h" | 23 #include "png.h" |
24 | 24 |
| 25 static SkStreamAsset* resource(const char path[]) { |
| 26 SkString fullPath = GetResourcePath(path); |
| 27 return SkStream::NewFromFile(fullPath.c_str()); |
| 28 } |
| 29 |
25 static void md5(const SkBitmap& bm, SkMD5::Digest* digest) { | 30 static void md5(const SkBitmap& bm, SkMD5::Digest* digest) { |
26 SkAutoLockPixels autoLockPixels(bm); | 31 SkAutoLockPixels autoLockPixels(bm); |
27 SkASSERT(bm.getPixels()); | 32 SkASSERT(bm.getPixels()); |
28 SkMD5 md5; | 33 SkMD5 md5; |
29 size_t rowLen = bm.info().bytesPerPixel() * bm.width(); | 34 size_t rowLen = bm.info().bytesPerPixel() * bm.width(); |
30 for (int y = 0; y < bm.height(); ++y) { | 35 for (int y = 0; y < bm.height(); ++y) { |
31 md5.write(bm.getAddr(0, y), rowLen); | 36 md5.write(bm.getAddr(0, y), rowLen); |
32 } | 37 } |
33 md5.finish(*digest); | 38 md5.finish(*digest); |
34 } | 39 } |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 return false; | 192 return false; |
188 } | 193 } |
189 | 194 |
190 static void check(skiatest::Reporter* r, | 195 static void check(skiatest::Reporter* r, |
191 const char path[], | 196 const char path[], |
192 SkISize size, | 197 SkISize size, |
193 bool supportsScanlineDecoding, | 198 bool supportsScanlineDecoding, |
194 bool supportsSubsetDecoding, | 199 bool supportsSubsetDecoding, |
195 bool supportsIncomplete = true) { | 200 bool supportsIncomplete = true) { |
196 | 201 |
197 SkAutoTDelete<SkStream> stream(GetResourceAsStream(path)); | 202 SkAutoTDelete<SkStream> stream(resource(path)); |
198 if (!stream) { | 203 if (!stream) { |
| 204 SkDebugf("Missing resource '%s'\n", path); |
199 return; | 205 return; |
200 } | 206 } |
201 | 207 |
202 SkAutoTDelete<SkCodec> codec(nullptr); | 208 SkAutoTDelete<SkCodec> codec(nullptr); |
203 bool isIncomplete = supportsIncomplete; | 209 bool isIncomplete = supportsIncomplete; |
204 if (isIncomplete) { | 210 if (isIncomplete) { |
205 size_t size = stream->getLength(); | 211 size_t size = stream->getLength(); |
206 sk_sp<SkData> data((SkData::MakeFromStream(stream, 2 * size / 3))); | 212 sk_sp<SkData> data((SkData::MakeFromStream(stream, 2 * size / 3))); |
207 codec.reset(SkCodec::NewFromData(data)); | 213 codec.reset(SkCodec::NewFromData(data)); |
208 } else { | 214 } else { |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTo
p)); | 322 REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTo
p)); |
317 } else { | 323 } else { |
318 // No subsets will work. | 324 // No subsets will work. |
319 REPORTER_ASSERT(r, result == SkCodec::kUnimplemented); | 325 REPORTER_ASSERT(r, result == SkCodec::kUnimplemented); |
320 } | 326 } |
321 } | 327 } |
322 | 328 |
323 // SkAndroidCodec tests | 329 // SkAndroidCodec tests |
324 if (supportsScanlineDecoding || supportsSubsetDecoding) { | 330 if (supportsScanlineDecoding || supportsSubsetDecoding) { |
325 | 331 |
326 SkAutoTDelete<SkStream> stream(GetResourceAsStream(path)); | 332 SkAutoTDelete<SkStream> stream(resource(path)); |
327 if (!stream) { | 333 if (!stream) { |
| 334 SkDebugf("Missing resource '%s'\n", path); |
328 return; | 335 return; |
329 } | 336 } |
330 | 337 |
331 SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr); | 338 SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr); |
332 if (isIncomplete) { | 339 if (isIncomplete) { |
333 size_t size = stream->getLength(); | 340 size_t size = stream->getLength(); |
334 sk_sp<SkData> data((SkData::MakeFromStream(stream, 2 * size / 3))); | 341 sk_sp<SkData> data((SkData::MakeFromStream(stream, 2 * size / 3))); |
335 androidCodec.reset(SkAndroidCodec::NewFromData(data)); | 342 androidCodec.reset(SkAndroidCodec::NewFromData(data)); |
336 } else { | 343 } else { |
337 androidCodec.reset(SkAndroidCodec::NewFromStream(stream.release())); | 344 androidCodec.reset(SkAndroidCodec::NewFromStream(stream.release())); |
338 } | 345 } |
339 if (!androidCodec) { | 346 if (!androidCodec) { |
340 ERRORF(r, "Unable to decode '%s'", path); | 347 ERRORF(r, "Unable to decode '%s'", path); |
341 return; | 348 return; |
342 } | 349 } |
343 | 350 |
344 SkBitmap bm; | 351 SkBitmap bm; |
345 SkMD5::Digest androidCodecDigest; | 352 SkMD5::Digest androidCodecDigest; |
346 test_codec(r, androidCodec.get(), bm, info, size, expectedResult, &andro
idCodecDigest, | 353 test_codec(r, androidCodec.get(), bm, info, size, expectedResult, &andro
idCodecDigest, |
347 &codecDigest); | 354 &codecDigest); |
348 } | 355 } |
349 | 356 |
350 if (!isIncomplete) { | 357 if (!isIncomplete) { |
351 // Test SkCodecImageGenerator | 358 // Test SkCodecImageGenerator |
352 SkAutoTDelete<SkStream> stream(GetResourceAsStream(path)); | 359 SkAutoTDelete<SkStream> stream(resource(path)); |
353 sk_sp<SkData> fullData(SkData::MakeFromStream(stream, stream->getLength(
))); | 360 sk_sp<SkData> fullData(SkData::MakeFromStream(stream, stream->getLength(
))); |
354 SkAutoTDelete<SkImageGenerator> gen( | 361 SkAutoTDelete<SkImageGenerator> gen( |
355 SkCodecImageGenerator::NewFromEncodedCodec(fullData.get())); | 362 SkCodecImageGenerator::NewFromEncodedCodec(fullData.get())); |
356 SkBitmap bm; | 363 SkBitmap bm; |
357 bm.allocPixels(info); | 364 bm.allocPixels(info); |
358 SkAutoLockPixels autoLockPixels(bm); | 365 SkAutoLockPixels autoLockPixels(bm); |
359 REPORTER_ASSERT(r, gen->getPixels(info, bm.getPixels(), bm.rowBytes())); | 366 REPORTER_ASSERT(r, gen->getPixels(info, bm.getPixels(), bm.rowBytes())); |
360 compare_to_good_digest(r, codecDigest, bm); | 367 compare_to_good_digest(r, codecDigest, bm); |
361 | 368 |
362 // Test using SkFrontBufferedStream, as Android does | 369 // Test using SkFrontBufferedStream, as Android does |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32)) | 442 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32)) |
436 check(r, "sample_1mp.dng", SkISize::Make(600, 338), false, false, false); | 443 check(r, "sample_1mp.dng", SkISize::Make(600, 338), false, false, false); |
437 check(r, "sample_1mp_rotated.dng", SkISize::Make(600, 338), false, false, fa
lse); | 444 check(r, "sample_1mp_rotated.dng", SkISize::Make(600, 338), false, false, fa
lse); |
438 check(r, "dng_with_preview.dng", SkISize::Make(600, 338), true, false, false
); | 445 check(r, "dng_with_preview.dng", SkISize::Make(600, 338), true, false, false
); |
439 #endif | 446 #endif |
440 } | 447 } |
441 | 448 |
442 // Test interlaced PNG in stripes, similar to DM's kStripe_Mode | 449 // Test interlaced PNG in stripes, similar to DM's kStripe_Mode |
443 DEF_TEST(Codec_stripes, r) { | 450 DEF_TEST(Codec_stripes, r) { |
444 const char * path = "plane_interlaced.png"; | 451 const char * path = "plane_interlaced.png"; |
445 SkAutoTDelete<SkStream> stream(GetResourceAsStream(path)); | 452 SkAutoTDelete<SkStream> stream(resource(path)); |
446 REPORTER_ASSERT(r, stream); | |
447 if (!stream) { | 453 if (!stream) { |
448 return; | 454 SkDebugf("Missing resource '%s'\n", path); |
449 } | 455 } |
450 | 456 |
451 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release())); | 457 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release())); |
452 REPORTER_ASSERT(r, codec); | 458 REPORTER_ASSERT(r, codec); |
453 | 459 |
454 if (!codec) { | 460 if (!codec) { |
455 return; | 461 return; |
456 } | 462 } |
457 | 463 |
458 switch (codec->getScanlineOrder()) { | 464 switch (codec->getScanlineOrder()) { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 // crash. | 575 // crash. |
570 SkCodec* codec = SkCodec::NewFromStream(nullptr); | 576 SkCodec* codec = SkCodec::NewFromStream(nullptr); |
571 REPORTER_ASSERT(r, !codec); | 577 REPORTER_ASSERT(r, !codec); |
572 | 578 |
573 SkAndroidCodec* androidCodec = SkAndroidCodec::NewFromStream(nullptr); | 579 SkAndroidCodec* androidCodec = SkAndroidCodec::NewFromStream(nullptr); |
574 REPORTER_ASSERT(r, !androidCodec); | 580 REPORTER_ASSERT(r, !androidCodec); |
575 } | 581 } |
576 | 582 |
577 static void test_dimensions(skiatest::Reporter* r, const char path[]) { | 583 static void test_dimensions(skiatest::Reporter* r, const char path[]) { |
578 // Create the codec from the resource file | 584 // Create the codec from the resource file |
579 SkAutoTDelete<SkStream> stream(GetResourceAsStream(path)); | 585 SkAutoTDelete<SkStream> stream(resource(path)); |
580 if (!stream) { | 586 if (!stream) { |
| 587 SkDebugf("Missing resource '%s'\n", path); |
581 return; | 588 return; |
582 } | 589 } |
583 SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(stream.rel
ease())); | 590 SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(stream.rel
ease())); |
584 if (!codec) { | 591 if (!codec) { |
585 ERRORF(r, "Unable to create codec '%s'", path); | 592 ERRORF(r, "Unable to create codec '%s'", path); |
586 return; | 593 return; |
587 } | 594 } |
588 | 595 |
589 // Check that the decode is successful for a variety of scales | 596 // Check that the decode is successful for a variety of scales |
590 for (int sampleSize = 1; sampleSize < 32; sampleSize++) { | 597 for (int sampleSize = 1; sampleSize < 32; sampleSize++) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 // RAW | 640 // RAW |
634 // Disable RAW tests for Win32. | 641 // Disable RAW tests for Win32. |
635 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32)) | 642 #if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32)) |
636 test_dimensions(r, "sample_1mp.dng"); | 643 test_dimensions(r, "sample_1mp.dng"); |
637 test_dimensions(r, "sample_1mp_rotated.dng"); | 644 test_dimensions(r, "sample_1mp_rotated.dng"); |
638 test_dimensions(r, "dng_with_preview.dng"); | 645 test_dimensions(r, "dng_with_preview.dng"); |
639 #endif | 646 #endif |
640 } | 647 } |
641 | 648 |
642 static void test_invalid(skiatest::Reporter* r, const char path[]) { | 649 static void test_invalid(skiatest::Reporter* r, const char path[]) { |
643 SkAutoTDelete<SkStream> stream(GetResourceAsStream(path)); | 650 SkAutoTDelete<SkStream> stream(resource(path)); |
644 if (!stream) { | 651 if (!stream) { |
| 652 SkDebugf("Missing resource '%s'\n", path); |
645 return; | 653 return; |
646 } | 654 } |
647 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release())); | 655 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release())); |
648 REPORTER_ASSERT(r, nullptr == codec); | 656 REPORTER_ASSERT(r, nullptr == codec); |
649 } | 657 } |
650 | 658 |
651 DEF_TEST(Codec_Empty, r) { | 659 DEF_TEST(Codec_Empty, r) { |
652 // Test images that should not be able to create a codec | 660 // Test images that should not be able to create a codec |
653 test_invalid(r, "empty_images/zero-dims.gif"); | 661 test_invalid(r, "empty_images/zero-dims.gif"); |
654 test_invalid(r, "empty_images/zero-embedded.ico"); | 662 test_invalid(r, "empty_images/zero-embedded.ico"); |
655 test_invalid(r, "empty_images/zero-width.bmp"); | 663 test_invalid(r, "empty_images/zero-width.bmp"); |
656 test_invalid(r, "empty_images/zero-height.bmp"); | 664 test_invalid(r, "empty_images/zero-height.bmp"); |
657 test_invalid(r, "empty_images/zero-width.jpg"); | 665 test_invalid(r, "empty_images/zero-width.jpg"); |
658 test_invalid(r, "empty_images/zero-height.jpg"); | 666 test_invalid(r, "empty_images/zero-height.jpg"); |
659 test_invalid(r, "empty_images/zero-width.png"); | 667 test_invalid(r, "empty_images/zero-width.png"); |
660 test_invalid(r, "empty_images/zero-height.png"); | 668 test_invalid(r, "empty_images/zero-height.png"); |
661 test_invalid(r, "empty_images/zero-width.wbmp"); | 669 test_invalid(r, "empty_images/zero-width.wbmp"); |
662 test_invalid(r, "empty_images/zero-height.wbmp"); | 670 test_invalid(r, "empty_images/zero-height.wbmp"); |
663 // This image is an ico with an embedded mask-bmp. This is illegal. | 671 // This image is an ico with an embedded mask-bmp. This is illegal. |
664 test_invalid(r, "invalid_images/mask-bmp-ico.ico"); | 672 test_invalid(r, "invalid_images/mask-bmp-ico.ico"); |
665 } | 673 } |
666 | 674 |
667 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) { | 675 static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) { |
668 SkAutoTDelete<SkStream> stream(GetResourceAsStream(path)); | 676 SkAutoTDelete<SkStream> stream(resource(path)); |
669 if (!stream) { | 677 if (!stream) { |
| 678 SkDebugf("Missing resource '%s'\n", path); |
670 return; | 679 return; |
671 } | 680 } |
672 SkAutoTDelete<SkCodec> decoder(SkCodec::NewFromStream(stream.release())); | 681 SkAutoTDelete<SkCodec> decoder(SkCodec::NewFromStream(stream.release())); |
673 | 682 |
674 // This should return kSuccess because kIndex8 is supported. | 683 // This should return kSuccess because kIndex8 is supported. |
675 SkPMColor colorStorage[256]; | 684 SkPMColor colorStorage[256]; |
676 int colorCount; | 685 int colorCount; |
677 SkCodec::Result result = decoder->startScanlineDecode( | 686 SkCodec::Result result = decoder->startScanlineDecode( |
678 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, colorSt
orage, &colorCount); | 687 decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, colorSt
orage, &colorCount); |
679 REPORTER_ASSERT(r, SkCodec::kSuccess == result); | 688 REPORTER_ASSERT(r, SkCodec::kSuccess == result); |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
949 | 958 |
950 test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); | 959 test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); |
951 } | 960 } |
952 | 961 |
953 // SkCodec's wbmp decoder was initially unnecessarily restrictive. | 962 // SkCodec's wbmp decoder was initially unnecessarily restrictive. |
954 // It required the second byte to be zero. The wbmp specification allows | 963 // It required the second byte to be zero. The wbmp specification allows |
955 // a couple of bits to be 1 (so long as they do not overlap with 0x9F). | 964 // a couple of bits to be 1 (so long as they do not overlap with 0x9F). |
956 // Test that SkCodec now supports an image with these bits set. | 965 // Test that SkCodec now supports an image with these bits set. |
957 DEF_TEST(Codec_wbmp, r) { | 966 DEF_TEST(Codec_wbmp, r) { |
958 const char* path = "mandrill.wbmp"; | 967 const char* path = "mandrill.wbmp"; |
959 SkAutoTDelete<SkStream> stream(GetResourceAsStream(path)); | 968 SkAutoTDelete<SkStream> stream(resource(path)); |
960 if (!stream) { | 969 if (!stream) { |
| 970 SkDebugf("Missing resource '%s'\n", path); |
961 return; | 971 return; |
962 } | 972 } |
963 | 973 |
964 // Modify the stream to contain a second byte with some bits set. | 974 // Modify the stream to contain a second byte with some bits set. |
965 auto data = SkCopyStreamToData(stream); | 975 auto data = SkCopyStreamToData(stream); |
966 uint8_t* writeableData = static_cast<uint8_t*>(data->writable_data()); | 976 uint8_t* writeableData = static_cast<uint8_t*>(data->writable_data()); |
967 writeableData[1] = static_cast<uint8_t>(~0x9F); | 977 writeableData[1] = static_cast<uint8_t>(~0x9F); |
968 | 978 |
969 // SkCodec should support this. | 979 // SkCodec should support this. |
970 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data)); | 980 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data)); |
(...skipping 28 matching lines...) Expand all Loading... |
999 0x84, 0x80, 0x00, // W: 65536 | 1009 0x84, 0x80, 0x00, // W: 65536 |
1000 0x84, 0x80, 0x00 }; // H: 65536 | 1010 0x84, 0x80, 0x00 }; // H: 65536 |
1001 stream.reset(new SkMemoryStream(tooBigWbmp, sizeof(tooBigWbmp), false)); | 1011 stream.reset(new SkMemoryStream(tooBigWbmp, sizeof(tooBigWbmp), false)); |
1002 codec.reset(SkCodec::NewFromStream(stream.release())); | 1012 codec.reset(SkCodec::NewFromStream(stream.release())); |
1003 | 1013 |
1004 REPORTER_ASSERT(r, !codec); | 1014 REPORTER_ASSERT(r, !codec); |
1005 } | 1015 } |
1006 | 1016 |
1007 DEF_TEST(Codec_jpeg_rewind, r) { | 1017 DEF_TEST(Codec_jpeg_rewind, r) { |
1008 const char* path = "mandrill_512_q075.jpg"; | 1018 const char* path = "mandrill_512_q075.jpg"; |
1009 SkAutoTDelete<SkStream> stream(GetResourceAsStream(path)); | 1019 SkAutoTDelete<SkStream> stream(resource(path)); |
1010 if (!stream) { | 1020 if (!stream) { |
| 1021 SkDebugf("Missing resource '%s'\n", path); |
1011 return; | 1022 return; |
1012 } | 1023 } |
1013 SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(stream.rel
ease())); | 1024 SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(stream.rel
ease())); |
1014 if (!codec) { | 1025 if (!codec) { |
1015 ERRORF(r, "Unable to create codec '%s'.", path); | 1026 ERRORF(r, "Unable to create codec '%s'.", path); |
1016 return; | 1027 return; |
1017 } | 1028 } |
1018 | 1029 |
1019 const int width = codec->getInfo().width(); | 1030 const int width = codec->getInfo().width(); |
1020 const int height = codec->getInfo().height(); | 1031 const int height = codec->getInfo().height(); |
1021 size_t rowBytes = sizeof(SkPMColor) * width; | 1032 size_t rowBytes = sizeof(SkPMColor) * width; |
1022 SkAutoMalloc pixelStorage(height * rowBytes); | 1033 SkAutoMalloc pixelStorage(height * rowBytes); |
1023 | 1034 |
1024 // Perform a sampled decode. | 1035 // Perform a sampled decode. |
1025 SkAndroidCodec::AndroidOptions opts; | 1036 SkAndroidCodec::AndroidOptions opts; |
1026 opts.fSampleSize = 12; | 1037 opts.fSampleSize = 12; |
1027 codec->getAndroidPixels(codec->getInfo().makeWH(width / 12, height / 12), pi
xelStorage.get(), | 1038 codec->getAndroidPixels(codec->getInfo().makeWH(width / 12, height / 12), pi
xelStorage.get(), |
1028 rowBytes, &opts); | 1039 rowBytes, &opts); |
1029 | 1040 |
1030 // Rewind the codec and perform a full image decode. | 1041 // Rewind the codec and perform a full image decode. |
1031 SkCodec::Result result = codec->getPixels(codec->getInfo(), pixelStorage.get
(), rowBytes); | 1042 SkCodec::Result result = codec->getPixels(codec->getInfo(), pixelStorage.get
(), rowBytes); |
1032 REPORTER_ASSERT(r, SkCodec::kSuccess == result); | 1043 REPORTER_ASSERT(r, SkCodec::kSuccess == result); |
1033 } | 1044 } |
1034 | 1045 |
1035 static void check_color_xform(skiatest::Reporter* r, const char* path) { | 1046 static void check_color_xform(skiatest::Reporter* r, const char* path) { |
1036 SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(GetResourc
eAsStream(path))); | 1047 SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(resource(p
ath))); |
1037 | 1048 |
1038 SkAndroidCodec::AndroidOptions opts; | 1049 SkAndroidCodec::AndroidOptions opts; |
1039 opts.fSampleSize = 3; | 1050 opts.fSampleSize = 3; |
1040 const int subsetWidth = codec->getInfo().width() / 2; | 1051 const int subsetWidth = codec->getInfo().width() / 2; |
1041 const int subsetHeight = codec->getInfo().height() / 2; | 1052 const int subsetHeight = codec->getInfo().height() / 2; |
1042 SkIRect subset = SkIRect::MakeWH(subsetWidth, subsetHeight); | 1053 SkIRect subset = SkIRect::MakeWH(subsetWidth, subsetHeight); |
1043 opts.fSubset = ⊂ | 1054 opts.fSubset = ⊂ |
1044 | 1055 |
1045 const int dstWidth = subsetWidth / opts.fSampleSize; | 1056 const int dstWidth = subsetWidth / opts.fSampleSize; |
1046 const int dstHeight = subsetHeight / opts.fSampleSize; | 1057 const int dstHeight = subsetHeight / opts.fSampleSize; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 REPORTER_ASSERT(r, SkCodec::kSuccess == result); | 1123 REPORTER_ASSERT(r, SkCodec::kSuccess == result); |
1113 | 1124 |
1114 SkMD5::Digest d1, d2; | 1125 SkMD5::Digest d1, d2; |
1115 md5(bm1, &d1); | 1126 md5(bm1, &d1); |
1116 md5(bm2, &d2); | 1127 md5(bm2, &d2); |
1117 REPORTER_ASSERT(r, d1 == d2); | 1128 REPORTER_ASSERT(r, d1 == d2); |
1118 } | 1129 } |
1119 | 1130 |
1120 DEF_TEST(Codec_PngRoundTrip, r) { | 1131 DEF_TEST(Codec_PngRoundTrip, r) { |
1121 const char* path = "mandrill_512_q075.jpg"; | 1132 const char* path = "mandrill_512_q075.jpg"; |
1122 SkAutoTDelete<SkStream> stream(GetResourceAsStream(path)); | 1133 SkAutoTDelete<SkStream> stream(resource(path)); |
1123 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release())); | 1134 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release())); |
1124 | 1135 |
1125 SkColorType colorTypesOpaque[] = { | 1136 SkColorType colorTypesOpaque[] = { |
1126 kRGB_565_SkColorType, kRGBA_8888_SkColorType, kBGRA_8888_SkColorType | 1137 kRGB_565_SkColorType, kRGBA_8888_SkColorType, kBGRA_8888_SkColorType |
1127 }; | 1138 }; |
1128 for (SkColorType colorType : colorTypesOpaque) { | 1139 for (SkColorType colorType : colorTypesOpaque) { |
1129 SkImageInfo newInfo = codec->getInfo().makeColorType(colorType); | 1140 SkImageInfo newInfo = codec->getInfo().makeColorType(colorType); |
1130 check_round_trip(r, codec.get(), newInfo); | 1141 check_round_trip(r, codec.get(), newInfo); |
1131 } | 1142 } |
1132 | 1143 |
1133 path = "grayscale.jpg"; | 1144 path = "grayscale.jpg"; |
1134 stream.reset(GetResourceAsStream(path)); | 1145 stream.reset(resource(path)); |
1135 codec.reset(SkCodec::NewFromStream(stream.release())); | 1146 codec.reset(SkCodec::NewFromStream(stream.release())); |
1136 check_round_trip(r, codec.get(), codec->getInfo()); | 1147 check_round_trip(r, codec.get(), codec->getInfo()); |
1137 | 1148 |
1138 path = "yellow_rose.png"; | 1149 path = "yellow_rose.png"; |
1139 stream.reset(GetResourceAsStream(path)); | 1150 stream.reset(resource(path)); |
1140 codec.reset(SkCodec::NewFromStream(stream.release())); | 1151 codec.reset(SkCodec::NewFromStream(stream.release())); |
1141 | 1152 |
1142 SkColorType colorTypesWithAlpha[] = { | 1153 SkColorType colorTypesWithAlpha[] = { |
1143 kRGBA_8888_SkColorType, kBGRA_8888_SkColorType | 1154 kRGBA_8888_SkColorType, kBGRA_8888_SkColorType |
1144 }; | 1155 }; |
1145 SkAlphaType alphaTypes[] = { | 1156 SkAlphaType alphaTypes[] = { |
1146 kUnpremul_SkAlphaType, kPremul_SkAlphaType | 1157 kUnpremul_SkAlphaType, kPremul_SkAlphaType |
1147 }; | 1158 }; |
1148 for (SkColorType colorType : colorTypesWithAlpha) { | 1159 for (SkColorType colorType : colorTypesWithAlpha) { |
1149 for (SkAlphaType alphaType : alphaTypes) { | 1160 for (SkAlphaType alphaType : alphaTypes) { |
1150 // Set color space to nullptr because color correct premultiplies do
not round trip. | 1161 // Set color space to nullptr because color correct premultiplies do
not round trip. |
1151 SkImageInfo newInfo = codec->getInfo().makeColorType(colorType) | 1162 SkImageInfo newInfo = codec->getInfo().makeColorType(colorType) |
1152 .makeAlphaType(alphaType) | 1163 .makeAlphaType(alphaType) |
1153 .makeColorSpace(nullptr); | 1164 .makeColorSpace(nullptr); |
1154 check_round_trip(r, codec.get(), newInfo); | 1165 check_round_trip(r, codec.get(), newInfo); |
1155 } | 1166 } |
1156 } | 1167 } |
1157 | 1168 |
1158 path = "index8.png"; | 1169 path = "index8.png"; |
1159 stream.reset(GetResourceAsStream(path)); | 1170 stream.reset(resource(path)); |
1160 codec.reset(SkCodec::NewFromStream(stream.release())); | 1171 codec.reset(SkCodec::NewFromStream(stream.release())); |
1161 | 1172 |
1162 for (SkAlphaType alphaType : alphaTypes) { | 1173 for (SkAlphaType alphaType : alphaTypes) { |
1163 SkImageInfo newInfo = codec->getInfo().makeAlphaType(alphaType) | 1174 SkImageInfo newInfo = codec->getInfo().makeAlphaType(alphaType) |
1164 .makeColorSpace(nullptr); | 1175 .makeColorSpace(nullptr); |
1165 check_round_trip(r, codec.get(), newInfo); | 1176 check_round_trip(r, codec.get(), newInfo); |
1166 } | 1177 } |
1167 } | 1178 } |
1168 | 1179 |
1169 static void test_conversion_possible(skiatest::Reporter* r, const char* path, | 1180 static void test_conversion_possible(skiatest::Reporter* r, const char* path, |
1170 bool testScanlineDecoder) { | 1181 bool testScanlineDecoder) { |
1171 SkAutoTDelete<SkStream> stream(GetResourceAsStream(path)); | 1182 SkAutoTDelete<SkStream> stream(resource(path)); |
1172 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release())); | 1183 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release())); |
1173 SkImageInfo infoF16 = codec->getInfo().makeColorType(kRGBA_F16_SkColorType); | 1184 SkImageInfo infoF16 = codec->getInfo().makeColorType(kRGBA_F16_SkColorType); |
1174 | 1185 |
1175 SkBitmap bm; | 1186 SkBitmap bm; |
1176 bm.allocPixels(infoF16); | 1187 bm.allocPixels(infoF16); |
1177 SkCodec::Result result = codec->getPixels(infoF16, bm.getPixels(), bm.rowByt
es()); | 1188 SkCodec::Result result = codec->getPixels(infoF16, bm.getPixels(), bm.rowByt
es()); |
1178 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result); | 1189 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result); |
1179 if (testScanlineDecoder) { | 1190 if (testScanlineDecoder) { |
1180 result = codec->startScanlineDecode(infoF16); | 1191 result = codec->startScanlineDecode(infoF16); |
1181 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result); | 1192 REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result); |
1182 } | 1193 } |
1183 | 1194 |
1184 infoF16 = infoF16.makeColorSpace(infoF16.colorSpace()->makeLinearGamma()); | 1195 infoF16 = infoF16.makeColorSpace(infoF16.colorSpace()->makeLinearGamma()); |
1185 result = codec->getPixels(infoF16, bm.getPixels(), bm.rowBytes()); | 1196 result = codec->getPixels(infoF16, bm.getPixels(), bm.rowBytes()); |
1186 REPORTER_ASSERT(r, SkCodec::kSuccess == result); | 1197 REPORTER_ASSERT(r, SkCodec::kSuccess == result); |
1187 if (testScanlineDecoder) { | 1198 if (testScanlineDecoder) { |
1188 result = codec->startScanlineDecode(infoF16); | 1199 result = codec->startScanlineDecode(infoF16); |
1189 REPORTER_ASSERT(r, SkCodec::kSuccess == result); | 1200 REPORTER_ASSERT(r, SkCodec::kSuccess == result); |
1190 } | 1201 } |
1191 } | 1202 } |
1192 | 1203 |
1193 DEF_TEST(Codec_F16ConversionPossible, r) { | 1204 DEF_TEST(Codec_F16ConversionPossible, r) { |
1194 test_conversion_possible(r, "color_wheel.webp", false); | 1205 test_conversion_possible(r, "color_wheel.webp", false); |
1195 test_conversion_possible(r, "mandrill_512_q075.jpg", true); | 1206 test_conversion_possible(r, "mandrill_512_q075.jpg", true); |
1196 test_conversion_possible(r, "yellow_rose.png", true); | 1207 test_conversion_possible(r, "yellow_rose.png", true); |
1197 } | 1208 } |
OLD | NEW |