SeExpr
imageSynth.cpp
Go to the documentation of this file.
1/*
2* Copyright Disney Enterprises, Inc. All rights reserved.
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License
6* and the following modification to it: Section 6 Trademarks.
7* deleted and replaced with:
8*
9* 6. Trademarks. This License does not grant permission to use the
10* trade names, trademarks, service marks, or product names of the
11* Licensor and its affiliates, except as required for reproducing
12* the content of the NOTICE file.
13*
14* You may obtain a copy of the License at
15* http://www.apache.org/licenses/LICENSE-2.0
16*/
20#include <map>
21#include <cstdlib>
22#include <cstdio>
23#include <cstring>
24#include <png.h>
25#include <fstream>
26
27#include <SeExpr2/Expression.h>
28#include <SeExpr2/Interpreter.h>
29#include <SeExpr2/Platform.h>
30
31namespace SeExpr2 {
33class ImageSynthExpr : public Expression {
34 public:
36 ImageSynthExpr(const std::string& expr) : Expression(expr) {}
37
39 struct Var : public ExprVarRef {
40 Var(const double val) : ExprVarRef(ExprType().FP(1).Varying()), val(val) {}
41
42 Var() : ExprVarRef(ExprType().FP(1).Varying()), val(0.0) {}
43
44 double val; // independent variable
45 void eval(double* result) { result[0] = val; }
46
47 void eval(const char** result) { assert(false); }
48 };
50 mutable std::map<std::string, Var> vars;
51
53 ExprVarRef* resolveVar(const std::string& name) const {
54 std::map<std::string, Var>::iterator i = vars.find(name);
55 if (i != vars.end()) return &i->second;
56 return 0;
57 }
58};
59}
60
61double clamp(double x) { return std::max(0., std::min(255., x)); }
62
63using namespace SeExpr2;
64
65int main(int argc, char* argv[]) {
66 if (argc != 5) {
67 std::cerr << "Usage: " << argv[0] << " <image file> <width> <height> <exprFile>" << std::endl;
68 return 1;
69 }
70
71 // parse arguments
72 const char* imageFile = argv[1];
73 const char* exprFile = argv[4];
74 int width = atoi(argv[2]), height = atoi(argv[3]);
75 if (width < 0 || height < 0) {
76 std::cerr << "invalid width/height" << std::endl;
77 return 1;
78 }
79
80 std::ifstream istream(exprFile);
81 if (!istream) {
82 std::cerr << "Cannot read file " << exprFile << std::endl;
83 return 1;
84 }
85 std::string exprStr((std::istreambuf_iterator<char>(istream)), std::istreambuf_iterator<char>());
86 ImageSynthExpr expr(exprStr);
87
88 // make variables
89 expr.vars["u"] = ImageSynthExpr::Var(0.);
90 expr.vars["v"] = ImageSynthExpr::Var(0.);
91 expr.vars["w"] = ImageSynthExpr::Var(width);
92 expr.vars["h"] = ImageSynthExpr::Var(height);
93
94 // check if expression is valid
95 bool valid = expr.isValid();
96 if (!valid) {
97 std::cerr << "Invalid expression " << std::endl;
98 std::cerr << expr.parseError() << std::endl;
99 return 1;
100 }
101 if (!expr.returnType().isFP(3)) {
102 std::cerr << "Expected color FP[3] got type " << expr.returnType().toString() << std::endl;
103 return 1;
104 }
105
106 // evaluate expression
107 std::cerr << "Evaluating expresion...from " << exprFile << std::endl;
108 unsigned char* image = new unsigned char[width * height * 4];
109
110 {
111 PrintTiming evalTime("eval time");
112 double one_over_width = 1. / width, one_over_height = 1. / height;
113 double& u = expr.vars["u"].val;
114 double& v = expr.vars["v"].val;
115 unsigned char* pixel = image;
116 for (int row = 0; row < height; row++) {
117 for (int col = 0; col < width; col++) {
118 u = one_over_width * (col + .5);
119 v = one_over_height * (row + .5);
120
121 const double* result = expr.evalFP();
122
123 // expr._interpreter->print();
124 pixel[0] = clamp(result[0] * 256.);
125 pixel[1] = clamp(result[1] * 256.);
126 pixel[2] = clamp(result[2] * 256.);
127 pixel[3] = 255;
128 pixel += 4;
129 }
130 }
131 } // timer
132
133 // write image as png
134 std::cerr << "Writing image..." << imageFile << std::endl;
135 FILE* fp = fopen(imageFile, "wb");
136 if (!fp) {
137 perror("fopen");
138 return 1;
139 }
140 png_structp png_ptr;
141 png_infop info_ptr;
142 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
143 info_ptr = png_create_info_struct(png_ptr);
144 png_init_io(png_ptr, fp);
145 int color_type = PNG_COLOR_TYPE_RGBA;
146 png_set_IHDR(png_ptr,
147 info_ptr,
148 width,
149 height,
150 8,
151 color_type,
152 PNG_INTERLACE_NONE,
153 PNG_COMPRESSION_TYPE_DEFAULT,
154 PNG_FILTER_TYPE_DEFAULT);
155 const unsigned char* ptrs[height];
156 for (int i = 0; i < height; i++) {
157 ptrs[i] = &image[width * i * 4];
158 }
159 png_set_rows(png_ptr, info_ptr, (png_byte**)ptrs);
160 png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0);
161
162 fclose(fp);
163}
Platform-specific classes, functions, and includes.
abstract class for implementing variable references
Definition Expression.h:45
virtual void eval(double *result)=0
returns this variable's value by setting result
main expression class
Definition Expression.h:76
int main(int argc, char *argv[])
double clamp(double x, double lo, double hi)
</pre >< h3 > Binding our variable reference</h3 > If we now tried to use the variable would still not be found by our expressions To make it bindable we need to override the resolveVar() function as follows</pre >< h3 > Variable setting</h3 > Next we need to make a way of setting the variable As the controlling code will use the expression it will repeatedly alternate between setting the independent variables that are used and calling evaluate(). What it has to do depends very much on the application. In this case we only need to set the independent variable x as</pre >< h2 > Evaluating expressions</h2 > Evaluating an expression is pretty easy But before we can do that we need to make an instance< pre > GrapherExpr expr("x+x^2")
</pre > Once we have this we need an instance to store our variable and provide a reference to that We make it because resolveVar() is const . One does not need to store a variable reference in a given expression. In fact
</pre >< h3 > A simple variable reference</h3 > This is not a very interesting subclass of expression until we add some additional variables Variables on some applications may be very dynamic In this we only need x
Definition tutorial.txt:108