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 
270  template <class T>
271  RES_T resizeClosest(Image<T> &imIn, size_t sx, size_t sy, Image<T> &imOut)
272  {
273  ASSERT_ALLOCATED(&imIn)
274 
275  if (&imIn==&imOut)
276  {
277  Image<T> tmpIm(imIn, true); // clone
278  return resizeClosest(tmpIm, sx, sy, imIn);
279  }
280 
281  ImageFreezer freeze(imOut);
282 
283  imOut.setSize(sx, sy);
284 
285  ASSERT_ALLOCATED(&imOut)
286 
287  size_t w = imIn.getWidth();
288  size_t h = imIn.getHeight();
289 
290  typedef typename Image<T>::lineType lineType;
291 
292  lineType pixIn = imIn.getPixels();
293  lineType pixOut = imOut.getPixels();
294 
295  size_t A, B, C, D, maxVal = numeric_limits<T>::max() ;
296  size_t x, y, index;
297 
298  double x_ratio = ((double)(w))/sx;// BMI -1 removed
299  double y_ratio = ((double)(h))/sy;// BMI -1 removed
300  double x_diff, y_diff;
301  int offset = 0 ;
302 
303  for (size_t i=0;i<sy;i++)
304  {
305  for (size_t j=0;j<sx;j++)
306  {
307  x = (int)(x_ratio * j) ;
308  y = (int)(y_ratio * i) ;
309  x_diff = (x_ratio * j) - x ;
310  y_diff = (y_ratio * i) - y ;
311  index = y*w+x ;
312 
313 
314 
315  A = size_t(pixIn[index]) & maxVal ;
316  if(x==w-1){
317  B = size_t(pixIn[index]) & maxVal ;
318  }
319  else{
320  B = size_t(pixIn[index+1]) & maxVal ;
321  }
322  if(y<h-1){
323  C = size_t(pixIn[index+w]) & maxVal ;
324  }
325  else{
326  C = size_t(pixIn[index]) & maxVal ;
327  }
328  size_t myindex;
329  myindex = index;
330  if(y<h-1)
331  myindex+=w;
332  if(x<w-1)
333  myindex+=1;
334  D = size_t(pixIn[myindex]) & maxVal ;
335 
336  // Y = A(1-w)(1-h) + B(w)(1-h) + C(h)(1-w) + Dwh
337  if( (x_diff<0.5) && (y_diff<0.5)){
338  pixOut[offset++] = A;
339  }
340  else if(x_diff<0.5){
341  pixOut[offset++] = C;
342  }
343  else if(y_diff<0.5){
344  pixOut[offset++] = B;
345  }
346  else{
347  pixOut[offset++] = D;
348  }
349  }
350  }
351 
352  return RES_OK;
353  }
354 
355 
356 
360  template <class T>
361  RES_T resizeClosest(Image<T> &imIn, Image<T> &imOut)
362  {
363  return resizeClosest(imIn, imOut.getWidth(), imOut.getHeight(), imOut);
364  }
365 
366 
367 
368 
376  template <class T>
377  RES_T resize(Image<T> &imIn, size_t sx, size_t sy, Image<T> &imOut)
378  {
379  ASSERT_ALLOCATED(&imIn)
380 
381  if (&imIn==&imOut)
382  {
383  Image<T> tmpIm(imIn, true); // clone
384  return resize(tmpIm, sx, sy, imIn);
385  }
386 
387  ImageFreezer freeze(imOut);
388 
389  imOut.setSize(sx, sy);
390 
391  ASSERT_ALLOCATED(&imOut)
392 
393  size_t w = imIn.getWidth();
394  size_t h = imIn.getHeight();
395 
396  typedef typename Image<T>::lineType lineType;
397 
398  lineType pixIn = imIn.getPixels();
399  lineType pixOut = imOut.getPixels();
400 
401  size_t A, B, C, D, maxVal = numeric_limits<T>::max() ;
402  size_t x, y, index;
403 
404  double x_ratio = ((double)(w-1))/sx;
405  double y_ratio = ((double)(h-1))/sy;
406  double x_diff, y_diff;
407  int offset = 0 ;
408 
409  for (size_t i=0;i<sy;i++)
410  {
411  for (size_t j=0;j<sx;j++)
412  {
413  x = (int)(x_ratio * j) ;
414  y = (int)(y_ratio * i) ;
415  x_diff = (x_ratio * j) - x ;
416  y_diff = (y_ratio * i) - y ;
417  index = y*w+x ;
418 
419  A = size_t(pixIn[index]) & maxVal ;
420  B = size_t(pixIn[index+1]) & maxVal ;
421  C = size_t(pixIn[index+w]) & maxVal ;
422  D = size_t(pixIn[index+w+1]) & maxVal ;
423 
424  // Y = A(1-w)(1-h) + B(w)(1-h) + C(h)(1-w) + Dwh
425  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));
426  }
427  }
428 
429  return RES_OK;
430  }
431 
432 
433 
437  template <class T>
438  RES_T resize(Image<T> &imIn, Image<T> &imOut)
439  {
440  return resize(imIn, imOut.getWidth(), imOut.getHeight(), imOut);
441  }
442 
443 
448  template <class T>
449  RES_T scale(Image<T> &imIn, double cx, double cy, Image<T> &imOut)
450  {
451  return resize<T>(imIn, size_t(imIn.getWidth()*cx), size_t(imIn.getHeight()*cy), imOut);
452  }
453 
454  template <class T>
455  RES_T scale(Image<T> &imIn, double cx, double cy)
456  {
457  ASSERT_ALLOCATED(&imIn)
458  Image<T> tmpIm(imIn, true); // clone
459  return resize(tmpIm, cx, cy, imIn);
460  }
461 
466  template <class T>
467  RES_T scaleClosest(Image<T> &imIn, double cx, double cy, Image<T> &imOut)
468  {
469  return resizeClosest<T>(imIn, size_t(imIn.getWidth()*cx), size_t(imIn.getHeight()*cy), imOut);
470  }
471 
472  template <class T>
473  RES_T scaleClosest(Image<T> &imIn, double cx, double cy)
474  {
475  ASSERT_ALLOCATED(&imIn)
476  Image<T> tmpIm(imIn, true); // clone
477  return resizeClosest(tmpIm, cx, cy, imIn);
478  }
479 
480 
481  template <class T>
482  RES_T resize(Image<T> &imIn, UINT sx, UINT sy)
483  {
484  ASSERT_ALLOCATED(&imIn)
485  Image<T> tmpIm(imIn, true); // clone
486  imIn.setSize(sx, sy);
487  return resize<T>(tmpIm, imIn);
488  }
489 
490  template <class T>
491  RES_T resizeClosest(Image<T> &imIn, UINT sx, UINT sy)
492  {
493  ASSERT_ALLOCATED(&imIn)
494  Image<T> tmpIm(imIn, true); // clone
495  imIn.setSize(sx, sy);
496  return resizeClosest<T>(tmpIm, imIn);
497  }
498 
499 
502 } // namespace smil
503 
504 
505 #endif // _D_IMAGE_TRANSFORM_HPP
506 
Author Vincent Morard Date : 7 march 2011 See : Morard V. and Dokladal P. and Decenciere E...
Definition: DApplyThreshold.hpp:36
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
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
Definition: Chabardes/include/private/DUtils.h:13
RES_T resizeClosest(Image< T > &imIn, size_t sx, size_t sy, Image< T > &imOut)
BMI: 08.08.2018.
Definition: DImageTransform.hpp:271
RES_T fill(Image< T > &imOut, const T &value)
Fill an image with a given value.
Definition: DImageArith.hpp:62
size_t getDepth() const
Get image depth (Z)
Definition: DBaseImage.h:95
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:449
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
volType getSlices() const
Get an array containing the start offset of each slice.
Definition: DImage.hpp:118
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
UINT getDimension() const
Get dimension (2D or 3D)
Definition: DBaseImage.h:105
RES_T resize(Image< T > &imIn, size_t sx, size_t sy, Image< T > &imOut)
2D bilinear resize algorithm.
Definition: DImageTransform.hpp:377
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:80
Main Image class.
Definition: DQVtkViewer.hpp:42
lineType getPixels() const
Get the pixels as a 1D array.
Definition: DImage.hpp:110
T maxVal(const Image< T > &imIn, bool onlyNonZero=false)
Max value of an image.
Definition: Base/include/private/DMeasures.hpp:260
RES_T scaleClosest(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:467