SMIL  0.9.1
DImageTransform.hpp
1 /*
2  * Copyright (c) 2011-2016, Matthieu FAESSEL and ARMINES
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of Matthieu FAESSEL, or ARMINES nor the
14  * names of its contributors may be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 
30 #ifndef _D_IMAGE_TRANSFORM_HPP
31 #define _D_IMAGE_TRANSFORM_HPP
32 
33 #include "DBaseImageOperations.hpp"
34 #include "DLineArith.hpp"
35 
36 namespace smil
37 {
38 
56  template <class T>
57  RES_T crop(const Image<T> &imIn, size_t startX, size_t startY, size_t startZ, size_t sizeX, size_t sizeY, size_t sizeZ, Image<T> &imOut)
58  {
59  ASSERT_ALLOCATED(&imIn);
60 
61  size_t inW = imIn.getWidth();
62  size_t inH = imIn.getHeight();
63  size_t inD = imIn.getDepth();
64 
65  size_t realSx = min(sizeX, inW-startX);
66  size_t realSy = min(sizeY, inH-startY);
67  size_t realSz = min(sizeZ, inD-startZ);
68 
69  imOut.setSize(realSx, realSy, realSz);
70  return copy(imIn, startX, startY, startZ, realSx, realSy, realSz, imOut, 0, 0, 0);
71  }
72 
73  template <class T>
74  RES_T crop(Image<T> &imInOut, size_t startX, size_t startY, size_t startZ, size_t sizeX, size_t sizeY, size_t sizeZ)
75  {
76  Image<T> tmpIm(imInOut, true); // clone
77  return crop(tmpIm, startX, startY, startZ, sizeX, sizeY, sizeZ, imInOut);
78  }
79 
80  // 2D overload
81  template <class T>
82  RES_T crop(const Image<T> &imIn, size_t startX, size_t startY, size_t sizeX, size_t sizeY, Image<T> &imOut)
83  {
84  return crop(imIn, startX, startY, 0, sizeX, sizeY, 1, imOut);
85  }
86 
87  template <class T>
88  RES_T crop(Image<T> &imInOut, size_t startX, size_t startY, size_t sizeX, size_t sizeY)
89  {
90  return crop(imInOut, startX, startY, 0, sizeX, sizeY, 1);
91  }
92 
93 
98  template <class T>
99  RES_T addBorder(const Image<T> &imIn, const size_t &bSize, Image<T> &imOut, const T &borderValue=ImDtTypes<T>::max())
100  {
101  ASSERT_ALLOCATED(&imIn)
102 
103  if (&imIn==&imOut)
104  {
105  Image<T> tmpIm(imIn, true); // clone
106  return addBorder(tmpIm, bSize, imOut, borderValue);
107  }
108 
109  ImageFreezer freeze(imOut);
110 
111  size_t s[3];
112  imIn.getSize(s);
113 
114  if (imIn.getDimension()==3)
115  {
116  imOut.setSize(s[0] + 2*bSize, s[1] + 2*bSize, s[2] + 2*bSize);
117  ASSERT_ALLOCATED(&imOut)
118  fill(imOut, borderValue);
119  copy(imIn, 0, 0, 0, s[0], s[1], s[2], imOut, bSize, bSize, bSize);
120  }
121  else
122  {
123  imOut.setSize(s[0] + 2*bSize, s[1] + 2*bSize, 1);
124  ASSERT_ALLOCATED(&imOut)
125  fill(imOut, borderValue);
126  copy(imIn, 0, 0, s[0], s[1], imOut, bSize, bSize);
127  }
128  return RES_OK;
129  }
130 
131 
132 
138  template <class T>
139  RES_T vFlip(Image<T> &imIn, Image<T> &imOut)
140  {
141  if (&imIn==&imOut)
142  return vFlip(imIn);
143 
144  ASSERT_ALLOCATED(&imIn);
145  ASSERT_SAME_SIZE(&imIn, &imOut);
146 
147  typename Image<T>::sliceType *slicesIn = imIn.getSlices();
148  typename Image<T>::sliceType *slicesOut = imOut.getSlices();
149  typename Image<T>::sliceType linesIn;
150  typename Image<T>::sliceType linesOut;
151 
152  size_t width = imIn.getWidth();
153  size_t height = imIn.getHeight();
154  size_t depth = imIn.getDepth();
155 
156  for (size_t k=0;k<depth;k++)
157  {
158  linesIn = slicesIn[k];
159  linesOut = slicesOut[k];
160 
161  for (size_t j=0;j<height;j++)
162  copyLine<T>(linesIn[j], width, linesOut[height-1-j]);
163  }
164 
165  imOut.modified();
166 
167  return RES_OK;
168  }
169 
170  template <class T>
171  RES_T vFlip(Image<T> &imInOut)
172  {
173  ASSERT_ALLOCATED(&imInOut)
174 
175  typename Image<T>::sliceType *slicesIn = imInOut.getSlices();
176  typename Image<T>::sliceType linesIn;
177 
178  size_t width = imInOut.getWidth();
179  size_t height = imInOut.getHeight();
180  size_t depth = imInOut.getDepth();
181 
182  typename Image<T>::lineType tmpLine = ImDtTypes<T>::createLine(width);
183 
184  for (size_t k=0;k<depth;k++)
185  {
186  linesIn = slicesIn[k];
187 
188  for (size_t j=0;j<height/2;j++)
189  {
190  copyLine<T>(linesIn[j], width, tmpLine);
191  copyLine<T>(linesIn[height-1-j], width, linesIn[j]);
192  copyLine<T>(tmpLine, width, linesIn[height-1-j]);
193  }
194  }
195 
196  ImDtTypes<T>::deleteLine(tmpLine);
197  imInOut.modified();
198  return RES_OK;
199  }
200 
205  template <class T>
206  RES_T trans(const Image<T> &imIn, int dx, int dy, int dz, Image<T> &imOut, T borderValue = ImDtTypes<T>::min())
207  {
208  ASSERT_ALLOCATED(&imIn)
209  ASSERT_SAME_SIZE(&imIn, &imOut)
210 
211  size_t lineLen = imIn.getWidth();
212  typename ImDtTypes<T>::lineType borderBuf = ImDtTypes<T>::createLine(lineLen);
213  fillLine<T>(borderBuf, lineLen, borderValue);
214 
215  size_t height = imIn.getHeight();
216  size_t depth = imIn.getDepth();
217 
218  for (size_t k=0;k<depth;k++)
219  {
220  typename Image<T>::sliceType lOut = imOut.getSlices()[k];
221 
222  int z = k-dz;
223  for (size_t j=0;j<height;j++, lOut++)
224  {
225  int y = j-dy;
226 
227  if (z<0 || z>=(int)depth || y<0 || y>=(int)height)
228  copyLine<T>(borderBuf, lineLen, *lOut);
229  else
230  shiftLine<T>(imIn.getSlices()[z][y], dx, lineLen, *lOut, borderValue);
231  }
232  }
233 
234  ImDtTypes<T>::deleteLine(borderBuf);
235 
236  imOut.modified();
237 
238  return RES_OK;
239  }
240 
241  template <class T>
242  RES_T trans(const Image<T> &imIn, int dx, int dy, Image<T> &imOut, T borderValue = ImDtTypes<T>::min())
243  {
244  return trans<T>(imIn, dx, dy, 0, imOut, borderValue);
245  }
246 
247  template <class T>
248  ResImage<T> trans(const Image<T> &imIn, int dx, int dy, int dz)
249  {
250  ResImage<T> imOut(imIn);
251  trans<T>(imIn, dx, dy, dz, imOut);
252  return imOut;
253  }
254 
255  template <class T>
256  ResImage<T> trans(const Image<T> &imIn, int dx, int dy)
257  {
258  ResImage<T> imOut(imIn);
259  trans<T>(imIn, dx, dy, 0, imOut);
260  return imOut;
261  }
262 
263 
271  template <class T>
272  RES_T resize(Image<T> &imIn, size_t sx, size_t sy, Image<T> &imOut)
273  {
274  ASSERT_ALLOCATED(&imIn)
275 
276  if (&imIn==&imOut)
277  {
278  Image<T> tmpIm(imIn, true); // clone
279  return resize(tmpIm, sx, sy, imIn);
280  }
281 
282  ImageFreezer freeze(imOut);
283 
284  imOut.setSize(sx, sy);
285 
286  ASSERT_ALLOCATED(&imOut)
287 
288  size_t w = imIn.getWidth();
289  size_t h = imIn.getHeight();
290 
291  typedef typename Image<T>::lineType lineType;
292 
293  lineType pixIn = imIn.getPixels();
294  lineType pixOut = imOut.getPixels();
295 
296  size_t A, B, C, D, maxVal = numeric_limits<T>::max() ;
297  size_t x, y, index;
298 
299  double x_ratio = ((double)(w-1))/sx;
300  double y_ratio = ((double)(h-1))/sy;
301  double x_diff, y_diff;
302  int offset = 0 ;
303 
304  for (size_t i=0;i<sy;i++)
305  {
306  for (size_t j=0;j<sx;j++)
307  {
308  x = (int)(x_ratio * j) ;
309  y = (int)(y_ratio * i) ;
310  x_diff = (x_ratio * j) - x ;
311  y_diff = (y_ratio * i) - y ;
312  index = y*w+x ;
313 
314  A = size_t(pixIn[index]) & maxVal ;
315  B = size_t(pixIn[index+1]) & maxVal ;
316  C = size_t(pixIn[index+w]) & maxVal ;
317  D = size_t(pixIn[index+w+1]) & maxVal ;
318 
319  // Y = A(1-w)(1-h) + B(w)(1-h) + C(h)(1-w) + Dwh
320  pixOut[offset++] = T(A*(1.-x_diff)*(1.-y_diff) + B*(x_diff)*(1.-y_diff) + C*(y_diff)*(1.-x_diff) + D*(x_diff*y_diff));
321  }
322  }
323 
324  return RES_OK;
325  }
326 
327 
328 
332  template <class T>
333  RES_T resize(Image<T> &imIn, Image<T> &imOut)
334  {
335  return resize(imIn, imOut.getWidth(), imOut.getHeight(), imOut);
336  }
337 
338 
343  template <class T>
344  RES_T scale(Image<T> &imIn, double cx, double cy, Image<T> &imOut)
345  {
346  return resize<T>(imIn, size_t(imIn.getWidth()*cx), size_t(imIn.getHeight()*cy), imOut);
347  }
348 
349  template <class T>
350  RES_T scale(Image<T> &imIn, double cx, double cy)
351  {
352  ASSERT_ALLOCATED(&imIn)
353  Image<T> tmpIm(imIn, true); // clone
354  return resize(tmpIm, cx, cy, imIn);
355  }
356 
357 
358  template <class T>
359  RES_T resize(Image<T> &imIn, UINT sx, UINT sy)
360  {
361  ASSERT_ALLOCATED(&imIn)
362  Image<T> tmpIm(imIn, true); // clone
363  imIn.setSize(sx, sy);
364  return resize<T>(tmpIm, imIn);
365  }
366 
367 
370 } // namespace smil
371 
372 
373 #endif // _D_IMAGE_TRANSFORM_HPP
374 
Definition: DColorConvert.h:38
RES_T vFlip(Image< T > &imIn, Image< T > &imOut)
Vertical flip (horizontal mirror).
Definition: DImageTransform.hpp:139
RES_T copy(const Image< T1 > &imIn, size_t startX, size_t startY, size_t startZ, size_t sizeX, size_t sizeY, size_t sizeZ, Image< T2 > &imOut, size_t outStartX=0, size_t outStartY=0, size_t outStartZ=0)
Copy image.
Definition: DImageArith.hpp:114
Definition: DBaseImage.h:235
Definition: DImage.hpp:50
lineType getPixels() const
Get the pixels as a 1D array.
Definition: DImage.hpp:110
virtual RES_T setSize(size_t w, size_t h, size_t d=1, bool doAllocate=true)
Set the size of image.
Definition: DImage.hxx:319
RES_T fill(Image< T > &imOut, const T &value)
Fill an image with a given value.
Definition: DImageArith.hpp:62
RES_T scale(Image< T > &imIn, double cx, double cy, Image< T > &imOut)
Scale image If imIn has the size (W,H), the size of imOut will be (W*cx, H*cy).
Definition: DImageTransform.hpp:344
RES_T crop(const Image< T > &imIn, size_t startX, size_t startY, size_t startZ, size_t sizeX, size_t sizeY, size_t sizeZ, Image< T > &imOut)
Crop image.
Definition: DImageTransform.hpp:57
size_t getHeight() const
Get image height.
Definition: DBaseImage.h:91
Definition: DBaseImageOperations.hxx:39
virtual void modified()
Trigger modified event (allows to force display update)
Definition: DImage.hxx:223
RES_T resize(Image< T > &imIn, size_t sx, size_t sy, Image< T > &imOut)
2D bilinear resize algorithm.
Definition: DImageTransform.hpp:272
RES_T trans(const Image< T > &imIn, int dx, int dy, int dz, Image< T > &imOut, T borderValue=ImDtTypes< T >::min())
Image translation.
Definition: DImageTransform.hpp:206
size_t getWidth() const
Get image width.
Definition: DBaseImage.h:87
RES_T addBorder(const Image< T > &imIn, const size_t &bSize, Image< T > &imOut, const T &borderValue=ImDtTypes< T >::max())
Add a border of size bSize around the original image.
Definition: DImageTransform.hpp:99
Definition: DTypes.hpp:78
Main Image class.
Definition: DQVtkViewer.hpp:44
UINT getDimension() const
Get dimension (2D or 3D)
Definition: DBaseImage.h:105
T maxVal(const Image< T > &imIn, bool onlyNonZero=false)
Max value of an image.
Definition: DMeasures.hpp:260
volType getSlices() const
Get an array containing the start offset of each slice.
Definition: DImage.hpp:118
size_t getDepth() const
Get image depth (Z)
Definition: DBaseImage.h:95