00001 #ifndef CVD_UTILITY_H
00002 #define CVD_UTILITY_H
00003
00004 #include <cvd/image.h>
00005 #include <cvd/internal/is_pod.h>
00006 #include <cvd/internal/pixel_traits.h>
00007 #include <cvd/internal/convert_pixel_types.h>
00008
00009 namespace CVD {
00010
00026 template<class S, class T> void copy(const BasicImage<S>& in, BasicImage<T>& out, ImageRef size=ImageRef(-1,-1), ImageRef begin = ImageRef(), ImageRef dst = ImageRef())
00027 {
00028 if (size.x == -1 && size.y == -1)
00029 size = in.size();
00030
00031
00032 if (!(in.in_image(begin) && out.in_image(dst) && in.in_image(begin+size - ImageRef(1,1)) && out.in_image(dst+size - ImageRef(1,1)))){
00033 std::cerr << "bad copy: " << in.size() << " " << out.size() << " " << size << " " << begin << " " << dst << std::endl;
00034 int *p = 0;
00035 *p = 1;
00036 }
00037 if (in.size() == out.size() && size == in.size() && begin == ImageRef() && dst == ImageRef()) {
00038 Pixel::ConvertPixels<S,T>::convert(in.data(), out.data(), in.totalsize());
00039 return;
00040 }
00041
00042 const S* from = &in[begin];
00043 T* to = &out[dst];
00044 int i = 0;
00045 while (i++<size.y) {
00046 Pixel::ConvertPixels<S,T>::convert(from, to, size.x);
00047 from += in.size().x;
00048 to += out.size().x;
00049 }
00050 }
00051
00052 template <class T, bool pod = Internal::is_POD<T>::is_pod> struct ZeroPixel {
00053 static void zero(T& t) {
00054 for (unsigned int c=0; c<Pixel::Component<T>::count; c++)
00055 Pixel::Component<T>::get(t,c) = 0;
00056 }
00057 };
00058
00059 template <class T> struct ZeroPixel<T,true> {
00060 static void zero(T& t) { memset(&t,0,sizeof(T)); }
00061 };
00062
00063 template <class T, bool pod = Internal::is_POD<T>::is_pod> struct ZeroPixels {
00064 static void zero(T* pixels, int count) {
00065 if (count) {
00066 ZeroPixel<T>::zero(*pixels);
00067 std::fill(pixels+1, pixels+count, *pixels);
00068 }
00069 }
00070 };
00071
00072 template <class T> struct ZeroPixels<T,true> {
00073 static void zero(T* pixels, int count) {
00074 memset(pixels, 0, sizeof(T)*count);
00075 }
00076 };
00077
00078
00081 template <class T> inline void zeroPixel(T& pixel) { ZeroPixel<T>::zero(pixel); }
00082
00085 template <class T> inline void zeroPixels(T* pixels, int count) { ZeroPixels<T>::zero(pixels, count); }
00086
00088 template <class T> void zeroBorders(BasicImage<T>& I)
00089 {
00090 if (I.size().y == 0)
00091 return;
00092 zeroPixels(I[0], I.size().x);
00093 for (int r=0;r<I.size().y-1; r++)
00094 zeroPixels(I[r]+I.size().x-1,2);
00095 zeroPixels(I[I.size().y-1], I.size().x);
00096 }
00097
00101 template <class A, class B> inline void differences(const A* a, const A* b, B* diff, size_t count)
00102 {
00103 while (count--)
00104 *(diff++) = (B)*(a++) - (B)*(b++);
00105 }
00106
00110 template <class A, class B> inline void add_multiple_of_sum(const A* a, const A* b, const float& c, B* out, size_t count)
00111 {
00112 while (count--)
00113 *(out++) += (*(a++) + *(b++)) * c;
00114 }
00115
00119 template <class A, class B, class C> inline void assign_multiple(const A* a, const B& c, C* out, size_t count)
00120 {
00121 while (count--)
00122 *(out++) = static_cast<C>(*(a++) * c);
00123 }
00124
00128 template <class T> double inner_product(const T* a, const T* b, size_t count) {
00129 double dot = 0;
00130 while (count--)
00131 dot += *(a++) * *(b++);
00132 return dot;
00133 }
00134
00135 template <class R, class D, class T> struct SumSquaredDifferences {
00136 static inline R sum_squared_differences(const T* a, const T* b, size_t count) {
00137 R ssd = 0;
00138 while (count--) {
00139 D d = *a++ - *b++;
00140 ssd += d*d;
00141 }
00142 return ssd;
00143 }
00144 };
00145
00146 template <class T1, class T2> inline void square(const T1* in, T2* out, size_t count)
00147 {
00148 while (count--) {
00149 *(out++) = static_cast<T2>(*in * *in);
00150 ++in;
00151 }
00152 }
00153
00154 template <class T1, class T2> inline void subtract_square(const T1* in, T2* out, size_t count)
00155 {
00156 while (count--) {
00157 *(out++) -= static_cast<T2>(*in * *in);
00158 ++in;
00159 }
00160 }
00161
00165 template <class T> inline double sum_squared_differences(const T* a, const T* b, size_t count) {
00166 return SumSquaredDifferences<double,double,T>::sum_squared_differences(a,b,count);
00167 }
00168
00170 template<int bytes> bool is_aligned(const void* ptr);
00171 template<> inline bool is_aligned<8>(const void* ptr) { return ((reinterpret_cast<size_t>(ptr)) & 0x7) == 0; }
00172 template<> inline bool is_aligned<16>(const void* ptr) { return ((reinterpret_cast<size_t>(ptr)) & 0xF) == 0; }
00173
00175 template<int A, class T> inline size_t steps_to_align(const T* ptr)
00176 {
00177 return is_aligned<A>(ptr) ? 0 : (A-((reinterpret_cast<size_t>(ptr)) & (A-1)))/sizeof(T);
00178 }
00179
00180 void differences(const byte* a, const byte* b, short* diff, unsigned int size);
00181 void differences(const short* a, const short* b, short* diff, unsigned int size);
00182
00183
00184 void differences(const float* a, const float* b, float* diff, size_t size);
00185 void add_multiple_of_sum(const float* a, const float* b, const float& c, float* out, size_t count);
00186 void assign_multiple(const float* a, const float& c, float* out, size_t count);
00187 double inner_product(const float* a, const float* b, size_t count);
00188 double sum_squared_differences(const float* a, const float* b, size_t count);
00189 void square(const float* in, float* out, size_t count);
00190 void subtract_square(const float* in, float* out, size_t count);
00191
00192 void differences(const int32_t* a, const int32_t* b, int32_t* diff, size_t size);
00193 void differences(const double* a, const double* b, double* diff, size_t size);
00194 void add_multiple_of_sum(const double* a, const double* b, const float& c, double* out, size_t count);
00195 void assign_multiple(const double* a, const double& c, double* out, size_t count);
00196 double inner_product(const double* a, const double* b, size_t count);
00197 double sum_squared_differences(const double* a, const double* b, size_t count);
00198 long long sum_squared_differences(const byte* a, const byte* b, size_t count);
00199
00200
00201 }
00202
00203 #endif