1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2015 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "FakeStreams.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Resources.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkAndroidCodec.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkAutoMalloc.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBitmap.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCodec.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCodecImageGenerator.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorSpace_XYZ.h" 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorSpacePriv.h" 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkData.h" 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkFrontBufferedStream.h" 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkImageEncoder.h" 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkImageEncoderPriv.h" 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMakeUnique.h" 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMD5.h" 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOSPath.h" 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkJpegEncoder.h" 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPngChunkReader.h" 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPngEncoder.h" 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRandom.h" 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStream.h" 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStreamPriv.h" 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkWebpEncoder.h" 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Test.h" 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "png.h" 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "sk_tool_utils.h" 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 5 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FIXME (scroggo): Google3 needs to be updated to use a newer version of libpng. In 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // the meantime, we had to break some pieces of SkPngCodec in order to support Google3. 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The parts that are broken are likely not used by Google3. 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot #define SK_PNG_DISABLE_TESTS 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void md5(const SkBitmap& bm, SkMD5::Digest* digest) { 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(bm.getPixels()); 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMD5 md5; 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t rowLen = bm.info().bytesPerPixel() * bm.width(); 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int y = 0; y < bm.height(); ++y) { 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot md5.write(bm.getAddr(0, y), rowLen); 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot md5.finish(*digest); 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/** 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Compute the digest for bm and compare it to a known good digest. 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param r Reporter to assert that bm's digest matches goodDigest. 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param goodDigest The known good digest to compare to. 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param bm The bitmap to test. 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void compare_to_good_digest(skiatest::Reporter* r, const SkMD5::Digest& goodDigest, 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkBitmap& bm) { 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMD5::Digest digest; 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot md5(bm, &digest); 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, digest == goodDigest); 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/** 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Test decoding an SkCodec to a particular SkImageInfo. 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Calling getPixels(info) should return expectedResult, and if goodDigest is non nullptr, 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * the resulting decode should match. 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate<typename Codec> 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_info(skiatest::Reporter* r, Codec* codec, const SkImageInfo& info, 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Result expectedResult, const SkMD5::Digest* goodDigest) { 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(info); 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes()); 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, result == expectedResult); 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (goodDigest) { 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot compare_to_good_digest(r, *goodDigest, bm); 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkIRect generate_random_subset(SkRandom* rand, int w, int h) { 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect rect; 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rect.fLeft = rand->nextRangeU(0, w); 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rect.fTop = rand->nextRangeU(0, h); 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rect.fRight = rand->nextRangeU(0, w); 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rect.fBottom = rand->nextRangeU(0, h); 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rect.sort(); 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (rect.isEmpty()); 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return rect; 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_incremental_decode(skiatest::Reporter* r, SkCodec* codec, const SkImageInfo& info, 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMD5::Digest& goodDigest) { 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(info); 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kSuccess == codec->startIncrementalDecode(info, bm.getPixels(), 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.rowBytes())); 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kSuccess == codec->incrementalDecode()); 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot compare_to_good_digest(r, goodDigest, bm); 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Test in stripes, similar to DM's kStripe_Mode 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_in_stripes(skiatest::Reporter* r, SkCodec* codec, const SkImageInfo& info, 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMD5::Digest& goodDigest) { 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(info); 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.eraseColor(SK_ColorYELLOW); 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int height = info.height(); 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Note that if numStripes does not evenly divide height there will be an extra 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // stripe. 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int numStripes = 4; 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (numStripes > height) { 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Image is too small. 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int stripeHeight = height / numStripes; 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Iterate through the image twice. Once to decode odd stripes, and once for even. 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int oddEven = 1; oddEven >= 0; oddEven--) { 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int y = oddEven * stripeHeight; y < height; y += 2 * stripeHeight) { 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect subset = SkIRect::MakeLTRB(0, y, info.width(), 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTMin(y + stripeHeight, height)); 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Options options; 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot options.fSubset = ⊂ 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkCodec::kSuccess != codec->startIncrementalDecode(info, bm.getAddr(0, y), 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.rowBytes(), &options)) { 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "failed to start incremental decode!\ttop: %i\tbottom%i\n", 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot subset.top(), subset.bottom()); 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkCodec::kSuccess != codec->incrementalDecode()) { 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "failed incremental decode starting from line %i\n", y); 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot compare_to_good_digest(r, goodDigest, bm); 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate<typename Codec> 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_codec(skiatest::Reporter* r, Codec* codec, SkBitmap& bm, const SkImageInfo& info, 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkISize& size, SkCodec::Result expectedResult, SkMD5::Digest* digest, 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMD5::Digest* goodDigest) { 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, info.dimensions() == size); 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(info); 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes()); 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, result == expectedResult); 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot md5(bm, digest); 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (goodDigest) { 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, *digest == *goodDigest); 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Test decoding to 565 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo info565 = info.makeColorType(kRGB_565_SkColorType); 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (info.alphaType() == kOpaque_SkAlphaType) { 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Decoding to 565 should succeed. 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm565; 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm565.allocPixels(info565); 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This will allow comparison even if the image is incomplete. 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm565.eraseColor(SK_ColorBLACK); 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, expectedResult == codec->getPixels(info565, 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm565.getPixels(), bm565.rowBytes())); 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMD5::Digest digest565; 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot md5(bm565, &digest565); 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // A dumb client's request for non-opaque should also succeed. 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (auto alpha : { kPremul_SkAlphaType, kUnpremul_SkAlphaType }) { 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info565 = info565.makeAlphaType(alpha); 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec, info565, expectedResult, &digest565); 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec, info565, SkCodec::kInvalidConversion, nullptr); 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (codec->getInfo().colorType() == kGray_8_SkColorType) { 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo grayInfo = codec->getInfo(); 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap grayBm; 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot grayBm.allocPixels(grayInfo); 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot grayBm.eraseColor(SK_ColorBLACK); 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, expectedResult == codec->getPixels(grayInfo, 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot grayBm.getPixels(), grayBm.rowBytes())); 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMD5::Digest grayDigest; 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot md5(grayBm, &grayDigest); 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (auto alpha : { kPremul_SkAlphaType, kUnpremul_SkAlphaType }) { 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot grayInfo = grayInfo.makeAlphaType(alpha); 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec, grayInfo, expectedResult, &grayDigest); 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Verify that re-decoding gives the same result. It is interesting to check this after 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // a decode to 565, since choosing to decode to 565 may result in some of the decode 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // options being modified. These options should return to their defaults on another 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // decode to kN32, so the new digest should match the old digest. 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec, info, expectedResult, digest); 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Check alpha type conversions 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (info.alphaType() == kOpaque_SkAlphaType) { 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec, info.makeAlphaType(kUnpremul_SkAlphaType), 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot expectedResult, digest); 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec, info.makeAlphaType(kPremul_SkAlphaType), 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot expectedResult, digest); 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Decoding to opaque should fail 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec, info.makeAlphaType(kOpaque_SkAlphaType), 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::kInvalidConversion, nullptr); 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAlphaType otherAt = info.alphaType(); 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (kPremul_SkAlphaType == otherAt) { 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot otherAt = kUnpremul_SkAlphaType; 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot otherAt = kPremul_SkAlphaType; 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The other non-opaque alpha type should always succeed, but not match. 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec, info.makeAlphaType(otherAt), expectedResult, nullptr); 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool supports_partial_scanlines(const char path[]) { 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const char* const exts[] = { 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "jpg", "jpeg", "png", "webp" 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "JPG", "JPEG", "PNG", "WEBP" 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) { 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkStrEndsWith(path, exts[i])) { 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// FIXME: Break up this giant function 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void check(skiatest::Reporter* r, 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char path[], 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkISize size, 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool supportsScanlineDecoding, 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool supportsSubsetDecoding, 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool supportsIncomplete, 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool supportsNewScanlineDecoding = false) { 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStream> stream(GetResourceAsStream(path)); 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream) { 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(nullptr); 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool isIncomplete = supportsIncomplete; 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (isIncomplete) { 276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t size = stream->getLength(); 277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot codec = SkCodec::MakeFromData(SkData::MakeFromStream(stream.get(), 2 * size / 3)); 278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot codec = SkCodec::MakeFromStream(std::move(stream)); 280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!codec) { 282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "Unable to decode '%s'", path); 283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Test full image decodes with SkCodec 287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMD5::Digest codecDigest; 288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); 289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Result expectedResult = isIncomplete ? SkCodec::kIncompleteInput : SkCodec::kSuccess; 291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_codec(r, codec.get(), bm, info, size, expectedResult, &codecDigest, nullptr); 292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Scanline decoding follows. 294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (supportsNewScanlineDecoding && !isIncomplete) { 296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_incremental_decode(r, codec.get(), info, codecDigest); 297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This is only supported by codecs that use incremental decoding to 298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // support subset decodes - png and jpeg (once SkJpegCodec is 299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // converted). 300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkStrEndsWith(path, "png") || SkStrEndsWith(path, "PNG")) { 301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_in_stripes(r, codec.get(), info, codecDigest); 302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Need to call startScanlineDecode() first. 306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) == 0); 307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, !codec->skipScanlines(1)); 308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCodec::Result startResult = codec->startScanlineDecode(info); 309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (supportsScanlineDecoding) { 310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.eraseColor(SK_ColorYELLOW); 311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, startResult == SkCodec::kSuccess); 313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int y = 0; y < info.height(); y++) { 315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0); 316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!isIncomplete) { 317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, 1 == lines); 318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // verify that scanline decoding gives the same result. 321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder()) { 322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot compare_to_good_digest(r, codecDigest, bm); 323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Cannot continue to decode scanlines beyond the end 326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) 327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot == 0); 328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Interrupting a scanline decode with a full decode starts from 330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // scratch 331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec->startScanlineDecode(info) == SkCodec::kSuccess); 332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int lines = codec->getScanlines(bm.getAddr(0, 0), 1, 0); 333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!isIncomplete) { 334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, lines == 1); 335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes()) 337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot == expectedResult); 338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) 339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot == 0); 340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec->skipScanlines(1) 341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot == 0); 342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Test partial scanline decodes 344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (supports_partial_scanlines(path) && info.width() >= 3) { 345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Options options; 346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int width = info.width(); 347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int height = info.height(); 348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect subset = SkIRect::MakeXYWH(2 * (width / 3), 0, width / 3, height); 349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot options.fSubset = ⊂ 350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const auto partialStartResult = codec->startScanlineDecode(info, &options); 352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, partialStartResult == SkCodec::kSuccess); 353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int y = 0; y < height; y++) { 355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0); 356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!isIncomplete) { 357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, 1 == lines); 358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, startResult == SkCodec::kUnimplemented); 363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The rest of this function tests decoding subsets, and will decode an arbitrary number of 366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // random subsets. 367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Do not attempt to decode subsets of an image of only once pixel, since there is no 368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // meaningful subset. 369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (size.width() * size.height() == 1) { 370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRandom rand; 374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect subset; 375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Options opts; 376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fSubset = ⊂ 377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < 5; i++) { 378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot subset = generate_random_subset(&rand, size.width(), size.height()); 379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!subset.isEmpty()); 380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const bool supported = codec->getValidSubset(&subset); 381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, supported == supportsSubsetDecoding); 382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo subsetInfo = info.makeWH(subset.width(), subset.height()); 384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(subsetInfo); 386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const auto result = codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes(), &opts); 387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (supportsSubsetDecoding) { 389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (expectedResult == SkCodec::kSuccess) { 390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, result == expectedResult); 391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Webp is the only codec that supports subsets, and it will have modified the subset 393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // to have even left/top. 394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTop)); 395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // No subsets will work. 397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, result == SkCodec::kUnimplemented); 398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // SkAndroidCodec tests 402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (supportsScanlineDecoding || supportsSubsetDecoding || supportsNewScanlineDecoding) { 403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStream> stream(GetResourceAsStream(path)); 405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream) { 406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec)); 410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!androidCodec) { 411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "Unable to decode '%s'", path); 412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMD5::Digest androidCodecDigest; 417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_codec(r, androidCodec.get(), bm, info, size, expectedResult, &androidCodecDigest, 418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot &codecDigest); 419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!isIncomplete) { 422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Test SkCodecImageGenerator 423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStream> stream(GetResourceAsStream(path)); 424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkData> fullData(SkData::MakeFromStream(stream.get(), stream->getLength())); 425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkImageGenerator> gen( 426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodecImageGenerator::MakeFromEncodedCodec(fullData)); 427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(info); 429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, gen->getPixels(info, bm.getPixels(), bm.rowBytes())); 430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot compare_to_good_digest(r, codecDigest, bm); 431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_PNG_DISABLE_TESTS 433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Test using SkFrontBufferedStream, as Android does 434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto bufferedStream = SkFrontBufferedStream::Make( 435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMemoryStream::Make(std::move(fullData)), SkCodec::MinBufferedBytesNeeded()); 436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, bufferedStream); 437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot codec = SkCodec::MakeFromStream(std::move(bufferedStream)); 438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec); 439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (codec) { 440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec.get(), info, SkCodec::kSuccess, &codecDigest); 441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If we've just tested incomplete decodes, let's run the same test again on full decodes. 446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (isIncomplete) { 447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, path, size, supportsScanlineDecoding, supportsSubsetDecoding, false, 448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot supportsNewScanlineDecoding); 449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_wbmp, r) { 453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/mandrill.wbmp", SkISize::Make(512, 512), true, false, true); 454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_webp, r) { 457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/baby_tux.webp", SkISize::Make(386, 395), false, true, true); 458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/color_wheel.webp", SkISize::Make(128, 128), false, true, true); 459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/yellow_rose.webp", SkISize::Make(400, 301), false, true, true); 460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_bmp, r) { 463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/randPixels.bmp", SkISize::Make(8, 8), true, false, true); 464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/rle.bmp", SkISize::Make(320, 240), true, false, true); 465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_ico, r) { 468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FIXME: We are not ready to test incomplete ICOs 469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // These two tests examine interestingly different behavior: 470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Decodes an embedded BMP image 471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/color_wheel.ico", SkISize::Make(128, 128), true, false, false); 472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Decodes an embedded PNG image 473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/google_chrome.ico", SkISize::Make(256, 256), false, false, false, true); 474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_gif, r) { 477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/box.gif", SkISize::Make(200, 55), false, false, true, true); 478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/color_wheel.gif", SkISize::Make(128, 128), false, false, true, true); 479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // randPixels.gif is too small to test incomplete 480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/randPixels.gif", SkISize::Make(8, 8), false, false, false, true); 481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_jpg, r) { 484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/CMYK.jpg", SkISize::Make(642, 516), true, false, true); 485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/color_wheel.jpg", SkISize::Make(128, 128), true, false, true); 486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // grayscale.jpg is too small to test incomplete 487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/grayscale.jpg", SkISize::Make(128, 128), true, false, false); 488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false, true); 489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // randPixels.jpg is too small to test incomplete 490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/randPixels.jpg", SkISize::Make(8, 8), true, false, false); 491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_png, r) { 494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/arrow.png", SkISize::Make(187, 312), false, false, true, true); 495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/baby_tux.png", SkISize::Make(240, 246), false, false, true, true); 496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/color_wheel.png", SkISize::Make(128, 128), false, false, true, true); 497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // half-transparent-white-pixel.png is too small to test incomplete 498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/half-transparent-white-pixel.png", SkISize::Make(1, 1), false, false, false, true); 499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/mandrill_128.png", SkISize::Make(128, 128), false, false, true, true); 500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/mandrill_16.png", SkISize::Make(16, 16), false, false, true, true); 501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/mandrill_256.png", SkISize::Make(256, 256), false, false, true, true); 502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/mandrill_32.png", SkISize::Make(32, 32), false, false, true, true); 503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/mandrill_512.png", SkISize::Make(512, 512), false, false, true, true); 504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/mandrill_64.png", SkISize::Make(64, 64), false, false, true, true); 505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/plane.png", SkISize::Make(250, 126), false, false, true, true); 506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/plane_interlaced.png", SkISize::Make(250, 126), false, false, true, true); 507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/randPixels.png", SkISize::Make(8, 8), false, false, true, true); 508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/yellow_rose.png", SkISize::Make(400, 301), false, false, true, true); 509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Disable RAW tests for Win32. 512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32)) 513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_raw, r) { 514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/sample_1mp.dng", SkISize::Make(600, 338), false, false, false); 515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/sample_1mp_rotated.dng", SkISize::Make(600, 338), false, false, false); 516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check(r, "images/dng_with_preview.dng", SkISize::Make(600, 338), true, false, false); 517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_t len) { 521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Neither of these calls should return a codec. Bots should catch us if we leaked anything. 522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, !SkCodec::MakeFromStream( 523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot skstd::make_unique<SkMemoryStream>(stream, len, false))); 524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, !SkAndroidCodec::MakeFromStream( 525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot skstd::make_unique<SkMemoryStream>(stream, len, false))); 526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Ensure that SkCodec::NewFromStream handles freeing the passed in SkStream, 529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// even on failure. Test some bad streams. 530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_leaks, r) { 531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // No codec should claim this as their format, so this tests SkCodec::NewFromStream. 532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char nonSupportedStream[] = "hello world"; 533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The other strings should look like the beginning of a file type, so we'll call some 534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // internal version of NewFromStream, which must also delete the stream on failure. 535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const unsigned char emptyPng[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a }; 536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const unsigned char emptyJpeg[] = { 0xFF, 0xD8, 0xFF }; 537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char emptyWebp[] = "RIFF1234WEBPVP"; 538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char emptyBmp[] = { 'B', 'M' }; 539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char emptyIco[] = { '\x00', '\x00', '\x01', '\x00' }; 540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char emptyGif[] = "GIFVER"; 541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_stream(r, nonSupportedStream, sizeof(nonSupportedStream)); 543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_stream(r, emptyPng, sizeof(emptyPng)); 544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_stream(r, emptyJpeg, sizeof(emptyJpeg)); 545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_stream(r, emptyWebp, sizeof(emptyWebp)); 546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_stream(r, emptyBmp, sizeof(emptyBmp)); 547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_stream(r, emptyIco, sizeof(emptyIco)); 548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_stream(r, emptyGif, sizeof(emptyGif)); 549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_null, r) { 552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Attempting to create an SkCodec or an SkAndroidCodec with null should not 553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // crash. 554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, !SkCodec::MakeFromStream(nullptr)); 555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, !SkAndroidCodec::MakeFromStream(nullptr)); 556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_dimensions(skiatest::Reporter* r, const char path[]) { 559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Create the codec from the resource file 560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStream> stream(GetResourceAsStream(path)); 561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream) { 562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::MakeFromStream(std::move(stream))); 565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!codec) { 566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "Unable to create codec '%s'", path); 567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Check that the decode is successful for a variety of scales 571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int sampleSize = 1; sampleSize < 32; sampleSize++) { 572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Scale the output dimensions 573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkISize scaledDims = codec->getSampledDimensions(sampleSize); 574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo scaledInfo = codec->getInfo() 575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot .makeWH(scaledDims.width(), scaledDims.height()) 576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot .makeColorType(kN32_SkColorType); 577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Set up for the decode 579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t rowBytes = scaledDims.width() * sizeof(SkPMColor); 580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t totalBytes = scaledInfo.computeByteSize(rowBytes); 581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoTMalloc<SkPMColor> pixels(totalBytes); 582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAndroidCodec::AndroidOptions options; 584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot options.fSampleSize = sampleSize; 585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Result result = 586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot codec->getAndroidPixels(scaledInfo, pixels.get(), rowBytes, &options); 587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kSuccess == result); 588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Ensure that onGetScaledDimensions returns valid image dimensions to use for decodes 592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_Dimensions, r) { 593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // JPG 594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/CMYK.jpg"); 595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/color_wheel.jpg"); 596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/grayscale.jpg"); 597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/mandrill_512_q075.jpg"); 598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/randPixels.jpg"); 599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Decoding small images with very large scaling factors is a potential 601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // source of bugs and crashes. We disable these tests in Gold because 602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // tiny images are not very useful to look at. 603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Here we make sure that we do not crash or access illegal memory when 604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // performing scaled decodes on small images. 605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/1x1.png"); 606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/2x2.png"); 607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/3x3.png"); 608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/3x1.png"); 609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/1x1.png"); 610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/16x1.png"); 611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/1x16.png"); 612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/mandrill_16.png"); 613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // RAW 615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Disable RAW tests for Win32. 616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32)) 617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/sample_1mp.dng"); 618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/sample_1mp_rotated.dng"); 619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_dimensions(r, "images/dng_with_preview.dng"); 620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_invalid(skiatest::Reporter* r, const char path[]) { 624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStream> stream(GetResourceAsStream(path)); 625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream) { 626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, !SkCodec::MakeFromStream(std::move(stream))); 629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_Empty, r) { 632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Test images that should not be able to create a codec 633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "empty_images/zero-dims.gif"); 634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "empty_images/zero-embedded.ico"); 635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "empty_images/zero-width.bmp"); 636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "empty_images/zero-height.bmp"); 637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "empty_images/zero-width.jpg"); 638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "empty_images/zero-height.jpg"); 639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "empty_images/zero-width.png"); 640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "empty_images/zero-height.png"); 641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "empty_images/zero-width.wbmp"); 642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "empty_images/zero-height.wbmp"); 643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This image is an ico with an embedded mask-bmp. This is illegal. 644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "invalid_images/mask-bmp-ico.ico"); 645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // It is illegal for a webp frame to not be fully contained by the canvas. 646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "invalid_images/invalid-offset.webp"); 647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32)) 648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "empty_images/zero_height.tiff"); 649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid(r, "invalid_images/b37623797.ico"); 651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED 654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_PNG_DISABLE_TESTS // reading chunks does not work properly with older versions. 656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // It does not appear that anyone in Google3 is reading chunks. 657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void codex_test_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { 659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); 660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!sk_stream->write(data, len)) { 661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_error(png_ptr, "sk_write_fn Error!"); 662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_pngChunkReader, r) { 666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Create a dummy bitmap. Use unpremul RGBA for libpng. 667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int w = 1; 669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int h = 1; 670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkImageInfo bmInfo = SkImageInfo::Make(w, h, kRGBA_8888_SkColorType, 671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kUnpremul_SkAlphaType); 672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.setInfo(bmInfo); 673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(); 674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.eraseColor(SK_ColorBLUE); 675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMD5::Digest goodDigest; 676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot md5(bm, &goodDigest); 677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Write to a png file. 679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); 680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, png); 681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!png) { 682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_infop info = png_create_info_struct(png); 686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, info); 687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!info) { 688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_destroy_write_struct(&png, nullptr); 689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (setjmp(png_jmpbuf(png))) { 693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "failed writing png"); 694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_destroy_write_struct(&png, &info); 695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDynamicMemoryWStream wStream; 699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_set_write_fn(png, (void*) (&wStream), codex_test_write_fn, nullptr); 700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_set_IHDR(png, info, (png_uint_32)w, (png_uint_32)h, 8, 702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, 703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Create some chunks that match the Android framework's use. 706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static png_unknown_chunk gUnknowns[] = { 707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "npOl", (png_byte*)"outline", sizeof("outline"), PNG_HAVE_IHDR }, 708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "npLb", (png_byte*)"layoutBounds", sizeof("layoutBounds"), PNG_HAVE_IHDR }, 709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "npTc", (png_byte*)"ninePatchData", sizeof("ninePatchData"), PNG_HAVE_IHDR }, 710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_set_keep_unknown_chunks(png, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"npOl\0npLb\0npTc\0", 3); 713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_set_unknown_chunks(png, info, gUnknowns, SK_ARRAY_COUNT(gUnknowns)); 714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if PNG_LIBPNG_VER < 10600 715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /* Deal with unknown chunk location bug in 1.5.x and earlier */ 716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_set_unknown_chunk_location(png, info, 0, PNG_HAVE_IHDR); 717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_set_unknown_chunk_location(png, info, 1, PNG_HAVE_IHDR); 718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_write_info(png, info); 721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int j = 0; j < h; j++) { 723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_bytep row = (png_bytep)(bm.getAddr(0, j)); 724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_write_rows(png, &row, 1); 725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_write_end(png, info); 727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot png_destroy_write_struct(&png, &info); 728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot class ChunkReader : public SkPngChunkReader { 730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot public: 731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ChunkReader(skiatest::Reporter* r) 732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fReporter(r) 733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->reset(); 735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool readChunk(const char tag[], const void* data, size_t length) override { 738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (size_t i = 0; i < SK_ARRAY_COUNT(gUnknowns); ++i) { 739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!strcmp(tag, (const char*) gUnknowns[i].name)) { 740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Tag matches. This should have been the first time we see it. 741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(fReporter, !fSeen[i]); 742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fSeen[i] = true; 743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 744fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Data and length should match 745fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(fReporter, length == gUnknowns[i].size); 746fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(fReporter, !strcmp((const char*) data, 747fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (const char*) gUnknowns[i].data)); 748fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 749fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 750fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 751fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(fReporter, "Saw an unexpected unknown chunk."); 752fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 753fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 754fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 755fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool allHaveBeenSeen() { 756fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool ret = true; 757fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (auto seen : fSeen) { 758fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ret &= seen; 759fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 760fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return ret; 761fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 762fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 763fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void reset() { 764fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(fSeen, sizeof(fSeen)); 765fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 766fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 767fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot private: 768fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot skiatest::Reporter* fReporter; // Unowned 769fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool fSeen[3]; 770fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 771fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 772fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ChunkReader chunkReader(r); 773fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 774fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Now read the file with SkCodec. 775fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(wStream.detachAsData(), &chunkReader)); 776fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec); 777fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!codec) { 778fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 779fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 780fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 781fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Now compare to the original. 782fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap decodedBm; 783fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot decodedBm.setInfo(codec->getInfo()); 784fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot decodedBm.allocPixels(); 785fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Result result = codec->getPixels(codec->getInfo(), decodedBm.getPixels(), 786fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot decodedBm.rowBytes()); 787fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kSuccess == result); 788fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 789fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (decodedBm.colorType() != bm.colorType()) { 790fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap tmp; 791fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool success = sk_tool_utils::copy_to(&tmp, bm.colorType(), decodedBm); 792fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, success); 793fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!success) { 794fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 795fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 796fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 797fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tmp.swap(decodedBm); 798fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 799fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 800fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot compare_to_good_digest(r, goodDigest, decodedBm); 801fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, chunkReader.allHaveBeenSeen()); 802fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 803fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Decoding again will read the chunks again. 804fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot chunkReader.reset(); 805fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, !chunkReader.allHaveBeenSeen()); 806fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = codec->getPixels(codec->getInfo(), decodedBm.getPixels(), decodedBm.rowBytes()); 807fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kSuccess == result); 808fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, chunkReader.allHaveBeenSeen()); 809fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 810fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif // SK_PNG_DISABLE_TESTS 811fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif // PNG_READ_UNKNOWN_CHUNKS_SUPPORTED 812fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 813fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Stream that can only peek up to a limit 814fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass LimitedPeekingMemStream : public SkStream { 815fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 816fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot LimitedPeekingMemStream(sk_sp<SkData> data, size_t limit) 817fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fStream(std::move(data)) 818fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fLimit(limit) {} 819fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 820fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t peek(void* buf, size_t bytes) const override { 821fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fStream.peek(buf, SkTMin(bytes, fLimit)); 822fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 823fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t read(void* buf, size_t bytes) override { 824fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fStream.read(buf, bytes); 825fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 826fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool rewind() override { 827fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fStream.rewind(); 828fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 829fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool isAtEnd() const override { 830fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fStream.isAtEnd(); 831fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 832fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 833fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMemoryStream fStream; 834fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const size_t fLimit; 835fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 836fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 837fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Disable RAW tests for Win32. 838fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32)) 839fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Test that the RawCodec works also for not asset stream. This will test the code path using 840fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkRawBufferedStream instead of SkRawAssetStream. 841fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_raw_notseekable, r) { 842fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot constexpr char path[] = "images/dng_with_preview.dng"; 843fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkData> data(GetResourceAsData(path)); 844fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!data) { 845fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("Missing resource '%s'\n", path); 846fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 847fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 848fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 849fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream( 850fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot skstd::make_unique<NotAssetMemStream>(std::move(data)))); 851fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec); 852fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 853fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); 854fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 855fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 856fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 857fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Test that even if webp_parse_header fails to peek enough, it will fall back to read() 858fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// + rewind() and succeed. 859fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_webp_peek, r) { 860fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot constexpr char path[] = "images/baby_tux.webp"; 861fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto data = GetResourceAsData(path); 862fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!data) { 863fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("Missing resource '%s'\n", path); 864fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 865fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 866fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 867fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The limit is less than webp needs to peek or read. 868fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream( 869fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot skstd::make_unique<LimitedPeekingMemStream>(data, 25))); 870fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec); 871fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 872fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); 873fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 874fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Similarly, a stream which does not peek should still succeed. 875fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot codec = SkCodec::MakeFromStream(skstd::make_unique<LimitedPeekingMemStream>(data, 0)); 876fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec); 877fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 878fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); 879fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 880fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 881fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkCodec's wbmp decoder was initially unnecessarily restrictive. 882fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// It required the second byte to be zero. The wbmp specification allows 883fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// a couple of bits to be 1 (so long as they do not overlap with 0x9F). 884fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Test that SkCodec now supports an image with these bits set. 885fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_wbmp_restrictive, r) { 886fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* path = "images/mandrill.wbmp"; 887fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStream> stream(GetResourceAsStream(path)); 888fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream) { 889fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 890fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 891fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 892fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Modify the stream to contain a second byte with some bits set. 893fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto data = SkCopyStreamToData(stream.get()); 894fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t* writeableData = static_cast<uint8_t*>(data->writable_data()); 895fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot writeableData[1] = static_cast<uint8_t>(~0x9F); 896fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 897fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // SkCodec should support this. 898fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(data)); 899fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec); 900fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!codec) { 901fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 902fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 903fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec.get(), codec->getInfo(), SkCodec::kSuccess, nullptr); 904fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 905fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 906fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// wbmp images have a header that can be arbitrarily large, depending on the 907fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// size of the image. We cap the size at 65535, meaning we only need to look at 908fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// 8 bytes to determine whether we can read the image. This is important 909fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// because SkCodec only passes a limited number of bytes to SkWbmpCodec to 910fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// determine whether the image is a wbmp. 911fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_wbmp_max_size, r) { 912fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const unsigned char maxSizeWbmp[] = { 0x00, 0x00, // Header 913fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 0x83, 0xFF, 0x7F, // W: 65535 914fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 0x83, 0xFF, 0x7F }; // H: 65535 915fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStream> stream(new SkMemoryStream(maxSizeWbmp, sizeof(maxSizeWbmp), false)); 916fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream))); 917fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 918fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec); 919fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!codec) return; 920fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 921fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec->getInfo().width() == 65535); 922fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec->getInfo().height() == 65535); 923fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 924fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Now test an image which is too big. Any image with a larger header (i.e. 925fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // has bigger width/height) is also too big. 926fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const unsigned char tooBigWbmp[] = { 0x00, 0x00, // Header 927fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 0x84, 0x80, 0x00, // W: 65536 928fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 0x84, 0x80, 0x00 }; // H: 65536 929fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot stream.reset(new SkMemoryStream(tooBigWbmp, sizeof(tooBigWbmp), false)); 930fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot codec = SkCodec::MakeFromStream(std::move(stream)); 931fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 932fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, !codec); 933fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 934fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 935fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_jpeg_rewind, r) { 936fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* path = "images/mandrill_512_q075.jpg"; 937fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkData> data(GetResourceAsData(path)); 938fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!data) { 939fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 940fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 941fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 942fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot data = SkData::MakeSubset(data.get(), 0, data->size() / 2); 943fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::MakeFromData(data)); 944fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!codec) { 945fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "Unable to create codec '%s'.", path); 946fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 947fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 948fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 949fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int width = codec->getInfo().width(); 950fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int height = codec->getInfo().height(); 951fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t rowBytes = sizeof(SkPMColor) * width; 952fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMalloc pixelStorage(height * rowBytes); 953fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 954fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Perform a sampled decode. 955fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAndroidCodec::AndroidOptions opts; 956fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fSampleSize = 12; 957fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto sampledInfo = codec->getInfo().makeWH(width / 12, height / 12); 958fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto result = codec->getAndroidPixels(sampledInfo, pixelStorage.get(), rowBytes, &opts); 959fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kIncompleteInput == result); 960fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 961fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Rewind the codec and perform a full image decode. 962fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = codec->getPixels(codec->getInfo(), pixelStorage.get(), rowBytes); 963fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kIncompleteInput == result); 964fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 965fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Now perform a subset decode. 966fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 967fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fSampleSize = 1; 968fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect subset = SkIRect::MakeWH(100, 100); 969fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fSubset = ⊂ 970fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = codec->getAndroidPixels(codec->getInfo().makeWH(100, 100), pixelStorage.get(), 971fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rowBytes, &opts); 972fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Though we only have half the data, it is enough to decode this subset. 973fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kSuccess == result); 974fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 975fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 976fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Perform another full image decode. ASAN will detect if we look at the subset when it is 977fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // out of scope. This would happen if we depend on the old state in the codec. 978fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This tests two layers of bugs: both SkJpegCodec::readRows and SkCodec::fillIncompleteImage 979fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // used to look at the old subset. 980fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fSubset = nullptr; 981fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = codec->getAndroidPixels(codec->getInfo(), pixelStorage.get(), rowBytes, &opts); 982fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kIncompleteInput == result); 983fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 984fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 985fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void check_color_xform(skiatest::Reporter* r, const char* path) { 986fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::MakeFromStream(GetResourceAsStream(path))); 987fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 988fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAndroidCodec::AndroidOptions opts; 989fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fSampleSize = 3; 990fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int subsetWidth = codec->getInfo().width() / 2; 991fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int subsetHeight = codec->getInfo().height() / 2; 992fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect subset = SkIRect::MakeWH(subsetWidth, subsetHeight); 993fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fSubset = ⊂ 994fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 995fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int dstWidth = subsetWidth / opts.fSampleSize; 996fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int dstHeight = subsetHeight / opts.fSampleSize; 997fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkData> data = GetResourceAsData("icc_profiles/HP_ZR30w.icc"); 998fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeICC(data->data(), data->size()); 999fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo dstInfo = codec->getInfo().makeWH(dstWidth, dstHeight) 1000fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot .makeColorType(kN32_SkColorType) 1001fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot .makeColorSpace(colorSpace); 1002fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1003fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t rowBytes = dstInfo.minRowBytes(); 1004fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMalloc pixelStorage(dstInfo.computeByteSize(rowBytes)); 1005fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Result result = codec->getAndroidPixels(dstInfo, pixelStorage.get(), rowBytes, &opts); 1006fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kSuccess == result); 1007fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1008fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1009fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_ColorXform, r) { 1010fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check_color_xform(r, "images/mandrill_512_q075.jpg"); 1011fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check_color_xform(r, "images/mandrill_512.png"); 1012fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1013fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1014fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool color_type_match(SkColorType origColorType, SkColorType codecColorType) { 1015fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (origColorType) { 1016fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kRGBA_8888_SkColorType: 1017fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kBGRA_8888_SkColorType: 1018fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return kRGBA_8888_SkColorType == codecColorType || 1019fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kBGRA_8888_SkColorType == codecColorType; 1020fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 1021fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return origColorType == codecColorType; 1022fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1023fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1024fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1025fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool alpha_type_match(SkAlphaType origAlphaType, SkAlphaType codecAlphaType) { 1026fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (origAlphaType) { 1027fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kUnpremul_SkAlphaType: 1028fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kPremul_SkAlphaType: 1029fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return kUnpremul_SkAlphaType == codecAlphaType || 1030fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kPremul_SkAlphaType == codecAlphaType; 1031fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 1032fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return origAlphaType == codecAlphaType; 1033fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1034fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1035fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1036fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void check_round_trip(skiatest::Reporter* r, SkCodec* origCodec, const SkImageInfo& info) { 1037fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm1; 1038fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm1.allocPixels(info); 1039fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Result result = origCodec->getPixels(info, bm1.getPixels(), bm1.rowBytes()); 1040fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kSuccess == result); 1041fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1042fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Encode the image to png. 1043fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkData> data = 1044fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkData>(sk_tool_utils::EncodeImageToData(bm1, SkEncodedImageFormat::kPNG, 100)); 1045fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1046fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(data)); 1047fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, color_type_match(info.colorType(), codec->getInfo().colorType())); 1048fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, alpha_type_match(info.alphaType(), codec->getInfo().alphaType())); 1049fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1050fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm2; 1051fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm2.allocPixels(info); 1052fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = codec->getPixels(info, bm2.getPixels(), bm2.rowBytes()); 1053fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kSuccess == result); 1054fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1055fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMD5::Digest d1, d2; 1056fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot md5(bm1, &d1); 1057fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot md5(bm2, &d2); 1058fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, d1 == d2); 1059fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1060fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1061fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_PngRoundTrip, r) { 1062fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto codec = SkCodec::MakeFromStream(GetResourceAsStream("images/mandrill_512_q075.jpg")); 1063fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1064fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColorType colorTypesOpaque[] = { 1065fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kRGB_565_SkColorType, kRGBA_8888_SkColorType, kBGRA_8888_SkColorType 1066fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 1067fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (SkColorType colorType : colorTypesOpaque) { 1068fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo newInfo = codec->getInfo().makeColorType(colorType); 1069fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check_round_trip(r, codec.get(), newInfo); 1070fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1071fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1072fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot codec = SkCodec::MakeFromStream(GetResourceAsStream("images/grayscale.jpg")); 1073fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check_round_trip(r, codec.get(), codec->getInfo()); 1074fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1075fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot codec = SkCodec::MakeFromStream(GetResourceAsStream("images/yellow_rose.png")); 1076fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1077fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColorType colorTypesWithAlpha[] = { 1078fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kRGBA_8888_SkColorType, kBGRA_8888_SkColorType 1079fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 1080fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAlphaType alphaTypes[] = { 1081fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kUnpremul_SkAlphaType, kPremul_SkAlphaType 1082fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 1083fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (SkColorType colorType : colorTypesWithAlpha) { 1084fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (SkAlphaType alphaType : alphaTypes) { 1085fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Set color space to nullptr because color correct premultiplies do not round trip. 1086fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo newInfo = codec->getInfo().makeColorType(colorType) 1087fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot .makeAlphaType(alphaType) 1088fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot .makeColorSpace(nullptr); 1089fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check_round_trip(r, codec.get(), newInfo); 1090fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1091fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1092fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1093fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot codec = SkCodec::MakeFromStream(GetResourceAsStream("images/index8.png")); 1094fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1095fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (SkAlphaType alphaType : alphaTypes) { 1096fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo newInfo = codec->getInfo().makeAlphaType(alphaType) 1097fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot .makeColorSpace(nullptr); 1098fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check_round_trip(r, codec.get(), newInfo); 1099fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_conversion_possible(skiatest::Reporter* r, const char* path, 1103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool supportsScanlineDecoder, 1104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool supportsIncrementalDecoder) { 1105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStream> stream(GetResourceAsStream(path)); 1106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream) { 1107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream))); 1111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!codec) { 1112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "failed to create a codec for %s", path); 1113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo infoF16 = codec->getInfo().makeColorType(kRGBA_F16_SkColorType); 1117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 1119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(infoF16); 1120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Result result = codec->getPixels(infoF16, bm.getPixels(), bm.rowBytes()); 1121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result); 1122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = codec->startScanlineDecode(infoF16); 1124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (supportsScanlineDecoder) { 1125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result); 1126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kUnimplemented == result 1128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || SkCodec::kInvalidConversion == result); 1129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = codec->startIncrementalDecode(infoF16, bm.getPixels(), bm.rowBytes()); 1132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (supportsIncrementalDecoder) { 1133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result); 1134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kUnimplemented == result 1136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || SkCodec::kInvalidConversion == result); 1137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot infoF16 = infoF16.makeColorSpace(infoF16.colorSpace()->makeLinearGamma()); 1140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = codec->getPixels(infoF16, bm.getPixels(), bm.rowBytes()); 1141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kSuccess == result); 1142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = codec->startScanlineDecode(infoF16); 1143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (supportsScanlineDecoder) { 1144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kSuccess == result); 1145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kUnimplemented == result); 1147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = codec->startIncrementalDecode(infoF16, bm.getPixels(), bm.rowBytes()); 1150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (supportsIncrementalDecoder) { 1151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kSuccess == result); 1152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kUnimplemented == result); 1154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_F16ConversionPossible, r) { 1158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_conversion_possible(r, "images/color_wheel.webp", false, false); 1159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_conversion_possible(r, "images/mandrill_512_q075.jpg", true, false); 1160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_conversion_possible(r, "images/yellow_rose.png", false, true); 1161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void decode_frame(skiatest::Reporter* r, SkCodec* codec, size_t frame) { 1164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 1165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto info = codec->getInfo().makeColorType(kN32_SkColorType); 1166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(info); 1167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Options opts; 1169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fFrameIndex = frame; 1170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, SkCodec::kSuccess == codec->getPixels(info, 1171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.getPixels(), bm.rowBytes(), &opts)); 1172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// For an animated GIF, we should only read enough to decode frame 0 if the 1175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// client never calls getFrameInfo and only decodes frame 0. 1176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_skipFullParse, r) { 1177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto path = "images/test640x479.gif"; 1178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto streamObj = GetResourceAsStream(path); 1179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!streamObj) { 1180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkStream* stream = streamObj.get(); 1183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Note that we cheat and hold on to the stream pointer, but SkCodec will 1185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // take ownership. We will not refer to the stream after the SkCodec 1186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // deletes it. 1187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(streamObj))); 1188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!codec) { 1189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "Failed to create codec for %s", path); 1190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, stream->hasPosition()); 1194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const size_t sizePosition = stream->getPosition(); 1195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, stream->hasLength() && sizePosition < stream->getLength()); 1196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This should read more of the stream, but not the whole stream. 1198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot decode_frame(r, codec.get(), 0); 1199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const size_t positionAfterFirstFrame = stream->getPosition(); 1200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, positionAfterFirstFrame > sizePosition 1201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot && positionAfterFirstFrame < stream->getLength()); 1202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // There is more data in the stream. 1204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto frameInfo = codec->getFrameInfo(); 1205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, frameInfo.size() == 4); 1206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, stream->getPosition() > positionAfterFirstFrame); 1207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Only rewinds up to a limit. 1210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass LimitedRewindingStream : public SkStream { 1211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 1212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static std::unique_ptr<SkStream> Make(const char path[], size_t limit) { 1213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto stream = GetResourceAsStream(path); 1214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream) { 1215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 1216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return std::unique_ptr<SkStream>(new LimitedRewindingStream(std::move(stream), limit)); 1218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t read(void* buffer, size_t size) override { 1221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const size_t bytes = fStream->read(buffer, size); 1222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPosition += bytes; 1223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return bytes; 1224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool isAtEnd() const override { 1227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fStream->isAtEnd(); 1228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool rewind() override { 1231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fPosition <= fLimit && fStream->rewind()) { 1232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPosition = 0; 1233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 1240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStream> fStream; 1241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const size_t fLimit; 1242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t fPosition; 1243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot LimitedRewindingStream(std::unique_ptr<SkStream> stream, size_t limit) 1245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fStream(std::move(stream)) 1246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fLimit(limit) 1247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fPosition(0) 1248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 1249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fStream); 1250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 1252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_fallBack, r) { 1254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // SkAndroidCodec needs to be able to fall back to scanline decoding 1255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // if incremental decoding does not work. Make sure this does not 1256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // require a rewind. 1257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Formats that currently do not support incremental decoding 1259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto files = { 1260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "images/CMYK.jpg", 1261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "images/color_wheel.ico", 1262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "images/mandrill.wbmp", 1263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "images/randPixels.bmp", 1264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 1265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (auto file : files) { 1266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto stream = LimitedRewindingStream::Make(file, SkCodec::MinBufferedBytesNeeded()); 1267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream) { 1268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("Missing resources (%s). Set --resourcePath.\n", file); 1269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream))); 1273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!codec) { 1274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "Failed to create codec for %s,", file); 1275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); 1279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 1280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(info); 1281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkCodec::kUnimplemented != codec->startIncrementalDecode(info, bm.getPixels(), 1283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.rowBytes())) { 1284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "Is scanline decoding now implemented for %s?", file); 1285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Scanline decoding should not require a rewind. 1289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Result result = codec->startScanlineDecode(info); 1290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkCodec::kSuccess != result) { 1291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "Scanline decoding failed for %s with %i", file, result); 1292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// This test verifies that we fixed an assert statement that fired when reusing a png codec 1297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// after scaling. 1298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_reusePng, r) { 1299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStream> stream(GetResourceAsStream("images/plane.png")); 1300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream) { 1301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::MakeFromStream(std::move(stream))); 1305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!codec) { 1306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "Failed to create codec\n"); 1307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAndroidCodec::AndroidOptions opts; 1311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fSampleSize = 5; 1312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto size = codec->getSampledDimensions(opts.fSampleSize); 1313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto info = codec->getInfo().makeWH(size.fWidth, size.fHeight).makeColorType(kN32_SkColorType); 1314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 1315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(info); 1316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto result = codec->getAndroidPixels(info, bm.getPixels(), bm.rowBytes(), &opts); 1317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, result == SkCodec::kSuccess); 1318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info = codec->getInfo().makeColorType(kN32_SkColorType); 1320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(info); 1321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fSampleSize = 1; 1322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = codec->getAndroidPixels(info, bm.getPixels(), bm.rowBytes(), &opts); 1323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, result == SkCodec::kSuccess); 1324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_rowsDecoded, r) { 1327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto file = "images/plane_interlaced.png"; 1328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStream> stream(GetResourceAsStream(file)); 1329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream) { 1330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This is enough to read the header etc, but no rows. 1334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(SkData::MakeFromStream(stream.get(), 99))); 1335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!codec) { 1336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "Failed to create codec\n"); 1337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto info = codec->getInfo().makeColorType(kN32_SkColorType); 1341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 1342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(info); 1343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto result = codec->startIncrementalDecode(info, bm.getPixels(), bm.rowBytes()); 1344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, result == SkCodec::kSuccess); 1345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This is an arbitrary value. The important fact is that it is not zero, and rowsDecoded 1347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // should get set to zero by incrementalDecode. 1348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int rowsDecoded = 77; 1349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = codec->incrementalDecode(&rowsDecoded); 1350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, result == SkCodec::kIncompleteInput); 1351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, rowsDecoded == 0); 1352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_invalid_images(skiatest::Reporter* r, const char* path, 1355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Result expectedResult) { 1356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto stream = GetResourceAsStream(path); 1357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream) { 1358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream))); 1362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec); 1363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec.get(), codec->getInfo().makeColorType(kN32_SkColorType), expectedResult, 1365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nullptr); 1366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_InvalidImages, r) { 1369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // ASAN will complain if there is an issue. 1370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_images(r, "invalid_images/skbug5887.gif", SkCodec::kErrorInInput); 1371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_images(r, "invalid_images/many-progressive-scans.jpg", SkCodec::kInvalidInput); 1372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_images(r, "invalid_images/b33251605.bmp", SkCodec::kIncompleteInput); 1373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_images(r, "invalid_images/bad_palette.png", SkCodec::kInvalidInput); 1374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_invalid_header(skiatest::Reporter* r, const char* path) { 1377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto data = GetResourceAsData(path); 1378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!data) { 1379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStreamAsset> stream(new SkMemoryStream(std::move(data))); 1382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream) { 1383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream))); 1386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, !codec); 1387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_InvalidHeader, r) { 1390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_header(r, "invalid_images/int_overflow.ico"); 1391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // These files report values that have caused problems with SkFILEStreams. 1393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // They are invalid, and should not create SkCodecs. 1394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_header(r, "invalid_images/b33651913.bmp"); 1395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_invalid_header(r, "invalid_images/b34778578.bmp"); 1396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_InvalidAnimated, r) { 1399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // ASAN will complain if there is an issue. 1400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto path = "invalid_images/skbug6046.gif"; 1401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto stream = GetResourceAsStream(path); 1402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream) { 1403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream))); 1407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, codec); 1408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!codec) { 1409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const auto info = codec->getInfo().makeColorType(kN32_SkColorType); 1413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 1414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.allocPixels(info); 1415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto frameInfos = codec->getFrameInfo(); 1417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCodec::Options opts; 1418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; static_cast<size_t>(i) < frameInfos.size(); i++) { 1419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fFrameIndex = i; 1420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const auto reqFrame = frameInfos[i].fRequiredFrame; 1421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot opts.fPriorFrame = reqFrame == i - 1 ? reqFrame : SkCodec::kNone; 1422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto result = codec->startIncrementalDecode(info, bm.getPixels(), bm.rowBytes(), &opts); 1423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (result != SkCodec::kSuccess) { 1424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "Failed to start decoding frame %i (out of %i) with error %i\n", i, 1425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot frameInfos.size(), result); 1426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot codec->incrementalDecode(); 1430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void encode_format(SkDynamicMemoryWStream* stream, const SkPixmap& pixmap, 1434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTransferFunctionBehavior unpremulBehavior, 1435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkEncodedImageFormat format) { 1436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPngEncoder::Options pngOptions; 1437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkWebpEncoder::Options webpOptions; 1438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pngOptions.fUnpremulBehavior = unpremulBehavior; 1439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot webpOptions.fUnpremulBehavior = unpremulBehavior; 1440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (format) { 1441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkEncodedImageFormat::kPNG: 1442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPngEncoder::Encode(stream, pixmap, pngOptions); 1443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkEncodedImageFormat::kJPEG: 1445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkJpegEncoder::Encode(stream, pixmap, SkJpegEncoder::Options()); 1446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkEncodedImageFormat::kWEBP: 1448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkWebpEncoder::Encode(stream, pixmap, webpOptions); 1449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 1451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(false); 1452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_encode_icc(skiatest::Reporter* r, SkEncodedImageFormat format, 1457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTransferFunctionBehavior unpremulBehavior) { 1458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Test with sRGB color space. 1459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap srgbBitmap; 1460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo srgbInfo = SkImageInfo::MakeS32(1, 1, kOpaque_SkAlphaType); 1461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot srgbBitmap.allocPixels(srgbInfo); 1462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *srgbBitmap.getAddr32(0, 0) = 0; 1463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPixmap pixmap; 1464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot srgbBitmap.peekPixels(&pixmap); 1465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDynamicMemoryWStream srgbBuf; 1466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot encode_format(&srgbBuf, pixmap, unpremulBehavior, format); 1467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkData> srgbData = srgbBuf.detachAsData(); 1468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> srgbCodec(SkCodec::MakeFromData(srgbData)); 1469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, srgbCodec->getInfo().colorSpace() == SkColorSpace::MakeSRGB().get()); 1470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Test with P3 color space. 1472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDynamicMemoryWStream p3Buf; 1473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkColorSpace> p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, 1474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColorSpace::kDCIP3_D65_Gamut); 1475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixmap.setColorSpace(p3); 1476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot encode_format(&p3Buf, pixmap, unpremulBehavior, format); 1477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkData> p3Data = p3Buf.detachAsData(); 1478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> p3Codec(SkCodec::MakeFromData(p3Data)); 1479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, p3Codec->getInfo().colorSpace()->gammaCloseToSRGB()); 1480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix44 mat0(SkMatrix44::kUninitialized_Constructor); 1481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix44 mat1(SkMatrix44::kUninitialized_Constructor); 1482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool success = p3->toXYZD50(&mat0); 1483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, success); 1484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot success = p3Codec->getInfo().colorSpace()->toXYZD50(&mat1); 1485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, success); 1486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < 4; i++) { 1488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int j = 0; j < 4; j++) { 1489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot REPORTER_ASSERT(r, color_space_almost_equal(mat0.get(i, j), mat1.get(i, j))); 1490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_EncodeICC, r) { 1495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_encode_icc(r, SkEncodedImageFormat::kPNG, SkTransferFunctionBehavior::kRespect); 1496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_encode_icc(r, SkEncodedImageFormat::kJPEG, SkTransferFunctionBehavior::kRespect); 1497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_encode_icc(r, SkEncodedImageFormat::kWEBP, SkTransferFunctionBehavior::kRespect); 1498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_encode_icc(r, SkEncodedImageFormat::kPNG, SkTransferFunctionBehavior::kIgnore); 1499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_encode_icc(r, SkEncodedImageFormat::kJPEG, SkTransferFunctionBehavior::kIgnore); 1500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_encode_icc(r, SkEncodedImageFormat::kWEBP, SkTransferFunctionBehavior::kIgnore); 1501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(Codec_webp_rowsDecoded, r) { 1504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* path = "images/baby_tux.webp"; 1505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkData> data(GetResourceAsData(path)); 1506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!data) { 1507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Truncate this file so that the header is available but no rows can be 1511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // decoded. This should create a codec but fail to decode. 1512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t truncatedSize = 5000; 1513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkData> subset = SkData::MakeSubset(data.get(), 0, truncatedSize); 1514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(std::move(subset)); 1515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!codec) { 1516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ERRORF(r, "Failed to create a codec for %s truncated to only %lu bytes", 1517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path, truncatedSize); 1518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test_info(r, codec.get(), codec->getInfo(), SkCodec::kInvalidInput, nullptr); 1522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1523