Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(200)

Side by Side Diff: tests/ImageDecodingTest.cpp

Issue 93703004: Change SkDecodingImageGenerator API (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: changes from reed Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 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 "Test.h" 8 #include "Test.h"
9 #include "TestClassDef.h" 9 #include "TestClassDef.h"
10 #include "SkBitmap.h" 10 #include "SkBitmap.h"
11 #include "SkCanvas.h" 11 #include "SkCanvas.h"
12 #include "SkColor.h" 12 #include "SkColor.h"
13 #include "SkColorPriv.h" 13 #include "SkColorPriv.h"
14 #include "SkData.h" 14 #include "SkData.h"
15 #include "SkDecodingImageGenerator.h"
16 #include "SkDiscardableMemoryPool.h"
15 #include "SkForceLinking.h" 17 #include "SkForceLinking.h"
16 #include "SkGradientShader.h" 18 #include "SkGradientShader.h"
17 #include "SkImageDecoder.h" 19 #include "SkImageDecoder.h"
18 #include "SkImageEncoder.h" 20 #include "SkImageEncoder.h"
21 #include "SkImageGenerator.h"
22 #include "SkImagePriv.h"
19 #include "SkOSFile.h" 23 #include "SkOSFile.h"
20 #include "SkPoint.h" 24 #include "SkPoint.h"
21 #include "SkShader.h" 25 #include "SkShader.h"
22 #include "SkStream.h" 26 #include "SkStream.h"
23 #include "SkString.h" 27 #include "SkString.h"
24 28
25 __SK_FORCE_IMAGE_DECODER_LINKING; 29 __SK_FORCE_IMAGE_DECODER_LINKING;
26 30
27 /** 31 /**
28 * Interprets c as an unpremultiplied color, and returns the 32 * Interprets c as an unpremultiplied color, and returns the
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 SkString resourcePath = skiatest::Test::GetResourcePath(); 149 SkString resourcePath = skiatest::Test::GetResourcePath();
146 if (resourcePath.isEmpty()) { 150 if (resourcePath.isEmpty()) {
147 SkDebugf("Could not run unpremul test because resourcePath not specified ."); 151 SkDebugf("Could not run unpremul test because resourcePath not specified .");
148 return; 152 return;
149 } 153 }
150 SkOSFile::Iter iter(resourcePath.c_str()); 154 SkOSFile::Iter iter(resourcePath.c_str());
151 SkString basename; 155 SkString basename;
152 if (iter.next(&basename)) { 156 if (iter.next(&basename)) {
153 do { 157 do {
154 SkString filename = SkOSPath::SkPathJoin(resourcePath.c_str(), basen ame.c_str()); 158 SkString filename = SkOSPath::SkPathJoin(resourcePath.c_str(), basen ame.c_str());
155 //SkDebugf("about to decode \"%s\"\n", filename.c_str()); 159 // SkDebugf("about to decode \"%s\"\n", filename.c_str());
156 compare_unpremul(reporter, filename); 160 compare_unpremul(reporter, filename);
157 } while (iter.next(&basename)); 161 } while (iter.next(&basename));
158 } else { 162 } else {
159 SkDebugf("Failed to find any files :(\n"); 163 SkDebugf("Failed to find any files :(\n");
160 } 164 }
161 } 165 }
162 166
163 #ifdef SK_DEBUG 167 #ifdef SK_DEBUG
164 // Create a stream containing a bitmap encoded to Type type. 168 // Create a stream containing a bitmap encoded to Type type.
165 static SkMemoryStream* create_image_stream(SkImageEncoder::Type type) { 169 static SkMemoryStream* create_image_stream(SkImageEncoder::Type type) {
(...skipping 27 matching lines...) Expand all
193 // Only runs in debug mode since we are testing for a crash. 197 // Only runs in debug mode since we are testing for a crash.
194 static void test_stream_life() { 198 static void test_stream_life() {
195 const SkImageEncoder::Type gTypes[] = { 199 const SkImageEncoder::Type gTypes[] = {
196 #ifdef SK_BUILD_FOR_ANDROID 200 #ifdef SK_BUILD_FOR_ANDROID
197 SkImageEncoder::kJPEG_Type, 201 SkImageEncoder::kJPEG_Type,
198 SkImageEncoder::kPNG_Type, 202 SkImageEncoder::kPNG_Type,
199 #endif 203 #endif
200 SkImageEncoder::kWEBP_Type, 204 SkImageEncoder::kWEBP_Type,
201 }; 205 };
202 for (size_t i = 0; i < SK_ARRAY_COUNT(gTypes); ++i) { 206 for (size_t i = 0; i < SK_ARRAY_COUNT(gTypes); ++i) {
203 //SkDebugf("encoding to %i\n", i); 207 // SkDebugf("encoding to %i\n", i);
204 SkAutoTUnref<SkMemoryStream> stream(create_image_stream(gTypes[i])); 208 SkAutoTUnref<SkMemoryStream> stream(create_image_stream(gTypes[i]));
205 if (NULL == stream.get()) { 209 if (NULL == stream.get()) {
206 SkDebugf("no stream\n"); 210 SkDebugf("no stream\n");
207 continue; 211 continue;
208 } 212 }
209 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream)); 213 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
210 if (NULL == decoder.get()) { 214 if (NULL == decoder.get()) {
211 SkDebugf("no decoder\n"); 215 SkDebugf("no decoder\n");
212 continue; 216 continue;
213 } 217 }
214 int width, height; 218 int width, height;
215 if (!decoder->buildTileIndex(stream.get(), &width, &height)) { 219 if (!decoder->buildTileIndex(stream.get(), &width, &height)) {
216 SkDebugf("could not build a tile index\n"); 220 SkDebugf("could not build a tile index\n");
217 continue; 221 continue;
218 } 222 }
219 // Now unref the stream to make sure it survives 223 // Now unref the stream to make sure it survives
220 stream.reset(NULL); 224 stream.reset(NULL);
221 SkBitmap bm; 225 SkBitmap bm;
222 decoder->decodeSubset(&bm, SkIRect::MakeWH(width, height), 226 decoder->decodeSubset(&bm, SkIRect::MakeWH(width, height),
223 SkBitmap::kARGB_8888_Config); 227 SkBitmap::kARGB_8888_Config);
224 } 228 }
225 } 229 }
226 230
227 // Test inside SkScaledBitmapSampler.cpp 231 // Test inside SkScaledBitmapSampler.cpp
228 extern void test_row_proc_choice(); 232 extern void test_row_proc_choice();
229 233
230 #endif // SK_DEBUG 234 #endif // SK_DEBUG
231 235
232 DEF_TEST(ImageDecoding, reporter) { 236 DEF_TEST(ImageDecoding, reporter) {
233 test_unpremul(reporter); 237 test_unpremul(reporter);
234 #ifdef SK_DEBUG 238 #ifdef SK_DEBUG
235 test_stream_life(); 239 test_stream_life();
236 test_row_proc_choice(); 240 test_row_proc_choice();
237 #endif 241 #endif
238 } 242 }
243
244 ////////////////////////////////////////////////////////////////////////////////
245
246 // example of how Android will do this inside their BitmapFactory
247 static SkPixelRef* install_pixel_ref(SkBitmap* bitmap,
248 SkStreamRewindable* stream,
249 int sampleSize, bool ditherImage) {
250 SkASSERT(bitmap != NULL);
251 SkASSERT(stream != NULL);
252 SkASSERT(stream->rewind());
253 SkASSERT(stream->unique());
254 SkColorType colorType;
255 if (!SkBitmapConfigToColorType(bitmap->config(), &colorType)) {
256 return NULL;
257 }
258 SkDecodingImageGenerator::Options opts(sampleSize, ditherImage, colorType);
259 SkAutoTDelete<SkImageGenerator> gen(
260 SkDecodingImageGenerator::Create(stream, opts));
261 SkImageInfo info;
262 if ((NULL == gen.get()) || !gen->getInfo(&info)) {
263 return NULL;
264 }
265 SkDiscardableMemory::Factory* factory = NULL;
266 if (info.getSafeSize(info.minRowBytes()) < (32 * 1024)) {
267 // only use ashmem for large images, since mmaps come at a price
268 factory = SkGetGlobalDiscardableMemoryPool();
269 }
270 if (SkInstallDiscardablePixelRef(gen.detach(), bitmap, factory)) {
271 return bitmap->pixelRef();
272 }
273 return NULL;
274 }
275 /**
276 * A test for the SkDecodingImageGenerator::Create and
277 * SkInstallDiscardablePixelRef functions.
278 */
279 DEF_TEST(ImprovedBitmapFactory, reporter) {
280 SkString resourcePath = skiatest::Test::GetResourcePath();
281 SkString directory = SkOSPath::SkPathJoin(resourcePath.c_str(), "encoding");
282 SkString path = SkOSPath::SkPathJoin(directory.c_str(), "randPixels.png");
283 SkAutoTUnref<SkStreamRewindable> stream(
284 SkStream::NewFromFile(path.c_str()));
285 if (sk_exists(path.c_str())) {
286 SkBitmap bm;
287 SkAssertResult(bm.setConfig(SkBitmap::kARGB_8888_Config, 1, 1));
288 REPORTER_ASSERT(reporter,
289 NULL != install_pixel_ref(&bm, stream.detach(), 1, true));
290 SkAutoLockPixels alp(bm);
291 REPORTER_ASSERT(reporter, NULL != bm.getPixels());
292 }
293 }
294
295
296 ////////////////////////////////////////////////////////////////////////////////
297
298
299 static inline bool check_rounding(int value, int dividend, int divisor) {
300 // returns true if (dividend/divisor) rounds up OR down to value
301 return (((divisor * value) > (dividend - divisor))
302 && ((divisor * value) < (dividend + divisor)));
303 }
304 namespace {
305 // expected output for 8x8 bitmap
306 const int kExpectedWidth = 8;
307 const int kExpectedHeight = 8;
308 const SkColor kExpectedPixels[] = {
309 0xffbba570, 0xff395f5d, 0xffe25c39, 0xff197666,
310 0xff3cba27, 0xffdefcb0, 0xffc13874, 0xfffa0093,
311 0xffbda60e, 0xffc01db6, 0xff2bd688, 0xff9362d4,
312 0xffc641b2, 0xffa5cede, 0xff606eba, 0xff8f4bf3,
313 0xff3bf742, 0xff8f02a8, 0xff5509df, 0xffc7027e,
314 0xff24aa8a, 0xff886c96, 0xff625481, 0xff403689,
315 0xffc52152, 0xff78ccd6, 0xffdcb4ab, 0xff09d27d,
316 0xffca00f3, 0xff605d47, 0xff446fb2, 0xff576e46,
317 0xff273df9, 0xffb41a83, 0xfff812c3, 0xffccab67,
318 0xff034218, 0xff7db9a7, 0xff821048, 0xfffe4ab4,
319 0xff6fac98, 0xff941d27, 0xff5fe411, 0xfffbb283,
320 0xffd86e99, 0xff169162, 0xff71128c, 0xff39cab4,
321 0xffa7fe63, 0xff4c956b, 0xffbc22e0, 0xffb272e4,
322 0xff129f4a, 0xffe34513, 0xff3d3742, 0xffbd190a,
323 0xffb07222, 0xff2e23f8, 0xfff089d9, 0xffb35738,
324 0xffa86022, 0xff3340fe, 0xff95fe71, 0xff6a71df
325 };
326 SK_COMPILE_ASSERT((kExpectedWidth * kExpectedHeight)
327 == SK_ARRAY_COUNT(kExpectedPixels), array_size_mismatch);
328 } // namespace
329
330 /**
331 * Given either a SkStream or a SkData, try to decode the encoded
332 * image using the specified options and report errors.
333 */
334 static void test_options(skiatest::Reporter* reporter,
335 const SkDecodingImageGenerator::Options& opts,
336 SkStreamRewindable* encodedStream,
337 SkData* encodedData,
338 bool useData,
339 const SkString& path) {
340 SkBitmap bm;
341 bool success = false;
342 if (useData) {
343 if (NULL == encodedData) {
344 return;
345 }
346 success = SkInstallDiscardablePixelRef(
347 SkDecodingImageGenerator::Create(encodedData, opts), &bm, NULL);
348 } else {
349 if (NULL == encodedStream) {
350 return;
351 }
352 success = SkInstallDiscardablePixelRef(
353 SkDecodingImageGenerator::Create(encodedStream->duplicate(), opts),
354 &bm, NULL);
355 }
356
357 REPORTER_ASSERT(reporter, success
358 || (kARGB_4444_SkColorType == opts.fRequestedColorType));
359 if (!success) {
360 return;
361 }
362 REPORTER_ASSERT(reporter, check_rounding(bm.height(), kExpectedHeight,
363 opts.fSampleSize));
364 REPORTER_ASSERT(reporter, check_rounding(bm.width(), kExpectedWidth,
365 opts.fSampleSize));
366
367 SkAutoLockPixels alp(bm);
368 REPORTER_ASSERT(reporter, bm.getPixels() != NULL);
369
370 SkBitmap::Config requestedConfig
371 = SkColorTypeToBitmapConfig(opts.fRequestedColorType);
372 REPORTER_ASSERT(reporter,
373 (!opts.fUseRequestedColorType)
374 || (bm.config() == requestedConfig));
375
376 // Condition under which we should check the decoding results:
377 if ((SkBitmap::kARGB_8888_Config == bm.config())
378 && (NULL != bm.getPixels())
379 && (!path.endsWith(".jpg")) // lossy
380 && (!path.endsWith(".webp")) // decoder error
381 && (opts.fSampleSize == 1)) { // scaled
382 bool pixelError = false;
383 const SkColor* correctPixels = kExpectedPixels;
384 SkASSERT(bm.height() == kExpectedHeight);
385 SkASSERT(bm.width() == kExpectedWidth);
386 for (int y = 0; y < bm.height(); ++y) {
387 for (int x = 0; x < bm.width(); ++x) {
388 pixelError |= (*correctPixels != bm.getColor(x, y));
389 ++correctPixels;
390 }
391 }
392 REPORTER_ASSERT(reporter, !pixelError);
393 }
394 }
395
396 /**
397 * SkDecodingImageGenerator has an Options struct which lets the
398 * client of the generator set sample size, dithering, and bitmap
399 * config. This test loops through many possible options and tries
400 * them on a set of 5 small encoded images (each in a different
401 * format). We test both SkData and SkStreamRewindable decoding.
402 */
403 DEF_TEST(ImageDecoderOptions, reporter) {
404 const char* files[] = {
405 "randPixels.bmp",
406 "randPixels.jpg",
407 "randPixels.png",
408 "randPixels.webp",
409 "randPixels.gif"
410 };
411
412 SkString resourceDir = skiatest::Test::GetResourcePath();
413 SkString directory = SkOSPath::SkPathJoin(resourceDir.c_str(), "encoding");
414 if (!sk_exists(directory.c_str())) {
415 return;
416 }
417
418 int scaleList[] = {1, 2, 3, 4};
419 bool ditherList[] = {true, false};
420 SkColorType colorList[] = {
421 kAlpha_8_SkColorType,
422 kRGB_565_SkColorType,
423 kARGB_4444_SkColorType, // Most decoders will fail on 4444.
424 kPMColor_SkColorType
425 // Note that indexed color is left out of the list. Lazy
426 // decoding doesn't do indexed color.
427 };
428 const bool useDataList[] = {true, false};
429
430 for (size_t fidx = 0; fidx < SK_ARRAY_COUNT(files); ++fidx) {
431 SkString path = SkOSPath::SkPathJoin(directory.c_str(), files[fidx]);
432 if (!sk_exists(path.c_str())) {
433 continue;
434 }
435
436 SkAutoDataUnref encodedData(SkData::NewFromFileName(path.c_str()));
437 REPORTER_ASSERT(reporter, encodedData.get() != NULL);
438 SkAutoTUnref<SkStreamRewindable> encodedStream(
439 SkStream::NewFromFile(path.c_str()));
440 REPORTER_ASSERT(reporter, encodedStream.get() != NULL);
441
442 for (size_t i = 0; i < SK_ARRAY_COUNT(scaleList); ++i) {
443 for (size_t j = 0; j < SK_ARRAY_COUNT(ditherList); ++j) {
444 for (size_t m = 0; m < SK_ARRAY_COUNT(useDataList); ++m) {
445 for (size_t k = 0; k < SK_ARRAY_COUNT(colorList); ++k) {
446 SkDecodingImageGenerator::Options opts(scaleList[i],
447 ditherList[j],
448 colorList[k]);
449 test_options(reporter, opts, encodedStream, encodedData,
450 useDataList[m], path);
451
452 }
453 SkDecodingImageGenerator::Options options(scaleList[i],
454 ditherList[j]);
455 test_options(reporter, options, encodedStream, encodedData,
456 useDataList[m], path);
457 }
458 }
459 }
460 }
461 }
462
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698