SeExpr
imageSynthForPaint3d.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/Vec.h>
29 #include <SeExpr2/Interpreter.h>
30 #include <SeExpr2/ExprFunc.h>
31 #include <SeExpr2/ExprFuncX.h>
32 #include <SeExpr2/Platform.h>
33 
34 namespace SeExpr2 {
35 class RandFuncX : public ExprFuncSimple {
36 
37  struct Data : public ExprFuncNode::Data {
38  std::vector<std::pair<int, int> > ranges;
39  std::string format;
40  };
41 
42  virtual ExprType prep(ExprFuncNode* node, bool wantScalar, ExprVarEnvBuilder& envBuilder) const {
43  bool valid = true;
44  for (int i = 0; i < node->numChildren(); i++)
45  valid &= node->checkArg(i, ExprType().FP(1).Varying(), envBuilder);
46  return valid ? ExprType().FP(1).Varying() : ExprType().Error();
47  }
48 
49  virtual ExprFuncNode::Data* evalConstant(const ExprFuncNode* node, ArgHandle args) const { return new Data; }
50 
51  virtual void eval(ArgHandle args) {
52  if (args.nargs() >= 2) {
53  args.outFp = (args.inFp<1>(0)[0] - args.inFp<1>(1)[0]) / 2.0;
54  } else
55  args.outFp = 0.5;
56  }
57 
58  public:
59  RandFuncX() : ExprFuncSimple(true) {} // Thread Safe
60  virtual ~RandFuncX() {}
61 } rand;
62 
63 // map(string name, [float format-arg], [float u], [float v], [int channel])
64 class MapFuncX : public ExprFuncSimple {
65  struct Data : public ExprFuncNode::Data {
66  std::vector<std::pair<int, int> > ranges;
67  std::string format;
68  };
69 
70  virtual ExprType prep(ExprFuncNode* node, bool wantScalar, ExprVarEnvBuilder& envBuilder) const {
71  bool valid = true;
72  valid &= node->checkArg(0, ExprType().String().Constant(), envBuilder);
73  for (int i = 1; i < node->numChildren(); i++)
74  valid &= node->checkArg(i, ExprType().FP(1).Varying(), envBuilder);
75  return valid ? ExprType().FP(3).Varying() : ExprType().Error();
76  }
77 
78  virtual ExprFuncNode::Data* evalConstant(const ExprFuncNode* node, ArgHandle args) const { return new Data; }
79 
80  virtual void eval(ArgHandle args) {
81  double* out = &args.outFp;
82 
83  double val = 0.5;
84  int num = args.nargs();
85  if (num > 2)
86  for (int k = 2; k < num; k++) val += args.inFp<1>(k)[0];
87 
88  for (int k = 0; k < 3; k++) out[k] = val;
89  }
90 
91  public:
92  MapFuncX() : ExprFuncSimple(true) {} // Thread Safe
93  virtual ~MapFuncX() {}
94 } map;
95 
96 // triplanar(string name, [vector scale], [float blend], [vector rotation], [vector translation])
98  struct Data : public ExprFuncNode::Data {
99  std::vector<std::pair<int, int> > ranges;
100  std::string format;
101  };
102 
103  virtual ExprType prep(ExprFuncNode* node, bool wantScalar, ExprVarEnvBuilder& envBuilder) const {
104  bool valid = true;
105  valid &= node->checkArg(0, ExprType().String().Constant(), envBuilder);
106  for (int i = 1; i < node->numChildren(); i++)
107  valid &= node->checkArg(i, ExprType().FP(1).Varying(), envBuilder);
108  return valid ? ExprType().FP(3).Varying() : ExprType().Error();
109  }
110 
111  virtual ExprFuncNode::Data* evalConstant(const ExprFuncNode* node, ArgHandle args) const { return new Data; }
112 
113  virtual void eval(ArgHandle args) {
114  double* out = &args.outFp;
115 
116  double val = 0.5;
117  int num = args.nargs();
118  if (num > 1)
119  for (int k = 1; k < num; k++) val += (args.inFp<3>(k)[0] + args.inFp<3>(k)[1] + args.inFp<3>(k)[2]);
120 
121  for (int k = 0; k < 3; k++) out[k] = val;
122  }
123 
124  public:
125  TriplanarFuncX() : ExprFuncSimple(true) {} // Thread Safe
126  virtual ~TriplanarFuncX() {}
128 }
129 
130 static const char* rand_docstring = "rand\n";
131 static const char* map_docstring = "map\n";
132 static const char* triplanar_docstring = "triplanar\n";
133 
134 using namespace SeExpr2;
135 
137 class ImageSynthExpr : public Expression {
138  public:
140  ImageSynthExpr(const std::string& expr) : Expression(expr, ExprType().FP(3)) {}
141 
143  struct Var : public ExprVarRef {
144  Var(const double val) : ExprVarRef(ExprType().FP(1).Varying()), val(val) {}
145 
146  Var() : ExprVarRef(ExprType().FP(1).Varying()), val(0.0) {}
147 
148  double val; // independent variable
149  void eval(double* result) { result[0] = val; }
150 
151  void eval(const char** result) { assert(false); }
152  };
153 
154  struct VecVar : public ExprVarRef {
155  VecVar() : ExprVarRef(ExprType().FP(3).Varying()), val(0.0) {}
156 
157  Vec<double, 3, false> val; // independent variable
158 
159  void eval(double* result) {
160  for (int k = 0; k < 3; k++) result[k] = val[k];
161  }
162 
163  void eval(const char** reuslt) {}
164  };
165 
167  mutable std::map<std::string, Var> vars;
168  mutable std::map<std::string, VecVar> vecvars;
169 
171  ExprVarRef* resolveVar(const std::string& name) const {
172  {
173  std::map<std::string, Var>::iterator i = vars.find(name);
174  if (i != vars.end()) return &i->second;
175  }
176  {
177  std::map<std::string, VecVar>::iterator i = vecvars.find(name);
178  if (i != vecvars.end()) return &i->second;
179  }
180  return 0;
181  }
182 };
183 
184 double clamp(double x) { return std::max(0., std::min(255., x)); }
185 
186 int main(int argc, char* argv[]) {
187  if (argc != 5) {
188  std::cerr << "Usage: " << argv[0] << " <image file> <width> <height> <exprFile>" << std::endl;
189  return 1;
190  }
191 
195 
196  // parse arguments
197  const char* imageFile = argv[1];
198  const char* exprFile = argv[4];
199  int width = atoi(argv[2]), height = atoi(argv[3]);
200  if (width < 0 || height < 0) {
201  std::cerr << "invalid width/height" << std::endl;
202  return 1;
203  }
204 
205  std::ifstream istream(exprFile);
206  if (!istream) {
207  std::cerr << "Cannot read file " << exprFile << std::endl;
208  return 1;
209  }
210  std::string exprStr((std::istreambuf_iterator<char>(istream)), std::istreambuf_iterator<char>());
211  ImageSynthExpr expr(exprStr);
212 
213  // make variables
214  expr.vars["u"] = ImageSynthExpr::Var(0.);
215  expr.vars["v"] = ImageSynthExpr::Var(0.);
216  expr.vars["w"] = ImageSynthExpr::Var(width);
217  expr.vars["h"] = ImageSynthExpr::Var(height);
218 
219  expr.vars["faceId"] = ImageSynthExpr::Var(0.);
220  expr.vecvars["P"] = ImageSynthExpr::VecVar();
221  expr.vecvars["Cs"] = ImageSynthExpr::VecVar();
222  expr.vecvars["Ci"] = ImageSynthExpr::VecVar();
223 
224  // check if expression is valid
225  bool valid = expr.isValid();
226  if (!valid) {
227  std::cerr << "Invalid expression " << std::endl;
228  std::cerr << expr.parseError() << std::endl;
229  return 1;
230  }
231  // if(!expr.returnType().isFP(3)){
232  // std::cerr<<"Expected color FP[3] got type "<<expr.returnType().toString()<<std::endl;
233  // return 1;
234  // }
235 
236  // evaluate expression
237  std::cerr << "Evaluating expresion...from " << exprFile << std::endl;
238  unsigned char* image = new unsigned char[width * height * 4];
239  double one_over_width = 1. / width, one_over_height = 1. / height;
240  double& u = expr.vars["u"].val;
241  double& v = expr.vars["v"].val;
242 
243  double& faceId = expr.vars["faceId"].val;
244  Vec<double, 3, false>& P = expr.vecvars["P"].val;
245  Vec<double, 3, false>& Cs = expr.vecvars["Cs"].val;
246  Vec<double, 3, false>& Ci = expr.vecvars["Ci"].val;
247 
248  unsigned char* pixel = image;
249 
250  {
251  PrintTiming timer("eval time: ");
252  for (int row = 0; row < height; row++) {
253  for (int col = 0; col < width; col++) {
254  u = one_over_width * (col + .5);
255  v = one_over_height * (row + .5);
256 
257  faceId = floor(u * 5);
258  P[0] = u * 10;
259  P[1] = v * 10;
260  P[2] = 0.5 * 10;
261  Cs[0] = 0.;
262  Cs[1] = 0.4;
263  Cs[2] = 0.6;
264  Ci[0] = 0.;
265  Ci[1] = 0.4;
266  Ci[2] = 0.6;
267 
268  const double* result = expr.evalFP();
269 
270  // expr._interpreter->print();
271  pixel[0] = clamp(result[0] * 256.);
272  pixel[1] = clamp(result[1] * 256.);
273  pixel[2] = clamp(result[2] * 256.);
274  pixel[3] = 255;
275  pixel += 4;
276  }
277  }
278  }
279 
280  // write image as png
281  std::cerr << "Writing image..." << imageFile << std::endl;
282  FILE* fp = fopen(imageFile, "wb");
283  if (!fp) {
284  perror("fopen");
285  return 1;
286  }
287  png_structp png_ptr;
288  png_infop info_ptr;
289  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
290  info_ptr = png_create_info_struct(png_ptr);
291  png_init_io(png_ptr, fp);
292  int color_type = PNG_COLOR_TYPE_RGBA;
293  png_set_IHDR(png_ptr,
294  info_ptr,
295  width,
296  height,
297  8,
298  color_type,
299  PNG_INTERLACE_NONE,
300  PNG_COMPRESSION_TYPE_DEFAULT,
301  PNG_FILTER_TYPE_DEFAULT);
302  const unsigned char* ptrs[height];
303  for (int i = 0; i < height; i++) {
304  ptrs[i] = &image[width * i * 4];
305  }
306  png_set_rows(png_ptr, info_ptr, (png_byte**)ptrs);
307  png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0);
308 
309  fclose(fp);
310 }
SeExpr2::TriplanarFuncX::TriplanarFuncX
TriplanarFuncX()
Definition: imageSynthForPaint3d.cpp:125
SeExpr2::RandFuncX::RandFuncX
RandFuncX()
Definition: imageSynthForPaint3d.cpp:59
SeExpr2::ExprType::FP
ExprType & FP(int d)
Mutate this into a floating point type of dimension d.
Definition: ExprType.h:90
SeExpr2::ExprNode::numChildren
int numChildren() const
Number of children.
Definition: ExprNode.h:114
SeExpr2::TriplanarFuncX::Data::format
std::string format
Definition: imageSynthForPaint3d.cpp:100
rand_docstring
static const char * rand_docstring
Definition: imageSynthForPaint3d.cpp:130
SeExpr2::Vec< double, 3, false >
SeExpr2::TriplanarFuncX::prep
virtual ExprType prep(ExprFuncNode *node, bool wantScalar, ExprVarEnvBuilder &envBuilder) const
Definition: imageSynthForPaint3d.cpp:103
SeExpr2::MapFuncX::evalConstant
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
Definition: imageSynthForPaint3d.cpp:78
SeExpr2::ExprFuncSimple::ArgHandle::nargs
int nargs() const
Definition: ExprFuncX.h:89
SeExpr2::RandFuncX::Data::format
std::string format
Definition: imageSynthForPaint3d.cpp:39
SeExpr2::PrintTiming
Definition: Platform.h:150
Interpreter.h
SeExpr2::ExprType::Varying
ExprType & Varying()
Mutate this into a varying lifetime.
Definition: ExprType.h:122
SeExpr2::RandFuncX::prep
virtual ExprType prep(ExprFuncNode *node, bool wantScalar, ExprVarEnvBuilder &envBuilder) const
Definition: imageSynthForPaint3d.cpp:42
map_docstring
static const char * map_docstring
Definition: imageSynthForPaint3d.cpp:131
SeExpr2::ExprFuncSimple
Definition: ExprFuncX.h:72
SeExpr2::MapFuncX
Definition: imageSynthForPaint3d.cpp:64
SeExpr2::ExprFuncSimple::ArgHandle
Definition: ExprFuncX.h:76
SeExpr2::ExprFuncSimple::ArgHandle::inFp
Vec< double, d, true > inFp(int i)
Definition: ExprFuncX.h:85
SeExpr2::MapFuncX::Data::format
std::string format
Definition: imageSynthForPaint3d.cpp:67
ExprFunc.h
SeExpr2::ExprType
Definition: ExprType.h:39
SeExpr2::TriplanarFuncX::Data::ranges
std::vector< std::pair< int, int > > ranges
Definition: imageSynthForPaint3d.cpp:99
SeExpr2::RandFuncX::eval
virtual void eval(ArgHandle args)
Definition: imageSynthForPaint3d.cpp:51
SeExpr2::ExprFuncNode
Node that calls a function.
Definition: ExprNode.h:517
Platform.h
Platform-specific classes, functions, and includes.
SeExpr2::ExprFunc
Function Definition, used in parse tree and func table.
Definition: ExprFunc.h:44
SeExpr2::RandFuncX::Data
Definition: imageSynthForPaint3d.cpp:37
SeExpr2::MapFuncX::Data
Definition: imageSynthForPaint3d.cpp:65
SeExpr2::RandFuncX::~RandFuncX
virtual ~RandFuncX()
Definition: imageSynthForPaint3d.cpp:60
SeExpr2::triplanar
SeExpr2::TriplanarFuncX triplanar
SeExpr2
Definition: Context.h:22
SeExpr2::TriplanarFuncX::evalConstant
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
Definition: imageSynthForPaint3d.cpp:111
Vec.h
SeExpr2::min
double min(double x, double y)
Definition: ExprBuiltins.h:43
SeExpr2::ExprFuncSimple::ArgHandle::outFp
double & outFp
Definition: ExprFuncX.h:97
SeExpr2::ExprType::Error
ExprType & Error()
Mutate this into an error type.
Definition: ExprType.h:102
SeExpr2::clamp
double clamp(double x, double lo, double hi)
Definition: ExprBuiltins.h:40
SeExpr2::ExprVarEnvBuilder
Variable scope builder is used by the type checking and code gen to track visiblity of variables and ...
Definition: ExprEnv.h:148
ExprFuncX.h
SeExpr2::ExprFuncNode::checkArg
bool checkArg(int argIndex, ExprType type, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:578
SeExpr2::Expression
main expression class
Definition: Expression.h:76
SeExpr2::max
double max(double x, double y)
Definition: ExprBuiltins.h:42
SeExpr2::TriplanarFuncX::eval
virtual void eval(ArgHandle args)
Definition: imageSynthForPaint3d.cpp:113
SeExpr2::TriplanarFuncX
Definition: imageSynthForPaint3d.cpp:97
eval
virtual void eval(ArgHandle args)
Definition: ExprBuiltins.cpp:22
SeExpr2::MapFuncX::prep
virtual ExprType prep(ExprFuncNode *node, bool wantScalar, ExprVarEnvBuilder &envBuilder) const
Definition: imageSynthForPaint3d.cpp:70
SeExpr2::map
SeExpr2::MapFuncX map
SeExpr2::RandFuncX
Definition: imageSynthForPaint3d.cpp:35
SeExpr2::MapFuncX::MapFuncX
MapFuncX()
Definition: imageSynthForPaint3d.cpp:92
SeExpr2::ExprFuncNode::Data
base class for custom instance data
Definition: ExprNode.h:570
SeExpr2::MapFuncX::Data::ranges
std::vector< std::pair< int, int > > ranges
Definition: imageSynthForPaint3d.cpp:66
SeExpr2::MapFuncX::~MapFuncX
virtual ~MapFuncX()
Definition: imageSynthForPaint3d.cpp:93
SeExpr2::RandFuncX::evalConstant
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
Definition: imageSynthForPaint3d.cpp:49
SeExpr2::rand
SeExpr2::RandFuncX rand
SeExpr2::MapFuncX::eval
virtual void eval(ArgHandle args)
Definition: imageSynthForPaint3d.cpp:80
SeExpr2::ExprVarRef
abstract class for implementing variable references
Definition: Expression.h:45
SeExpr2::ExprFunc::define
static void define(const char *name, ExprFunc f, const char *docString)
Definition: ExprFunc.cpp:169
triplanar_docstring
static const char * triplanar_docstring
Definition: imageSynthForPaint3d.cpp:132
SeExpr2::RandFuncX::Data::ranges
std::vector< std::pair< int, int > > ranges
Definition: imageSynthForPaint3d.cpp:38
SeExpr2::TriplanarFuncX::Data
Definition: imageSynthForPaint3d.cpp:98
main
int main(int argc, char *argv[])
Definition: imageSynthForPaint3d.cpp:186
Expression.h
expr
</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")
x
</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
resolveVar
</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
SeExpr2::TriplanarFuncX::~TriplanarFuncX
virtual ~TriplanarFuncX()
Definition: imageSynthForPaint3d.cpp:126