App
TSeparableFilter.cpp
Go to the documentation of this file.
1 
6 #include "TSeparableFilter.hpp"
7 #include "../utils/MirroredReindexer.hpp"
8 
9 // lze ušetřit na kraji oblasti - zbytečně se tam pracuje s x, lepe xxMin ktere se bude jen inkrementovat. Stejny postup lze aplikovat i na ostatni cykly. v prostrednim je navic zbytecna inkrementace x, promenna je asi nepouzita.
11 #define SEPARABLE_FILTER_ALGORITHM_GENERAL(ROW_INIT, PX_INIT, KERNEL_ACTION, PX_COMMIT, PX_INCREMENT) \
12  double * kernelEnd = kernel + kernelWidth;\
13 \
14  int noReindexFrom = kernelCenter < srcWidth ? kernelCenter : srcWidth; /* index, který již není potřeba přeindexovávat. */\
15  int noReindexTo = srcWidth - kernelCenter; /* index, který již je potřeba přeindexovat. */\
16 \
17  int initialReindexLimit = (xSrcMax < noReindexFrom) ? xSrcMax : noReindexFrom;\
18  int noReindexLimit = (xSrcMax < noReindexTo) ? xSrcMax : noReindexTo;\
19 \
20  MirroredReindexer *loReindexer = NULL, *hiReindexer = NULL;\
21 \
22  int initOk = 1;\
23  if (xSrcMin < noReindexFrom) {\
24  loReindexer = new MirroredReindexer(-kernelCenter, kernelWidth - 1, srcWidth);\
25  if (loReindexer == NULL) {\
26  initOk = 0;\
27  } else if (loReindexer->getVals() == NULL) {\
28  initOk = 0;\
29  }\
30  }\
31  if ((noReindexTo < xSrcMax) && initOk) {\
32  hiReindexer = new MirroredReindexer(srcWidth - kernelWidth - 1, srcWidth + kernelCenter, srcWidth);\
33  if (hiReindexer == NULL) {\
34  initOk = 0;\
35  } else if (hiReindexer->getVals() == NULL) {\
36  initOk = 0;\
37  }\
38  }\
39 \
40  TPIXEL * sPtr;\
41  TPIXEL * sTmpPtr;\
42  TPIXEL * sPtrRowEnd;\
43  TPIXEL * sRowBgnPtr = src + ySrcMin * srcWidth;\
44  TPIXEL * sRowBgnPtrEnd = src + ySrcMax * srcWidth;\
45 \
46  TPIXEL * dPtrColBgn = dst + yDstMin * dstWidth + xDstMin;\
47  TPIXEL * dPtr;\
48 \
49  TCHANNEL * mPtrColBgn = msk + yMskMin * mskWidth + xMskMin;\
50  TCHANNEL * mPtr;\
51 \
52  double * kernelPtr;\
53  int y, x, xx;\
54 \
55 \
56  y = ySrcMin;\
57 \
58  if (initOk) {\
59  while (sRowBgnPtr < sRowBgnPtrEnd) {\
60  x = xSrcMin;\
61  ROW_INIT\
62  while (x < initialReindexLimit) {\
63  PX_INIT\
64  xx = x - kernelCenter;\
65  kernelPtr = kernel;\
66  while (kernelPtr < kernelEnd) {\
67  sTmpPtr = sRowBgnPtr + loReindexer->reindex(xx++);\
68  KERNEL_ACTION\
69  kernelPtr++;\
70  }\
71  PX_COMMIT\
72  PX_INCREMENT\
73  x++;\
74  }\
75 \
76  sPtr = sRowBgnPtr + x;\
77  sPtrRowEnd = sRowBgnPtr + noReindexLimit;\
78  while (sPtr < sPtrRowEnd) {\
79  PX_INIT\
80  kernelPtr = kernel;\
81  sTmpPtr = sPtr++ - kernelCenter;\
82  while (kernelPtr < kernelEnd) {\
83  KERNEL_ACTION\
84  sTmpPtr++;\
85  kernelPtr++;\
86  }\
87  PX_COMMIT\
88  PX_INCREMENT\
89  x++;\
90  }\
91 \
92  while (x < xSrcMax) {\
93  PX_INIT\
94  xx = x - kernelCenter;\
95  kernelPtr = kernel;\
96  while (kernelPtr < kernelEnd) {\
97  sTmpPtr = sRowBgnPtr + hiReindexer->reindex(xx++);\
98  KERNEL_ACTION\
99  kernelPtr++;\
100  }\
101  PX_COMMIT\
102  PX_INCREMENT\
103  x++;\
104  }\
105  sRowBgnPtr += srcWidth;\
106  y++;\
107  }\
108  }\
109 \
110  if (loReindexer != NULL) {\
111  delete loReindexer;\
112  }\
113  if (hiReindexer != NULL) {\
114  delete hiReindexer;\
115  }
116 
117 namespace app {
118 
121 
122 template<typename TPIXEL, typename TCHANNEL>
124  // Ikdyž nealokoval, uvolňuje, protože ukazatele jsou v jeho kompetanci.
125  if (xKernel != NULL) {
126  free(xKernel);
127  }
128  if (yKernel != NULL) {
129  free(yKernel);
130  }
131 }
132 
133 
134 template<typename TPIXEL, typename TCHANNEL>
136  if (this->chCount != 1) {
137  return 1;
138  }
139 
140  if (xKernel == NULL || yKernel == NULL) { // Kontrola 1 vlastne neni potreba
141  return 2;
142  }
143 
144  TPIXEL * const srcData = bitmap.getData();
145  if (srcData == NULL) {
146  return 3;
147  }
148 
149  unsigned origWidth = bitmap.getWidth();
150  unsigned origHeight = bitmap.getHeight();
151  unsigned tmpWidth = origHeight;
152  unsigned tmpHeight = origWidth;
153 
154  TPIXEL * const tmpData = (TPIXEL *) malloc(tmpWidth * tmpHeight * sizeof(TPIXEL));
155  if (tmpData == NULL) {
156  delete tmpData;
157  return 4;
158  }
159 
160  Rect crop = Rect::getIntersection(srcRect, bitmap.getRect());
161 
162  int wasOk = 0;
163 
164  {
165 
166 /* JMENNÉ KONVENCE PRO PROMĚNNÉ FILTRU.
167  TPIXEL * src, *dst;
168  TCHANNEL * msk;
169  double alpha;
170  int srcWidth, srcHeight;
171  int dstWidth, dstHeight;
172  int mskWidth, mskHeight;
173 
174  int xSrcMin, xSrcMax, ySrcMin, ySrcMax;
175  int xDstMin, xDstMax, yDstMin, yDstMax;
176  int xMskMin, xMskMax, yMskMin, yMskMax;
177 
178  double * kernel;
179  int kernelCenter;
180  int kernelWidth;
181 */
182 
183  TPIXEL * src = srcData;
184  int srcWidth = origWidth;
185  int xSrcMin = crop.tl.x;
186  int xSrcMax = crop.br.x;
187  int ySrcMin = crop.tl.y - yKernelCenter;
188  ySrcMin = (ySrcMin < 0) ? 0 : ySrcMin;
189  int ySrcMax = crop.br.y + yKernelCenter;
190  ySrcMax = (ySrcMax > origHeight) ? origHeight : ySrcMax;
191 
192  TPIXEL * dst = tmpData;
193  int dstWidth = tmpWidth;
194 
195  TCHANNEL * msk = NULL;
196  int mskWidth = 0;
197  int xMskMin = 0;
198  int yMskMin = 0;
199 
200  int xDstMin = ySrcMin;
201  int yDstMin = xSrcMin;
202 
203  double * kernel = xKernel;
204  int kernelCenter = xKernelCenter;
205  int kernelWidth = xKernelWidth;
206 
207  double sum;
208 
209  SEPARABLE_FILTER_ALGORITHM_GENERAL(dPtr = dPtrColBgn++;, sum = 0;, sum += *sTmpPtr * *kernelPtr;, *dPtr = sum + 0.5;, dPtr += dstWidth;)
210 
211  wasOk = initOk;
212  }
213 
214  if (wasOk) {
215 
216  TPIXEL * src = tmpData;
217  int srcWidth = tmpWidth;
218  int xSrcMin = crop.tl.y;
219  int xSrcMax = crop.br.y;
220  int ySrcMin = crop.tl.x;
221  int ySrcMax = crop.br.x;
222 
223  TPIXEL * dst = srcData;
224  int dstWidth = origWidth;
225  int xDstMin = crop.tl.x;
226  int yDstMin = crop.tl.y;
227 
228  TCHANNEL * msk = NULL;
229  int mskWidth = 0;
230  int xMskMin = 0;
231  int yMskMin = 0;
232 
233  double * kernel = yKernel;
234  int kernelCenter = yKernelCenter;
235  int kernelWidth = yKernelWidth;
236 
237  double sum;
238 
239  SEPARABLE_FILTER_ALGORITHM_GENERAL(dPtr = dPtrColBgn++;, sum = 0;, sum += *sTmpPtr * *kernelPtr;, *dPtr = sum + 0.5;, dPtr += dstWidth;)
240 
241  }
242 
243  free(tmpData);
244 
245  return 0;
246 }
247 
248 template<typename TPIXEL, typename TCHANNEL>
250  if (this->chCount != 4) {
251  return 1;
252  }
253  if (xKernel == NULL || yKernel == NULL) {
254  return 2;
255  } // pro mensi nez 2 se nepodari vytvorit reindexer, zkolabuje, navic je cely nesmysl - bodova operace v danem smeru
256  TPIXEL * const srcData = bitmap.getData();
257  if (srcData == NULL) {
258  return 3;
259  }
260  unsigned origWidth = bitmap.getWidth();
261  unsigned origHeight = bitmap.getHeight();
262 
263  unsigned tmpWidth = origHeight;
264  unsigned tmpHeight = origWidth;
265 
266  TPIXEL * const tmpData = (TPIXEL *) malloc(tmpWidth * tmpHeight * sizeof(TPIXEL)); // Dočasná bitmapa, do které se provede filtr dle řádků a ze které se filtruje dle sloupců do původní bitmapy.
267  if (tmpData == NULL) {
268  delete tmpData;
269  return 4;
270  }
271 
272  Rect crop = Rect::getIntersection(srcRect, bitmap.getRect());
273 
274  int wasOk = 0;
275 
276  {
277 
278  TPIXEL * src = srcData;
279  int srcWidth = origWidth;
280  int xSrcMin = crop.tl.x;
281  int xSrcMax = crop.br.x;
282  int ySrcMin = crop.tl.y - yKernelCenter;
283  ySrcMin = (ySrcMin < 0) ? 0 : ySrcMin;
284  int ySrcMax = crop.br.y + yKernelCenter;
285  ySrcMax = (ySrcMax > origHeight) ? origHeight : ySrcMax;
286 
287  TPIXEL * dst = tmpData;
288  int dstWidth = tmpWidth;
289 
290  TCHANNEL * msk = NULL;
291  int mskWidth = 0;
292  int xMskMin = 0;
293  int yMskMin = 0;
294 
295  int xDstMin = ySrcMin;
296  int yDstMin = xSrcMin;
297 
298  double * kernel = xKernel;
299  int kernelCenter = xKernelCenter;
300  int kernelWidth = xKernelWidth;
301 
302  double sumR;
303  double sumG;
304  double sumB;
305  double sumA;
306  double A;
307 
308  TCHANNEL * chPtr;
309  double kv;
310 
312  dPtr = dPtrColBgn++;,
313 
314  sumR = 0; sumG = 0; sumB = 0; sumA = 0;,
315 
316  kv = *kernelPtr;
317  chPtr = (TCHANNEL *) sTmpPtr;
318  A = *(chPtr + 3) * kv;
319  sumR += *(chPtr++) * A;
320  sumG += *(chPtr++) * A;
321  sumB += *chPtr * A;
322  sumA += A;,
323 
324  chPtr = (TCHANNEL *) dPtr;
325  *chPtr = sumR / (sumA) + 0.5; chPtr++;
326  *chPtr = sumG / (sumA) + 0.5; chPtr++;
327  *chPtr = sumB / (sumA) + 0.5; chPtr++;
328  *chPtr = sumA + 0.5;,
329 
330  dPtr += dstWidth;
331  )
332 
333 
334  wasOk = initOk; // Pokud ne, v tmp jsou nahodna data.
335  }
336 
337  if (wasOk) {
338 
339  TPIXEL * src = tmpData;
340  int srcWidth = tmpWidth;
341  int xSrcMin = crop.tl.y;
342  int xSrcMax = crop.br.y;
343  int ySrcMin = crop.tl.x;
344  int ySrcMax = crop.br.x;
345 
346  TPIXEL * dst = srcData;
347  int dstWidth = origWidth;
348  int xDstMin = crop.tl.x;
349  int yDstMin = crop.tl.y;
350 
351  TCHANNEL * msk = NULL;
352  int mskWidth = 0;
353  int xMskMin = 0;
354  int yMskMin = 0;
355 
356  double * kernel = yKernel;
357  int kernelCenter = yKernelCenter;
358  int kernelWidth = yKernelWidth;
359 
360  double sumR;
361  double sumG;
362  double sumB;
363  double sumA;
364  double A;
365 
366  TCHANNEL * chPtr;
367  double kv;
368 
370  dPtr = dPtrColBgn++;,
371 
372  sumR = 0; sumG = 0; sumB = 0; sumA = 0;,
373 
374  kv = *kernelPtr;
375  chPtr = (TCHANNEL *) sTmpPtr;
376  A = *(chPtr + 3) * kv;
377  sumR += *(chPtr++) * A;
378  sumG += *(chPtr++) * A;
379  sumB += *chPtr * A;
380  sumA += A;,
381 
382  chPtr = (TCHANNEL *) dPtr;
383  *chPtr = sumR / (sumA) + 0.5; chPtr++;
384  *chPtr = sumG / (sumA) + 0.5; chPtr++;
385  *chPtr = sumB / (sumA) + 0.5; chPtr++;
386  *chPtr = sumA + 0.5;,
387 
388  dPtr += dstWidth;
389  )
390 
391  }
392 
393  free(tmpData);
394 
395  return 0;
396 }
397 
398 
399 template<typename TPIXEL, typename TCHANNEL>
401  if (this->chCount != 4) {
402  return 1;
403  }
404  if (xKernel == NULL || yKernel == NULL) {
405  return 2;
406  } // pro mensi nez 2 se nepodari vytvorit reindexer, zkolabuje, navic je cely nesmysl - bodova operace v danem smeru
407  TPIXEL * const srcData = bitmap.getData();
408  if (srcData == NULL) {
409  return 3;
410  }
411  unsigned origWidth = bitmap.getWidth();
412  unsigned origHeight = bitmap.getHeight();
413 
414  unsigned tmpWidth = origHeight;
415  unsigned tmpHeight = origWidth;
416 
417  TPIXEL * const tmpData = (TPIXEL *) malloc(tmpWidth * tmpHeight * sizeof(TPIXEL)); // Dočasná bitmapa, do které se provede filtr dle řádků a ze které se filtruje dle sloupců do původní bitmapy.
418  if (tmpData == NULL) {
419  delete tmpData;
420  return 4;
421  }
422 
423  Rect crop = Rect::getIntersection(srcRect, bitmap.getRect());
424 
425  int wasOk = 0;
426 
427  {
428 
429  TPIXEL * src = srcData;
430  int srcWidth = origWidth;
431  int xSrcMin = crop.tl.x;
432  int xSrcMax = crop.br.x;
433  int ySrcMin = crop.tl.y - yKernelCenter;
434  ySrcMin = (ySrcMin < 0) ? 0 : ySrcMin;
435  int ySrcMax = crop.br.y + yKernelCenter;
436  ySrcMax = (ySrcMax > origHeight) ? origHeight : ySrcMax;
437 
438  TPIXEL * dst = tmpData;
439  int dstWidth = tmpWidth;
440 
441  TCHANNEL * msk = NULL;
442  int mskWidth = 0;
443  int xMskMin = 0;
444  int yMskMin = 0;
445 
446  int xDstMin = ySrcMin;
447  int yDstMin = xSrcMin;
448 
449  double * kernel = xKernel;
450  int kernelCenter = xKernelCenter;
451  int kernelWidth = xKernelWidth;
452 
453  double sumR;
454  double sumG;
455  double sumB;
456  double sumA;
457  double A;
458 
459  TCHANNEL * chPtr;
460  double kv;
461 
463  dPtr = dPtrColBgn++;,
464 
465  sumR = 0; sumG = 0; sumB = 0; sumA = 0;,
466 
467  kv = *kernelPtr;
468  chPtr = (TCHANNEL *) sTmpPtr;
469  A = *(chPtr + 3) * kv;
470  sumR += *(chPtr++) * A;
471  sumG += *(chPtr++) * A;
472  sumB += *chPtr * A;
473  sumA += A;,
474 
475  chPtr = (TCHANNEL *) dPtr;
476  *chPtr = sumR / (sumA) + 0.5; chPtr++;
477  *chPtr = sumG / (sumA) + 0.5; chPtr++;
478  *chPtr = sumB / (sumA) + 0.5; chPtr++;
479  *chPtr = sumA + 0.5;,
480 
481  dPtr += dstWidth;
482  )
483 
484 
485  wasOk = initOk; // Pokud ne, v tmp jsou nahodna data.
486  }
487 
488  if (wasOk) {
489 
490  TPIXEL * src = tmpData;
491  int srcWidth = tmpWidth;
492  int xSrcMin = crop.tl.y;
493  int xSrcMax = crop.br.y;
494  int ySrcMin = crop.tl.x;
495  int ySrcMax = crop.br.x;
496 
497  TPIXEL * dst = srcData;
498  int dstWidth = origWidth;
499  int xDstMin = crop.tl.x;
500  int yDstMin = crop.tl.y;
501 
502  TCHANNEL * msk = NULL;
503  int mskWidth = 0;
504  int xMskMin = 0;
505  int yMskMin = 0;
506 
507  double * kernel = yKernel;
508  int kernelCenter = yKernelCenter;
509  int kernelWidth = yKernelWidth;
510 
511  double sumR;
512  double sumG;
513  double sumB;
514  double sumA;
515  double A;
516 
517  TCHANNEL * chPtr;
518  double kv;
519 
520  TCHANNEL doa;
521  double da;
522  double sa;
523  double sac;
524  double ra;
525 
527  dPtr = dPtrColBgn++;,
528 
529  sumR = 0; sumG = 0; sumB = 0; sumA = 0;,
530 
531  kv = *kernelPtr;
532  chPtr = (TCHANNEL *) sTmpPtr;
533  A = *(chPtr + 3) * kv;
534  sumR += *(chPtr++) * A;
535  sumG += *(chPtr++) * A;
536  sumB += *chPtr * A;
537  sumA += A;,
538 
539  chPtr = (TCHANNEL *) dPtr;
540 
541  doa = *(chPtr + 3);
542  da = doa / 255.0;
543  sa = sumA * alpha / 255.0;
544  sac = 1 - sa;
545  ra = sa + da * sac;
546 
547  *chPtr = ((sumR / (sumA)) * sa + *chPtr * da * sac) / ra + 0.5; chPtr++;
548  *chPtr = ((sumG / (sumA)) * sa + *chPtr * da * sac) / ra + 0.5; chPtr++;
549  *chPtr = ((sumB / (sumA)) * sa + *chPtr * da * sac) / ra + 0.5; chPtr++;
550  *chPtr = ra * 255 + 0.5;,
551 
552  dPtr += dstWidth;
553  )
554 
555  }
556 
557  free(tmpData);
558 
559  return 0;
560 }
561 
562 
563 template<typename TPIXEL, typename TCHANNEL>
565  if (this->chCount != 4) {
566  return 1;
567  }
568  if (xKernel == NULL || yKernel == NULL) {
569  return 2;
570  } // pro mensi nez 2 se nepodari vytvorit reindexer, zkolabuje, navic je cely nesmysl - bodova operace v danem smeru
571  TPIXEL * const srcData = bitmap.getData();
572  if (srcData == NULL) {
573  return 3;
574  }
575  unsigned origWidth = bitmap.getWidth();
576  unsigned origHeight = bitmap.getHeight();
577 
578  unsigned tmpWidth = origHeight;
579  unsigned tmpHeight = origWidth;
580 
581  TPIXEL * const tmpData = (TPIXEL *) malloc(tmpWidth * tmpHeight * sizeof(TPIXEL)); // Dočasná bitmapa, do které se provede filtr dle řádků a ze které se filtruje dle sloupců do původní bitmapy.
582  if (tmpData == NULL) {
583  delete tmpData;
584  return 4;
585  }
586 
587  PointerArea mskArea(mask.getData(), mask.getRect(), mskRect, mask.getBpp());
588  PointerArea dstArea = bitmap.getPointerArea();
589 
590  int err = PointerArea::makeCommon(dstArea, mskArea, mskOrig);
591  if (err) {
592  return 100 + err;
593  }
594 
595  Rect crop = dstArea.getArea();
596  Rect mskCrop = mskArea.getArea();
597 
598  int wasOk = 0;
599 
600  {
601 
602  TPIXEL * src = srcData;
603  int srcWidth = origWidth;
604  int xSrcMin = crop.tl.x;
605  int xSrcMax = crop.br.x;
606  int ySrcMin = crop.tl.y - yKernelCenter;
607  ySrcMin = (ySrcMin < 0) ? 0 : ySrcMin;
608  int ySrcMax = crop.br.y + yKernelCenter;
609  ySrcMax = (ySrcMax > origHeight) ? origHeight : ySrcMax;
610 
611  TPIXEL * dst = tmpData;
612  int dstWidth = tmpWidth;
613 
614  TCHANNEL * msk = NULL;
615  int mskWidth = 0;
616  int xMskMin = 0;
617  int yMskMin = 0;
618 
619  int xDstMin = ySrcMin;
620  int yDstMin = xSrcMin;
621 
622  double * kernel = xKernel;
623  int kernelCenter = xKernelCenter;
624  int kernelWidth = xKernelWidth;
625 
626  double sumR;
627  double sumG;
628  double sumB;
629  double sumA;
630  double A;
631 
632  TCHANNEL * chPtr;
633  double kv;
634 
636  dPtr = dPtrColBgn++;,
637 
638  sumR = 0; sumG = 0; sumB = 0; sumA = 0;,
639 
640  kv = *kernelPtr;
641  chPtr = (TCHANNEL *) sTmpPtr;
642  A = *(chPtr + 3) * kv;
643  sumR += *(chPtr++) * A;
644  sumG += *(chPtr++) * A;
645  sumB += *chPtr * A;
646  sumA += A;,
647 
648  chPtr = (TCHANNEL *) dPtr;
649  *chPtr = sumR / (sumA) + 0.5; chPtr++;
650  *chPtr = sumG / (sumA) + 0.5; chPtr++;
651  *chPtr = sumB / (sumA) + 0.5; chPtr++;
652  *chPtr = sumA + 0.5;,
653 
654  dPtr += dstWidth;
655  )
656 
657 
658  wasOk = initOk; // Pokud ne, v tmp jsou nahodna data.
659  }
660 
661  if (wasOk) {
662 
663  TPIXEL * src = tmpData;
664  int srcWidth = tmpWidth;
665  int xSrcMin = crop.tl.y;
666  int xSrcMax = crop.br.y;
667  int ySrcMin = crop.tl.x;
668  int ySrcMax = crop.br.x;
669 
670  TPIXEL * dst = srcData;
671  int dstWidth = origWidth;
672  int xDstMin = crop.tl.x;
673  int yDstMin = crop.tl.y;
674 
675  TCHANNEL * msk = mask.getData();
676  int mskWidth = mask.getWidth();
677  int xMskMin = mskCrop.tl.x;
678  int yMskMin = mskCrop.tl.y;
679 
680  double * kernel = yKernel;
681  int kernelCenter = yKernelCenter;
682  int kernelWidth = yKernelWidth;
683 
684  double sumR;
685  double sumG;
686  double sumB;
687  double sumA;
688  double A;
689 
690  TCHANNEL * chPtr;
691  double kv;
692 
693  TCHANNEL doa;
694  double da;
695  double sa;
696  double sac;
697  double ra;
698 
700  dPtr = dPtrColBgn++;
701  mPtr = mPtrColBgn++;,
702 
703  sumR = 0; sumG = 0; sumB = 0; sumA = 0;,
704 
705  kv = *kernelPtr;
706  chPtr = (TCHANNEL *) sTmpPtr;
707  A = *(chPtr + 3) * kv;
708  sumR += *(chPtr++) * A;
709  sumG += *(chPtr++) * A;
710  sumB += *chPtr * A;
711  sumA += A;,
712 
713  chPtr = (TCHANNEL *) dPtr;
714 
715  doa = *(chPtr + 3);
716  da = doa / 255.0;
717  sa = sumA * *mPtr/ 65025.0;
718  sac = 1 - sa;
719  ra = sa + da * sac;
720 
721  *chPtr = ((sumR / (sumA)) * sa + *chPtr * da * sac) / ra + 0.5; chPtr++;
722  *chPtr = ((sumG / (sumA)) * sa + *chPtr * da * sac) / ra + 0.5; chPtr++;
723  *chPtr = ((sumB / (sumA)) * sa + *chPtr * da * sac) / ra + 0.5; chPtr++;
724  *chPtr = ra * 255 + 0.5;,
725 
726  dPtr += dstWidth;
727  mPtr += mskWidth;
728  )
729 
730  }
731 
732  free(tmpData);
733 
734  return 0;
735 }
736 
737 
738 template<typename TPIXEL, typename TCHANNEL>
740  if (this->chCount != 4) {
741  return 1;
742  }
743  if (xKernel == NULL || yKernel == NULL) {
744  return 2;
745  } // pro mensi nez 2 se nepodari vytvorit reindexer, zkolabuje, navic je cely nesmysl - bodova operace v danem smeru
746  TPIXEL * const srcData = bitmap.getData();
747  if (srcData == NULL) {
748  return 3;
749  }
750  unsigned origWidth = bitmap.getWidth();
751  unsigned origHeight = bitmap.getHeight();
752 
753  unsigned tmpWidth = origHeight;
754  unsigned tmpHeight = origWidth;
755 
756  TPIXEL * const tmpData = (TPIXEL *) malloc(tmpWidth * tmpHeight * sizeof(TPIXEL)); // Dočasná bitmapa, do které se provede filtr dle řádků a ze které se filtruje dle sloupců do původní bitmapy.
757  if (tmpData == NULL) {
758  delete tmpData;
759  return 4;
760  }
761 
762  PointerArea mskArea(mask.getData(), mask.getRect(), mskRect, mask.getBpp());
763  PointerArea dstArea = bitmap.getPointerArea();
764 
765  int err = PointerArea::makeCommon(dstArea, mskArea, mskOrig);
766  if (err) {
767  return 100 + err;
768  }
769 
770  Rect crop = dstArea.getArea();
771  Rect mskCrop = mskArea.getArea();
772 
773  int wasOk = 0;
774 
775  {
776 
777  TPIXEL * src = srcData;
778  int srcWidth = origWidth;
779  int xSrcMin = crop.tl.x;
780  int xSrcMax = crop.br.x;
781  int ySrcMin = crop.tl.y - yKernelCenter;
782  ySrcMin = (ySrcMin < 0) ? 0 : ySrcMin;
783  int ySrcMax = crop.br.y + yKernelCenter;
784  ySrcMax = (ySrcMax > origHeight) ? origHeight : ySrcMax;
785 
786  TPIXEL * dst = tmpData;
787  int dstWidth = tmpWidth;
788 
789  TCHANNEL * msk = NULL;
790  int mskWidth = 0;
791  int xMskMin = 0;
792  int yMskMin = 0;
793 
794  int xDstMin = ySrcMin;
795  int yDstMin = xSrcMin;
796 
797  double * kernel = xKernel;
798  int kernelCenter = xKernelCenter;
799  int kernelWidth = xKernelWidth;
800 
801  double sumR;
802  double sumG;
803  double sumB;
804  double sumA;
805  double A;
806 
807  TCHANNEL * chPtr;
808  double kv;
809 
811  dPtr = dPtrColBgn++;,
812 
813  sumR = 0; sumG = 0; sumB = 0; sumA = 0;,
814 
815  kv = *kernelPtr;
816  chPtr = (TCHANNEL *) sTmpPtr;
817  A = *(chPtr + 3) * kv;
818  sumR += *(chPtr++) * A;
819  sumG += *(chPtr++) * A;
820  sumB += *chPtr * A;
821  sumA += A;,
822 
823  chPtr = (TCHANNEL *) dPtr;
824  *chPtr = sumR / (sumA) + 0.5; chPtr++;
825  *chPtr = sumG / (sumA) + 0.5; chPtr++;
826  *chPtr = sumB / (sumA) + 0.5; chPtr++;
827  *chPtr = sumA + 0.5;,
828 
829  dPtr += dstWidth;
830  )
831 
832 
833  wasOk = initOk; // Pokud ne, v tmp jsou nahodna data.
834  }
835 
836  if (wasOk) {
837 
838  TPIXEL * src = tmpData;
839  int srcWidth = tmpWidth;
840  int xSrcMin = crop.tl.y;
841  int xSrcMax = crop.br.y;
842  int ySrcMin = crop.tl.x;
843  int ySrcMax = crop.br.x;
844 
845  TPIXEL * dst = srcData;
846  int dstWidth = origWidth;
847  int xDstMin = crop.tl.x;
848  int yDstMin = crop.tl.y;
849 
850  TCHANNEL * msk = mask.getData();
851  int mskWidth = mask.getWidth();
852  int xMskMin = mskCrop.tl.x;
853  int yMskMin = mskCrop.tl.y;
854 
855  double * kernel = yKernel;
856  int kernelCenter = yKernelCenter;
857  int kernelWidth = yKernelWidth;
858 
859  double sumR;
860  double sumG;
861  double sumB;
862  double sumA;
863  double A;
864 
865  TCHANNEL * chPtr;
866  double kv;
867 
868  TCHANNEL doa;
869  double da;
870  double sa;
871  double sac;
872  double ra;
873 
875  dPtr = dPtrColBgn++;
876  mPtr = mPtrColBgn++;,
877 
878  sumR = 0; sumG = 0; sumB = 0; sumA = 0;,
879 
880  kv = *kernelPtr;
881  chPtr = (TCHANNEL *) sTmpPtr;
882  A = *(chPtr + 3) * kv;
883  sumR += *(chPtr++) * A;
884  sumG += *(chPtr++) * A;
885  sumB += *chPtr * A;
886  sumA += A;,
887 
888  chPtr = (TCHANNEL *) dPtr;
889 
890  doa = *(chPtr + 3);
891  da = doa / 255.0;
892  sa = sumA * *mPtr * alpha / 65025.0;
893  sac = 1 - sa;
894  ra = sa + da * sac;
895 
896  *chPtr = ((sumR / (sumA)) * sa + *chPtr * da * sac) / ra + 0.5; chPtr++;
897  *chPtr = ((sumG / (sumA)) * sa + *chPtr * da * sac) / ra + 0.5; chPtr++;
898  *chPtr = ((sumB / (sumA)) * sa + *chPtr * da * sac) / ra + 0.5; chPtr++;
899  *chPtr = ra * 255 + 0.5;,
900 
901  dPtr += dstWidth;
902  mPtr += mskWidth;
903  )
904 
905  }
906 
907  free(tmpData);
908 
909  return 0;
910 }
911 
912 
913 
914 
915 } /* namespace app */