| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "Resources.h" | 8 #include "Resources.h" |
| 9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
| 10 #include "SkCodec.h" | 10 #include "SkCodec.h" |
| 11 #include "SkMD5.h" | 11 #include "SkMD5.h" |
| 12 #include "SkRandom.h" |
| 12 #include "SkScanlineDecoder.h" | 13 #include "SkScanlineDecoder.h" |
| 13 #include "Test.h" | 14 #include "Test.h" |
| 14 | 15 |
| 15 static SkStreamAsset* resource(const char path[]) { | 16 static SkStreamAsset* resource(const char path[]) { |
| 16 SkString fullPath = GetResourcePath(path); | 17 SkString fullPath = GetResourcePath(path); |
| 17 return SkStream::NewFromFile(fullPath.c_str()); | 18 return SkStream::NewFromFile(fullPath.c_str()); |
| 18 } | 19 } |
| 19 | 20 |
| 20 static void md5(const SkBitmap& bm, SkMD5::Digest* digest) { | 21 static void md5(const SkBitmap& bm, SkMD5::Digest* digest) { |
| 21 SkAutoLockPixels autoLockPixels(bm); | 22 SkAutoLockPixels autoLockPixels(bm); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 34 * @param goodDigest The known good digest to compare to. | 35 * @param goodDigest The known good digest to compare to. |
| 35 * @param bm The bitmap to test. | 36 * @param bm The bitmap to test. |
| 36 */ | 37 */ |
| 37 static void compare_to_good_digest(skiatest::Reporter* r, const SkMD5::Digest& g
oodDigest, | 38 static void compare_to_good_digest(skiatest::Reporter* r, const SkMD5::Digest& g
oodDigest, |
| 38 const SkBitmap& bm) { | 39 const SkBitmap& bm) { |
| 39 SkMD5::Digest digest; | 40 SkMD5::Digest digest; |
| 40 md5(bm, &digest); | 41 md5(bm, &digest); |
| 41 REPORTER_ASSERT(r, digest == goodDigest); | 42 REPORTER_ASSERT(r, digest == goodDigest); |
| 42 } | 43 } |
| 43 | 44 |
| 45 SkIRect generate_random_subset(SkRandom* rand, int w, int h) { |
| 46 SkIRect rect; |
| 47 do { |
| 48 rect.fLeft = rand->nextRangeU(0, w); |
| 49 rect.fTop = rand->nextRangeU(0, h); |
| 50 rect.fRight = rand->nextRangeU(0, w); |
| 51 rect.fBottom = rand->nextRangeU(0, h); |
| 52 rect.sort(); |
| 53 } while (rect.isEmpty()); |
| 54 return rect; |
| 55 } |
| 56 |
| 44 static void check(skiatest::Reporter* r, | 57 static void check(skiatest::Reporter* r, |
| 45 const char path[], | 58 const char path[], |
| 46 SkISize size, | 59 SkISize size, |
| 47 bool supportsScanlineDecoding) { | 60 bool supportsScanlineDecoding, |
| 61 bool supportsSubsetDecoding) { |
| 48 SkAutoTDelete<SkStream> stream(resource(path)); | 62 SkAutoTDelete<SkStream> stream(resource(path)); |
| 49 if (!stream) { | 63 if (!stream) { |
| 50 SkDebugf("Missing resource '%s'\n", path); | 64 SkDebugf("Missing resource '%s'\n", path); |
| 51 return; | 65 return; |
| 52 } | 66 } |
| 53 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach())); | 67 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach())); |
| 54 if (!codec) { | 68 if (!codec) { |
| 55 ERRORF(r, "Unable to decode '%s'", path); | 69 ERRORF(r, "Unable to decode '%s'", path); |
| 56 return; | 70 return; |
| 57 } | 71 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 | 109 |
| 96 for (int y = 0; y < info.height(); y++) { | 110 for (int y = 0; y < info.height(); y++) { |
| 97 result = scanlineDecoder->getScanlines(bm.getAddr(0, y), 1, 0); | 111 result = scanlineDecoder->getScanlines(bm.getAddr(0, y), 1, 0); |
| 98 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | 112 REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
| 99 } | 113 } |
| 100 // verify that scanline decoding gives the same result. | 114 // verify that scanline decoding gives the same result. |
| 101 compare_to_good_digest(r, digest, bm); | 115 compare_to_good_digest(r, digest, bm); |
| 102 } else { | 116 } else { |
| 103 REPORTER_ASSERT(r, !scanlineDecoder); | 117 REPORTER_ASSERT(r, !scanlineDecoder); |
| 104 } | 118 } |
| 119 |
| 120 // The rest of this function tests decoding subsets, and will decode an arbi
trary number of |
| 121 // random subsets. |
| 122 // Do not attempt to decode subsets of an image of only once pixel, since th
ere is no |
| 123 // meaningful subset. |
| 124 if (size.width() * size.height() == 1) { |
| 125 return; |
| 126 } |
| 127 |
| 128 SkRandom rand; |
| 129 SkIRect subset; |
| 130 SkCodec::Options opts; |
| 131 opts.fSubset = ⊂ |
| 132 for (int i = 0; i < 5; i++) { |
| 133 subset = generate_random_subset(&rand, size.width(), size.height()); |
| 134 SkASSERT(!subset.isEmpty()); |
| 135 const bool supported = codec->getValidSubset(&subset); |
| 136 REPORTER_ASSERT(r, supported == supportsSubsetDecoding); |
| 137 |
| 138 SkImageInfo subsetInfo = info.makeWH(subset.width(), subset.height()); |
| 139 SkBitmap bm; |
| 140 bm.allocPixels(subsetInfo); |
| 141 const SkCodec::Result result = codec->getPixels(bm.info(), bm.getPixels(
), bm.rowBytes(), |
| 142 &opts, NULL, NULL); |
| 143 |
| 144 if (supportsSubsetDecoding) { |
| 145 REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
| 146 // Webp is the only codec that supports subsets, and it will have mo
dified the subset |
| 147 // to have even left/top. |
| 148 REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTo
p)); |
| 149 } else { |
| 150 // No subsets will work. |
| 151 REPORTER_ASSERT(r, result == SkCodec::kUnimplemented); |
| 152 } |
| 153 } |
| 105 } | 154 } |
| 106 | 155 |
| 107 DEF_TEST(Codec, r) { | 156 DEF_TEST(Codec, r) { |
| 108 // WBMP | 157 // WBMP |
| 109 check(r, "mandrill.wbmp", SkISize::Make(512, 512), false); | 158 check(r, "mandrill.wbmp", SkISize::Make(512, 512), false, false); |
| 110 | 159 |
| 111 // WEBP | 160 // WEBP |
| 112 check(r, "baby_tux.webp", SkISize::Make(386, 395), false); | 161 check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true); |
| 113 check(r, "color_wheel.webp", SkISize::Make(128, 128), false); | 162 check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true); |
| 114 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false); | 163 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true); |
| 115 | 164 |
| 116 // BMP | 165 // BMP |
| 117 check(r, "randPixels.bmp", SkISize::Make(8, 8), false); | 166 check(r, "randPixels.bmp", SkISize::Make(8, 8), false, false); |
| 118 | 167 |
| 119 // ICO | 168 // ICO |
| 120 // These two tests examine interestingly different behavior: | 169 // These two tests examine interestingly different behavior: |
| 121 // Decodes an embedded BMP image | 170 // Decodes an embedded BMP image |
| 122 check(r, "color_wheel.ico", SkISize::Make(128, 128), false); | 171 check(r, "color_wheel.ico", SkISize::Make(128, 128), false, false); |
| 123 // Decodes an embedded PNG image | 172 // Decodes an embedded PNG image |
| 124 check(r, "google_chrome.ico", SkISize::Make(256, 256), false); | 173 check(r, "google_chrome.ico", SkISize::Make(256, 256), false, false); |
| 125 | 174 |
| 126 // GIF | 175 // GIF |
| 127 check(r, "box.gif", SkISize::Make(200, 55), false); | 176 check(r, "box.gif", SkISize::Make(200, 55), false, false); |
| 128 check(r, "color_wheel.gif", SkISize::Make(128, 128), false); | 177 check(r, "color_wheel.gif", SkISize::Make(128, 128), false, false); |
| 129 check(r, "randPixels.gif", SkISize::Make(8, 8), false); | 178 check(r, "randPixels.gif", SkISize::Make(8, 8), false, false); |
| 130 | 179 |
| 131 // JPG | 180 // JPG |
| 132 check(r, "CMYK.jpg", SkISize::Make(642, 516), true); | 181 check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false); |
| 133 check(r, "color_wheel.jpg", SkISize::Make(128, 128), true); | 182 check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false); |
| 134 check(r, "grayscale.jpg", SkISize::Make(128, 128), true); | 183 check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false); |
| 135 check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true); | 184 check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false); |
| 136 check(r, "randPixels.jpg", SkISize::Make(8, 8), true); | 185 check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false); |
| 137 | 186 |
| 138 // PNG | 187 // PNG |
| 139 check(r, "arrow.png", SkISize::Make(187, 312), true); | 188 check(r, "arrow.png", SkISize::Make(187, 312), true, false); |
| 140 check(r, "baby_tux.png", SkISize::Make(240, 246), true); | 189 check(r, "baby_tux.png", SkISize::Make(240, 246), true, false); |
| 141 check(r, "color_wheel.png", SkISize::Make(128, 128), true); | 190 check(r, "color_wheel.png", SkISize::Make(128, 128), true, false); |
| 142 check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), true); | 191 check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), true, fals
e); |
| 143 check(r, "mandrill_128.png", SkISize::Make(128, 128), true); | 192 check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false); |
| 144 check(r, "mandrill_16.png", SkISize::Make(16, 16), true); | 193 check(r, "mandrill_16.png", SkISize::Make(16, 16), true, false); |
| 145 check(r, "mandrill_256.png", SkISize::Make(256, 256), true); | 194 check(r, "mandrill_256.png", SkISize::Make(256, 256), true, false); |
| 146 check(r, "mandrill_32.png", SkISize::Make(32, 32), true); | 195 check(r, "mandrill_32.png", SkISize::Make(32, 32), true, false); |
| 147 check(r, "mandrill_512.png", SkISize::Make(512, 512), true); | 196 check(r, "mandrill_512.png", SkISize::Make(512, 512), true, false); |
| 148 check(r, "mandrill_64.png", SkISize::Make(64, 64), true); | 197 check(r, "mandrill_64.png", SkISize::Make(64, 64), true, false); |
| 149 check(r, "plane.png", SkISize::Make(250, 126), true); | 198 check(r, "plane.png", SkISize::Make(250, 126), true, false); |
| 150 check(r, "randPixels.png", SkISize::Make(8, 8), true); | 199 check(r, "randPixels.png", SkISize::Make(8, 8), true, false); |
| 151 check(r, "yellow_rose.png", SkISize::Make(400, 301), true); | 200 check(r, "yellow_rose.png", SkISize::Make(400, 301), true, false); |
| 152 } | 201 } |
| 153 | 202 |
| 154 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_
t len) { | 203 static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_
t len) { |
| 155 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals
e)); | 204 SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, fals
e)); |
| 156 // We should not have gotten a codec. Bots should catch us if we leaked anyt
hing. | 205 // We should not have gotten a codec. Bots should catch us if we leaked anyt
hing. |
| 157 REPORTER_ASSERT(r, !codec); | 206 REPORTER_ASSERT(r, !codec); |
| 158 } | 207 } |
| 159 | 208 |
| 160 // Ensure that SkCodec::NewFromStream handles freeing the passed in SkStream, | 209 // Ensure that SkCodec::NewFromStream handles freeing the passed in SkStream, |
| 161 // even on failure. Test some bad streams. | 210 // even on failure. Test some bad streams. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 test_empty(r, "empty_images/zero-embedded.ico"); | 285 test_empty(r, "empty_images/zero-embedded.ico"); |
| 237 test_empty(r, "empty_images/zero-width.bmp"); | 286 test_empty(r, "empty_images/zero-width.bmp"); |
| 238 test_empty(r, "empty_images/zero-height.bmp"); | 287 test_empty(r, "empty_images/zero-height.bmp"); |
| 239 test_empty(r, "empty_images/zero-width.jpg"); | 288 test_empty(r, "empty_images/zero-width.jpg"); |
| 240 test_empty(r, "empty_images/zero-height.jpg"); | 289 test_empty(r, "empty_images/zero-height.jpg"); |
| 241 test_empty(r, "empty_images/zero-width.png"); | 290 test_empty(r, "empty_images/zero-width.png"); |
| 242 test_empty(r, "empty_images/zero-height.png"); | 291 test_empty(r, "empty_images/zero-height.png"); |
| 243 test_empty(r, "empty_images/zero-width.wbmp"); | 292 test_empty(r, "empty_images/zero-width.wbmp"); |
| 244 test_empty(r, "empty_images/zero-height.wbmp"); | 293 test_empty(r, "empty_images/zero-height.wbmp"); |
| 245 } | 294 } |
| OLD | NEW |