FaceGen 3 SDKs Reference
Loading...
Searching...
No Matches
fimImg.hpp
1//
2// Copyright (c) Singular Inversions Inc. 2000.
3//
4// Authors: JBrewster, ABeatty
5//
6// Pixel alignment is not implemented for simplicity.
7//
8
9#ifndef FIM_IMG_H
10#define FIM_IMG_H
11
12#include <cmath>
13
14#include "algs.hpp"
15#include "vect2.hpp"
16
17#include "fimRgba.hpp"
18#include "fimCoord.hpp"
19
20namespace Fg {
21
22typedef enum
23{
24 FIMRGB_R = 0,
25 FIMRGB_G,
26 FIMRGB_B,
27
28 FIMRGB_SIZE
29
30} FimRgbE;
31
32template <typename T>
33struct FimImgT
34{
35 uint m_width;
36 uint m_height;
37 std::vector<T> m_image;
38
39 void init(int wid,int hgt);
40 void init(int wid,int hgt,T fill);
41
42 typedef T pixel_type;
43 // Constructor forms. Note that the fill option will only fill with
44 // a single scalar value - multi-channel images will have all channels
45 // filled to the same value.
46 //
47 FimImgT() : m_width(0), m_height(0) {}
48 FimImgT(int width,int height) {init(width,height); }
49 FimImgT(int width,int height,T fill) {init(width,height,fill); }
50 void resize(uint w,uint h) {init(w,h); }
51 void resize(uint w,uint h,T fill) {init(w,h,fill); }
52 void clear() {m_width = m_height = 0; m_image.clear(); }
53
54 // Pixel Access Functions
55 //-----------------------
56 // While these dereference operators are convenient and generally result
57 // in neat code, they are slow compared to pointers.
58 T* operator[](size_t i) {return &m_image[i*width()]; }
59 T const* operator[](size_t i) const {return &m_image[i*width()]; }
60 T* imageData() { return (m_image.size() > 0) ? &m_image[0] : NULL; }
61 T const* imageData() const { return (m_image.size() > 0) ? &m_image[0] : NULL; }
62
63 typedef typename std::vector<T>::const_iterator const_iterator;
64 typedef typename std::vector<T>::iterator iterator;
65
66 // The following functions provide iterator based access in row-major
67 const_iterator begin() const { return m_image.begin(); }
68 const_iterator end() const { return m_image.end(); }
69 iterator begin() { return m_image.begin(); }
70 iterator end() { return m_image.end(); }
71
72 uint width() const {return m_width; }
73 uint height() const {return m_height; }
74 uint widthStepType() const {return width(); }
75 uint widthStepByte() const {return width() * sizeof(T); }
76 bool imageAllocated() const {return (m_image.size() > 0); }
77
78 //-------------------------------------------------------------------------
79 // Image related coordinate transforms.
80 //-------------------------------------------------------------------------
81 FutVect2FC rcsToOics(FutVect2FC p) const
82 {return fimRcsToOics(p,width(),height());}
83 FutVect2FC rcsToOxcs(FutVect2FC) const;
84 FutVect2FC oxcsToRcs(FutVect2FC) const;
85
86 FimImgT<T> operator+(const FimImgT<T>& operand) const;
87 FimImgT<T> operator-(const FimImgT<T>& operand) const;
88 FimImgT<T> operator*(T scalar) const;
89 void operator*=(T scalar);
90
91 void fill(T scalar);
92
93 // Create an integer subsampled image.
94 // Note: Calling this function with ratio < 1 or offset < 0 will result in
95 // undefined behaviour.
96 // calling this function when the image data is not allocated will
97 // cause undefined behaviour.
98 void setFromShrinkInt(const FimImgT<T>&,uint ws,uint hs);
99 FimImgT<T> shrinkInt(int sx, int sy) const;
100
101 bool empty() const { return m_width==0 || m_height==0; }
102};
103
104template<class T>
105void FimImgT<T>::init(int wid,int hgt)
106{
107 FGASSERT((wid > 0) && (hgt > 0));
108 m_width = wid;
109 m_height = hgt;
110 m_image.resize(wid*hgt);
111};
112template<class T>
113void FimImgT<T>::init(int wid,int hgt,T fill)
114{
115 FGASSERT((wid > 0) && (hgt > 0));
116 m_width = wid;
117 m_height = hgt;
118 m_image.resize(wid*hgt,fill);
119}
120
121 // OpenGL texture coordinates (OTCS) vary from 0 to 1 at the outer edges of the
122 // image (left to right and bottom to top).
123template <typename T>
124inline FutVect2FC FimImgT<T>::rcsToOxcs(FutVect2FC pos) const
125{
126 return FutVect2FC((pos.x1 + 0.5f) / width(),
127 1.0f - (pos.x2 + 0.5f) / height());
128}
129template <typename T>
130inline FutVect2FC FimImgT<T>::oxcsToRcs(FutVect2FC pos) const
131{
132 return FutVect2FC(width() * pos.x1 - 0.5f,
133 height() * (1.0f - pos.x2) - 0.5f);
134}
135template <typename T>
136FimImgT<T> FimImgT<T>::operator+( const FimImgT<T>& operand) const
137{
138 FGASSERT((width() == operand.width()) && (height() == operand.height()));
139 FimImgT<T> retval(width(),height());
140 for (uint ii=0; ii<m_image.size(); ii++)
141 retval.m_image[ii] = m_image[ii] + operand.m_image[ii];
142 return retval;
143}
144template <typename T>
145FimImgT<T> FimImgT<T>::operator-( const FimImgT<T>& operand) const
146{
147 FGASSERT((width() == operand.width()) && (height() == operand.height()));
148 FimImgT<T> retval(width(),height());
149 for (uint ii=0; ii<m_image.size(); ii++)
150 retval.m_image[ii] = m_image[ii] - operand.m_image[ii];
151 return retval;
152}
153template <typename T>
154FimImgT<T> FimImgT<T>::operator*(T scalar) const
155{
156 FimImgT<T> retval(width(),height());
157 for (uint ii=0; ii<m_image.size(); ii++)
158 retval.m_image[ii] = m_image[ii] * scalar;
159 return retval;
160}
161template <typename T>
162void FimImgT<T>::operator*=(T scalar)
163{
164 for (uint ii=0; ii<m_image.size(); ii++)
165 m_image[ii] *= scalar;
166}
167
168template <typename T>
169void FimImgT<T>::fill(T val)
170{
171 for (uint ii=0; ii<m_image.size(); ii++)
172 m_image[ii] = val;
173}
174
175// Shrinks an image in both dimensions by an integer factor, sampling
176// the number of source image pixels covered by the destination
177// image pixel. The actual number of destination pixels is rounded down.
178// This routine is NOT optimized. To optimize it a forward transform scheme
179// with a floating point line buffer would be much faster.
180template <typename T>
181void
182FimImgT<T>::setFromShrinkInt(
183 const FimImgT<T> &src, // Source image.
184 uint sx, // Column number shrinking multiple
185 uint sy) // Row number shrinking multiple
186{
187 FGASSERT(sx >= 1);
188 FGASSERT(sy >= 1);
189 FGASSERT(width() == src.width() / sx);
190 FGASSERT(height() == src.height() / sy);
191 FGASSERT((width() > 0) && (height() > 0));
192
193 T const *srcPtr = (T const *) src.imageData();
194 T *dstPtr = (T *) imageData();
195
196 uint srcStep = src.widthStepType();
197 uint dstStep = widthStepType();
198
199 uint xd,yd,xs,ys,off;
200 double acc,
201 invArea = 1.0 / (double)(sx * sy);
202
203 for (yd=0; yd<height(); yd++)
204 {
205 for (xd=0; xd<width(); xd++)
206 {
207 off = yd * sy * srcStep + xd * sx;
208 acc = 0.0;
209 for (ys=0; ys<sy; ys++)
210 {
211 for (xs=0; xs<sx; xs++)
212 {
213 acc += srcPtr[off + xs];
214 }
215 off += srcStep;
216 }
217 // This inline template function supplies the appropriate
218 // downcast type conversion.
219 futConvert(acc * invArea,dstPtr[xd]);
220 }
221 dstPtr += dstStep;
222 }
223}
224
225template <typename T>
226FimImgT<T> FimImgT<T>::shrinkInt(
227 int sx, // Column number shrinking multiple (>= 1)
228 int sy) const // Row number shrinking multiple
229{
230 FGASSERT(imageAllocated());
231 FGASSERT(sx >= 1);
232 FGASSERT(sy >= 1);
233
234 if ((sx == 1) && (sy == 1)) // The easy case !
235 return *this;
236
237 int newWidth = m_width / sx;
238 int newHeight = m_height / sy;
239
240 FGASSERT(newWidth > 0);
241 FGASSERT(newHeight > 0);
242
243 FimImgT<T> retval(newWidth,newHeight);
244
245 retval.setFromShrinkInt(*this,sx,sy);
246
247 return retval;
248}
249
250//**********************************************************************************************
251// Aliases
252//**********************************************************************************************
253
254typedef FimImgT<uchar> FimImgUbC;
255typedef FimImgT<schar> FimImgSbC;
256typedef FimImgT<short> FimImgSsC;
257typedef FimImgT<long> FimImgSlC;
258typedef FimImgT<int> FimImgIC;
259typedef FimImgT<float> FimImgFC;
260
261typedef FimImgT<FimRgbaUbC> FimImgRgbaUbC;
262typedef FimImgT<FimRgbaSbC> FimImgRgbaSbC;
263typedef FimImgT<FimRgbaUsC> FimImgRgbaUsC;
264typedef FimImgT<FimRgbaSsC> FimImgRgbaSsC;
265typedef FimImgT<FimRgbaFC> FimImgRgbaFC;
266
267}
268
269#endif // FIM_IMG_H
270