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