1 /**************************************************************************/
2 /*  Copyright 2012 Tim Day                                                */
3 /*                                                                        */
4 /*  This file is part of Evolvotron                                       */
5 /*                                                                        */
6 /*  Evolvotron is free software: you can redistribute it and/or modify    */
7 /*  it under the terms of the GNU General Public License as published by  */
8 /*  the Free Software Foundation, either version 3 of the License, or     */
9 /*  (at your option) any later version.                                   */
10 /*                                                                        */
11 /*  Evolvotron is distributed in the hope that it will be useful,         */
12 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
13 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
14 /*  GNU General Public License for more details.                          */
15 /*                                                                        */
16 /*  You should have received a copy of the GNU General Public License     */
17 /*  along with Evolvotron.  If not, see <http://www.gnu.org/licenses/>.   */
18 /**************************************************************************/
19 
20 /*! \file
21   \brief Interfaces for class MutatableImage.
22 */
23 
24 #ifndef _mutatable_image_h_
25 #define _mutatable_image_h_
26 
27 #include "common.h"
28 
29 #include "xyz.h"
30 
31 class FunctionNull;
32 class FunctionRegistry;
33 class FunctionTop;
34 class MutationParameters;
35 
36 //! Class to hold the base FunctionNode of an image.
37 /*! Once it owns a root FunctionNode* the whole structure should be fixed (mutate isn't available, only mutated).
38   \todo Do reference counting on this object ?  Maybe not: have to worry about stateful nodes,
39   \todo Generally tighten up const-ness of interfaces.
40  */
41 class MutatableImage
42 {
43  protected:
44 
45   //! The top level FunctionNode of the image.
46   /*! This is partly here because FunctionNode::mutate can't change the type of
47     the node it is invoked on (only child nodes can be zapped), partly so we
48     can keep colour and space transforms under control.
49    */
50   std::unique_ptr<FunctionTop> _top;
51 
52   //! Whether to sweep z sinusoidally (vs linearly)
53   bool _sinusoidal_z;
54 
55   //! Whether xyz should be interpreted as long/lat/radius
56   bool _spheremap;
57 
58   //! Whether this image is locked \todo Should be a property of display, not image.
59   bool _locked;
60 
61   //! Serial number for identity tracking (used by display to discover whether a recompute is needed)
62   unsigned long long _serial;
63 
64   //! Object count to generate serial numbers
65   static unsigned long long _count;
66 
67  public:
68 
69   //! Take ownership of the image tree with the specified root node.
70   MutatableImage(std::unique_ptr<FunctionTop>&,bool sinz,bool sm,bool lock);
71 
72   //! Create a new random image tree.
73   MutatableImage(const MutationParameters& parameters,bool exciting,bool sinz,bool sm);
74 
75   //! Destructor.  NB Deletes owned image function tree.
76   virtual ~MutatableImage();
77 
78   //! Returns the sampling co-ordinate given a (sub)pixel position in the given frame of an animation.
79   /*! This depends on things like sinusoidal_z and spheremap
80    */
81   const XYZ sampling_coordinate(real x,real y,uint z,uint sx,uint sy,uint sz) const;
82 
83   //! Accessor.
84   const FunctionTop& top() const;
85 
86   //! Accessor.
sinusoidal_z()87   bool sinusoidal_z() const
88     {
89       return _sinusoidal_z;
90     }
91 
92   //! Accessor.
spheremap()93   bool spheremap() const
94     {
95       return _spheremap;
96     }
97 
98   //! Accessor.
locked()99   bool locked() const
100     {
101       return _locked;
102     }
103 
104   //! Accessor.
locked(bool l)105   void locked(bool l)
106     {
107       _locked=l;
108     }
109 
110   //! Accessor.
serial()111   unsigned long long serial() const
112     {
113       return _serial;
114     }
115 
116   //! Clone this image.  The cloned image will not have locked state.
117   boost::shared_ptr<const MutatableImage> deepclone() const;
118 
119   //! Clone this image, setting locked state to that specified.
120   boost::shared_ptr<const MutatableImage> deepclone(bool lock) const;
121 
122   //! Return a mutated version of this image
123   boost::shared_ptr<const MutatableImage> mutated(const MutationParameters& p) const;
124 
125   //! Return a simplified version of this image
126   boost::shared_ptr<const MutatableImage> simplified() const;
127 
128   //! Return the a 0-255-scaled RGB value at the specified location.
129   const XYZ get_rgb(const XYZ& p) const;
130 
131   //! Return the a 0-255-scaled RGB value at the specified pixel of an image/animation taking jitter (if random number generator provided) and multisampling into account
132   const XYZ get_rgb(uint x,uint y,uint f,uint width,uint height,uint frames,Random01* r01,uint multisample) const;
133 
134   //! Return whether image value is independent of position.
135   bool is_constant() const;
136 
137   //! Save the function-tree to the stream
138   std::ostream& save_function(std::ostream& out) const;
139 
140   //! Obtain some statistics about the image function
141   void get_stats(uint& total_nodes,uint& total_parameters,uint& depth,uint& width,real& proportion_constant) const;
142 
143   //! Check the function tree is ok.
144   bool ok() const;
145 
146   //! Read a new function tree from the given stream.
147   static boost::shared_ptr<const MutatableImage> load_function(const FunctionRegistry& function_registry,std::istream& in,std::string& report);
148 };
149 
150 #endif
151