App

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

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
119 template class TSeparableFilter<px_4x8bit, px_1x8bit> ;
120 template class TSeparableFilter<px_1x8bit, px_1x8bit> ;
121
122 template<typename TPIXEL, typename TCHANNEL>
123 TSeparableFilter<TPIXEL, TCHANNEL>::~TSeparableFilter() {
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>
135 int TSeparableFilter<TPIXEL, TCHANNEL>::applyTo_1ch(TBitmap<TPIXEL, TCHANNEL> &bitmap, Rect srcRect) {
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>
249 int TSeparableFilter<TPIXEL, TCHANNEL>::applyTo_4ch(TBitmap<TPIXEL, TCHANNEL> &bitmap, Rect srcRect) {
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
311 SEPARABLE_FILTER_ALGORITHM_GENERAL(
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
369 SEPARABLE_FILTER_ALGORITHM_GENERAL(
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>
400 int TSeparableFilter<TPIXEL, TCHANNEL>::applyTo_4ch(TBitmap<TPIXEL, TCHANNEL> &bitmap, Rect srcRect, double alpha) {
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
462 SEPARABLE_FILTER_ALGORITHM_GENERAL(
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
526 SEPARABLE_FILTER_ALGORITHM_GENERAL(
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>
564 int TSeparableFilter<TPIXEL, TCHANNEL>::applyTo_4ch(TBitmap<TPIXEL, TCHANNEL> &bitmap, TBitmap<TCHANNEL, TCHANNEL> &mask, Rect mskRect, Point mskOrig) {
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
635 SEPARABLE_FILTER_ALGORITHM_GENERAL(
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
699 SEPARABLE_FILTER_ALGORITHM_GENERAL(
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>
739 int TSeparableFilter<TPIXEL, TCHANNEL>::applyTo_4ch(TBitmap<TPIXEL, TCHANNEL> &bitmap, TBitmap<TCHANNEL, TCHANNEL> &mask, Rect mskRect, Point mskOrig, double alpha) {
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
810 SEPARABLE_FILTER_ALGORITHM_GENERAL(
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
874 SEPARABLE_FILTER_ALGORITHM_GENERAL(
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 */