1 /**************************************************************************/
2 /*  Copyright 2009 Tim Day                                                */
3 /*                                                                        */
4 /*  This file is part of Fracplanet                                       */
5 /*                                                                        */
6 /*  Fracplanet 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 /*  Fracplanet 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 Fracplanet.  If not, see <http://www.gnu.org/licenses/>.   */
18 /**************************************************************************/
19 
20 /* Copyright (C) 1998,1999 T Day */
21 
22 /*! \file
23   \brief Interface for class ByteRGBA and class FloatRGBA.
24 */
25 
26 #ifndef _image_rgb_h_
27 #define _image_rgb_h_
28 
29 #include "common.h"
30 
31 /*! Direct access to class members is permitted.
32   The uchar version is intended as a minimal class for efficient storage of colours.
33   (However, padding means there is a wasted byte if we just want RGB so we
34   might as well have an alpha channel).
35  */
36 template <typename T> class RGBA
37 {
38  public:
39   //@{
40   //! Colour component.
41   T r;
42   T g;
43   T b;
44   T a;
45   //@}
46 
47   //! Null constructor.
48   /* NB There are no default values.
49    */
RGBA()50   RGBA()
51     {}
52 
53   //! Copy constructor.
RGBA(const RGBA & c)54   RGBA(const RGBA& c)
55     :r(c.r)
56     ,g(c.g)
57     ,b(c.b)
58     ,a(c.a)
59     {}
60 
61   //! Initialise from separate components.
RGBA(T vr,T vg,T vb,T va)62   RGBA(T vr,T vg,T vb,T va)
63     :r(vr)
64     ,g(vg)
65     ,b(vb)
66     ,a(va)
67     {}
68 
69   //! Colour addition.
70   void operator+=(const RGBA& v)
71     {
72       r+=v.r;
73       g+=v.g;
74       b+=v.b;
75       a+=v.a;
76     }
77 
78   //! Colour subtraction.
79   void operator-=(const RGBA& v)
80     {
81       r-=v.r;
82       g-=v.g;
83       b-=v.b;
84       a-=v.a;
85     }
86 };
87 
88 //! Colour equality operator.
89 template <typename T> inline bool operator==(const RGBA<T>& a,const RGBA<T>& b)
90 {
91   return (a.r==b.r && a.g==b.g && a.b==b.b && a.a==b.a);
92 }
93 
94 //! Colour inequality operator.
95 template <typename T> inline bool operator!=(const RGBA<T>& a,const RGBA<T>& b)
96 {
97   return (a.r!=b.r || a.g!=b.g || a.b!=b.b || a.a!=b.a);
98 }
99 
100 //! Colour addition operator.
101 template <typename T> inline RGBA<T> operator+(const RGBA<T>& a,const RGBA<T>& b)
102 {
103   return RGBA<T>
104     (
105      a.r+b.r,
106      a.g+b.g,
107      a.b+b.b,
108      a.a+b.a
109      );
110 }
111 
112 //! Colour negation operator.
113 template <typename T> inline RGBA<T> operator-(const RGBA<T>& c)
114 {
115   return RGBA<T>
116     (
117      -c.r,
118      -c.g,
119      -c.b,
120      -c.a
121      );
122 }
123 
124 //! Colour subtraction operator.
125 template <typename T> inline RGBA<T> operator-(const RGBA<T>& a,const RGBA<T>& b)
126 {
127   return RGBA<T>
128     (
129      a.r-b.r,
130      a.g-b.g,
131      a.b-b.b,
132      a.a-b.a
133      );
134 }
135 
136 
137 //! Class to represent red-green-blue-alpha colours stored with 8-bit resolution.
138 class ByteRGBA : public RGBA<uchar>
139 {
140  public:
141 
142   //! Null constructor.  NB There are no default values.
ByteRGBA()143   ByteRGBA()
144     :RGBA<uchar>()
145     {}
146 
147   //! Copy constructor.
ByteRGBA(const RGBA<uchar> & c)148   ByteRGBA(const RGBA<uchar>& c)
149     :RGBA<uchar>(c)
150     {}
151 
152   //! Componentwise initialization.
ByteRGBA(uchar vr,uchar vg,uchar vb,uchar va)153   ByteRGBA(uchar vr,uchar vg,uchar vb,uchar va)
154     :RGBA<uchar>(vr,vg,vb,va)
155     {}
156 
157   //! Construct ByteRGBA from float RGBAs.
158   /*! Components in the range [0.0,1.0] are scaled to [0,255].
159    */
ByteRGBA(const RGBA<float> & c)160   explicit ByteRGBA(const RGBA<float>& c)
161     :RGBA<uchar>
162     (
163      static_cast<uchar>(255.0*clamped(c.r,0.0f,1.0f)),
164      static_cast<uchar>(255.0*clamped(c.g,0.0f,1.0f)),
165      static_cast<uchar>(255.0*clamped(c.b,0.0f,1.0f)),
166      static_cast<uchar>(255.0*clamped(c.a,0.0f,1.0f))
167      )
168     {}
169 
170   std::ostream& write(std::ostream&) const;
171   const std::string format_comma() const;
172 };
173 
174 //! Class to represent red-green-blue-alpha colours stored to floating point accuracy.
175 class FloatRGBA : public RGBA<float>
176 {
177 public:
178 
179   //! Null constructor.
180   /* NB There are no default values.
181    */
FloatRGBA()182   FloatRGBA()
183     {}
184 
185   //! Copy constructor.
FloatRGBA(const RGBA<float> & c)186   FloatRGBA(const RGBA<float>& c)
187     :RGBA<float>(c)
188     {}
189 
190   //! Initialise from separate components.
FloatRGBA(float vr,float vg,float vb,float va)191   FloatRGBA(float vr,float vg,float vb,float va)
192     :RGBA<float>(vr,vg,vb,va)
193     {}
194 
195   //! Initialise from ByteRGBA.
196   /*! Byte values [0,255] are normalised to [0.0,1.0]
197    */
FloatRGBA(const RGBA<uchar> & c)198   explicit FloatRGBA(const RGBA<uchar>& c)
199     :RGBA<float>(c.r/255.0f,c.g/255.0f,c.b/255.0,c.a/255.0)
200     {}
201 
202   //! Output method.
203   std::ostream& write(std::ostream&) const;
204 
205   const std::string format_pov_rgb() const;
206 
207   const std::string format_pov_rgbf() const;
208 };
209 
210 //! Colour multiplication-by-scalar operator.
211 inline FloatRGBA operator*(float k,const FloatRGBA& c)
212 {
213   return FloatRGBA
214     (
215      k*c.r,
216      k*c.g,
217      k*c.b,
218      k*c.a
219      );
220 }
221 
222 //! Colour multiplication-by-scalar operator.
223 inline FloatRGBA operator*(const FloatRGBA& c,float k)
224 {
225   return FloatRGBA
226     (
227      k*c.r,
228      k*c.g,
229      k*c.b,
230      k*c.a
231      );
232 }
233 
234 //! Colour division-by-scalar operator.
235 inline FloatRGBA operator/(const FloatRGBA& c,float k)
236 {
237   return FloatRGBA
238     (
239      c.r/k,
240      c.g/k,
241      c.b/k,
242      c.a/k
243      );
244 }
245 
246 
247 //! Colour multiplication operator.
248 /*! Componentwise multiplication.
249  */
250 inline FloatRGBA operator*(const FloatRGBA& a,const FloatRGBA& b)
251 {
252   return FloatRGBA
253     (
254      a.r*b.r,
255      a.g*b.g,
256      a.b*b.b,
257      a.a*b.a
258      );
259 }
260 
261 inline std::ostream& operator<<(std::ostream& out,const FloatRGBA& c)
262 {
263   return c.write(out);
264 }
265 
266 #endif
267