OSDN Git Service

イニシャルコミット
[marathon/Aorta.git] / FloatImage.h
1 // This code is in the public domain -- castanyo@yahoo.es
2
3 #ifndef NV_IMAGE_FLOATIMAGE_H
4 #define NV_IMAGE_FLOATIMAGE_H
5
6 //#include <nvcore/Debug.h>
7 //#include <nvcore/Containers.h> // clamp
8 //#include <nvimage/nvimage.h>
9
10 #include <algorithm>
11
12 class Filter;
13 class Kernel1;
14 class Kernel2;
15 class PolyphaseKernel;
16
17 #define uint unsigned int
18
19 /// Clamp between two values.
20 template <typename T> 
21 inline const T & clamp(const T & x, const T & a, const T & b)
22 {
23         return std::min(std::max(x, a), b);
24 }
25
26 inline float lerp(float f0, float f1, float t)
27 {
28         const float s = 1.0f - t;
29         return f0 * s + f1 * t;
30 }
31
32 /// Multicomponent floating point image class.
33 class FloatImage
34 {
35 public:
36
37         enum WrapMode {
38                 WrapMode_Clamp,
39                 WrapMode_Repeat,
40                 WrapMode_Mirror
41         };
42         
43         FloatImage();
44 //      FloatImage(const Image * img);
45         virtual ~FloatImage();
46
47         /** @name Conversion. */
48         //@{
49 /*
50         void initFrom(const Image * img);
51         Image * createImage(uint base_component = 0, uint num = 4) const;
52         Image * createImageGammaCorrect(float gamma = 2.2f) const;
53 */
54         //@}
55
56         /** @name Allocation. */
57         //@{
58         void allocate(uint c, uint w, uint h);
59         void free(); // Does not clear members.
60         //@}
61
62         /** @name Manipulation. */
63         //@{
64         void clear(float f=0.0f);
65
66 //      void normalize(uint base_component);
67         
68         void packNormals(uint base_component);
69         void expandNormals(uint base_component);
70         void scaleBias(uint base_component, uint num, float scale, float add);
71         
72         //NVIMAGE_API void clamp(uint base_component, uint num);
73         void clamp(float low, float high);
74         
75         void toLinear(uint base_component, uint num, float gamma = 2.2f);
76         void toGamma(uint base_component, uint num, float gamma = 2.2f);
77         void exponentiate(uint base_component, uint num, float power);
78         
79         
80         FloatImage * fastDownSample() const;
81         FloatImage * downSample(const Filter & filter, WrapMode wm) const;
82         FloatImage * downSample(const Filter & filter, uint w, uint h, WrapMode wm) const;
83
84         //NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, WrapMode wm) const;
85         //NVIMAGE_API FloatImage * downSample(const Kernel1 & filter, uint w, uint h, WrapMode wm) const;
86         //@}
87
88         float applyKernel(const Kernel2 * k, int x, int y, int c, WrapMode wm) const;
89         float applyKernelVertical(const Kernel1 * k, int x, int y, int c, WrapMode wm) const;
90         float applyKernelHorizontal(const Kernel1 * k, int x, int y, int c, WrapMode wm) const;
91         void applyKernelVertical(const PolyphaseKernel & k, int x, int c, WrapMode wm, float * output) const;
92         void applyKernelHorizontal(const PolyphaseKernel & k, int y, int c, WrapMode wm, float * output) const;
93         
94         
95         uint width() const { return m_width; }
96         uint height() const { return m_height; }
97         uint componentNum() const { return m_componentNum; }
98         uint count() const { return m_count; }
99
100
101         /** @name Pixel access. */
102         //@{
103         const float * channel(uint c) const;
104         float * channel(uint c);
105         
106         const float * scanline(uint y, uint c) const;
107         float * scanline(uint y, uint c);
108         
109         void setPixel(float f, uint x, uint y, uint c);
110         void addPixel(float f, uint x, uint y, uint c);
111         float pixel(uint x, uint y, uint c) const;
112         
113         void setPixel(float f, uint idx);
114         float pixel(uint idx) const;
115         
116         float sampleNearest(float x, float y, int c, WrapMode wm) const;
117         float sampleLinear(float x, float y, int c, WrapMode wm) const;
118         
119         float sampleNearestClamp(float x, float y, int c) const;
120         float sampleNearestRepeat(float x, float y, int c) const;
121         float sampleNearestMirror(float x, float y, int c) const;
122         
123         float sampleLinearClamp(float x, float y, int c) const;
124         float sampleLinearRepeat(float x, float y, int c) const;
125         float sampleLinearMirror(float x, float y, int c) const;
126         //@}
127         
128 public:
129         
130         uint index(uint x, uint y) const;
131         uint indexClamp(int x, int y) const;
132         uint indexRepeat(int x, int y) const;
133         uint indexMirror(int x, int y) const;
134         uint index(int x, int y, WrapMode wm) const;
135
136 public:
137
138         uint m_width;                   ///< Width of the texture.
139         uint m_height;          ///< Height of the texture.
140         uint m_componentNum;    ///< Number of components.
141         uint m_count;                   ///< Image pixel count.
142         float * m_mem;
143
144 };
145
146
147 /// Get const channel pointer.
148 inline const float * FloatImage::channel(uint c) const
149 {
150         return m_mem + c * m_width * m_height;
151 }
152
153 /// Get channel pointer.
154 inline float * FloatImage::channel(uint c) {
155         return m_mem + c * m_width * m_height;
156 }
157
158 /// Get const scanline pointer.
159 inline const float * FloatImage::scanline(uint y, uint c) const
160 {
161         return channel(c) + y * m_width;
162 }
163
164 /// Get scanline pointer.
165 inline float * FloatImage::scanline(uint y, uint c)
166 {
167         return channel(c) + y * m_width;
168 }
169
170 /// Set pixel component.
171 inline void FloatImage::setPixel(float f, uint x, uint y, uint c)
172 {
173         m_mem[(c * m_height + y) * m_width + x] = f;
174 }
175
176 /// Add to pixel component.
177 inline void FloatImage::addPixel(float f, uint x, uint y, uint c)
178 {
179         m_mem[(c * m_height + y) * m_width + x] += f;
180 }
181
182 /// Get pixel component.
183 inline float FloatImage::pixel(uint x, uint y, uint c) const
184 {
185         return m_mem[(c * m_height + y) * m_width + x];
186 }
187
188 /// Set pixel component.
189 inline void FloatImage::setPixel(float f, uint idx)
190 {
191         m_mem[idx] = f;
192 }
193
194 /// Get pixel component.
195 inline float FloatImage::pixel(uint idx) const
196 {
197         return m_mem[idx];
198 }
199
200 inline uint FloatImage::index(uint x, uint y) const
201 {
202         return y * m_width + x;
203 }
204
205 inline uint FloatImage::indexClamp(int x, int y) const
206 {
207         return ::clamp(y, int(0), int(m_height-1)) * m_width + ::clamp(x, int(0), int(m_width-1));
208 }
209
210 inline int repeat_remainder(int a, int b)
211 {
212    if (a >= 0) return a % b;
213    else return (a + 1) % b + b - 1;
214 }
215
216 inline uint FloatImage::indexRepeat(int x, int y) const
217 {
218         return repeat_remainder(y, m_height) * m_width + repeat_remainder(x, m_width);
219 }
220
221 inline uint FloatImage::indexMirror(int x, int y) const
222 {
223         x = abs(x);
224         while (x >= m_width) {
225                 x = m_width + m_width - x - 2;
226         }
227
228         y = abs(y);
229         while (y >= m_height) {
230                 y = m_height + m_height - y - 2;
231         }
232
233         return index(x, y);
234 }
235
236 inline uint FloatImage::index(int x, int y, WrapMode wm) const
237 {
238         if (wm == WrapMode_Clamp) return indexClamp(x, y);
239         if (wm == WrapMode_Repeat) return indexRepeat(x, y);
240         /*if (wm == WrapMode_Mirror)*/ return indexMirror(x, y);
241 }
242
243 #endif // NV_IMAGE_FLOATIMAGE_H