iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TransformImpl.H
Go to the documentation of this file.
1 /*! @file
2  @author Lior Elazary
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 #include <algorithm>
36 
37 // ######################################################################
38 template <class PixType> inline
40 {
41  const int w = src.width(), h = src.height();
43 
45  typename nrt::Image<PixType>::iterator dptr = result.begin() + w * (h-1);
46 
47  for (int y = 0; y < h; ++y)
48  {
49  // NOTE: we may revert to a more object-safe implementation if
50  // the need arises...
51  memcpy(dptr, sptr, w * sizeof(PixType));
52  sptr += w; dptr -= w;
53  }
54 
55  return result;
56 }
57 
58 // ######################################################################
59 template <class PixType> inline
61 {
62  const int w = src.width(), h = src.height();
63  Image<PixType> result(w, h, nrt::ImageInitPolicy::None);
64 
65  typename Image<PixType>::const_iterator sptr = src.const_begin();
66  typename Image<PixType>::iterator dptr = result.begin() + w - 1;
67 
68  for (int y = 0; y < h; ++y)
69  {
70  for (int x = 0; x < w; ++x) *dptr-- = *sptr++;
71  dptr += 2 * w;
72  }
73 
74  return result;
75 }
76 
77 // ######################################################################
78 template <NRT_PROMOTE_PIX_NO_DEFAULT>
79 nrt::Image<DestType> nrt::shiftImage(nrt::Image<PixType> const srcImage, float const dx, float const dy)
80 {
81  nrt::Image<DestType> const srcImg(srcImage);
82 
83  if(srcImage.size() == 0) return srcImg;
84 
85  // create and clear the return image
86  nrt::Dims<int> dim = srcImg.dims();
87  int w = dim.width(), h = dim.height();
88  nrt::Image<DestType> retImg(dim, nrt::ImageInitPolicy::Zeros);
89 
90  // prepare a couple of variables for the x direction
91  int xt = (int)floor(dx);
92  float xfrac = dx - xt;
93  int startx = std::max(0,xt);
94  int endx = std::min(0,xt) + w;
95  if (fabs(xfrac) < 1.0e-10) xfrac = 0.0;
96  else endx--;
97 
98  // prepare a couple of variable for the y direction
99  int yt = (int)floor(dy);
100  float yfrac = dy - yt;
101  int starty = std::max(0,yt);
102  int endy = std::min(0,yt) + h;
103  if (fabs(yfrac) < 1.0e-10) yfrac = 0.0;
104  else endy--;
105 
106  // dispatch to faster shiftClean() if displacements are roughly integer:
107  if (fabs(xfrac) < 1.0e-10 && fabs(yfrac) < 1.0e-10)
108  return shiftClean(srcImg, xt, yt);
109 
110  if (xfrac > 0.0)
111  {
112  xfrac = 1.0 - xfrac;
113  xt++;
114  }
115 
116  if (yfrac > 0.0)
117  {
118  yfrac = 1.0 - yfrac;
119  yt++;
120  }
121 
122  // prepare the coefficients
123  float tl = (1.0 - xfrac) * (1.0 - yfrac);
124  float tr = xfrac * (1.0 - yfrac);
125  float bl = (1.0 - xfrac) * yfrac;
126  float br = xfrac * yfrac;
127 
128  // prepare the pointers
129  typename nrt::Image<DestType>::const_iterator src, src2 = srcImg.const_begin();
130  typename nrt::Image<DestType>::iterator ret, ret2 = retImg.begin();
131  if (xt > 0) ret2 += xt;
132  if (xt < 0) src2 -= xt;
133  if (yt > 0) ret2 += yt * w;
134  if (yt < 0) src2 -= yt * w;
135 
136  // now loop over the images
137  for (int y = starty; y < endy; ++y)
138  {
139  src = src2; ret = ret2;
140  for (int x = startx; x < endx; ++x)
141  {
142  (*ret) = (DestType)((*src) * tl);
143  if (tr > 0.0) (*ret) += (DestType)((*(src + 1)) * tr);
144  if (bl > 0.0) (*ret) += (DestType)((*(src + w)) * bl);
145  if (br > 0.0) (*ret) += (DestType)((*(src + w + 1)) * br);
146  ++src; ++ret;
147  }
148  src2 += w; ret2 += w;
149  }
150  return retImg;
151 }
152 
153 // ######################################################################
154 template <class PixType>
155 nrt::Image<PixType> nrt::shiftClean(nrt::Image<PixType> const img, int const dx, int const dy, PixType const bgval)
156 {
158 
159  // make sure the source image is valid
160  assert(srcImg.size() > 0);
161 
162  // create and clear the return image
163  int w = srcImg.width(), h = srcImg.height();
165  retImg.clear(bgval);
166 
167  // create the source and destination iterators
168  typename nrt::Image<PixType>::const_iterator src = srcImg.const_begin();
169  typename nrt::Image<PixType>::iterator dst = retImg.begin();
170 
171  // find range of pixels to copy:
172  int startx = std::max(0, -dx), endx = std::min(w - 1, w - 1 - dx);
173  if (startx >= w || endx < 0) return retImg; // empty result
174  int starty = std::max(0, -dy), endy = std::min(h - 1, h - 1 - dy);
175  if (starty >= h || endy < 0) return retImg; // empty result
176 
177  int dstx = std::max(0, std::min(w - 1, dx));
178  int dsty = std::max(0, std::min(h - 1, dy));
179 
180  src += startx + starty * w;
181  dst += dstx + dsty * w;
182 
183  int skip = w - endx + startx - 1;
184 
185  // do the copy:
186  for (int j = starty; j <= endy; j ++)
187  {
188  for (int i = startx; i <= endx; i ++) *dst++ = *src++;
189 
190  // ready for next row of pixels:
191  src += skip; dst += skip;
192  }
193 
194  return retImg;
195 }
196 
197 // ######################################################################
198 template <NRT_PROMOTE_PIX_NO_DEFAULT>
199 nrt::Image<DestType> nrt::rotate(nrt::Image<PixType> const srcImg, nrt::Point2D<nrt::int32> const p, float const angRad)
200 {
201  if(srcImg.empty()) return nrt::Image<DestType>();
202 
203  int const x = p.x();
204  int const y = p.y();
205 
206  // create and clear the return image
207  int w = srcImg.width(), h = srcImg.height();
208  nrt::Image<DestType> retImg(w, h, nrt::ImageInitPolicy::Zeros);
209 
210  // create temporary working image, put srcImg in the middle
211  // put some padding (values are 0) around the image
212  // so we won't need to check out of bounds when rotating
213  int pad = int(ceil(sqrt(w * w + h * h)));
214  int wR = 2 * pad + w;
215  int hR = 2 * pad + h;
216  nrt::Image<PixType> tempImg(wR, hR, nrt::ImageInitPolicy::Zeros);
217  nrt::paste(tempImg, srcImg, nrt::Point2D<nrt::int32>(pad,pad));
218 
219  typename nrt::Image<DestType>::iterator rBPtr = retImg.begin();
220  float cAng = cos(angRad), sAng = sin(angRad);
221 
222  // fill in the return image with the appropriate values
223  float xR = 0.0; float yR = 0.0;
224  int const dx = pad + x;
225  int const dy = pad + y;
226  for(int j = -y; j < h-y; j++)
227  for(int i = -x; i < w-x; i++)
228  {
229  xR = dx + i*cAng + j*sAng;
230  yR = dy - i*sAng + j*cAng;
231  *rBPtr++ = DestType(tempImg.interpolate(xR,yR));
232  }
233 
234  return retImg;
235 }
236 
237 // ######################################################################
238 template <NRT_PROMOTE_PIX_NO_DEFAULT>
239 nrt::Image<DestType> nrt::rotate(nrt::Image<PixType> const src, const float angRad)
240 {
241  return nrt::rotate(src, nrt::Point2D<nrt::int32>(src.width()/2, src.height()/2), angRad);
242 }
243