| 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" |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 if (!stream) { | 203 if (!stream) { |
| 204 SkDebugf("Missing resource '%s'\n", path); | 204 SkDebugf("Missing resource '%s'\n", path); |
| 205 return; | 205 return; |
| 206 } | 206 } |
| 207 | 207 |
| 208 SkAutoTDelete<SkCodec> codec(nullptr); | 208 SkAutoTDelete<SkCodec> codec(nullptr); |
| 209 bool isIncomplete = supportsIncomplete; | 209 bool isIncomplete = supportsIncomplete; |
| 210 if (isIncomplete) { | 210 if (isIncomplete) { |
| 211 size_t size = stream->getLength(); | 211 size_t size = stream->getLength(); |
| 212 sk_sp<SkData> data((SkData::MakeFromStream(stream, 2 * size / 3))); | 212 sk_sp<SkData> data((SkData::MakeFromStream(stream, 2 * size / 3))); |
| 213 codec.reset(SkCodec::NewFromData(data.get())); | 213 codec.reset(SkCodec::NewFromData(data)); |
| 214 } else { | 214 } else { |
| 215 codec.reset(SkCodec::NewFromStream(stream.release())); | 215 codec.reset(SkCodec::NewFromStream(stream.release())); |
| 216 } | 216 } |
| 217 if (!codec) { | 217 if (!codec) { |
| 218 ERRORF(r, "Unable to decode '%s'", path); | 218 ERRORF(r, "Unable to decode '%s'", path); |
| 219 return; | 219 return; |
| 220 } | 220 } |
| 221 | 221 |
| 222 // Test full image decodes with SkCodec | 222 // Test full image decodes with SkCodec |
| 223 SkMD5::Digest codecDigest; | 223 SkMD5::Digest codecDigest; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 SkAutoTDelete<SkStream> stream(resource(path)); | 332 SkAutoTDelete<SkStream> stream(resource(path)); |
| 333 if (!stream) { | 333 if (!stream) { |
| 334 SkDebugf("Missing resource '%s'\n", path); | 334 SkDebugf("Missing resource '%s'\n", path); |
| 335 return; | 335 return; |
| 336 } | 336 } |
| 337 | 337 |
| 338 SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr); | 338 SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr); |
| 339 if (isIncomplete) { | 339 if (isIncomplete) { |
| 340 size_t size = stream->getLength(); | 340 size_t size = stream->getLength(); |
| 341 sk_sp<SkData> data((SkData::MakeFromStream(stream, 2 * size / 3))); | 341 sk_sp<SkData> data((SkData::MakeFromStream(stream, 2 * size / 3))); |
| 342 androidCodec.reset(SkAndroidCodec::NewFromData(data.get())); | 342 androidCodec.reset(SkAndroidCodec::NewFromData(data)); |
| 343 } else { | 343 } else { |
| 344 androidCodec.reset(SkAndroidCodec::NewFromStream(stream.release())); | 344 androidCodec.reset(SkAndroidCodec::NewFromStream(stream.release())); |
| 345 } | 345 } |
| 346 if (!androidCodec) { | 346 if (!androidCodec) { |
| 347 ERRORF(r, "Unable to decode '%s'", path); | 347 ERRORF(r, "Unable to decode '%s'", path); |
| 348 return; | 348 return; |
| 349 } | 349 } |
| 350 | 350 |
| 351 SkBitmap bm; | 351 SkBitmap bm; |
| 352 SkMD5::Digest androidCodecDigest; | 352 SkMD5::Digest androidCodecDigest; |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 817 } | 817 } |
| 818 | 818 |
| 819 private: | 819 private: |
| 820 skiatest::Reporter* fReporter; // Unowned | 820 skiatest::Reporter* fReporter; // Unowned |
| 821 bool fSeen[3]; | 821 bool fSeen[3]; |
| 822 }; | 822 }; |
| 823 | 823 |
| 824 ChunkReader chunkReader(r); | 824 ChunkReader chunkReader(r); |
| 825 | 825 |
| 826 // Now read the file with SkCodec. | 826 // Now read the file with SkCodec. |
| 827 sk_sp<SkData> data(wStream.copyToData()); | 827 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(wStream.detachAsData(), &c
hunkReader)); |
| 828 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data.get(), &chunkReader))
; | |
| 829 REPORTER_ASSERT(r, codec); | 828 REPORTER_ASSERT(r, codec); |
| 830 if (!codec) { | 829 if (!codec) { |
| 831 return; | 830 return; |
| 832 } | 831 } |
| 833 | 832 |
| 834 // Now compare to the original. | 833 // Now compare to the original. |
| 835 SkBitmap decodedBm; | 834 SkBitmap decodedBm; |
| 836 decodedBm.setInfo(codec->getInfo()); | 835 decodedBm.setInfo(codec->getInfo()); |
| 837 decodedBm.allocPixels(); | 836 decodedBm.allocPixels(); |
| 838 SkCodec::Result result = codec->getPixels(codec->getInfo(), decodedBm.getPix
els(), | 837 SkCodec::Result result = codec->getPixels(codec->getInfo(), decodedBm.getPix
els(), |
| (...skipping 19 matching lines...) Expand all Loading... |
| 858 REPORTER_ASSERT(r, !chunkReader.allHaveBeenSeen()); | 857 REPORTER_ASSERT(r, !chunkReader.allHaveBeenSeen()); |
| 859 result = codec->getPixels(codec->getInfo(), decodedBm.getPixels(), decodedBm
.rowBytes()); | 858 result = codec->getPixels(codec->getInfo(), decodedBm.getPixels(), decodedBm
.rowBytes()); |
| 860 REPORTER_ASSERT(r, SkCodec::kSuccess == result); | 859 REPORTER_ASSERT(r, SkCodec::kSuccess == result); |
| 861 REPORTER_ASSERT(r, chunkReader.allHaveBeenSeen()); | 860 REPORTER_ASSERT(r, chunkReader.allHaveBeenSeen()); |
| 862 } | 861 } |
| 863 #endif // PNG_READ_UNKNOWN_CHUNKS_SUPPORTED | 862 #endif // PNG_READ_UNKNOWN_CHUNKS_SUPPORTED |
| 864 | 863 |
| 865 // Stream that can only peek up to a limit | 864 // Stream that can only peek up to a limit |
| 866 class LimitedPeekingMemStream : public SkStream { | 865 class LimitedPeekingMemStream : public SkStream { |
| 867 public: | 866 public: |
| 868 LimitedPeekingMemStream(SkData* data, size_t limit) | 867 LimitedPeekingMemStream(sk_sp<SkData> data, size_t limit) |
| 869 : fStream(data) | 868 : fStream(std::move(data)) |
| 870 , fLimit(limit) {} | 869 , fLimit(limit) {} |
| 871 | 870 |
| 872 size_t peek(void* buf, size_t bytes) const override { | 871 size_t peek(void* buf, size_t bytes) const override { |
| 873 return fStream.peek(buf, SkTMin(bytes, fLimit)); | 872 return fStream.peek(buf, SkTMin(bytes, fLimit)); |
| 874 } | 873 } |
| 875 size_t read(void* buf, size_t bytes) override { | 874 size_t read(void* buf, size_t bytes) override { |
| 876 return fStream.read(buf, bytes); | 875 return fStream.read(buf, bytes); |
| 877 } | 876 } |
| 878 bool rewind() override { | 877 bool rewind() override { |
| 879 return fStream.rewind(); | 878 return fStream.rewind(); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 941 const char* path = "baby_tux.webp"; | 940 const char* path = "baby_tux.webp"; |
| 942 SkString fullPath(GetResourcePath(path)); | 941 SkString fullPath(GetResourcePath(path)); |
| 943 auto data = SkData::MakeFromFileName(fullPath.c_str()); | 942 auto data = SkData::MakeFromFileName(fullPath.c_str()); |
| 944 if (!data) { | 943 if (!data) { |
| 945 SkDebugf("Missing resource '%s'\n", path); | 944 SkDebugf("Missing resource '%s'\n", path); |
| 946 return; | 945 return; |
| 947 } | 946 } |
| 948 | 947 |
| 949 // The limit is less than webp needs to peek or read. | 948 // The limit is less than webp needs to peek or read. |
| 950 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream( | 949 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream( |
| 951 new LimitedPeekingMemStream(data.get(), 25))); | 950 new LimitedPeekingMemStream(data, 25))); |
| 952 REPORTER_ASSERT(r, codec); | 951 REPORTER_ASSERT(r, codec); |
| 953 | 952 |
| 954 test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); | 953 test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); |
| 955 | 954 |
| 956 // Similarly, a stream which does not peek should still succeed. | 955 // Similarly, a stream which does not peek should still succeed. |
| 957 codec.reset(SkCodec::NewFromStream(new LimitedPeekingMemStream(data.get(), 0
))); | 956 codec.reset(SkCodec::NewFromStream(new LimitedPeekingMemStream(data, 0))); |
| 958 REPORTER_ASSERT(r, codec); | 957 REPORTER_ASSERT(r, codec); |
| 959 | 958 |
| 960 test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); | 959 test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); |
| 961 } | 960 } |
| 962 | 961 |
| 963 // SkCodec's wbmp decoder was initially unnecessarily restrictive. | 962 // SkCodec's wbmp decoder was initially unnecessarily restrictive. |
| 964 // 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 |
| 965 // 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). |
| 966 // Test that SkCodec now supports an image with these bits set. | 965 // Test that SkCodec now supports an image with these bits set. |
| 967 DEF_TEST(Codec_wbmp, r) { | 966 DEF_TEST(Codec_wbmp, r) { |
| 968 const char* path = "mandrill.wbmp"; | 967 const char* path = "mandrill.wbmp"; |
| 969 SkAutoTDelete<SkStream> stream(resource(path)); | 968 SkAutoTDelete<SkStream> stream(resource(path)); |
| 970 if (!stream) { | 969 if (!stream) { |
| 971 SkDebugf("Missing resource '%s'\n", path); | 970 SkDebugf("Missing resource '%s'\n", path); |
| 972 return; | 971 return; |
| 973 } | 972 } |
| 974 | 973 |
| 975 // 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. |
| 976 auto data = SkCopyStreamToData(stream); | 975 auto data = SkCopyStreamToData(stream); |
| 977 uint8_t* writeableData = static_cast<uint8_t*>(data->writable_data()); | 976 uint8_t* writeableData = static_cast<uint8_t*>(data->writable_data()); |
| 978 writeableData[1] = static_cast<uint8_t>(~0x9F); | 977 writeableData[1] = static_cast<uint8_t>(~0x9F); |
| 979 | 978 |
| 980 // SkCodec should support this. | 979 // SkCodec should support this. |
| 981 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data.get())); | 980 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data)); |
| 982 REPORTER_ASSERT(r, codec); | 981 REPORTER_ASSERT(r, codec); |
| 983 if (!codec) { | 982 if (!codec) { |
| 984 return; | 983 return; |
| 985 } | 984 } |
| 986 test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); | 985 test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); |
| 987 } | 986 } |
| 988 | 987 |
| 989 // wbmp images have a header that can be arbitrarily large, depending on the | 988 // wbmp images have a header that can be arbitrarily large, depending on the |
| 990 // size of the image. We cap the size at 65535, meaning we only need to look at | 989 // size of the image. We cap the size at 65535, meaning we only need to look at |
| 991 // 8 bytes to determine whether we can read the image. This is important | 990 // 8 bytes to determine whether we can read the image. This is important |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1076 | 1075 |
| 1077 static void check_round_trip(skiatest::Reporter* r, const SkBitmap& bm1) { | 1076 static void check_round_trip(skiatest::Reporter* r, const SkBitmap& bm1) { |
| 1078 SkColorType origColorType = bm1.colorType(); | 1077 SkColorType origColorType = bm1.colorType(); |
| 1079 SkAlphaType origAlphaType = bm1.alphaType(); | 1078 SkAlphaType origAlphaType = bm1.alphaType(); |
| 1080 | 1079 |
| 1081 // Encode the image to png. | 1080 // Encode the image to png. |
| 1082 sk_sp<SkData> data = | 1081 sk_sp<SkData> data = |
| 1083 sk_sp<SkData>(SkImageEncoder::EncodeData(bm1, SkImageEncoder::kPNG_T
ype, 100)); | 1082 sk_sp<SkData>(SkImageEncoder::EncodeData(bm1, SkImageEncoder::kPNG_T
ype, 100)); |
| 1084 | 1083 |
| 1085 // Prepare to decode. The codec should recognize that the PNG is 565. | 1084 // Prepare to decode. The codec should recognize that the PNG is 565. |
| 1086 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data.get())); | 1085 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data)); |
| 1087 REPORTER_ASSERT(r, origColorType == codec->getInfo().colorType()); | 1086 REPORTER_ASSERT(r, origColorType == codec->getInfo().colorType()); |
| 1088 REPORTER_ASSERT(r, origAlphaType == codec->getInfo().alphaType()); | 1087 REPORTER_ASSERT(r, origAlphaType == codec->getInfo().alphaType()); |
| 1089 | 1088 |
| 1090 SkBitmap bm2; | 1089 SkBitmap bm2; |
| 1091 bm2.allocPixels(codec->getInfo()); | 1090 bm2.allocPixels(codec->getInfo()); |
| 1092 SkCodec::Result result = codec->getPixels(codec->getInfo(), bm2.getPixels(),
bm2.rowBytes()); | 1091 SkCodec::Result result = codec->getPixels(codec->getInfo(), bm2.getPixels(),
bm2.rowBytes()); |
| 1093 REPORTER_ASSERT(r, SkCodec::kSuccess == result); | 1092 REPORTER_ASSERT(r, SkCodec::kSuccess == result); |
| 1094 | 1093 |
| 1095 SkMD5::Digest d1, d2; | 1094 SkMD5::Digest d1, d2; |
| 1096 md5(bm1, &d1); | 1095 md5(bm1, &d1); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1143 result = codec->startScanlineDecode(infoF16); | 1142 result = codec->startScanlineDecode(infoF16); |
| 1144 REPORTER_ASSERT(r, SkCodec::kSuccess == result); | 1143 REPORTER_ASSERT(r, SkCodec::kSuccess == result); |
| 1145 } | 1144 } |
| 1146 } | 1145 } |
| 1147 | 1146 |
| 1148 DEF_TEST(Codec_F16ConversionPossible, r) { | 1147 DEF_TEST(Codec_F16ConversionPossible, r) { |
| 1149 test_conversion_possible(r, "color_wheel.webp", false); | 1148 test_conversion_possible(r, "color_wheel.webp", false); |
| 1150 test_conversion_possible(r, "mandrill_512_q075.jpg", true); | 1149 test_conversion_possible(r, "mandrill_512_q075.jpg", true); |
| 1151 test_conversion_possible(r, "yellow_rose.png", true); | 1150 test_conversion_possible(r, "yellow_rose.png", true); |
| 1152 } | 1151 } |
| OLD | NEW |