KSeExpr 6.0.0.0
imageSynthForPaint3d.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2011-2019 Disney Enterprises, Inc.
2// SPDX-License-Identifier: LicenseRef-Apache-2.0
3// SPDX-FileCopyrightText: 2020 L. E. Segovia <amy@amyspark.me>
4// SPDX-License-Identifier: GPL-3.0-or-later
5
9#include <cstdio>
10#include <cstdlib>
11#include <cstring>
12#include <fstream>
13#include <map>
14#include <memory>
15#include <png.h>
16#include <vector>
17
18#include <KSeExpr/ExprFunc.h>
19#include <KSeExpr/ExprFuncX.h>
20#include <KSeExpr/Expression.h>
21#include <KSeExpr/Interpreter.h>
23#include <KSeExpr/Vec.h>
24
25namespace KSeExpr
26{
27class ImageSynthRandFuncX : public ExprFuncSimple
28{
29 struct Data : public ExprFuncNode::Data {
30 std::vector<std::pair<int, int>> ranges;
31 std::string format;
32 };
33
35 {
36 bool valid = true;
37 for (int i = 0; i < node->numChildren(); i++)
38 valid &= node->checkArg(i, ExprType().FP(1).Varying(), envBuilder);
39 return valid ? ExprType().FP(1).Varying() : ExprType().Error();
40 }
41
42 ExprFuncNode::Data *evalConstant(const ExprFuncNode *, ArgHandle) const override
43 {
44 return new Data;
45 }
46
47 void eval(ArgHandle args) override
48 {
49 if (args.nargs() >= 2) {
50 args.outFp = (args.inFp<1>(0)[0] - args.inFp<1>(1)[0]) / 2.0;
51 } else
52 args.outFp = 0.5;
53 }
54
55public:
56 ImageSynthRandFuncX()
58 {
59 } // Thread Safe
60 ~ImageSynthRandFuncX() override = default;
61 ImageSynthRandFuncX &operator=(ImageSynthRandFuncX &&) = default;
62 ImageSynthRandFuncX &operator=(const ImageSynthRandFuncX &) = default;
63 ImageSynthRandFuncX(ImageSynthRandFuncX &&) = default;
64 ImageSynthRandFuncX(const ImageSynthRandFuncX &) = default;
65};
66
67// map(string name, [float format-arg], [float u], [float v], [int channel])
69{
70 struct Data : public ExprFuncNode::Data {
71 std::vector<std::pair<int, int>> ranges;
72 std::string format;
73 };
74
76 {
77 bool valid = true;
78 valid &= node->checkArg(0, ExprType().String().Constant(), envBuilder);
79 for (int i = 1; i < node->numChildren(); i++)
80 valid &= node->checkArg(i, ExprType().FP(1).Varying(), envBuilder);
81 return valid ? ExprType().FP(3).Varying() : ExprType().Error();
82 }
83
85 {
86 return new Data;
87 }
88
89 void eval(ArgHandle args) override
90 {
91 double *out = &args.outFp;
92
93 double val = 0.5;
94 int num = args.nargs();
95 if (num > 2)
96 for (int k = 2; k < num; k++)
97 val += args.inFp<1>(k)[0];
98
99 for (int k = 0; k < 3; k++)
100 out[k] = val;
101 }
102
103public:
106 {
107 } // Thread Safe
108
109 ~MapFuncX() override = default;
111 MapFuncX &operator=(const MapFuncX &) = default;
112 MapFuncX(MapFuncX &&) = default;
113 MapFuncX(const MapFuncX &) = default;
114};
115
116// triplanar(string name, [vector scale], [float blend], [vector rotation], [vector translation])
118{
119 struct Data : public ExprFuncNode::Data {
120 std::vector<std::pair<int, int>> ranges;
121 std::string format;
122 };
123
125 {
126 bool valid = true;
127 valid &= node->checkArg(0, ExprType().String().Constant(), envBuilder);
128 for (int i = 1; i < node->numChildren(); i++)
129 valid &= node->checkArg(i, ExprType().FP(1).Varying(), envBuilder);
130 return valid ? ExprType().FP(3).Varying() : ExprType().Error();
131 }
132
134 {
135 return new Data;
136 }
137
138 void eval(ArgHandle args) override
139 {
140 double *out = &args.outFp;
141
142 double val = 0.5;
143 int num = args.nargs();
144 if (num > 1)
145 for (int k = 1; k < num; k++)
146 val += (args.inFp<3>(k)[0] + args.inFp<3>(k)[1] + args.inFp<3>(k)[2]);
147
148 for (int k = 0; k < 3; k++)
149 out[k] = val;
150 }
151
152public:
155 {
156 } // Thread Safe
157
158 ~TriplanarFuncX() override = default;
162 TriplanarFuncX(const TriplanarFuncX &) = default;
163};
164} // namespace KSeExpr
165
166static const char *rand_docstring = "rand\n";
167static const char *map_docstring = "map\n";
168static const char *triplanar_docstring = "triplanar\n";
169
170using namespace KSeExpr;
171
173class ImageSynthExpr : public Expression
174{
175public:
177 ImageSynthExpr(const std::string &expr)
178 : Expression(expr, ExprType().FP(3))
179 {
180 }
181
183 struct Var : public ExprVarRef {
184 Var(const double val)
185 : ExprVarRef(ExprType().FP(1).Varying())
186 , val(val)
187 {
188 }
189
190 Var()
191 : ExprVarRef(ExprType().FP(1).Varying())
192 {
193 }
194
195 double val {}; // independent variable
196 void eval(double *result) override
197 {
198 result[0] = val;
199 }
200
201 void eval(const char **) override
202 {
203 assert(false);
204 }
205 };
206
207 struct VecVar : public ExprVarRef {
208 VecVar()
209 : ExprVarRef(ExprType().FP(3).Varying())
210 , val(0.0)
211 {
212 }
213
214 Vec<double, 3, false> val; // independent variable
215
216 void eval(double *result) override
217 {
218 for (int k = 0; k < 3; k++)
219 result[k] = val[k];
220 }
221
222 void eval(const char **) override
223 {
224 }
225 };
226
228 mutable std::map<std::string, Var> vars;
229 mutable std::map<std::string, VecVar> vecvars;
230
232 ExprVarRef *resolveVar(const std::string &name) const override
233 {
234 {
235 auto i = vars.find(name);
236 if (i != vars.end())
237 return &i->second;
238 }
239 {
240 auto i = vecvars.find(name);
241 if (i != vecvars.end())
242 return &i->second;
243 }
244 return nullptr;
245 }
246};
247
248double clamp(double x)
249{
250 return std::max(0., std::min(255., x));
251}
252
253int main(int argc, char *argv[])
254{
255 if (argc != 5) {
256 std::cerr << "Usage: " << argv[0] << " <image file> <width> <height> <exprFile>" << std::endl;
257 return 1;
258 }
259
260 auto imageSynthRand = std::make_unique<KSeExpr::ImageSynthRandFuncX>();
261 auto map = std::make_unique<KSeExpr::MapFuncX>();
262 auto triplanar = std::make_unique<KSeExpr::TriplanarFuncX>();
263
264 // Disney: this function overrides the existing rand() -- amyspark
268
269 // parse arguments
270 const char *imageFile = argv[1];
271 const char *exprFile = argv[4];
272 size_t width = std::strtoul(argv[2], nullptr, 10); // NOLINT readability-magic-numbers
273 size_t height = std::strtoul(argv[3], nullptr, 10); // NOLINT readability-magic-numbers
274 if (!width || !height) {
275 std::cerr << "invalid width/height" << std::endl;
276 return 1;
277 }
278
279 std::ifstream istream(exprFile);
280 if (!istream) {
281 std::cerr << "Cannot read file " << exprFile << std::endl;
282 return 1;
283 }
284 std::string exprStr((std::istreambuf_iterator<char>(istream)), std::istreambuf_iterator<char>());
285 ImageSynthExpr expr(exprStr);
286
287 // make variables
288 expr.vars["u"] = ImageSynthExpr::Var(0.);
289 expr.vars["v"] = ImageSynthExpr::Var(0.);
290 expr.vars["w"] = ImageSynthExpr::Var(width);
291 expr.vars["h"] = ImageSynthExpr::Var(height);
292
293 expr.vars["faceId"] = ImageSynthExpr::Var(0.);
294 expr.vecvars["P"] = ImageSynthExpr::VecVar();
295 expr.vecvars["Cs"] = ImageSynthExpr::VecVar();
296 expr.vecvars["Ci"] = ImageSynthExpr::VecVar();
297
298 // check if expression is valid
299 bool valid = expr.isValid();
300 if (!valid) {
301 std::cerr << "Invalid expression " << std::endl;
302 std::cerr << expr.parseError() << std::endl;
303 return 1;
304 }
305 // if(!expr.returnType().isFP(3)){
306 // std::cerr<<"Expected color FP[3] got type "<<expr.returnType().toString()<<std::endl;
307 // return 1;
308 // }
309
310 // evaluate expression
311 std::cerr << "Evaluating expression... from " << exprFile << std::endl;
312 std::vector<unsigned char> image(width * height * 4);
313 double one_over_width = 1. / width;
314 double one_over_height = 1. / height;
315 double &u = expr.vars["u"].val;
316 double &v = expr.vars["v"].val;
317
318 double &faceId = expr.vars["faceId"].val;
319 Vec<double, 3, false> &P = expr.vecvars["P"].val;
320 Vec<double, 3, false> &Cs = expr.vecvars["Cs"].val;
321 Vec<double, 3, false> &Ci = expr.vecvars["Ci"].val;
322
323 {
324 PerformanceTimer timer("eval time: ");
325 for (size_t row {}; row < height; row++) {
326 for (size_t col {}; col < width; col++) {
327 auto i = (row * width + col) * 4;
328 u = one_over_width * (col + .5);
329 v = one_over_height * (row + .5);
330
331 faceId = floor(u * 5);
332 P[0] = u * 10;
333 P[1] = v * 10;
334 P[2] = 0.5 * 10;
335 Cs[0] = 0.;
336 Cs[1] = 0.4;
337 Cs[2] = 0.6;
338 Ci[0] = 0.;
339 Ci[1] = 0.4;
340 Ci[2] = 0.6;
341
342 const double *result = expr.evalFP();
343
344 // expr._interpreter->print();
345 image[i] = clamp(result[0] * 256.);
346 image[i + 1] = clamp(result[1] * 256.);
347 image[i + 2] = clamp(result[2] * 256.);
348 image[i + 3] = 255;
349 }
350 }
351 }
352
353 // write image as png
354 std::cerr << "Writing image..." << imageFile << std::endl;
355 std::unique_ptr<std::FILE, decltype(&std::fclose)> fp {fopen(imageFile, "wb"), &std::fclose};
356 if (!fp) {
357 perror("fopen");
358 return 1;
359 }
362 png_init_io(png_ptr, fp.get());
364 info_ptr,
365 width,
366 height,
367 8, // NOLINT readability-magic-numbers
372 std::vector<png_byte *> ptrs(height);
373 for (size_t i {}; i < height; i++) {
374 ptrs[i] = &image[width * i * 4];
375 }
378}
Node that calls a function.
Definition ExprNode.h:654
Vec< double, d, true > inFp(int i)
Definition ExprFuncX.h:77
virtual void eval(ArgHandle args)=0
ExprType prep(ExprFuncNode *node, bool scalarWanted, ExprVarEnvBuilder &envBuilder) const override=0
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const =0
ExprFuncX & operator=(const ExprFuncX &)=default
Function Definition, used in parse tree and func table.
Definition ExprFunc.h:35
static void define(const char *name, const ExprFunc &f, const char *docString)
Definition ExprFunc.cpp:158
ExprType & FP(int d)
Mutate this into a floating point type of dimension d.
Definition ExprType.h:97
ExprType & Varying()
Mutate this into a varying lifetime.
Definition ExprType.h:134
ExprType & Error()
Mutate this into an error type.
Definition ExprType.h:111
Variable scope builder is used by the type checking and code gen to track visiblity of variables and ...
Definition ExprEnv.h:181
abstract class for implementing variable references
Definition Expression.h:36
main expression class
Definition Expression.h:67
virtual ExprVarRef * resolveVar(const std::string &) const
Definition Expression.h:201
ExprFuncNode::Data * evalConstant(const ExprFuncNode *, ArgHandle) const override
MapFuncX & operator=(const MapFuncX &)=default
void eval(ArgHandle args) override
ExprType prep(ExprFuncNode *node, bool, ExprVarEnvBuilder &envBuilder) const override
MapFuncX(const MapFuncX &)=default
MapFuncX & operator=(MapFuncX &&)=default
MapFuncX(MapFuncX &&)=default
~MapFuncX() override=default
ExprFuncNode::Data * evalConstant(const ExprFuncNode *, ArgHandle) const override
TriplanarFuncX(const TriplanarFuncX &)=default
~TriplanarFuncX() override=default
TriplanarFuncX & operator=(const TriplanarFuncX &)=default
ExprType prep(ExprFuncNode *node, bool, ExprVarEnvBuilder &envBuilder) const override
void eval(ArgHandle args) override
TriplanarFuncX(TriplanarFuncX &&)=default
TriplanarFuncX & operator=(TriplanarFuncX &&)=default
int main(int argc, char *argv[])
static const char * triplanar_docstring
static const char * map_docstring
double clamp(double x, double lo, double hi)
static const char * rand_docstring
base class for custom instance data
Definition ExprNode.h:723
std::vector< std::pair< int, int > > ranges
std::vector< std::pair< int, int > > ranges