1 // This code is in the public domain -- castanyo@yahoo.es
3 #ifndef NV_IMAGE_FLOATIMAGE_H
4 #define NV_IMAGE_FLOATIMAGE_H
6 //#include <nvcore/Debug.h>
7 //#include <nvcore/Containers.h> // clamp
8 //#include <nvimage/nvimage.h>
15 class PolyphaseKernel;
17 #define uint unsigned int
19 /// Clamp between two values.
21 inline const T & clamp(const T & x, const T & a, const T & b)
23 return std::min(std::max(x, a), b);
26 inline float lerp(float f0, float f1, float t)
28 const float s = 1.0f - t;
29 return f0 * s + f1 * t;
32 /// Multicomponent floating point image class.
44 // FloatImage(const Image * img);
45 virtual ~FloatImage();
47 /** @name Conversion. */
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;
56 /** @name Allocation. */
58 void allocate(uint c, uint w, uint h);
59 void free(); // Does not clear members.
62 /** @name Manipulation. */
64 void clear(float f=0.0f);
66 // void normalize(uint base_component);
68 void packNormals(uint base_component);
69 void expandNormals(uint base_component);
70 void scaleBias(uint base_component, uint num, float scale, float add);
72 //NVIMAGE_API void clamp(uint base_component, uint num);
73 void clamp(float low, float high);
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);
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;
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;
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;
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; }
101 /** @name Pixel access. */
103 const float * channel(uint c) const;
104 float * channel(uint c);
106 const float * scanline(uint y, uint c) const;
107 float * scanline(uint y, uint c);
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;
113 void setPixel(float f, uint idx);
114 float pixel(uint idx) const;
116 float sampleNearest(float x, float y, int c, WrapMode wm) const;
117 float sampleLinear(float x, float y, int c, WrapMode wm) const;
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;
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;
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;
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.
147 /// Get const channel pointer.
148 inline const float * FloatImage::channel(uint c) const
150 return m_mem + c * m_width * m_height;
153 /// Get channel pointer.
154 inline float * FloatImage::channel(uint c) {
155 return m_mem + c * m_width * m_height;
158 /// Get const scanline pointer.
159 inline const float * FloatImage::scanline(uint y, uint c) const
161 return channel(c) + y * m_width;
164 /// Get scanline pointer.
165 inline float * FloatImage::scanline(uint y, uint c)
167 return channel(c) + y * m_width;
170 /// Set pixel component.
171 inline void FloatImage::setPixel(float f, uint x, uint y, uint c)
173 m_mem[(c * m_height + y) * m_width + x] = f;
176 /// Add to pixel component.
177 inline void FloatImage::addPixel(float f, uint x, uint y, uint c)
179 m_mem[(c * m_height + y) * m_width + x] += f;
182 /// Get pixel component.
183 inline float FloatImage::pixel(uint x, uint y, uint c) const
185 return m_mem[(c * m_height + y) * m_width + x];
188 /// Set pixel component.
189 inline void FloatImage::setPixel(float f, uint idx)
194 /// Get pixel component.
195 inline float FloatImage::pixel(uint idx) const
200 inline uint FloatImage::index(uint x, uint y) const
202 return y * m_width + x;
205 inline uint FloatImage::indexClamp(int x, int y) const
207 return ::clamp(y, int(0), int(m_height-1)) * m_width + ::clamp(x, int(0), int(m_width-1));
210 inline int repeat_remainder(int a, int b)
212 if (a >= 0) return a % b;
213 else return (a + 1) % b + b - 1;
216 inline uint FloatImage::indexRepeat(int x, int y) const
218 return repeat_remainder(y, m_height) * m_width + repeat_remainder(x, m_width);
221 inline uint FloatImage::indexMirror(int x, int y) const
224 while (x >= m_width) {
225 x = m_width + m_width - x - 2;
229 while (y >= m_height) {
230 y = m_height + m_height - y - 2;
236 inline uint FloatImage::index(int x, int y, WrapMode wm) const
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);
243 #endif // NV_IMAGE_FLOATIMAGE_H