render_pictures_main.cpp revision a2333d970329e8fffb7347f758f8c421452fe858
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
9#include "SkBitmap.h"
10#include "SamplePipeControllers.h"
11#include "SkCanvas.h"
12#include "SkColorPriv.h"
13#include "SkGPipe.h"
14#include "SkImageEncoder.h"
15#include "SkOSFile.h"
16#include "SkPicture.h"
17#include "SkStream.h"
18#include "SkString.h"
19#include "SkTArray.h"
20#include "picture_utils.h"
21
22typedef void (*RenderFunc) (SkPicture*, SkBitmap*);
23
24static void usage(const char* argv0) {
25    SkDebugf("SkPicture rendering tool\n");
26    SkDebugf("\n"
27"Usage: \n"
28"     %s <input>... <outputDir> \n\n"
29, argv0);
30    SkDebugf(
31"     input:     A list of directories and files to use as input.\n"
32"                    Files are expected to have the .skp extension.\n");
33    SkDebugf(
34"     outputDir: directory to write the rendered images.\n");
35}
36
37static void make_output_filepath(SkString* path, const SkString& dir,
38                                 const SkString& name) {
39    sk_tools::make_filepath(path, dir, name);
40    path->remove(path->size() - 3, 3);
41    path->append("png");
42}
43
44static void simple_render(SkPicture* pict, SkBitmap* bitmap) {
45    sk_tools::setup_bitmap(bitmap, pict->width(), pict->height());
46    SkCanvas canvas(*bitmap);
47    canvas.drawPicture(*pict);
48}
49
50/* since PNG insists on unpremultiplying our alpha, we take no precision chances
51    and force all pixels to be 100% opaque, otherwise on compare we may not get
52    a perfect match.
53 */
54static void force_all_opaque(const SkBitmap& bitmap) {
55    SkAutoLockPixels lock(bitmap);
56    for (int y = 0; y < bitmap.height(); y++) {
57        for (int x = 0; x < bitmap.width(); x++) {
58            *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT);
59        }
60    }
61}
62
63static bool write_bitmap(const SkString& path, const SkBitmap& bitmap) {
64    SkBitmap copy;
65    bitmap.copyTo(&copy, SkBitmap::kARGB_8888_Config);
66    force_all_opaque(copy);
67    return SkImageEncoder::EncodeFile(path.c_str(), copy,
68                                      SkImageEncoder::kPNG_Type, 100);
69}
70
71static void write_output(const SkString& outputDir, const SkString& inputFilename,
72                         const SkBitmap& bitmap) {
73    SkString outputPath;
74    make_output_filepath(&outputPath, outputDir, inputFilename);
75    bool isWritten = write_bitmap(outputPath, bitmap);
76    if (!isWritten) {
77        SkDebugf("Could not write to file %s\n", outputPath.c_str());
78    }
79}
80
81static void pipe_run(SkPicture* picture, SkCanvas* canvas) {
82    PipeController pipeController(canvas);
83    SkGPipeWriter writer;
84    SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
85    pipeCanvas->drawPicture(*picture);
86    writer.endRecording();
87}
88
89static void pipe_render(SkPicture* picture, SkBitmap* bitmap) {
90    sk_tools::setup_bitmap(bitmap, picture->width(), picture->height());
91
92    SkCanvas canvas(*bitmap);
93
94    pipe_run(picture, &canvas);
95}
96
97static void render_picture(const SkString& inputPath, const SkString& outputDir,
98                           RenderFunc renderFunc) {
99    SkString inputFilename;
100    sk_tools::get_basename(&inputFilename, inputPath);
101
102    SkFILEStream inputStream;
103    inputStream.setPath(inputPath.c_str());
104    if (!inputStream.isValid()) {
105        SkDebugf("Could not open file %s\n", inputPath.c_str());
106        return;
107    }
108
109    SkPicture picture(&inputStream);
110    SkBitmap bitmap;
111    renderFunc(&picture, &bitmap);
112    write_output(outputDir, inputFilename, bitmap);
113}
114
115static void process_input(const SkString& input, const SkString& outputDir,
116                          RenderFunc renderFunc) {
117    SkOSFile::Iter iter(input.c_str(), "skp");
118    SkString inputFilename;
119
120    if (iter.next(&inputFilename)) {
121        do {
122            SkString inputPath;
123            sk_tools::make_filepath(&inputPath, input, inputFilename);
124            render_picture(inputPath, outputDir, renderFunc);
125        } while(iter.next(&inputFilename));
126    } else {
127        SkString inputPath(input);
128        render_picture(inputPath, outputDir, renderFunc);
129    }
130}
131
132static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
133                              RenderFunc* renderFunc){
134    const char* argv0 = argv[0];
135    char* const* stop = argv + argc;
136
137    for (++argv; argv < stop; ++argv) {
138        if (0 == strcmp(*argv, "--pipe")) {
139            *renderFunc = pipe_render;
140        } else {
141            inputs->push_back(SkString(*argv));
142        }
143    }
144}
145
146int main(int argc, char* const argv[]) {
147    SkTArray<SkString> inputs;
148    RenderFunc renderFunc = simple_render;
149    parse_commandline(argc, argv, &inputs, &renderFunc);
150    SkString outputDir = inputs[inputs.count() - 1];
151
152    for (int i = 0; i < inputs.count() - 1; i ++) {
153        process_input(inputs[i], outputDir, renderFunc);
154    }
155}
156