App
TCubicFInt.hpp
Go to the documentation of this file.
1 
6 namespace app {
7 template<typename TPIXEL, typename TCHANNEL> class TCubicFInt;
8 }
9 
10 #ifndef TCUBICFINT_HPP_
11 #define TCUBICFINT_HPP_
12 
13 #include <cstdlib>
14 #include "../typedefs.hpp"
15 #include "../bitmaps/TBitmap.hpp"
16 
17 #include "TFInterpolator.hpp"
18 
20 #define INTERPOLATE_CUBIC(P0, P1, P2, P3, X, RES) \
21  RES = (-P0 + P3 + 3 * P1 - 3 * P2) * X * X * X / 0.2e1 + (-5 * P1 + 2 * P0 - P3 + 4 * P2) * X * X / 0.2e1 + (P2 - P0) * X / 0.2e1 + P1;
22 
23 namespace app {
24 
29 template<typename TPIXEL, typename TCHANNEL>
30 class TCubicFInt: public TFInterpolator<TPIXEL, TCHANNEL> {
31 protected:
32  TPIXEL * srcData;
33  unsigned srcWidth;
34  unsigned srcHeight;
35  int offset;
36 
37  int * xReindex;
38  int * yReindex;
40  double xNoReindexTo;
42  double yNoReindexTo;
43 
44  TPIXEL getAt_4ch(double x, double y) {
45  if (x > xNoReindexFrom && y > yNoReindexFrom && x < xNoReindexTo && y < yNoReindexTo) {
46  x -= 1.5;
47  y -= 1.5;
48  int X = x;
49  x -= X;
50  int Y = y;
51  y -= Y;
52 
53  TPIXEL retVal = 0;
54  TCHANNEL * ptr = (TCHANNEL *) &retVal;
55  TCHANNEL * sBgn = (TCHANNEL *) (srcData + (Y) * srcWidth + (X));
56  TCHANNEL * sPtr;
57  TCHANNEL p0, p1, p2, p3;
58  double tp0, tp1, tp2, tp3;
59  double clamp;
60 
61  sPtr = sBgn++;
62  p0 = *sPtr;
63  p1 = *(sPtr + 4);
64  p2 = *(sPtr + 8);
65  p3 = *(sPtr + 12);
66  sPtr += offset;
67  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp0);
68  p0 = *sPtr;
69  p1 = *(sPtr + 4);
70  p2 = *(sPtr + 8);
71  p3 = *(sPtr + 12);
72  sPtr += offset;
73  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp1);
74  p0 = *sPtr;
75  p1 = *(sPtr + 4);
76  p2 = *(sPtr + 8);
77  p3 = *(sPtr + 12);
78  sPtr += offset;
79  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp2);
80  p0 = *sPtr;
81  p1 = *(sPtr + 4);
82  p2 = *(sPtr + 8);
83  p3 = *(sPtr + 12);
84  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp3);
85  INTERPOLATE_CUBIC(tp0, tp1, tp2, tp3, y, clamp);
86  *ptr = (clamp > maxVal) ? maxVal : (clamp < 0) ? 0 : clamp;
87  ptr++;
88 
89  sPtr = sBgn++;
90  p0 = *sPtr;
91  p1 = *(sPtr + 4);
92  p2 = *(sPtr + 8);
93  p3 = *(sPtr + 12);
94  sPtr += offset;
95  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp0);
96  p0 = *sPtr;
97  p1 = *(sPtr + 4);
98  p2 = *(sPtr + 8);
99  p3 = *(sPtr + 12);
100  sPtr += offset;
101  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp1);
102  p0 = *sPtr;
103  p1 = *(sPtr + 4);
104  p2 = *(sPtr + 8);
105  p3 = *(sPtr + 12);
106  sPtr += offset;
107  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp2);
108  p0 = *sPtr;
109  p1 = *(sPtr + 4);
110  p2 = *(sPtr + 8);
111  p3 = *(sPtr + 12);
112  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp3);
113  INTERPOLATE_CUBIC(tp0, tp1, tp2, tp3, y, clamp);
114  *ptr = (clamp > maxVal) ? maxVal : (clamp < 0) ? 0 : clamp;
115  ptr++;
116 
117  sPtr = sBgn++;
118  p0 = *sPtr;
119  p1 = *(sPtr + 4);
120  p2 = *(sPtr + 8);
121  p3 = *(sPtr + 12);
122  sPtr += offset;
123  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp0);
124  p0 = *sPtr;
125  p1 = *(sPtr + 4);
126  p2 = *(sPtr + 8);
127  p3 = *(sPtr + 12);
128  sPtr += offset;
129  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp1);
130  p0 = *sPtr;
131  p1 = *(sPtr + 4);
132  p2 = *(sPtr + 8);
133  p3 = *(sPtr + 12);
134  sPtr += offset;
135  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp2);
136  p0 = *sPtr;
137  p1 = *(sPtr + 4);
138  p2 = *(sPtr + 8);
139  p3 = *(sPtr + 12);
140  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp3);
141  INTERPOLATE_CUBIC(tp0, tp1, tp2, tp3, y, clamp);
142  *ptr = (clamp > maxVal) ? maxVal : (clamp < 0) ? 0 : clamp;
143  ptr++;
144 
145  sPtr = sBgn;
146  p0 = *sPtr;
147  p1 = *(sPtr + 4);
148  p2 = *(sPtr + 8);
149  p3 = *(sPtr + 12);
150  sPtr += offset;
151  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp0);
152  p0 = *sPtr;
153  p1 = *(sPtr + 4);
154  p2 = *(sPtr + 8);
155  p3 = *(sPtr + 12);
156  sPtr += offset;
157  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp1);
158  p0 = *sPtr;
159  p1 = *(sPtr + 4);
160  p2 = *(sPtr + 8);
161  p3 = *(sPtr + 12);
162  sPtr += offset;
163  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp2);
164  p0 = *sPtr;
165  p1 = *(sPtr + 4);
166  p2 = *(sPtr + 8);
167  p3 = *(sPtr + 12);
168  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp3);
169  INTERPOLATE_CUBIC(tp0, tp1, tp2, tp3, y, clamp);
170  *ptr = (clamp > maxVal) ? maxVal : (clamp < 0) ? 0 : clamp;
171 
172  return retVal;
173 
174  } else {
175  x += 1.5;
176  y += 1.5;
177  int X = x;
178  x -= X;
179  int Y = y;
180  y -= Y;
181 
182  TPIXEL retVal = 0;
183  TCHANNEL * ptr = (TCHANNEL *) &retVal;
184  TCHANNEL p0, p1, p2, p3;
185 
186  TCHANNEL * p00 = (TCHANNEL *) (srcData + yReindex[Y - 1] * srcWidth + xReindex[X - 1]);
187  TCHANNEL * p01 = (TCHANNEL *) (srcData + yReindex[Y] * srcWidth + xReindex[X - 1]);
188  TCHANNEL * p02 = (TCHANNEL *) (srcData + yReindex[Y + 1] * srcWidth + xReindex[X - 1]);
189  TCHANNEL * p03 = (TCHANNEL *) (srcData + yReindex[Y + 2] * srcWidth + xReindex[X - 1]);
190 
191  TCHANNEL * p10 = (TCHANNEL *) (srcData + yReindex[Y - 1] * srcWidth + xReindex[X]);
192  TCHANNEL * p11 = (TCHANNEL *) (srcData + yReindex[Y] * srcWidth + xReindex[X]);
193  TCHANNEL * p12 = (TCHANNEL *) (srcData + yReindex[Y + 1] * srcWidth + xReindex[X]);
194  TCHANNEL * p13 = (TCHANNEL *) (srcData + yReindex[Y + 2] * srcWidth + xReindex[X]);
195 
196  TCHANNEL * p20 = (TCHANNEL *) (srcData + yReindex[Y - 1] * srcWidth + xReindex[X + 1]);
197  TCHANNEL * p21 = (TCHANNEL *) (srcData + yReindex[Y] * srcWidth + xReindex[X + 1]);
198  TCHANNEL * p22 = (TCHANNEL *) (srcData + yReindex[Y + 1] * srcWidth + xReindex[X + 1]);
199  TCHANNEL * p23 = (TCHANNEL *) (srcData + yReindex[Y + 2] * srcWidth + xReindex[X + 1]);
200 
201  TCHANNEL * p30 = (TCHANNEL *) (srcData + yReindex[Y - 1] * srcWidth + xReindex[X + 2]);
202  TCHANNEL * p31 = (TCHANNEL *) (srcData + yReindex[Y] * srcWidth + xReindex[X + 2]);
203  TCHANNEL * p32 = (TCHANNEL *) (srcData + yReindex[Y + 1] * srcWidth + xReindex[X + 2]);
204  TCHANNEL * p33 = (TCHANNEL *) (srcData + yReindex[Y + 2] * srcWidth + xReindex[X + 2]);
205 
206  double tp0, tp1, tp2, tp3;
207  double clamp;
208 
209  p0 = *(p00++);
210  p1 = *(p01++);
211  p2 = *(p02++);
212  p3 = *(p03++);
213  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp0);
214  p0 = *(p10++);
215  p1 = *(p11++);
216  p2 = *(p12++);
217  p3 = *(p13++);
218  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp1);
219  p0 = *(p20++);
220  p1 = *(p21++);
221  p2 = *(p22++);
222  p3 = *(p23++);
223  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp2);
224  p0 = *(p30++);
225  p1 = *(p31++);
226  p2 = *(p32++);
227  p3 = *(p33++);
228  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp3);
229  INTERPOLATE_CUBIC(tp0, tp1, tp2, tp3, y, clamp);
230  *ptr = (clamp > maxVal) ? maxVal : (clamp < 0) ? 0 : clamp;
231  ptr++;
232 
233  p0 = *(p00++);
234  p1 = *(p01++);
235  p2 = *(p02++);
236  p3 = *(p03++);
237  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp0);
238  p0 = *(p10++);
239  p1 = *(p11++);
240  p2 = *(p12++);
241  p3 = *(p13++);
242  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp1);
243  p0 = *(p20++);
244  p1 = *(p21++);
245  p2 = *(p22++);
246  p3 = *(p23++);
247  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp2);
248  p0 = *(p30++);
249  p1 = *(p31++);
250  p2 = *(p32++);
251  p3 = *(p33++);
252  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp3);
253  INTERPOLATE_CUBIC(tp0, tp1, tp2, tp3, y, clamp);
254  *ptr = (clamp > maxVal) ? maxVal : (clamp < 0) ? 0 : clamp;
255  ptr++;
256 
257  p0 = *(p00++);
258  p1 = *(p01++);
259  p2 = *(p02++);
260  p3 = *(p03++);
261  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp0);
262  p0 = *(p10++);
263  p1 = *(p11++);
264  p2 = *(p12++);
265  p3 = *(p13++);
266  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp1);
267  p0 = *(p20++);
268  p1 = *(p21++);
269  p2 = *(p22++);
270  p3 = *(p23++);
271  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp2);
272  p0 = *(p30++);
273  p1 = *(p31++);
274  p2 = *(p32++);
275  p3 = *(p33++);
276  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp3);
277  INTERPOLATE_CUBIC(tp0, tp1, tp2, tp3, y, clamp);
278  *ptr = (clamp > maxVal) ? maxVal : (clamp < 0) ? 0 : clamp;
279  ptr++;
280 
281  p0 = *(p00);
282  p1 = *(p01);
283  p2 = *(p02);
284  p3 = *(p03);
285  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp0);
286  p0 = *(p10);
287  p1 = *(p11);
288  p2 = *(p12);
289  p3 = *(p13);
290  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp1);
291  p0 = *(p20);
292  p1 = *(p21);
293  p2 = *(p22);
294  p3 = *(p23);
295  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp2);
296  p0 = *(p30);
297  p1 = *(p31);
298  p2 = *(p32);
299  p3 = *(p33);
300  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp3);
301  INTERPOLATE_CUBIC(tp0, tp1, tp2, tp3, y, clamp);
302  *ptr = (clamp > maxVal) ? maxVal : (clamp < 0) ? 0 : clamp;
303 
304  return retVal;
305  }
306  }
307 
308  TPIXEL getAt_1ch(double x, double y) {
309  if (x > xNoReindexFrom && y > yNoReindexFrom && x < xNoReindexTo && y < yNoReindexTo) {
310  x -= 1.5;
311  y -= 1.5;
312  int X = x;
313  x -= X;
314  int Y = y;
315  y -= Y;
316 
317  TPIXEL retVal = 0;
318  TPIXEL * sPtr = (srcData + (Y) * srcWidth + (X));
319  TPIXEL p0, p1, p2, p3;
320  double tp0, tp1, tp2, tp3;
321  double clamp;
322 
323  p0 = *sPtr;
324  p1 = *(sPtr + 1);
325  p2 = *(sPtr + 2);
326  p3 = *(sPtr + 3);
327  sPtr += offset;
328  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp0);
329  p0 = *sPtr;
330  p1 = *(sPtr + 1);
331  p2 = *(sPtr + 2);
332  p3 = *(sPtr + 3);
333  sPtr += offset;
334  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp1);
335  p0 = *sPtr;
336  p1 = *(sPtr + 1);
337  p2 = *(sPtr + 2);
338  p3 = *(sPtr + 3);
339  sPtr += offset;
340  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp2);
341  p0 = *sPtr;
342  p1 = *(sPtr + 1);
343  p2 = *(sPtr + 2);
344  p3 = *(sPtr + 3);
345  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp3);
346  INTERPOLATE_CUBIC(tp0, tp1, tp2, tp3, y, clamp);
347  retVal = (clamp > maxVal) ? maxVal : (clamp < 0) ? 0 : clamp;
348 
349  return retVal;
350 
351  } else {
352  x += 1.5;
353  y += 1.5;
354  int X = x;
355  x -= X;
356  int Y = y;
357  y -= Y;
358 
359  TPIXEL retVal = 0;
360  TPIXEL p0, p1, p2, p3;
361 
362  TPIXEL * p00 = (srcData + yReindex[Y - 1] * srcWidth + xReindex[X - 1]);
363  TPIXEL * p01 = (srcData + yReindex[Y] * srcWidth + xReindex[X - 1]);
364  TPIXEL * p02 = (srcData + yReindex[Y + 1] * srcWidth + xReindex[X - 1]);
365  TPIXEL * p03 = (srcData + yReindex[Y + 2] * srcWidth + xReindex[X - 1]);
366 
367  TPIXEL * p10 = (srcData + yReindex[Y - 1] * srcWidth + xReindex[X]);
368  TPIXEL * p11 = (srcData + yReindex[Y] * srcWidth + xReindex[X]);
369  TPIXEL * p12 = (srcData + yReindex[Y + 1] * srcWidth + xReindex[X]);
370  TPIXEL * p13 = (srcData + yReindex[Y + 2] * srcWidth + xReindex[X]);
371 
372  TPIXEL * p20 = (srcData + yReindex[Y - 1] * srcWidth + xReindex[X + 1]);
373  TPIXEL * p21 = (srcData + yReindex[Y] * srcWidth + xReindex[X + 1]);
374  TPIXEL * p22 = (srcData + yReindex[Y + 1] * srcWidth + xReindex[X + 1]);
375  TPIXEL * p23 = (srcData + yReindex[Y + 2] * srcWidth + xReindex[X + 1]);
376 
377  TPIXEL * p30 = (srcData + yReindex[Y - 1] * srcWidth + xReindex[X + 2]);
378  TPIXEL * p31 = (srcData + yReindex[Y] * srcWidth + xReindex[X + 2]);
379  TPIXEL * p32 = (srcData + yReindex[Y + 1] * srcWidth + xReindex[X + 2]);
380  TPIXEL * p33 = (srcData + yReindex[Y + 2] * srcWidth + xReindex[X + 2]);
381 
382  double tp0, tp1, tp2, tp3;
383  double clamp;
384 
385  p0 = *(p00);
386  p1 = *(p01);
387  p2 = *(p02);
388  p3 = *(p03);
389  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp0);
390  p0 = *(p10);
391  p1 = *(p11);
392  p2 = *(p12);
393  p3 = *(p13);
394  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp1);
395  p0 = *(p20);
396  p1 = *(p21);
397  p2 = *(p22);
398  p3 = *(p23);
399  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp2);
400  p0 = *(p30);
401  p1 = *(p31);
402  p2 = *(p32);
403  p3 = *(p33);
404  INTERPOLATE_CUBIC(p0, p1, p2, p3, x, tp3);
405  INTERPOLATE_CUBIC(tp0, tp1, tp2, tp3, y, clamp);
406  retVal = (clamp > maxVal) ? maxVal : (clamp < 0) ? 0 : clamp;
407 
408  return retVal;
409  }
410  }
411 
417  virtual int resampleTo_4ch(TBitmap<TPIXEL, TCHANNEL> &dst) const;
418 
419 // virtual int resampleTo_4ch_aliased(TBitmap<TPIXEL, TCHANNEL> &dst, double force) const;
420 // virtual int resampleTo_1ch_aliased(TBitmap<TPIXEL, TCHANNEL> &dst, double force) const;
421 
427  virtual int resampleTo_1ch(TBitmap<TPIXEL, TCHANNEL> &dst) const;
428 
430  return new TCubicFInt<TPIXEL, TCHANNEL>(over);
431  }
432 
433 public:
434  static const unsigned chCount;
435  static const TCHANNEL maxVal;
436 
438  srcData = over.getData();
439  srcWidth = over.getWidth();
440  srcHeight = over.getHeight();
441  xNoReindexFrom = 1.5;
442  xNoReindexTo = srcWidth - 1.5;
443  yNoReindexFrom = 1.5;
444  yNoReindexTo = srcHeight - 1.5;
445  offset = (srcWidth) * (sizeof(TPIXEL) / sizeof(TCHANNEL));
446 
447  int * ptr;
448  int * ptrEnd;
449  int i;
450  xReindex = (int *) malloc((unsigned long int) ((srcWidth + 4) * sizeof(int)));
451 
452  ptr = xReindex;
453  ptrEnd = xReindex + srcWidth + 2;
454  *ptr = 0;
455  ptr++;
456  *ptr = 0;
457  ptr++;
458  i = 0;
459  while (ptr < ptrEnd) {
460  *ptr = i++;
461  ptr++;
462  }
463  *ptr = srcWidth - 1;
464  ptr++;
465  *ptr = srcWidth - 1;
466 
467  yReindex = (int *) malloc((unsigned long int) ((srcHeight + 4) * sizeof(int)));
468  ptr = yReindex;
469  ptrEnd = yReindex + srcHeight + 2;
470  *ptr = 0;
471  ptr++;
472  *ptr = 0;
473  ptr++;
474  i = 0;
475  while (ptr < ptrEnd) {
476  *ptr = i++;
477  ptr++;
478  }
479  *ptr = srcHeight - 1;
480  ptr++;
481  *ptr = srcHeight - 1;
482 
483  }
484 
485  virtual int isInitOk() const {
486  if (xReindex != NULL && yReindex != NULL) {
487  return 1;
488  } else {
489  return 0;
490  }
491  }
492 
493  virtual TPIXEL * getSrcData() const {
494  return srcData;
495  }
496 
497  virtual unsigned getSrcWidth() const {
498  return srcWidth;
499  }
500  virtual unsigned getSrcHeight() const {
501  return srcHeight;
502  }
503 
504  virtual ~TCubicFInt();
505 
506  TPIXEL getAt(double x, double y) {
507  if (x <= 0 || y <= 0 || x >= srcWidth || y >= srcHeight) {
508  return 0;
509  } else if (chCount == 4) {
510  return getAt_4ch(x, y);
511  } else if (chCount == 1) {
512  return getAt_1ch(x, y);
513  } else {
514  return 0; // Jen kvůli warningu
515  }
516  }
517 };
518 
519 template<typename TPIXEL, typename TCHANNEL>
520 const unsigned TCubicFInt<TPIXEL, TCHANNEL>::chCount = sizeof(TPIXEL) / sizeof(TCHANNEL);
521 
522 template<typename TPIXEL, typename TCHANNEL>
523 const TCHANNEL TCubicFInt<TPIXEL, TCHANNEL>::maxVal = ~0;
524 
525 }
526 #endif