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 830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
841 | 841 |
842 // Decoding again will read the chunks again. | 842 // Decoding again will read the chunks again. |
843 chunkReader.reset(); | 843 chunkReader.reset(); |
844 REPORTER_ASSERT(r, !chunkReader.allHaveBeenSeen()); | 844 REPORTER_ASSERT(r, !chunkReader.allHaveBeenSeen()); |
845 result = codec->getPixels(codec->getInfo(), decodedBm.getPixels(), decodedBm
.rowBytes()); | 845 result = codec->getPixels(codec->getInfo(), decodedBm.getPixels(), decodedBm
.rowBytes()); |
846 REPORTER_ASSERT(r, SkCodec::kSuccess == result); | 846 REPORTER_ASSERT(r, SkCodec::kSuccess == result); |
847 REPORTER_ASSERT(r, chunkReader.allHaveBeenSeen()); | 847 REPORTER_ASSERT(r, chunkReader.allHaveBeenSeen()); |
848 } | 848 } |
849 #endif // PNG_READ_UNKNOWN_CHUNKS_SUPPORTED | 849 #endif // PNG_READ_UNKNOWN_CHUNKS_SUPPORTED |
850 | 850 |
| 851 // Stream that can only peek up to a limit |
| 852 class LimitedPeekingMemStream : public SkStream { |
| 853 public: |
| 854 LimitedPeekingMemStream(SkData* data, size_t limit) |
| 855 : fStream(data) |
| 856 , fLimit(limit) {} |
| 857 |
| 858 size_t peek(void* buf, size_t bytes) const override { |
| 859 return fStream.peek(buf, SkTMin(bytes, fLimit)); |
| 860 } |
| 861 size_t read(void* buf, size_t bytes) override { |
| 862 return fStream.read(buf, bytes); |
| 863 } |
| 864 bool rewind() override { |
| 865 return fStream.rewind(); |
| 866 } |
| 867 bool isAtEnd() const override { |
| 868 return false; |
| 869 } |
| 870 private: |
| 871 SkMemoryStream fStream; |
| 872 const size_t fLimit; |
| 873 }; |
| 874 |
| 875 // Test that even if webp_parse_header fails to peek enough, it will fall back t
o read() |
| 876 // + rewind() and succeed. |
| 877 DEF_TEST(Codec_webp_peek, r) { |
| 878 const char* path = "baby_tux.webp"; |
| 879 SkString fullPath(GetResourcePath(path)); |
| 880 SkAutoTUnref<SkData> data(SkData::NewFromFileName(fullPath.c_str())); |
| 881 if (!data) { |
| 882 SkDebugf("Missing resource '%s'\n", path); |
| 883 return; |
| 884 } |
| 885 |
| 886 // The limit is less than webp needs to peek or read. |
| 887 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(new LimitedPeekingMemStr
eam(data, 25))); |
| 888 REPORTER_ASSERT(r, codec); |
| 889 |
| 890 test_info(r, codec, codec->getInfo(), SkCodec::kSuccess, nullptr); |
| 891 |
| 892 // Similarly, a stream which does not peek should still succeed. |
| 893 codec.reset(SkCodec::NewFromStream(new LimitedPeekingMemStream(data, 0))); |
| 894 REPORTER_ASSERT(r, codec); |
| 895 |
| 896 test_info(r, codec, codec->getInfo(), SkCodec::kSuccess, nullptr); |
| 897 } |
| 898 |
851 // SkCodec's wbmp decoder was initially more restrictive than SkImageDecoder. | 899 // SkCodec's wbmp decoder was initially more restrictive than SkImageDecoder. |
852 // It required the second byte to be zero. But SkImageDecoder allowed a couple | 900 // It required the second byte to be zero. But SkImageDecoder allowed a couple |
853 // of bits to be 1 (so long as they do not overlap with 0x9F). Test that | 901 // of bits to be 1 (so long as they do not overlap with 0x9F). Test that |
854 // SkCodec now supports an image with these bits set. | 902 // SkCodec now supports an image with these bits set. |
855 DEF_TEST(Codec_wbmp, r) { | 903 DEF_TEST(Codec_wbmp, r) { |
856 const char* path = "mandrill.wbmp"; | 904 const char* path = "mandrill.wbmp"; |
857 SkAutoTDelete<SkStream> stream(resource(path)); | 905 SkAutoTDelete<SkStream> stream(resource(path)); |
858 if (!stream) { | 906 if (!stream) { |
859 SkDebugf("Missing resource '%s'\n", path); | 907 SkDebugf("Missing resource '%s'\n", path); |
860 return; | 908 return; |
861 } | 909 } |
862 | 910 |
863 // Modify the stream to contain a second byte with some bits set. | 911 // Modify the stream to contain a second byte with some bits set. |
864 SkAutoTUnref<SkData> data(SkCopyStreamToData(stream)); | 912 SkAutoTUnref<SkData> data(SkCopyStreamToData(stream)); |
865 uint8_t* writeableData = static_cast<uint8_t*>(data->writable_data()); | 913 uint8_t* writeableData = static_cast<uint8_t*>(data->writable_data()); |
866 writeableData[1] = static_cast<uint8_t>(~0x9F); | 914 writeableData[1] = static_cast<uint8_t>(~0x9F); |
867 | 915 |
868 // SkImageDecoder supports this. | 916 // SkImageDecoder supports this. |
869 SkBitmap bitmap; | 917 SkBitmap bitmap; |
870 REPORTER_ASSERT(r, SkImageDecoder::DecodeMemory(data->data(), data->size(),
&bitmap)); | 918 REPORTER_ASSERT(r, SkImageDecoder::DecodeMemory(data->data(), data->size(),
&bitmap)); |
871 | 919 |
872 // So SkCodec should, too. | 920 // So SkCodec should, too. |
873 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data)); | 921 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data)); |
874 REPORTER_ASSERT(r, codec); | 922 REPORTER_ASSERT(r, codec); |
875 if (!codec) { | 923 if (!codec) { |
876 return; | 924 return; |
877 } | 925 } |
878 test_info(r, codec, codec->getInfo(), SkCodec::kSuccess, nullptr); | 926 test_info(r, codec, codec->getInfo(), SkCodec::kSuccess, nullptr); |
879 } | 927 } |
| 928 |
| 929 // wbmp images have a header that can be arbitrarily large, depending on the |
| 930 // size of the image. We cap the size at 65535, meaning we only need to look at |
| 931 // 8 bytes to determine whether we can read the image. This is important |
| 932 // because SkCodec only passes 14 bytes to SkWbmpCodec to determine whether the |
| 933 // image is a wbmp. |
| 934 DEF_TEST(Codec_wbmp_max_size, r) { |
| 935 const unsigned char maxSizeWbmp[] = { 0x00, 0x00, // Header |
| 936 0x83, 0xFF, 0x7F, // W: 65535 |
| 937 0x83, 0xFF, 0x7F }; // H: 65535 |
| 938 SkAutoTDelete<SkStream> stream(new SkMemoryStream(maxSizeWbmp, sizeof(maxSiz
eWbmp), false)); |
| 939 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach())); |
| 940 |
| 941 REPORTER_ASSERT(r, codec); |
| 942 if (!codec) return; |
| 943 |
| 944 REPORTER_ASSERT(r, codec->getInfo().width() == 65535); |
| 945 REPORTER_ASSERT(r, codec->getInfo().height() == 65535); |
| 946 |
| 947 // Now test an image which is too big. Any image with a larger header (i.e. |
| 948 // has bigger width/height) is also too big. |
| 949 const unsigned char tooBigWbmp[] = { 0x00, 0x00, // Header |
| 950 0x84, 0x80, 0x00, // W: 65536 |
| 951 0x84, 0x80, 0x00 }; // H: 65536 |
| 952 stream.reset(new SkMemoryStream(tooBigWbmp, sizeof(tooBigWbmp), false)); |
| 953 codec.reset(SkCodec::NewFromStream(stream.detach())); |
| 954 |
| 955 REPORTER_ASSERT(r, !codec); |
| 956 } |
OLD | NEW |