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" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 do { | 67 do { |
68 rect.fLeft = rand->nextRangeU(0, w); | 68 rect.fLeft = rand->nextRangeU(0, w); |
69 rect.fTop = rand->nextRangeU(0, h); | 69 rect.fTop = rand->nextRangeU(0, h); |
70 rect.fRight = rand->nextRangeU(0, w); | 70 rect.fRight = rand->nextRangeU(0, w); |
71 rect.fBottom = rand->nextRangeU(0, h); | 71 rect.fBottom = rand->nextRangeU(0, h); |
72 rect.sort(); | 72 rect.sort(); |
73 } while (rect.isEmpty()); | 73 } while (rect.isEmpty()); |
74 return rect; | 74 return rect; |
75 } | 75 } |
76 | 76 |
77 static void check(skiatest::Reporter* r, | 77 static void test_codec(skiatest::Reporter* r, SkCodec* codec, SkBitmap& bm, cons
t SkImageInfo& info, |
78 const char path[], | 78 const SkISize& size, bool supports565, SkMD5::Digest* digest, |
79 SkISize size, | 79 const SkMD5::Digest* goodDigest) { |
80 bool supportsScanlineDecoding, | |
81 bool supportsSubsetDecoding, | |
82 bool supports565 = true) { | |
83 SkAutoTDelete<SkStream> stream(resource(path)); | |
84 if (!stream) { | |
85 SkDebugf("Missing resource '%s'\n", path); | |
86 return; | |
87 } | |
88 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach())); | |
89 if (!codec) { | |
90 ERRORF(r, "Unable to decode '%s'", path); | |
91 return; | |
92 } | |
93 | |
94 // This test is used primarily to verify rewinding works properly. Using kN
32 allows | |
95 // us to test this without the added overhead of creating different bitmaps
depending | |
96 // on the color type (ex: building a color table for kIndex8). DM is where
we test | |
97 // decodes to all possible destination color types. | |
98 SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); | |
99 REPORTER_ASSERT(r, info.dimensions() == size); | 80 REPORTER_ASSERT(r, info.dimensions() == size); |
100 | |
101 SkBitmap bm; | |
102 bm.allocPixels(info); | 81 bm.allocPixels(info); |
103 SkAutoLockPixels autoLockPixels(bm); | 82 SkAutoLockPixels autoLockPixels(bm); |
104 SkCodec::Result result = | 83 |
105 codec->getPixels(info, bm.getPixels(), bm.rowBytes(), nullptr, nullptr,
nullptr); | 84 SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes(
)); |
106 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | 85 REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
107 | 86 |
108 SkMD5::Digest digest; | 87 md5(bm, digest); |
109 md5(bm, &digest); | 88 if (goodDigest) { |
| 89 REPORTER_ASSERT(r, *digest == *goodDigest); |
| 90 } |
110 | 91 |
111 { | 92 { |
112 // Test decoding to 565 | 93 // Test decoding to 565 |
113 SkImageInfo info565 = info.makeColorType(kRGB_565_SkColorType); | 94 SkImageInfo info565 = info.makeColorType(kRGB_565_SkColorType); |
114 SkCodec::Result expected = (supports565 && info.alphaType() == kOpaque_S
kAlphaType) ? | 95 SkCodec::Result expected = (supports565 && info.alphaType() == kOpaque_S
kAlphaType) ? |
115 SkCodec::kSuccess : SkCodec::kInvalidConversion; | 96 SkCodec::kSuccess : SkCodec::kInvalidConversion; |
116 test_info(r, codec, info565, expected, nullptr); | 97 test_info(r, codec, info565, expected, nullptr); |
117 } | 98 } |
118 | 99 |
119 // Verify that re-decoding gives the same result. It is interesting to chec
k this after | 100 // Verify that re-decoding gives the same result. It is interesting to chec
k this after |
120 // a decode to 565, since choosing to decode to 565 may result in some of th
e decode | 101 // a decode to 565, since choosing to decode to 565 may result in some of th
e decode |
121 // options being modified. These options should return to their defaults on
another | 102 // options being modified. These options should return to their defaults on
another |
122 // decode to kN32, so the new digest should match the old digest. | 103 // decode to kN32, so the new digest should match the old digest. |
123 test_info(r, codec, info, SkCodec::kSuccess, &digest); | 104 test_info(r, codec, info, SkCodec::kSuccess, digest); |
124 | 105 |
125 { | 106 { |
126 // Check alpha type conversions | 107 // Check alpha type conversions |
127 if (info.alphaType() == kOpaque_SkAlphaType) { | 108 if (info.alphaType() == kOpaque_SkAlphaType) { |
128 test_info(r, codec, info.makeAlphaType(kUnpremul_SkAlphaType), | 109 test_info(r, codec, info.makeAlphaType(kUnpremul_SkAlphaType), |
129 SkCodec::kInvalidConversion, nullptr); | 110 SkCodec::kInvalidConversion, nullptr); |
130 test_info(r, codec, info.makeAlphaType(kPremul_SkAlphaType), | 111 test_info(r, codec, info.makeAlphaType(kPremul_SkAlphaType), |
131 SkCodec::kInvalidConversion, nullptr); | 112 SkCodec::kInvalidConversion, nullptr); |
132 } else { | 113 } else { |
133 // Decoding to opaque should fail | 114 // Decoding to opaque should fail |
134 test_info(r, codec, info.makeAlphaType(kOpaque_SkAlphaType), | 115 test_info(r, codec, info.makeAlphaType(kOpaque_SkAlphaType), |
135 SkCodec::kInvalidConversion, nullptr); | 116 SkCodec::kInvalidConversion, nullptr); |
136 SkAlphaType otherAt = info.alphaType(); | 117 SkAlphaType otherAt = info.alphaType(); |
137 if (kPremul_SkAlphaType == otherAt) { | 118 if (kPremul_SkAlphaType == otherAt) { |
138 otherAt = kUnpremul_SkAlphaType; | 119 otherAt = kUnpremul_SkAlphaType; |
139 } else { | 120 } else { |
140 otherAt = kPremul_SkAlphaType; | 121 otherAt = kPremul_SkAlphaType; |
141 } | 122 } |
142 // The other non-opaque alpha type should always succeed, but not ma
tch. | 123 // The other non-opaque alpha type should always succeed, but not ma
tch. |
143 test_info(r, codec, info.makeAlphaType(otherAt), SkCodec::kSuccess,
nullptr); | 124 test_info(r, codec, info.makeAlphaType(otherAt), SkCodec::kSuccess,
nullptr); |
144 } | 125 } |
145 } | 126 } |
| 127 } |
| 128 |
| 129 static void check(skiatest::Reporter* r, |
| 130 const char path[], |
| 131 SkISize size, |
| 132 bool supportsScanlineDecoding, |
| 133 bool supportsSubsetDecoding, |
| 134 bool supports565 = true) { |
| 135 |
| 136 SkAutoTDelete<SkStream> stream(resource(path)); |
| 137 if (!stream) { |
| 138 SkDebugf("Missing resource '%s'\n", path); |
| 139 return; |
| 140 } |
| 141 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach())); |
| 142 if (!codec) { |
| 143 ERRORF(r, "Unable to decode '%s'", path); |
| 144 return; |
| 145 } |
| 146 |
| 147 // Test full image decodes with SkCodec |
| 148 SkMD5::Digest codecDigest; |
| 149 SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); |
| 150 SkBitmap bm; |
| 151 test_codec(r, codec, bm, info, size, supports565, &codecDigest, nullptr); |
146 | 152 |
147 // Scanline decoding follows. | 153 // Scanline decoding follows. |
148 | 154 // Need to call startScanlineDecode() first. |
149 // Need to call start() first. | |
150 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) | 155 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) |
151 == SkCodec::kScanlineDecodingNotStarted); | 156 == SkCodec::kScanlineDecodingNotStarted); |
152 REPORTER_ASSERT(r, codec->skipScanlines(1) | 157 REPORTER_ASSERT(r, codec->skipScanlines(1) |
153 == SkCodec::kScanlineDecodingNotStarted); | 158 == SkCodec::kScanlineDecodingNotStarted); |
154 | 159 |
155 const SkCodec::Result startResult = codec->startScanlineDecode(info); | 160 const SkCodec::Result startResult = codec->startScanlineDecode(info); |
156 if (supportsScanlineDecoding) { | 161 if (supportsScanlineDecoding) { |
157 bm.eraseColor(SK_ColorYELLOW); | 162 bm.eraseColor(SK_ColorYELLOW); |
158 | 163 |
159 REPORTER_ASSERT(r, startResult == SkCodec::kSuccess); | 164 REPORTER_ASSERT(r, startResult == SkCodec::kSuccess); |
160 | 165 |
161 for (int y = 0; y < info.height(); y++) { | 166 for (int y = 0; y < info.height(); y++) { |
162 result = codec->getScanlines(bm.getAddr(0, y), 1, 0); | 167 SkCodec::Result result = codec->getScanlines(bm.getAddr(0, y), 1, 0)
; |
163 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | 168 REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
164 } | 169 } |
165 // verify that scanline decoding gives the same result. | 170 // verify that scanline decoding gives the same result. |
166 if (SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder()) { | 171 if (SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder()) { |
167 compare_to_good_digest(r, digest, bm); | 172 compare_to_good_digest(r, codecDigest, bm); |
168 } | 173 } |
169 | 174 |
170 // Cannot continue to decode scanlines beyond the end | 175 // Cannot continue to decode scanlines beyond the end |
171 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) | 176 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) |
172 == SkCodec::kInvalidParameters); | 177 == SkCodec::kInvalidParameters); |
173 | 178 |
174 // Interrupting a scanline decode with a full decode starts from | 179 // Interrupting a scanline decode with a full decode starts from |
175 // scratch | 180 // scratch |
176 REPORTER_ASSERT(r, codec->startScanlineDecode(info) == SkCodec::kSuccess
); | 181 REPORTER_ASSERT(r, codec->startScanlineDecode(info) == SkCodec::kSuccess
); |
177 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) | 182 REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 if (supportsSubsetDecoding) { | 218 if (supportsSubsetDecoding) { |
214 REPORTER_ASSERT(r, result == SkCodec::kSuccess); | 219 REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
215 // Webp is the only codec that supports subsets, and it will have mo
dified the subset | 220 // Webp is the only codec that supports subsets, and it will have mo
dified the subset |
216 // to have even left/top. | 221 // to have even left/top. |
217 REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTo
p)); | 222 REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTo
p)); |
218 } else { | 223 } else { |
219 // No subsets will work. | 224 // No subsets will work. |
220 REPORTER_ASSERT(r, result == SkCodec::kUnimplemented); | 225 REPORTER_ASSERT(r, result == SkCodec::kUnimplemented); |
221 } | 226 } |
222 } | 227 } |
| 228 |
| 229 // SkScaledCodec tests |
| 230 if (supportsScanlineDecoding || supportsSubsetDecoding){ |
| 231 SkAutoTDelete<SkStream> stream(resource(path)); |
| 232 if (!stream) { |
| 233 SkDebugf("Missing resource '%s'\n", path); |
| 234 return; |
| 235 } |
| 236 SkAutoTDelete<SkCodec> codec(SkScaledCodec::NewFromStream(stream.detach(
))); |
| 237 if (!codec) { |
| 238 ERRORF(r, "Unable to decode '%s'", path); |
| 239 return; |
| 240 } |
| 241 |
| 242 SkBitmap bm; |
| 243 SkMD5::Digest scaledCodecDigest; |
| 244 test_codec(r, codec, bm, info, size, supports565, &scaledCodecDigest, &c
odecDigest); |
| 245 } |
223 } | 246 } |
224 | 247 |
225 DEF_TEST(Codec, r) { | 248 DEF_TEST(Codec, r) { |
226 // WBMP | 249 // WBMP |
227 check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false); | 250 check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false); |
228 | 251 |
229 // WEBP | 252 // WEBP |
230 check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true); | 253 check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true); |
231 check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true); | 254 check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true); |
232 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true); | 255 check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true); |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result); | 522 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result); |
500 result = decoder->startScanlineDecode( | 523 result = decoder->startScanlineDecode( |
501 decoder->getInfo().makeColorType(kIndex_8_SkColorType)); | 524 decoder->getInfo().makeColorType(kIndex_8_SkColorType)); |
502 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result); | 525 REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result); |
503 } | 526 } |
504 | 527 |
505 DEF_TEST(Codec_Params, r) { | 528 DEF_TEST(Codec_Params, r) { |
506 test_invalid_parameters(r, "index8.png"); | 529 test_invalid_parameters(r, "index8.png"); |
507 test_invalid_parameters(r, "mandrill.wbmp"); | 530 test_invalid_parameters(r, "mandrill.wbmp"); |
508 } | 531 } |
OLD | NEW |