SeExpr
imageEditor.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 */
17 
22 #include <iostream>
23 #include <string>
24 #include <png.h>
25 
26 #include <QtGui/QApplication>
27 #include <QtGui/QDialog>
28 #include <QtGui/QVBoxLayout>
29 #include <QtGui/QScrollArea>
30 #include <QtGui/QLabel>
31 #include <QtGui/QImage>
32 #include <QtGui/QPushButton>
33 #include <QtGui/QMessageBox>
34 
35 #include <SeExpr2/UI/ExprControlCollection.h>
36 #include <SeExpr2/UI/ExprEditor.h>
37 #include <SeExpr2/UI/ExprBrowser.h>
38 #include <SeExpr2/Expression.h>
39 
40 #include "ImageEditorDialog.h"
41 
42 //-- IMAGE SYNTHESIZER CLASSES AND METHODS --//
43 
44 double clamp(double x){return std::max(0.,std::min(255.,x));}
45 
46 // Simple image synthesizer expression class to support demo image editor
47 class ImageSynthExpression:public SeExpr2::Expression
48 {
49 public:
50  // Constructor that takes the expression to parse
51  ImageSynthExpression(const std::string& expr)
52  :SeExpr2::Expression(expr)
53  {}
54 
55  // Simple variable that just returns its internal value
56  struct Var:public SeExpr2::ExprVarRef
57  {
58  Var(const double val)
59  : SeExpr2::ExprVarRef(SeExpr2::ExprType().FP(1).Varying()), val(val) {}
60  Var()
61  : SeExpr2::ExprVarRef(SeExpr2::ExprType().FP(1).Varying()), val(0.0) {}
62  double val; // independent variable
63  void eval(double* result){result[0]=val;}
64  void eval(const char** result){assert(false);}
65  };
66  // variable map
67  mutable std::map<std::string,Var> vars;
68 
69  // resolve function that only supports one external variable 'x'
70  SeExpr2::ExprVarRef* resolveVar(const std::string& name) const
71  {
72  std::map<std::string,Var>::iterator i=vars.find(name);
73  if(i != vars.end()) return &i->second;
74  return 0;
75  }
76 };
77 
78 class ImageSynthesizer
79 {
80 public:
81  ImageSynthesizer();
82  unsigned char *evaluateExpression(const std::string &exprStr);
83 private:
84  int _width;
85  int _height;
86 };
87 
88 ImageSynthesizer::ImageSynthesizer()
89 {
90  _width = 256;
91  _height = 256;
92 }
93 
94 unsigned char *ImageSynthesizer::evaluateExpression(const std::string &exprStr)
95 {
96  ImageSynthExpression expr(exprStr);
97 
98  // make variables
99  expr.vars["u"]=ImageSynthExpression::Var(0.);
100  expr.vars["v"]=ImageSynthExpression::Var(0.);
101  expr.vars["w"]=ImageSynthExpression::Var(_width);
102  expr.vars["h"]=ImageSynthExpression::Var(_height);
103 
104  // check if expression is valid
105  bool valid=expr.isValid();
106  if(!valid){
107  std::cerr<<"Invalid expression "<<std::endl;
108  std::cerr<<expr.parseError()<<std::endl;
109  return NULL;
110  }
111 
112  // evaluate expression
113  std::cerr<<"Evaluating expression..."<<std::endl;
114  unsigned char* image=new unsigned char[_width*_height*4];
115  double one_over_width=1./_width,one_over_height=1./_height;
116  double& u=expr.vars["u"].val;
117  double& v=expr.vars["v"].val;
118  unsigned char* pixel=image;
119  for(int row=0;row<_height;row++){
120  for(int col=0;col<_width;col++){
121  u=one_over_width*(col+.5);
122  v=one_over_height*(row+.5);
123  SeExpr2::Vec3d result=SeExpr2::Vec3dConstRef(expr.evalFP());
124  pixel[0]=clamp(result[2]*256.);
125  pixel[1]=clamp(result[1]*256.);
126  pixel[2]=clamp(result[0]*256.);
127  pixel[3]=255;
128  pixel+=4;
129  }
130  }
131 
132  return image;
133 }
134 
135 //-- IMAGE EDITOR DIALOG METHODS --//
136 
137 ImageEditorDialog::ImageEditorDialog(QWidget *parent)
138  :QDialog(parent)
139 {
140  _imageSynthesizer = new ImageSynthesizer();
141 
142  this->setWindowTitle("Image Synthesis Editor");
143 
144  // Image Previewer
145  _imageLabel = new QLabel();
146  _imageLabel->setFixedSize(256,256);
147  _imageLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter );
148 
149  // Locate logo image relative to location of the app itself
150  QString imageFile = QCoreApplication::applicationDirPath() + "/../share/doc/SeExpr2/seexprlogo.png";
151  QImage image(imageFile); // just a fun default
152 
153  QPixmap imagePixmap = QPixmap::fromImage(image);
154  imagePixmap = imagePixmap.scaled(256, 256, Qt::KeepAspectRatio);
155  _imageLabel->setPixmap(imagePixmap);
156  QWidget* imagePreviewWidget=new QWidget();
157  QHBoxLayout* imagePreviewLayout=new QHBoxLayout(imagePreviewWidget);
158  imagePreviewLayout->addStretch();
159  imagePreviewLayout->addWidget(_imageLabel);
160  imagePreviewLayout->addStretch();
161 
162  // Expression controls
164  QScrollArea* scrollArea=new QScrollArea();
165  scrollArea->setMinimumHeight(100);
166  scrollArea->setFixedWidth(450);
167  scrollArea->setWidgetResizable(true);
168  scrollArea->setWidget(controls);
169 
170  // Expression editor
171  _editor = new ExprEditor(this, controls);
172 
173  // Expression browser
174  ExprBrowser *browser = new ExprBrowser(0, _editor);
175 
176  // Add user expressions, example expressions to browser list.
177  browser->addUserExpressionPath("imageEditor");
178 #ifdef IMAGE_EDITOR_ROOT
179  std::string exPathStr = IMAGE_EDITOR_ROOT;
180  exPathStr += "/share/SeExpr2/expressions";
181  browser->addPath("Examples", exPathStr);
182 #else
183  browser->addPath("Examples", "./src/demos/imageEditor");
184 #endif
185  browser->update();
186 
187  // Create apply button and connect to image preview.
188  QPushButton *applyButton=new QPushButton("Apply");
189  connect(applyButton, SIGNAL(clicked()), (ImageEditorDialog*)this, SLOT(applyExpression()));
190 
191  // Layout widgets: Top section contains left side with previewer and
192  // controls, right side with browser. Bottom section contains editor
193  // and apply button.
194  QVBoxLayout *rootLayout = new QVBoxLayout();
195  this->setLayout(rootLayout);
196 
197  QWidget* topWidget=new QWidget();
198  QHBoxLayout* topLayout=new QHBoxLayout();
199  topLayout->setContentsMargins(0,0,0,0);
200  topWidget->setLayout(topLayout);
201 
202  QWidget *leftWidget=new QWidget();
203  QVBoxLayout *leftLayout=new QVBoxLayout();
204  leftLayout->setContentsMargins(0,0,0,0);
205  leftWidget->setLayout(leftLayout);
206  leftLayout->addWidget(imagePreviewWidget);
207  leftLayout->addWidget(scrollArea,1);
208 
209  QWidget *bottomWidget=new QWidget();
210  QVBoxLayout *bottomLayout=new QVBoxLayout();
211  bottomLayout->setContentsMargins(0,0,0,0);
212  bottomWidget->setLayout(bottomLayout);
213 
214  QWidget *buttonWidget=new QWidget();
215  QHBoxLayout *buttonLayout = new QHBoxLayout(0);
216  buttonWidget->setLayout(buttonLayout);
217  buttonLayout->addWidget(applyButton);
218 
219  topLayout->addWidget(leftWidget);
220  topLayout->addWidget(browser,1);
221 
222  bottomLayout->addWidget(_editor);
223  bottomLayout->addWidget(buttonWidget);
224 
225  rootLayout->addWidget(topWidget);
226  rootLayout->addWidget(bottomWidget);
227 }
228 
229 // Apply expression, if any, from the editor contents to the preview image
230 void ImageEditorDialog::applyExpression()
231 {
232  std::string exprStr = _editor->getExpr();
233  if( exprStr.empty() )
234  {
235  QMessageBox msgBox;
236  msgBox.setText("No expression entered in the editor.");
237  msgBox.exec();
238  } else {
239  QImage image(_imageSynthesizer->evaluateExpression(exprStr),
240  256,
241  256,
242  QImage::Format_RGB32);
243  if( image.isNull() )
244  {
245  QMessageBox msgBox;
246  msgBox.setText("Error evaluating expression to create preview image.");
247  msgBox.exec();
248  } else {
249  QPixmap imagePixmap = QPixmap::fromImage(image);
250  _imageLabel->setPixmap(imagePixmap);
251  }
252  }
253 }
254 
255 //-- MAIN --//
256 
257 int main(int argc, char *argv[]){
258  QApplication app(argc, argv);
259  ImageEditorDialog *dialog = new ImageEditorDialog(0);
260  dialog->show();
261  app.exec();
262  return 0;
263 }
void addPath(const std::string &name, const std::string &path)
virtual ExprVarRef * resolveVar(const std::string &name) const
Definition: Expression.h:199
</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
Vec< const double, 3, true > Vec3dConstRef
Definition: Vec.h:384
double min(double x, double y)
Definition: ExprBuiltins.h:43
main expression class
Definition: Expression.h:76
void addUserExpressionPath(const std::string &context)
</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
int main(int argc, char *argv[])
Definition: EditMain.cpp:24
ExprVarRef(const ExprType &type)
Definition: Expression.h:49
abstract class for implementing variable references
Definition: Expression.h:45
Expression(EvaluationStrategy be=Expression::defaultEvaluationStrategy)
Definition: Expression.cpp:85