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

Side by Side Diff: tests/ImageDecodingTest.cpp

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

Powered by Google App Engine
This is Rietveld 408576698