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

Side by Side Diff: tools/render_pictures_main.cpp

Issue 1416913003: Clean up some dead code. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: kill dump-record Created 5 years, 2 months 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
« no previous file with comments | « tools/image_expectations.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "LazyDecodeBitmap.h"
9 #include "CopyTilesRenderer.h"
10 #include "SkBitmap.h"
11 #include "SkDevice.h"
12 #include "SkCommandLineFlags.h"
13 #include "SkGraphics.h"
14 #include "SkImageDecoder.h"
15 #include "SkImageEncoder.h"
16 #include "SkMath.h"
17 #include "SkOSFile.h"
18 #include "SkPicture.h"
19 #include "SkPictureRecorder.h"
20 #include "SkStream.h"
21 #include "SkString.h"
22
23 #include "image_expectations.h"
24 #include "PictureRenderer.h"
25 #include "PictureRenderingFlags.h"
26 #include "picture_utils.h"
27
28 #include <stdlib.h>
29
30 // Flags used by this file, alphabetically:
31 DEFINE_bool(bench_record, false, "If true, drop into an infinite loop of recordi ng the picture.");
32 DECLARE_bool(deferImageDecoding);
33 DEFINE_string(descriptions, "", "one or more key=value pairs to add to the descr iptions section "
34 "of the JSON summary.");
35 DEFINE_string(imageBaseGSUrl, "", "The Google Storage image base URL the images are stored in.");
36 DEFINE_int32(maxComponentDiff, 256, "Maximum diff on a component, 0 - 256. Compo nents that differ "
37 "by more than this amount are considered errors, though all diffs a re reported. "
38 "Requires --validate.");
39 DEFINE_string(mismatchPath, "", "Write images for tests that failed due to "
40 "pixel mismatches into this directory.");
41 #if GR_GPU_STATS
42 DEFINE_bool(gpuStats, false, "Only meaningful with gpu configurations. "
43 "Report some GPU call statistics.");
44 #endif
45 DEFINE_bool(mpd, false, "If true, use MultiPictureDraw for rendering.");
46 DEFINE_string(readJsonSummaryPath, "", "JSON file to read image expectations fro m.");
47 DECLARE_string(readPath);
48 DEFINE_bool(writeChecksumBasedFilenames, false,
49 "When writing out images, use checksum-based filenames.");
50 DEFINE_bool(writeEncodedImages, false, "Any time the skp contains an encoded ima ge, write it to a "
51 "file rather than decoding it. Requires writePath to be set. Skips d rawing the full "
52 "skp to a file. Not compatible with deferImageDecoding.");
53 DEFINE_string(writeJsonSummaryPath, "", "File to write a JSON summary of image r esults to.");
54 DEFINE_string2(writePath, w, "", "Directory to write the rendered images into.") ;
55 DEFINE_bool(writeWholeImage, false, "In tile mode, write the entire rendered ima ge to a "
56 "file, instead of an image for each tile.");
57 DEFINE_bool(validate, false, "Verify that the rendered image contains the same p ixels as "
58 "the picture rendered in simple mode. When used in conjunction with --bbh, results "
59 "are validated against the picture rendered in the same mode, but wi thout the bbh.");
60
61 //////////////////////////////////////////////////////////////////////////////// ////////////////////
62
63 /**
64 * Table for translating from format of data to a suffix.
65 */
66 struct Format {
67 SkImageDecoder::Format fFormat;
68 const char* fSuffix;
69 };
70 static const Format gFormats[] = {
71 { SkImageDecoder::kBMP_Format, ".bmp" },
72 { SkImageDecoder::kGIF_Format, ".gif" },
73 { SkImageDecoder::kICO_Format, ".ico" },
74 { SkImageDecoder::kJPEG_Format, ".jpg" },
75 { SkImageDecoder::kPNG_Format, ".png" },
76 { SkImageDecoder::kWBMP_Format, ".wbmp" },
77 { SkImageDecoder::kWEBP_Format, ".webp" },
78 { SkImageDecoder::kUnknown_Format, "" },
79 };
80
81 /**
82 * Get an appropriate suffix for an image format.
83 */
84 static const char* get_suffix_from_format(SkImageDecoder::Format format) {
85 for (size_t i = 0; i < SK_ARRAY_COUNT(gFormats); i++) {
86 if (gFormats[i].fFormat == format) {
87 return gFormats[i].fSuffix;
88 }
89 }
90 return "";
91 }
92
93 /**
94 * Base name for an image file created from the encoded data in an skp.
95 */
96 static SkString gInputFileName;
97
98 /**
99 * Number to be appended to the image file name so that it is unique.
100 */
101 static uint32_t gImageNo;
102
103 /**
104 * Set up the name for writing encoded data to a file.
105 * Sets gInputFileName to name, minus any extension ".*"
106 * Sets gImageNo to 0, so images from file "X.skp" will
107 * look like "X_<gImageNo>.<suffix>", beginning with 0
108 * for each new skp.
109 */
110 static void reset_image_file_base_name(const SkString& name) {
111 gImageNo = 0;
112 // Remove ".skp"
113 const char* cName = name.c_str();
114 const char* dot = strrchr(cName, '.');
115 if (dot != nullptr) {
116 gInputFileName.set(cName, dot - cName);
117 } else {
118 gInputFileName.set(name);
119 }
120 }
121
122 /**
123 * Write the raw encoded bitmap data to a file.
124 */
125 static bool write_image_to_file(const void* buffer, size_t size, SkBitmap* bitma p) {
126 SkASSERT(!FLAGS_writePath.isEmpty());
127 SkMemoryStream memStream(buffer, size);
128 SkString outPath;
129 SkImageDecoder::Format format = SkImageDecoder::GetStreamFormat(&memStream);
130 SkString name = SkStringPrintf("%s_%d%s", gInputFileName.c_str(), gImageNo++ ,
131 get_suffix_from_format(format));
132 SkString dir(FLAGS_writePath[0]);
133 outPath = SkOSPath::Join(dir.c_str(), name.c_str());
134 SkFILEWStream fileStream(outPath.c_str());
135 if (!(fileStream.isValid() && fileStream.write(buffer, size))) {
136 SkDebugf("Failed to write encoded data to \"%s\"\n", outPath.c_str());
137 }
138 // Put in a dummy bitmap.
139 return SkImageDecoder::DecodeStream(&memStream, bitmap, kUnknown_SkColorType ,
140 SkImageDecoder::kDecodeBounds_Mode);
141 }
142
143 //////////////////////////////////////////////////////////////////////////////// ////////////////////
144
145 /**
146 * Called only by render_picture().
147 */
148 static bool render_picture_internal(const SkString& inputPath, const SkString* w ritePath,
149 const SkString* mismatchPath,
150 sk_tools::PictureRenderer& renderer,
151 SkBitmap** out) {
152 SkString inputFilename = SkOSPath::Basename(inputPath.c_str());
153 SkString writePathString;
154 if (writePath && writePath->size() > 0 && !FLAGS_writeEncodedImages) {
155 writePathString.set(*writePath);
156 }
157 SkString mismatchPathString;
158 if (mismatchPath && mismatchPath->size() > 0) {
159 mismatchPathString.set(*mismatchPath);
160 }
161
162 SkFILEStream inputStream;
163 inputStream.setPath(inputPath.c_str());
164 if (!inputStream.isValid()) {
165 SkDebugf("Could not open file %s\n", inputPath.c_str());
166 return false;
167 }
168
169 SkPicture::InstallPixelRefProc proc;
170 if (FLAGS_deferImageDecoding) {
171 proc = &sk_tools::LazyDecodeBitmap;
172 } else if (FLAGS_writeEncodedImages) {
173 SkASSERT(!FLAGS_writePath.isEmpty());
174 reset_image_file_base_name(inputFilename);
175 proc = &write_image_to_file;
176 } else {
177 proc = &SkImageDecoder::DecodeMemory;
178 }
179
180 SkDebugf("deserializing... %s\n", inputPath.c_str());
181
182 SkAutoTUnref<SkPicture> picture(SkPicture::CreateFromStream(&inputStream, pr oc));
183
184 if (nullptr == picture) {
185 SkDebugf("Could not read an SkPicture from %s\n", inputPath.c_str());
186 return false;
187 }
188
189 while (FLAGS_bench_record) {
190 SkPictureRecorder recorder;
191 picture->playback(recorder.beginRecording(picture->cullRect().width(),
192 picture->cullRect().height(),
193 nullptr, 0));
194 SkAutoTUnref<SkPicture> other(recorder.endRecording());
195 }
196
197 SkDebugf("drawing... [%f %f %f %f] %s\n",
198 picture->cullRect().fLeft, picture->cullRect().fTop,
199 picture->cullRect().fRight, picture->cullRect().fBottom,
200 inputPath.c_str());
201
202 renderer.init(picture, &writePathString, &mismatchPathString, &inputFilename ,
203 FLAGS_writeChecksumBasedFilenames, FLAGS_mpd);
204
205 renderer.setup();
206 renderer.enableWrites();
207
208 bool success = renderer.render(out);
209 if (!success) {
210 SkDebugf("Failed to render %s\n", inputFilename.c_str());
211 }
212
213 renderer.end();
214
215 return success;
216 }
217
218 static inline int getByte(uint32_t value, int index) {
219 SkASSERT(0 <= index && index < 4);
220 return (value >> (index * 8)) & 0xFF;
221 }
222
223 static int MaxByteDiff(uint32_t v1, uint32_t v2) {
224 return SkMax32(SkMax32(SkTAbs(getByte(v1, 0) - getByte(v2, 0)), SkTAbs(getBy te(v1, 1) - getByte(v2, 1))),
225 SkMax32(SkTAbs(getByte(v1, 2) - getByte(v2, 2)), SkTAbs(getBy te(v1, 3) - getByte(v2, 3))));
226 }
227
228 class AutoRestoreBbhType {
229 public:
230 AutoRestoreBbhType() {
231 fRenderer = nullptr;
232 fSavedBbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
233 }
234
235 void set(sk_tools::PictureRenderer* renderer,
236 sk_tools::PictureRenderer::BBoxHierarchyType bbhType) {
237 fRenderer = renderer;
238 fSavedBbhType = renderer->getBBoxHierarchyType();
239 renderer->setBBoxHierarchyType(bbhType);
240 }
241
242 ~AutoRestoreBbhType() {
243 if (fRenderer) {
244 fRenderer->setBBoxHierarchyType(fSavedBbhType);
245 }
246 }
247
248 private:
249 sk_tools::PictureRenderer* fRenderer;
250 sk_tools::PictureRenderer::BBoxHierarchyType fSavedBbhType;
251 };
252
253 /**
254 * Render the SKP file(s) within inputPath.
255 *
256 * @param inputPath path to an individual SKP file, or a directory of SKP files
257 * @param writePath if not nullptr, write all image(s) generated into this direc tory
258 * @param mismatchPath if not nullptr, write any image(s) not matching expectati ons into this directory
259 * @param renderer PictureRenderer to use to render the SKPs
260 * @param jsonSummaryPtr if not nullptr, add the image(s) generated to this summ ary
261 */
262 static bool render_picture(const SkString& inputPath, const SkString* writePath,
263 const SkString* mismatchPath, sk_tools::PictureRender er& renderer,
264 sk_tools::ImageResultsAndExpectations *jsonSummaryPtr ) {
265 int diffs[256] = {0};
266 SkBitmap* bitmap = nullptr;
267 renderer.setJsonSummaryPtr(jsonSummaryPtr);
268 bool success = render_picture_internal(inputPath,
269 FLAGS_writeWholeImage ? nullptr : writePath,
270 FLAGS_writeWholeImage ? nullptr : mismatchPath,
271 renderer,
272 FLAGS_validate || FLAGS_writeWholeImage ? &bitmap : nullptr);
273
274 if (!success || ((FLAGS_validate || FLAGS_writeWholeImage) && bitmap == null ptr)) {
275 SkDebugf("Failed to draw the picture.\n");
276 delete bitmap;
277 return false;
278 }
279
280 if (FLAGS_validate) {
281 SkBitmap* referenceBitmap = nullptr;
282 sk_tools::PictureRenderer* referenceRenderer;
283 // If the renderer uses a BBoxHierarchy, then the reference renderer
284 // will be the same renderer, without the bbh.
285 AutoRestoreBbhType arbbh;
286 if (sk_tools::PictureRenderer::kNone_BBoxHierarchyType !=
287 renderer.getBBoxHierarchyType()) {
288 referenceRenderer = &renderer;
289 referenceRenderer->ref(); // to match auto unref below
290 arbbh.set(referenceRenderer, sk_tools::PictureRenderer::kNone_BBoxHi erarchyType);
291 } else {
292 #if SK_SUPPORT_GPU
293 referenceRenderer = new sk_tools::SimplePictureRenderer(renderer.get GrContextOptions());
294 #else
295 referenceRenderer = new sk_tools::SimplePictureRenderer;
296 #endif
297 }
298 SkAutoTUnref<sk_tools::PictureRenderer> aurReferenceRenderer(referenceRe nderer);
299
300 success = render_picture_internal(inputPath, nullptr, nullptr, *referenc eRenderer,
301 &referenceBitmap);
302
303 if (!success || nullptr == referenceBitmap || nullptr == referenceBitmap ->getPixels()) {
304 SkDebugf("Failed to draw the reference picture.\n");
305 delete bitmap;
306 delete referenceBitmap;
307 return false;
308 }
309
310 if (success && (bitmap->width() != referenceBitmap->width())) {
311 SkDebugf("Expected image width: %i, actual image width %i.\n",
312 referenceBitmap->width(), bitmap->width());
313 delete bitmap;
314 delete referenceBitmap;
315 return false;
316 }
317 if (success && (bitmap->height() != referenceBitmap->height())) {
318 SkDebugf("Expected image height: %i, actual image height %i",
319 referenceBitmap->height(), bitmap->height());
320 delete bitmap;
321 delete referenceBitmap;
322 return false;
323 }
324
325 for (int y = 0; success && y < bitmap->height(); y++) {
326 for (int x = 0; success && x < bitmap->width(); x++) {
327 int diff = MaxByteDiff(*referenceBitmap->getAddr32(x, y),
328 *bitmap->getAddr32(x, y));
329 SkASSERT(diff >= 0 && diff <= 255);
330 diffs[diff]++;
331
332 if (diff > FLAGS_maxComponentDiff) {
333 SkDebugf("Expected pixel at (%i %i) exceedds maximum "
334 "component diff of %i: 0x%x, actual 0x%x\n",
335 x, y, FLAGS_maxComponentDiff,
336 *referenceBitmap->getAddr32(x, y),
337 *bitmap->getAddr32(x, y));
338 delete bitmap;
339 delete referenceBitmap;
340 return false;
341 }
342 }
343 }
344 delete referenceBitmap;
345
346 for (int i = 1; i <= 255; ++i) {
347 if(diffs[i] > 0) {
348 SkDebugf("Number of pixels with max diff of %i is %i\n", i, diff s[i]);
349 }
350 }
351 }
352
353 if (FLAGS_writeWholeImage) {
354 sk_tools::force_all_opaque(*bitmap);
355
356 SkString inputFilename = SkOSPath::Basename(inputPath.c_str());
357 SkString outputFilename(inputFilename);
358 sk_tools::replace_char(&outputFilename, '.', '_');
359 outputFilename.append(".png");
360
361 if (jsonSummaryPtr) {
362 sk_tools::ImageDigest imageDigest(*bitmap);
363 jsonSummaryPtr->add(inputFilename.c_str(), outputFilename.c_str(), i mageDigest);
364 if ((mismatchPath) && !mismatchPath->isEmpty() &&
365 !jsonSummaryPtr->getExpectation(inputFilename.c_str()).matches(i mageDigest)) {
366 success &= sk_tools::write_bitmap_to_disk(*bitmap, *mismatchPath , nullptr,
367 outputFilename);
368 }
369 }
370
371 if ((writePath) && !writePath->isEmpty()) {
372 success &= sk_tools::write_bitmap_to_disk(*bitmap, *writePath, nullp tr, outputFilename);
373 }
374 }
375 delete bitmap;
376
377 return success;
378 }
379
380
381 static int process_input(const char* input, const SkString* writePath,
382 const SkString* mismatchPath, sk_tools::PictureRenderer & renderer,
383 sk_tools::ImageResultsAndExpectations *jsonSummaryPtr) {
384 SkOSFile::Iter iter(input, "skp");
385 SkString inputFilename;
386 int failures = 0;
387 SkDebugf("process_input, %s\n", input);
388 if (iter.next(&inputFilename)) {
389 do {
390 SkString inputPath = SkOSPath::Join(input, inputFilename.c_str());
391 if (!render_picture(inputPath, writePath, mismatchPath, renderer, js onSummaryPtr)) {
392 ++failures;
393 }
394 } while(iter.next(&inputFilename));
395 } else if (SkStrEndsWith(input, ".skp")) {
396 SkString inputPath(input);
397 if (!render_picture(inputPath, writePath, mismatchPath, renderer, jsonSu mmaryPtr)) {
398 ++failures;
399 }
400 } else {
401 SkString warning;
402 warning.printf("Warning: skipping %s\n", input);
403 SkDebugf("%s", warning.c_str());
404 }
405 return failures;
406 }
407
408 int tool_main(int argc, char** argv);
409 int tool_main(int argc, char** argv) {
410 SkCommandLineFlags::SetUsage("Render .skp files.");
411 SkCommandLineFlags::Parse(argc, argv);
412
413 if (FLAGS_readPath.isEmpty()) {
414 SkDebugf(".skp files or directories are required.\n");
415 exit(-1);
416 }
417
418 if (FLAGS_maxComponentDiff < 0 || FLAGS_maxComponentDiff > 256) {
419 SkDebugf("--maxComponentDiff must be between 0 and 256\n");
420 exit(-1);
421 }
422
423 if (FLAGS_maxComponentDiff != 256 && !FLAGS_validate) {
424 SkDebugf("--maxComponentDiff requires --validate\n");
425 exit(-1);
426 }
427
428 if (FLAGS_writeEncodedImages) {
429 if (FLAGS_writePath.isEmpty()) {
430 SkDebugf("--writeEncodedImages requires --writePath\n");
431 exit(-1);
432 }
433 if (FLAGS_deferImageDecoding) {
434 SkDebugf("--writeEncodedImages is not compatible with --deferImageDe coding\n");
435 exit(-1);
436 }
437 }
438
439 SkString errorString;
440 SkAutoTUnref<sk_tools::PictureRenderer> renderer(parseRenderer(errorString,
441 kRender_Pictu reTool));
442 if (errorString.size() > 0) {
443 SkDebugf("%s\n", errorString.c_str());
444 }
445
446 if (renderer.get() == nullptr) {
447 exit(-1);
448 }
449
450 SkAutoGraphics ag;
451
452 SkString writePath;
453 if (FLAGS_writePath.count() == 1) {
454 writePath.set(FLAGS_writePath[0]);
455 }
456 SkString mismatchPath;
457 if (FLAGS_mismatchPath.count() == 1) {
458 mismatchPath.set(FLAGS_mismatchPath[0]);
459 }
460 sk_tools::ImageResultsAndExpectations jsonSummary;
461 sk_tools::ImageResultsAndExpectations* jsonSummaryPtr = nullptr;
462 if (FLAGS_writeJsonSummaryPath.count() == 1) {
463 jsonSummaryPtr = &jsonSummary;
464 if (FLAGS_readJsonSummaryPath.count() == 1) {
465 SkASSERT(jsonSummary.readExpectationsFile(FLAGS_readJsonSummaryPath[ 0]));
466 }
467 }
468
469 int failures = 0;
470 for (int i = 0; i < FLAGS_readPath.count(); i ++) {
471 failures += process_input(FLAGS_readPath[i], &writePath, &mismatchPath, *renderer.get(),
472 jsonSummaryPtr);
473 }
474 if (failures != 0) {
475 SkDebugf("Failed to render %i pictures.\n", failures);
476 return 1;
477 }
478 #if GR_CACHE_STATS && SK_SUPPORT_GPU
479 if (renderer->isUsingGpuDevice()) {
480 GrContext* ctx = renderer->getGrContext();
481 ctx->printCacheStats();
482 }
483 #endif
484
485 #if GR_GPU_STATS && SK_SUPPORT_GPU
486 if (FLAGS_gpuStats && renderer->isUsingGpuDevice()) {
487 renderer->getGrContext()->printGpuStats();
488 }
489 #endif
490
491 if (FLAGS_writeJsonSummaryPath.count() == 1) {
492 // If there were any descriptions on the command line, insert them now.
493 for (int i=0; i<FLAGS_descriptions.count(); i++) {
494 SkTArray<SkString> tokens;
495 SkStrSplit(FLAGS_descriptions[i], "=", &tokens);
496 SkASSERT(tokens.count() == 2);
497 jsonSummary.addDescription(tokens[0].c_str(), tokens[1].c_str());
498 }
499 if (FLAGS_imageBaseGSUrl.count() == 1) {
500 jsonSummary.setImageBaseGSUrl(FLAGS_imageBaseGSUrl[0]);
501 }
502 jsonSummary.writeToFile(FLAGS_writeJsonSummaryPath[0]);
503 }
504 return 0;
505 }
506
507 #if !defined SK_BUILD_FOR_IOS
508 int main(int argc, char * const argv[]) {
509 return tool_main(argc, (char**) argv);
510 }
511 #endif
OLDNEW
« no previous file with comments | « tools/image_expectations.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698