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 <Expression.h>
25 #include <Interpreter.h>
26 #include <Platform.h>
27 #include <png.h>
28 #include <fstream>
29 
30 namespace SeExpr2 {
32 class ImageSynthExpr : public Expression {
33  public:
35  ImageSynthExpr(const std::string& expr) : Expression(expr) {}
36 
38  struct Var : public ExprVarRef {
39  Var(const double val) : ExprVarRef(ExprType().FP(1).Varying()), val(val) {}
40 
41  Var() : ExprVarRef(ExprType().FP(1).Varying()), val(0.0) {}
42 
43  double val; // independent variable
44  void eval(double* result) { result[0] = val; }
45 
46  void eval(const char** result) { assert(false); }
47  };
49  mutable std::map<std::string, Var> vars;
50 
52  ExprVarRef* resolveVar(const std::string& name) const {
53  std::map<std::string, Var>::iterator i = vars.find(name);
54  if (i != vars.end()) return &i->second;
55  return 0;
56  }
57 };
58 }
59 
60 double clamp(double x) { return std::max(0., std::min(255., x)); }
61 
62 using namespace SeExpr2;
63 
64 int main(int argc, char* argv[]) {
65  if (argc != 5) {
66  std::cerr << "Usage: " << argv[0] << " <image file> <width> <height> <exprFile>" << std::endl;
67  return 1;
68  }
69 
70  // parse arguments
71  const char* imageFile = argv[1];
72  const char* exprFile = argv[4];
73  int width = atoi(argv[2]), height = atoi(argv[3]);
74  if (width < 0 || height < 0) {
75  std::cerr << "invalid width/height" << std::endl;
76  return 1;
77  }
78 
79  std::ifstream istream(exprFile);
80  if (!istream) {
81  std::cerr << "Cannot read file " << exprFile << std::endl;
82  return 1;
83  }
84  std::string exprStr((std::istreambuf_iterator<char>(istream)), std::istreambuf_iterator<char>());
85  ImageSynthExpr expr(exprStr);
86 
87  // make variables
88  expr.vars["u"] = ImageSynthExpr::Var(0.);
89  expr.vars["v"] = ImageSynthExpr::Var(0.);
90  expr.vars["w"] = ImageSynthExpr::Var(width);
91  expr.vars["h"] = ImageSynthExpr::Var(height);
92 
93  // check if expression is valid
94  bool valid = expr.isValid();
95  if (!valid) {
96  std::cerr << "Invalid expression " << std::endl;
97  std::cerr << expr.parseError() << std::endl;
98  return 1;
99  }
100  if (!expr.returnType().isFP(3)) {
101  std::cerr << "Expected color FP[3] got type " << expr.returnType().toString() << std::endl;
102  return 1;
103  }
104 
105  // evaluate expression
106  std::cerr << "Evaluating expresion...from " << exprFile << std::endl;
107  unsigned char* image = new unsigned char[width * height * 4];
108 
109  {
110  PrintTiming evalTime("eval time");
111  double one_over_width = 1. / width, one_over_height = 1. / height;
112  double& u = expr.vars["u"].val;
113  double& v = expr.vars["v"].val;
114  unsigned char* pixel = image;
115  for (int row = 0; row < height; row++) {
116  for (int col = 0; col < width; col++) {
117  u = one_over_width * (col + .5);
118  v = one_over_height * (row + .5);
119 
120  const double* result = expr.evalFP();
121 
122  // expr._interpreter->print();
123  pixel[0] = clamp(result[0] * 256.);
124  pixel[1] = clamp(result[1] * 256.);
125  pixel[2] = clamp(result[2] * 256.);
126  pixel[3] = 255;
127  pixel += 4;
128  }
129  }
130  } // timer
131 
132  // write image as png
133  std::cerr << "Writing image..." << imageFile << std::endl;
134  FILE* fp = fopen(imageFile, "wb");
135  if (!fp) {
136  perror("fopen");
137  return 1;
138  }
139  png_structp png_ptr;
140  png_infop info_ptr;
141  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
142  info_ptr = png_create_info_struct(png_ptr);
143  png_init_io(png_ptr, fp);
144  int color_type = PNG_COLOR_TYPE_RGBA;
145  png_set_IHDR(png_ptr,
146  info_ptr,
147  width,
148  height,
149  8,
150  color_type,
151  PNG_INTERLACE_NONE,
152  PNG_COMPRESSION_TYPE_DEFAULT,
153  PNG_FILTER_TYPE_DEFAULT);
154  const unsigned char* ptrs[height];
155  for (int i = 0; i < height; i++) {
156  ptrs[i] = &image[width * i * 4];
157  }
158  png_set_rows(png_ptr, info_ptr, (png_byte**)ptrs);
159  png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0);
160 
161  fclose(fp);
162 }
</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")
virtual void eval(ArgHandle args)
double max(double x, double y)
Definition: ExprBuiltins.h:42
double min(double x, double y)
Definition: ExprBuiltins.h:43
main expression class
Definition: Expression.h:76
</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
double clamp(double x, double lo, double hi)
Definition: ExprBuiltins.h:40
</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
abstract class for implementing variable references
Definition: Expression.h:45
Platform-specific classes, functions, and includes.