KSeExpr 6.0.0.0
imageSynth.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 <png.h>
15#include <vector>
16
17#include <KSeExpr/Expression.h>
18#include <KSeExpr/Interpreter.h>
20
21namespace KSeExpr
22{
24class ImageSynthExpr : public Expression
25{
26public:
28 ImageSynthExpr(const std::string &expr)
29 : Expression(expr)
30 {
31 }
32
34 struct Var : public ExprVarRef {
35 Var(const double val)
36 : ExprVarRef(ExprType().FP(1).Varying())
37 , val(val)
38 {
39 }
40
41 Var()
42 : ExprVarRef(ExprType().FP(1).Varying())
43 {
44 }
45
46 double val {0.0}; // independent variable
47 void eval(double *result) override
48 {
49 result[0] = val;
50 }
51
52 void eval(const char **) override
53 {
54 assert(false);
55 }
56 };
58 mutable std::map<std::string, Var> vars;
59
61 ExprVarRef *resolveVar(const std::string &name) const override
62 {
63 auto i = vars.find(name);
64 if (i != vars.end())
65 return &i->second;
66 return nullptr;
67 }
68};
69} // namespace KSeExpr
70
71constexpr double clamp(double x)
72{
73 return std::max(0., std::min(255., x)); // NOLINT readability-magic-numbers
74}
75
76using namespace KSeExpr;
77
78int main(int argc, char *argv[])
79{
80 if (argc != 5) { // NOLINT readability-magic-numbers
81 std::cerr << "Usage: " << argv[0] << " <image file> <width> <height> <exprFile>" << std::endl;
82 return 1;
83 }
84
85 // parse arguments
86 const char *imageFile = argv[1];
87 const char *exprFile = argv[4];
88 size_t width = std::strtoul(argv[2], nullptr, 10); // NOLINT readability-magic-numbers
89 size_t height = std::strtoul(argv[3], nullptr, 10); // NOLINT readability-magic-numbers
90 if (!width || !height) {
91 std::cerr << "invalid width/height" << std::endl;
92 return 1;
93 }
94
95 std::ifstream istream(exprFile);
96 if (!istream) {
97 std::cerr << "Cannot read file " << exprFile << std::endl;
98 return 1;
99 }
100 std::string exprStr((std::istreambuf_iterator<char>(istream)), std::istreambuf_iterator<char>());
101 ImageSynthExpr expr(exprStr);
102
103 // make variables
104 expr.vars["u"] = ImageSynthExpr::Var(0.);
105 expr.vars["v"] = ImageSynthExpr::Var(0.);
106 expr.vars["w"] = ImageSynthExpr::Var(width);
107 expr.vars["h"] = ImageSynthExpr::Var(height);
108
109 // check if expression is valid
110 bool valid = expr.isValid();
111 if (!valid) {
112 std::cerr << "Invalid expression " << std::endl;
113 std::cerr << expr.parseError() << std::endl;
114 return 1;
115 }
116 if (!expr.returnType().isFP(3)) {
117 std::cerr << "Expected color FP[3] got type " << expr.returnType().toString() << std::endl;
118 return 1;
119 }
120
121 // evaluate expression
122 std::cerr << "Evaluating expresion...from " << exprFile << std::endl;
123 std::vector<unsigned char> image(width * height * 4);
124
125 {
126 PerformanceTimer evalTime("eval time");
127 double one_over_width = 1. / width;
128 double one_over_height = 1. / height;
129 double &u = expr.vars["u"].val;
130 double &v = expr.vars["v"].val;
131 for (size_t row {}; row < height; row++) {
132 for (size_t col {}; col < width; col++) {
133 auto i = (row * width + col) * 4;
134 u = one_over_width * (col + .5); // NOLINT readability-magic-numbers
135 v = one_over_height * (row + .5); // NOLINT readability-magic-numbers
136
137 const double *result = expr.evalFP();
138
139 // expr._interpreter->print();
140 image[i] = clamp(result[0] * 256.); // NOLINT readability-magic-numbers
141 image[i + 1] = clamp(result[1] * 256.); // NOLINT readability-magic-numbers
142 image[i + 2] = clamp(result[2] * 256.); // NOLINT readability-magic-numbers
143 image[i + 3] = 255; // NOLINT readability-magic-numbers
144 }
145 }
146 } // timer
147
148 // write image as png
149 std::cerr << "Writing image..." << imageFile << std::endl;
150 std::unique_ptr<std::FILE, decltype(&std::fclose)> fp {fopen(imageFile, "wb"), &std::fclose};
151 if (!fp) {
152 perror("fopen");
153 return 1;
154 }
157 png_init_io(png_ptr, fp.get());
159 info_ptr,
160 width,
161 height,
162 8, // NOLINT readability-magic-numbers
167 std::vector<png_byte *> ptrs(height);
168 for (size_t i {}; i < height; i++) {
169 ptrs[i] = &image[width * i * 4];
170 }
173}
abstract class for implementing variable references
Definition Expression.h:36
virtual void eval(double *result)=0
returns this variable's value by setting result
main expression class
Definition Expression.h:67
virtual ExprVarRef * resolveVar(const std::string &) const
Definition Expression.h:201
int main(int argc, char *argv[])
double clamp(double x, double lo, double hi)