00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <algorithm>
00043 #include <sstream>
00044
00045 #include <qgarlib/GenImage.H>
00046 #include <qgarlib/LinDilatedImage.H>
00047 #include <qgarlib/QgarErrorDomain.H>
00048
00049
00050
00051 namespace qgar
00052 {
00053
00054
00055
00056
00057
00058 LinDilatedImage::LinDilatedImage(GreyLevelImage& anImg,
00059 QGEorientation anOrient,
00060 unsigned int aDilSize)
00061 throw(QgarErrorDomain)
00062
00063 : GreyLevelImage(anImg)
00064
00065 {
00066 perform(this, anOrient, aDilSize);
00067 }
00068
00069
00070
00071
00072
00073
00074 void LinDilatedImage::perform(GreyLevelImage* anImg,
00075 QGEorientation anOrient,
00076 unsigned int aDilSize)
00077 {
00078 switch (anOrient)
00079 {
00080 case QGE_ORIENTATION_HOR:
00081 dilateHor(anImg, aDilSize);
00082 break;
00083 case QGE_ORIENTATION_VER:
00084 dilateVer(anImg, aDilSize);
00085 break;
00086 case QGE_ORIENTATION_DIAG_POS:
00087 dilatePdiag(anImg, aDilSize);
00088 break;
00089 case QGE_ORIENTATION_DIAG_NEG:
00090 dilateNdiag(anImg, aDilSize);
00091 break;
00092 case QGE_ORIENTATION_ALL:
00093 dilateAll(anImg, aDilSize);
00094 }
00095 }
00096
00097
00098
00099
00100 void LinDilatedImage::dilateHor(GreyLevelImage* anImg,
00101 unsigned int aDilSize)
00102 throw(QgarErrorDomain)
00103 {
00104 int linsize = (2 * aDilSize) + 1;
00105 int width = anImg->width();
00106 int height = anImg->height();
00107
00108 if (linsize > width)
00109 {
00110 std::ostringstream os;
00111 os << "Horizontal dilation size ["
00112 << aDilSize
00113 << " -> "
00114 << linsize
00115 << "] too large for image ["
00116 << width
00117 << " X "
00118 << height
00119 << "]";
00120 throw QgarErrorDomain(__FILE__, __LINE__,
00121 "void qgar::LinDilatedImage::dilateHor(qgar::GreyLevelImage*, unsigned int)",
00122 os.str());
00123 }
00124
00125
00126 GreyLevelImage::value_type* outRow = new GreyLevelImage::value_type [width];
00127
00128 GreyLevelImage::value_type* pOutRow;
00129 GreyLevelImage::value_type* inRow;
00130 GreyLevelImage::value_type* pInRow;
00131
00132 int l = 0;
00133
00134
00135
00136
00137 int overPixels = width % linsize;
00138
00139
00140
00141 for (; l < height ; l++) {
00142
00143 GreyLevelImage::value_type maximum = 0;
00144 int firstPixel;
00145 int window;
00146
00147
00148
00149
00150 pInRow = anImg->pRow(l) + width - 1 - overPixels;
00151 pOutRow = outRow + width - 1 - overPixels;
00152
00153 for ( firstPixel = overPixels;
00154 firstPixel < width;
00155 firstPixel += linsize)
00156 {
00157
00158 *pOutRow = *pInRow--;
00159 maximum = *pOutRow--;
00160
00161 for (window = 1;
00162 window < linsize ;
00163 window++, pInRow--) {
00164 if (maximum < *pInRow) maximum = *pInRow;
00165 *pOutRow-- = maximum;
00166 }
00167 }
00168
00169
00170
00171 if (overPixels) {
00172
00173 pInRow = anImg->pRow(l) + width - 1;
00174 pOutRow = outRow + width - 1;
00175 *pOutRow = *pInRow--;
00176 maximum = *pOutRow--;
00177
00178 for ( firstPixel = 1;
00179 firstPixel < linsize;
00180 firstPixel++, pInRow--) {
00181 if (maximum < *pInRow) maximum = *pInRow;
00182 *pOutRow-- = maximum;
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 pInRow = anImg->pRow(l);
00195 inRow = pInRow + aDilSize;
00196
00197 pOutRow = outRow;
00198
00199 for ( firstPixel = 0, maximum = *pInRow;
00200 firstPixel < (int)aDilSize;
00201 firstPixel++, pInRow++) {
00202 if (maximum < *pInRow) maximum = *pInRow;
00203 }
00204
00205 for ( firstPixel++;
00206 firstPixel < linsize;
00207 firstPixel++, pInRow++) {
00208 if (maximum < *pInRow) maximum = *pInRow;
00209 }
00210
00211
00212 if (maximum < *pInRow) maximum = *pInRow;
00213 pOutRow++;
00214 pInRow++;
00215 *inRow++ = maximum;
00216
00217
00218
00219 for ( ;
00220 firstPixel < width - overPixels;
00221 firstPixel += linsize) {
00222 maximum = *pInRow++;
00223 *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00224 inRow++;
00225 pOutRow++;
00226
00227 for ( window = 1;
00228 window < linsize;
00229 window++, pInRow++, pOutRow++, inRow++){
00230 if (maximum < *pInRow) maximum = *pInRow;
00231 *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00232 }
00233 }
00234
00235
00236
00237 if (overPixels) {
00238
00239 for ( maximum = *pInRow;
00240 firstPixel < width;
00241 firstPixel++, pInRow++, pOutRow++, inRow++) {
00242 if (maximum < *pInRow) maximum = *pInRow;
00243 *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00244 }
00245 }
00246 }
00247
00248
00249 delete [] outRow;
00250
00251 }
00252
00253
00254
00255
00256 void LinDilatedImage::dilateVer(GreyLevelImage* anImg,
00257 unsigned int aDilSize)
00258 throw(QgarErrorDomain)
00259 {
00260 int linsize = (2 * aDilSize) + 1;
00261 int width = anImg->width();
00262 int height = anImg->height();
00263
00264 if (linsize > height)
00265 {
00266 std::ostringstream os;
00267 os << "Vertical dilation size ["
00268 << aDilSize
00269 << " -> "
00270 << linsize
00271 << "] too large for image ["
00272 << width
00273 << " X "
00274 << height
00275 << "]";
00276 throw QgarErrorDomain(__FILE__, __LINE__,
00277 "void qgar::LinDilatedImage::dilateVer(qgar::GreyLevelImage*, unsigned int)",
00278 os.str());
00279 }
00280
00281
00282 GreyLevelImage::value_type* outRow = new GreyLevelImage::value_type [height];
00283
00284 GreyLevelImage::value_type* pOutRow;
00285 GreyLevelImage::value_type* inRow;
00286 GreyLevelImage::value_type* pInRow;
00287
00288 int l = 0;
00289
00290
00291
00292
00293 int overPixels = height % linsize;
00294
00295
00296
00297 for (; l < width ; l++) {
00298
00299 GreyLevelImage::value_type maximum = 0;
00300 int firstPixel;
00301 int window;
00302
00303
00304
00305
00306 pInRow = anImg->pColumn(l) + width * (height - 1 - overPixels);
00307 pOutRow = outRow + height - 1 - overPixels;
00308
00309 for ( firstPixel = overPixels;
00310 firstPixel < height;
00311 firstPixel += linsize) {
00312
00313 *pOutRow = *pInRow;
00314 pInRow -= width;
00315 maximum = *pOutRow--;
00316
00317 for ( window = 1;
00318 window < linsize;
00319 window++, pInRow -= width) {
00320 if (maximum < *pInRow) maximum = *pInRow;
00321 *pOutRow-- = maximum;
00322 }
00323 }
00324
00325
00326
00327 if (overPixels) {
00328
00329 pInRow = anImg->pColumn(l) + width * (height - 1);
00330 pOutRow = outRow + height - 1;
00331 *pOutRow = *pInRow;
00332 pInRow -= width;
00333 maximum = *pOutRow--;
00334
00335 for ( firstPixel = 1;
00336 firstPixel < linsize;
00337 firstPixel++, pInRow -= width) {
00338 if (maximum < *pInRow) maximum = *pInRow;
00339 *pOutRow-- = maximum;
00340 }
00341 }
00342
00343
00344
00345
00346
00347
00348
00349 pInRow = anImg->pColumn(l);
00350 inRow = pInRow + aDilSize * width;
00351
00352 pOutRow = outRow;
00353
00354 for ( firstPixel = 0, maximum = *pInRow;
00355 firstPixel < (int)aDilSize;
00356 firstPixel++, pInRow += width) {
00357 if (maximum < *pInRow) maximum = *pInRow;
00358 }
00359
00360 for ( firstPixel++;
00361 firstPixel < linsize;
00362 firstPixel++, pInRow += width) {
00363 if (maximum < *pInRow) maximum = *pInRow;
00364 }
00365
00366
00367 if (maximum < *pInRow) maximum = *pInRow;
00368 pOutRow++;
00369 pInRow += width;
00370 *inRow = maximum;
00371 inRow += width;
00372
00373
00374 for ( ;
00375 firstPixel < height - overPixels;
00376 firstPixel += linsize) {
00377
00378 maximum = *pInRow;
00379 pInRow += width;
00380 *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00381 inRow += width;
00382 *pOutRow++;
00383
00384 for ( window = 1;
00385 window < linsize;
00386 window++, pInRow += width, pOutRow++, inRow += width){
00387 if (maximum < *pInRow) maximum = *pInRow;
00388 *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00389 }
00390 }
00391
00392
00393
00394 if (overPixels) {
00395
00396 for ( maximum = *pInRow;
00397 firstPixel < height;
00398 firstPixel++, pInRow += width, pOutRow++, inRow += width) {
00399 if (maximum < *pInRow) maximum = *pInRow;
00400 *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00401 }
00402 }
00403 }
00404
00405
00406 delete [] outRow;
00407 }
00408
00409
00410
00411
00412 void
00413 LinDilatedImage::dilatePdiag(GreyLevelImage* anImg,
00414 unsigned int aDilSize)
00415
00416 throw(QgarErrorDomain)
00417
00418 {
00419 int linsize = (2 * aDilSize) + 1;
00420 int width = anImg->width();
00421 int height = anImg->height();
00422
00423
00424
00425 int diagSize = (2 * linsize) / 3;
00426 if ((diagSize > height) || (diagSize > width))
00427 {
00428 std::ostringstream os;
00429 os << "NE-SW dilation size ["
00430 << aDilSize
00431 << " -> "
00432 << linsize
00433 << "] too large for image ["
00434 << width
00435 << " X "
00436 << height
00437 << "]";
00438 throw QgarErrorDomain(__FILE__, __LINE__,
00439 "void qgar::LinDilatedImage::dilatePDiag(qgar::GreyLevelImage*, unsigned int)",
00440 os.str());
00441 }
00442
00443 int i = (width > height ? width : height);
00444
00445
00446 GreyLevelImage::value_type* outRow = new GreyLevelImage::value_type [i];
00447
00448
00449 GreyLevelImage::value_type* diagRow = new GreyLevelImage::value_type [i];
00450
00451 GreyLevelImage::value_type* pOutRow;
00452
00453 GreyLevelImage::value_type* inRow;
00454 GreyLevelImage::value_type* pInRow;
00455
00456
00457 GreyLevelImage::value_type* end = anImg->pRow(height - 1) + 1;
00458
00459 int l = linsize;
00460
00461 int length;
00462
00463
00464
00465
00466 int overPixels;
00467
00468 GreyLevelImage::value_type maximum = 0;
00469 int firstPixel;
00470 int window;
00471
00472
00473
00474 for (; l < height + width - 1 - linsize; l++) {
00475
00476 if (l < height) {
00477 inRow = anImg->pRow(l);
00478 length = (width > l + 1 ? l + 1 : width);
00479 }
00480 else {
00481 inRow = end;
00482 i = width - l + height - 1;
00483 length = (i > height ? height : i);
00484 }
00485
00486 pInRow = diagRow;
00487
00488
00489 for (i = 0 ; i < length; i++) {
00490 *pInRow++ = *inRow;
00491 inRow -= (width - 1);
00492 }
00493
00494 overPixels = length % linsize;
00495
00496
00497
00498 pInRow = diagRow + length - 1 - overPixels;
00499 pOutRow = outRow + length - 1 - overPixels;
00500
00501 for ( firstPixel = overPixels;
00502 firstPixel < length;
00503 firstPixel += linsize) {
00504
00505 *pOutRow = *pInRow--;
00506 maximum = *pOutRow--;
00507
00508 for (window = 1;
00509 window < linsize ;
00510 window++, pInRow--) {
00511 if (maximum < *pInRow) maximum = *pInRow;
00512 *pOutRow-- = maximum;
00513 }
00514 }
00515
00516
00517
00518 if (overPixels) {
00519
00520 pInRow = diagRow + length - 1;
00521 pOutRow = outRow + length - 1;
00522 *pOutRow = *pInRow--;
00523 maximum = *pOutRow--;
00524
00525 for ( firstPixel = 1;
00526 firstPixel < linsize;
00527 firstPixel++, pInRow--) {
00528 if (maximum < *pInRow) maximum = *pInRow;
00529 *pOutRow-- = maximum;
00530 }
00531 }
00532
00533
00534
00535
00536
00537
00538
00539 pInRow = diagRow;
00540 inRow = pInRow + aDilSize;
00541
00542 pOutRow = outRow;
00543
00544 for ( firstPixel = 0, maximum = *pInRow;
00545 firstPixel < (int)aDilSize;
00546 firstPixel++, pInRow++) {
00547 if (maximum < *pInRow) maximum = *pInRow;
00548 }
00549
00550 for ( firstPixel++;
00551 firstPixel < linsize;
00552 firstPixel++, pInRow++) {
00553 if (maximum < *pInRow) maximum = *pInRow;
00554 }
00555
00556
00557 if (maximum < *pInRow) maximum = *pInRow;
00558 pOutRow++;
00559 pInRow++;
00560 *inRow++ = maximum;
00561
00562
00563
00564 for ( ;
00565 firstPixel < length - overPixels;
00566 firstPixel += linsize) {
00567 maximum = *pInRow++;
00568 *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00569 inRow++;
00570 pOutRow++;
00571
00572 for ( window = 1;
00573 window < linsize;
00574 window++, pInRow++, pOutRow++, inRow++){
00575 if (maximum < *pInRow) maximum = *pInRow;
00576 *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00577 }
00578 }
00579
00580
00581
00582 if (overPixels) {
00583
00584 for ( maximum = *pInRow;
00585 firstPixel < length;
00586 firstPixel++, pInRow++, pOutRow++, inRow++) {
00587 if (maximum < *pInRow) maximum = *pInRow;
00588 *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00589 }
00590 }
00591
00592
00593 if (l < height) inRow = anImg->pRow(l);
00594 else inRow = end++;
00595
00596 pInRow = diagRow;
00597
00598 for (i = 0 ; i < length ; i++) {
00599 *inRow = *pInRow++;
00600 inRow -= (width - 1);
00601 }
00602
00603 }
00604
00605
00606 delete [] outRow;
00607 delete [] diagRow;
00608 }
00609
00610
00611
00612
00613 void LinDilatedImage::dilateNdiag(GreyLevelImage* anImg,
00614 unsigned int aDilSize)
00615
00616 throw(QgarErrorDomain)
00617
00618 {
00619 int linsize = (2 * aDilSize) + 1;
00620 int width = anImg->width();
00621 int height = anImg->height();
00622
00623
00624
00625 int diagSize = (2 * linsize) / 3;
00626 if ((diagSize > height) || (diagSize > width))
00627 {
00628 std::ostringstream os;
00629 os << "NW-SE dilation size ["
00630 << aDilSize
00631 << " -> "
00632 << linsize
00633 << "] too large for image ["
00634 << width
00635 << " X "
00636 << height
00637 << "]";
00638 throw QgarErrorDomain(__FILE__, __LINE__,
00639 "void qgar::LinDilatedImage::dilateNDiag(qgar::GreyLevelImage*, unsigned int)",
00640 os.str());
00641 }
00642
00643 int i = (width > height ? width : height);
00644
00645
00646 GreyLevelImage::value_type* outRow = new GreyLevelImage::value_type [i];
00647
00648
00649 GreyLevelImage::value_type* diagRow = new GreyLevelImage::value_type [i];
00650
00651 GreyLevelImage::value_type* pOutRow;
00652
00653 GreyLevelImage::value_type* inRow;
00654 GreyLevelImage::value_type* pInRow;
00655
00656
00657 GreyLevelImage::value_type* first = anImg->pRow(1) - linsize - 1;
00658
00659 int l = linsize;
00660
00661 int length;
00662
00663
00664
00665
00666 int overPixels;
00667
00668 GreyLevelImage::value_type maximum = 0;
00669 int firstPixel;
00670 int window;
00671
00672
00673
00674 for (; l < height + width - 1 - linsize; l++) {
00675
00676 if (l < width) {
00677 inRow = first;
00678 length = (l + 1 > height ? height : l + 1);
00679 }
00680 else {
00681 inRow = anImg->pRow(l - width + 1);
00682 i = height - (l - width + 1);
00683 length = (i > width ? width : i);
00684 }
00685
00686 pInRow = diagRow;
00687
00688
00689 for (i = 0 ; i < length; i++) {
00690 *pInRow++ = *inRow;
00691 inRow += (width + 1);
00692 }
00693
00694 overPixels = length % linsize;
00695
00696
00697
00698 pInRow = diagRow + length - 1 - overPixels;
00699 pOutRow = outRow + length - 1 - overPixels;
00700
00701 for ( firstPixel = overPixels;
00702 firstPixel < length;
00703 firstPixel += linsize) {
00704
00705 *pOutRow = *pInRow--;
00706 maximum = *pOutRow--;
00707
00708 for (window = 1;
00709 window < linsize ;
00710 window++, pInRow--) {
00711 if (maximum < *pInRow) maximum = *pInRow;
00712 *pOutRow-- = maximum;
00713 }
00714 }
00715
00716
00717
00718 if (overPixels) {
00719
00720 pInRow = diagRow + length - 1;
00721 pOutRow = outRow + length - 1;
00722 *pOutRow = *pInRow--;
00723 maximum = *pOutRow--;
00724
00725 for ( firstPixel = 1;
00726 firstPixel < linsize;
00727 firstPixel++, pInRow--) {
00728 if (maximum < *pInRow) maximum = *pInRow;
00729 *pOutRow-- = maximum;
00730 }
00731 }
00732
00733
00734
00735
00736
00737
00738
00739 pInRow = diagRow;
00740 inRow = pInRow + aDilSize;
00741
00742 pOutRow = outRow;
00743
00744 for ( firstPixel = 0, maximum = *pInRow;
00745 firstPixel < (int)aDilSize;
00746 firstPixel++, pInRow++) {
00747 if (maximum < *pInRow) maximum = *pInRow;
00748 }
00749
00750 for ( firstPixel++;
00751 firstPixel < linsize;
00752 firstPixel++, pInRow++) {
00753 if (maximum < *pInRow) maximum = *pInRow;
00754 }
00755
00756
00757 if (maximum < *pInRow) maximum = *pInRow;
00758 pOutRow++;
00759 pInRow++;
00760 *inRow++ = maximum;
00761
00762
00763 for ( ;
00764 firstPixel < length - overPixels;
00765 firstPixel += linsize) {
00766 maximum = *pInRow++;
00767 *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00768 inRow++;
00769 pOutRow++;
00770
00771 for ( window = 1;
00772 window < linsize;
00773 window++, pInRow++, pOutRow++, inRow++){
00774 if (maximum < *pInRow) maximum = *pInRow;
00775 *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00776 }
00777 }
00778
00779
00780
00781 if (overPixels) {
00782
00783 for ( maximum = *pInRow;
00784 firstPixel < length;
00785 firstPixel++, pInRow++, pOutRow++, inRow++) {
00786 if (maximum < *pInRow) maximum = *pInRow;
00787 *inRow = (*pOutRow < maximum ? maximum : *pOutRow);
00788 }
00789 }
00790
00791
00792
00793 if (l < width) inRow = first--;
00794 else inRow = anImg->pRow(l - width + 1);
00795
00796 pInRow = diagRow;
00797
00798 for (i = 0 ; i < length ; i++) {
00799 *inRow = *pInRow++;
00800 inRow += (width + 1);
00801 }
00802
00803 }
00804
00805
00806 delete [] outRow;
00807 delete [] diagRow;
00808 }
00809
00810
00811
00812
00813 void LinDilatedImage::dilateAll(GreyLevelImage* anImg,
00814 unsigned int aDilSize)
00815
00816 throw(QgarErrorDomain)
00817
00818 {
00819 int linsize = (2 * aDilSize) + 1;
00820 int width = anImg->width();
00821 int height = anImg->height();
00822
00823
00824
00825 int diagSize = (2 * linsize) / 3;
00826 if ((diagSize > height) || (diagSize > width))
00827 {
00828 std::ostringstream os;
00829 os << "All-orientations dilation size ["
00830 << aDilSize
00831 << " -> "
00832 << linsize
00833 << "] too large for image ["
00834 << width
00835 << " X "
00836 << height
00837 << "]";
00838 throw QgarErrorDomain(__FILE__, __LINE__,
00839 "void qgar::LinDilatedImage::dilateAll(qgar::GreyLevelImage*, unsigned int)",
00840 os.str());
00841 }
00842
00843 GreyLevelImage work(*anImg);
00844
00845
00846 GreyLevelImage::value_type* crow = new GreyLevelImage::value_type [anImg->width() * linsize];
00847
00848
00849 GreyLevelImage::value_type* orow = new GreyLevelImage::value_type [anImg->width()];
00850
00851 GreyLevelImage::value_type* p;
00852 GreyLevelImage::value_type* q;
00853
00854
00855
00856 int i = 0;
00857 int l = aDilSize;
00858
00859 for ( ; l < height - (int)aDilSize ; l++, i++)
00860 {
00861 int ii = i;
00862
00863 for (q = crow ; ii < i + linsize ; ii++, q += width)
00864 anImg->row(ii, q);
00865
00866 int j = aDilSize;
00867 anImg->row(l, orow);
00868
00869 for (p = orow + aDilSize, q = crow + aDilSize ;
00870 j < width - (int)aDilSize ; j++, q++)
00871 {
00872 GreyLevelImage::value_type curhoriz = 0;
00873 GreyLevelImage::value_type curverti = 0;
00874 GreyLevelImage::value_type curpdiag = 0;
00875 GreyLevelImage::value_type curndiag = 0;
00876
00877 GreyLevelImage::value_type* sl = q;
00878 int k = 0;
00879
00880 for ( ; k < linsize ; k++, sl += width)
00881 {
00882 if (*(sl - aDilSize + k) > curndiag)
00883 curndiag = *(sl - aDilSize +k);
00884 if (*sl > curverti)
00885 curverti = *sl;
00886 if (*(sl + (int)aDilSize - k) > curpdiag)
00887 curpdiag = *(sl + aDilSize - k);
00888 if (k == (int)aDilSize)
00889 {
00890 GreyLevelImage::value_type* ssl = sl - aDilSize;
00891 int kk = 0;
00892 for ( ; kk < linsize ; kk++, ssl++)
00893 if (*ssl > curhoriz)
00894 curhoriz = *ssl;
00895
00896 }
00897 }
00898
00899
00900 *p++ = std::min(std::min(curndiag, curpdiag), std::min(curhoriz, curverti));
00901 }
00902
00903
00904 work.setRow(l, orow);
00905 }
00906
00907 for (i = 0; i < height; i++) {
00908 work.row(i, crow);
00909 anImg->setRow(i, crow);
00910 }
00911
00912
00913 delete [] crow;
00914 delete [] orow;
00915 }
00916
00917
00918
00919 }