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 
31 namespace SeExpr2 {
33 class 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 
61 double clamp(double x) { return std::max(0., std::min(255., x)); }
62 
63 using namespace SeExpr2;
64 
65 int 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 }
main
int main(int argc, char *argv[])
Definition: imageSynth.cpp:65
SeExpr2::PrintTiming
Definition: Platform.h:150
Interpreter.h
SeExpr2::ExprType
Definition: ExprType.h:39
Platform.h
Platform-specific classes, functions, and includes.
SeExpr2
Definition: Context.h:22
SeExpr2::min
double min(double x, double y)
Definition: ExprBuiltins.h:43
SeExpr2::clamp
double clamp(double x, double lo, double hi)
Definition: ExprBuiltins.h:40
SeExpr2::Expression
main expression class
Definition: Expression.h:76
SeExpr2::max
double max(double x, double y)
Definition: ExprBuiltins.h:42
eval
virtual void eval(ArgHandle args)
Definition: ExprBuiltins.cpp:1028
SeExpr2::ExprVarRef
abstract class for implementing variable references
Definition: Expression.h:45
clamp
double clamp(double x)
Definition: imageSynth.cpp:61
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