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