| 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 |