1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "Resources.h" 9 #include "Test.h" 10 11 #include "SkBitmap.h" 12 #include "SkCodec.h" 13 #include "SkData.h" 14 #include "SkMakeUnique.h" 15 #include "SkStream.h" 16 17 namespace { 18 // This class wraps another SkStream. It does not own the underlying stream, so 19 // that the underlying stream can be reused starting from where the first 20 // client left off. This mimics Android's JavaInputStreamAdaptor. 21 class UnowningStream : public SkStream { 22 public: 23 explicit UnowningStream(SkStream* stream) 24 : fStream(stream) 25 {} 26 27 size_t read(void* buf, size_t bytes) override { 28 return fStream->read(buf, bytes); 29 } 30 31 bool rewind() override { 32 return fStream->rewind(); 33 } 34 35 bool isAtEnd() const override { 36 return fStream->isAtEnd(); 37 } 38 private: 39 SkStream* fStream; // Unowned. 40 }; 41 } // namespace 42 43 // Test that some SkCodecs do not attempt to read input beyond the logical 44 // end of the data. Some other SkCodecs do, but some Android apps rely on not 45 // doing so for PNGs. Test on other formats that work. 46 DEF_TEST(Codec_end, r) { 47 for (const char* path : { "images/plane.png", 48 "images/yellow_rose.png", 49 "images/plane_interlaced.png", 50 "images/google_chrome.ico", 51 "images/color_wheel.ico", 52 "images/mandrill.wbmp", 53 "images/randPixels.bmp", 54 }) { 55 sk_sp<SkData> data = GetResourceAsData(path); 56 if (!data) { 57 continue; 58 } 59 60 const int kNumImages = 2; 61 const size_t size = data->size(); 62 sk_sp<SkData> multiData = SkData::MakeUninitialized(size * kNumImages); 63 void* dst = multiData->writable_data(); 64 for (int i = 0; i < kNumImages; i++) { 65 memcpy(SkTAddOffset<void>(dst, size * i), data->data(), size); 66 } 67 data.reset(); 68 69 SkMemoryStream stream(std::move(multiData)); 70 for (int i = 0; i < kNumImages; ++i) { 71 std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream( 72 skstd::make_unique<UnowningStream>(&stream))); 73 if (!codec) { 74 ERRORF(r, "Failed to create a codec from %s, iteration %i", path, i); 75 continue; 76 } 77 78 auto info = codec->getInfo().makeColorType(kN32_SkColorType); 79 SkBitmap bm; 80 bm.allocPixels(info); 81 82 auto result = codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes()); 83 if (result != SkCodec::kSuccess) { 84 ERRORF(r, "Failed to getPixels from %s, iteration %i error %i", path, i, result); 85 continue; 86 } 87 } 88 } 89 } 90