26#include <QApplication>
44double clamp(
double x) {
return std::max(0., std::min(255.,
x)); }
50 ImageSynthExpression(
const std::string &
expr) :
SeExpr2::Expression(
expr) {}
54 Var(
const double val) :
SeExpr2::ExprVarRef(
SeExpr2::ExprType().FP(1).Varying()), val(val) {}
55 Var() :
SeExpr2::ExprVarRef(
SeExpr2::ExprType().FP(1).Varying()), val(0.0) {}
57 void eval(
double *result) { result[0] = val; }
58 void eval(
const char **result) { assert(
false); }
61 mutable std::map<std::string, Var> vars;
65 std::map<std::string, Var>::iterator i = vars.find(name);
66 if (i != vars.end())
return &i->second;
71class ImageSynthesizer {
74 unsigned char *evaluateExpression(
const std::string &exprStr);
81ImageSynthesizer::ImageSynthesizer() {
86unsigned char *ImageSynthesizer::evaluateExpression(
const std::string &exprStr) {
87 ImageSynthExpression
expr(exprStr);
90 expr.vars[
"u"] = ImageSynthExpression::Var(0.);
91 expr.vars[
"v"] = ImageSynthExpression::Var(0.);
92 expr.vars[
"w"] = ImageSynthExpression::Var(_width);
93 expr.vars[
"h"] = ImageSynthExpression::Var(_height);
96 bool valid =
expr.isValid();
98 std::cerr <<
"Invalid expression " << std::endl;
99 std::cerr <<
expr.parseError() << std::endl;
104 std::cerr <<
"Evaluating expression..." << std::endl;
105 unsigned char *image =
new unsigned char[_width * _height * 4];
106 double one_over_width = 1. / _width, one_over_height = 1. / _height;
107 double &u =
expr.vars[
"u"].val;
108 double &v =
expr.vars[
"v"].val;
109 unsigned char *pixel = image;
110 for (
int row = 0; row < _height; row++) {
111 for (
int col = 0; col < _width; col++) {
112 u = one_over_width * (col + .5);
113 v = one_over_height * (row + .5);
115 pixel[0] =
clamp(result[2] * 256.);
116 pixel[1] =
clamp(result[1] * 256.);
117 pixel[2] =
clamp(result[0] * 256.);
128ImageEditorDialog::ImageEditorDialog(QWidget *parent) : QDialog(parent) {
129 _imageSynthesizer =
new ImageSynthesizer();
131 this->setWindowTitle(
"Image Synthesis Editor");
134 _imageLabel =
new QLabel();
135 _imageLabel->setFixedSize(256, 256);
136 _imageLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
139 QString imageFile = QCoreApplication::applicationDirPath() +
"/../share/doc/SeExpr2/seexprlogo.png";
140 QImage image(imageFile);
142 QPixmap imagePixmap = QPixmap::fromImage(image);
143 imagePixmap = imagePixmap.scaled(256, 256, Qt::KeepAspectRatio);
144 _imageLabel->setPixmap(imagePixmap);
145 QWidget *imagePreviewWidget =
new QWidget();
146 QHBoxLayout *imagePreviewLayout =
new QHBoxLayout(imagePreviewWidget);
147 imagePreviewLayout->addStretch();
148 imagePreviewLayout->addWidget(_imageLabel);
149 imagePreviewLayout->addStretch();
153 QScrollArea *scrollArea =
new QScrollArea();
154 scrollArea->setMinimumHeight(100);
155 scrollArea->setFixedWidth(450);
156 scrollArea->setWidgetResizable(
true);
157 scrollArea->setWidget(controls);
167#ifdef IMAGE_EDITOR_ROOT
168 std::string exPathStr = IMAGE_EDITOR_ROOT;
169 exPathStr +=
"/share/SeExpr2/expressions";
170 browser->
addPath(
"Examples", exPathStr);
172 browser->
addPath(
"Examples",
"./src/demos/imageEditor");
177 QPushButton *applyButton =
new QPushButton(
"Apply");
178 connect(applyButton, SIGNAL(clicked()), (ImageEditorDialog *)
this, SLOT(applyExpression()));
183 QVBoxLayout *rootLayout =
new QVBoxLayout();
184 this->setLayout(rootLayout);
186 QWidget *topWidget =
new QWidget();
187 QHBoxLayout *topLayout =
new QHBoxLayout();
188 topLayout->setContentsMargins(0, 0, 0, 0);
189 topWidget->setLayout(topLayout);
191 QWidget *leftWidget =
new QWidget();
192 QVBoxLayout *leftLayout =
new QVBoxLayout();
193 leftLayout->setContentsMargins(0, 0, 0, 0);
194 leftWidget->setLayout(leftLayout);
195 leftLayout->addWidget(imagePreviewWidget);
196 leftLayout->addWidget(scrollArea, 1);
198 QWidget *bottomWidget =
new QWidget();
199 QVBoxLayout *bottomLayout =
new QVBoxLayout();
200 bottomLayout->setContentsMargins(0, 0, 0, 0);
201 bottomWidget->setLayout(bottomLayout);
203 QWidget *buttonWidget =
new QWidget();
204 QHBoxLayout *buttonLayout =
new QHBoxLayout(0);
205 buttonWidget->setLayout(buttonLayout);
206 buttonLayout->addWidget(applyButton);
208 topLayout->addWidget(leftWidget);
209 topLayout->addWidget(browser, 1);
211 bottomLayout->addWidget(_editor);
212 bottomLayout->addWidget(buttonWidget);
214 rootLayout->addWidget(topWidget);
215 rootLayout->addWidget(bottomWidget);
219void ImageEditorDialog::applyExpression() {
220 std::string exprStr = _editor->getExpr();
221 if (exprStr.empty()) {
223 msgBox.setText(
"No expression entered in the editor.");
226 QImage image(_imageSynthesizer->evaluateExpression(exprStr), 256, 256, QImage::Format_RGB32);
227 if (image.isNull()) {
229 msgBox.setText(
"Error evaluating expression to create preview image.");
232 QPixmap imagePixmap = QPixmap::fromImage(image);
233 _imageLabel->setPixmap(imagePixmap);
240int main(
int argc,
char *argv[]) {
241 QApplication app(argc, argv);
242 ImageEditorDialog *dialog =
new ImageEditorDialog(0);
void addUserExpressionPath(const std::string &context)
void addPath(const std::string &name, const std::string &path)
abstract class for implementing variable references
virtual void eval(double *result)=0
returns this variable's value by setting result
int main(int argc, char *argv[])
Vec< const double, 3, true > Vec3dConstRef
</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")
</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
</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