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 <sstream>
00043
00044 #include <qgarlib/GenImage.H>
00045 #include <qgarlib/LinDilatedBinaryImage.H>
00046 #include <qgarlib/QgarErrorDomain.H>
00047
00048
00049
00050 namespace qgar
00051 {
00052
00053
00054
00055
00056
00057
00058 LinDilatedBinaryImage::LinDilatedBinaryImage(BinaryImage& anImg,
00059 QGEorientation anOrient,
00060 unsigned int aDilSize)
00061 throw(QgarErrorDomain)
00062
00063 : BinaryImage(anImg)
00064
00065 {
00066 perform(this, anOrient, aDilSize);
00067 }
00068
00069
00070
00071
00072
00073
00074
00075 void
00076 LinDilatedBinaryImage::perform(BinaryImage* anImg,
00077 QGEorientation anOrient,
00078 unsigned int aDilSize)
00079 {
00080
00081 switch (anOrient)
00082 {
00083 case QGE_ORIENTATION_HOR:
00084 dilateHor(anImg, aDilSize);
00085 break;
00086 case QGE_ORIENTATION_VER:
00087 dilateVer(anImg, aDilSize);
00088 break;
00089 case QGE_ORIENTATION_DIAG_POS:
00090 dilatePdiag(anImg, aDilSize);
00091 break;
00092 case QGE_ORIENTATION_DIAG_NEG:
00093 dilateNdiag(anImg, aDilSize);
00094 break;
00095 case QGE_ORIENTATION_ALL:
00096 dilateAll(anImg, aDilSize);
00097 }
00098 }
00099
00100
00101
00102
00103
00104
00105
00106 void
00107 LinDilatedBinaryImage::dilateHor(BinaryImage* anImg,
00108 unsigned int aDilSize)
00109
00110 throw(QgarErrorDomain)
00111
00112 {
00113 int linSize = (2 * aDilSize) + 1;
00114 int width = anImg->width();
00115 int height = anImg->height();
00116
00117 if (linSize > width)
00118 {
00119 std::ostringstream os;
00120 os << "Horizontal dilation size ["
00121 << aDilSize
00122 << " -> "
00123 << linSize
00124 << "] too large for image ["
00125 << width
00126 << " x "
00127 << height
00128 << "]";
00129 throw QgarErrorDomain(__FILE__, __LINE__,
00130 "void qgar::LinDilatedBinaryImage::dilateHor(qgar::BinaryImage*, unsigned int)",
00131 os.str());
00132 }
00133
00134
00135 BinaryImage::value_type* behind;
00136 BinaryImage::value_type* ahead;
00137
00138 int mask;
00139 int i;
00140 int j;
00141
00142
00143
00144 for (i = 0; i < height ; ++i)
00145 {
00146
00147
00148 behind = anImg->pRow(i);
00149
00150
00151 for (j = mask = 0; j < (int)aDilSize; ++j, ++behind)
00152 {
00153
00154 if (*behind)
00155 {
00156 mask = j + 1;
00157 }
00158 }
00159
00160
00161
00162 for (ahead = behind;
00163 (j < linSize - 1) && (j < (width - (int)aDilSize - 1));
00164 ++j, ++ahead)
00165 {
00166
00167 if (*ahead)
00168 {
00169 mask = aDilSize + 1;
00170 }
00171 if (mask)
00172 {
00173 *ahead = 1;
00174 --mask;
00175 }
00176 }
00177
00178
00179
00180 for (; j < (width - (int)aDilSize); ++j)
00181 {
00182 if (*ahead)
00183 {
00184 mask = aDilSize + 1;
00185 }
00186
00187 if (mask)
00188 {
00189 *behind = 1;
00190 *ahead = 1;
00191 --mask;
00192 }
00193
00194 ++behind;
00195 ++ahead;
00196 }
00197
00198
00199 for (; j < width ; j++)
00200 {
00201 if (*ahead)
00202 {
00203 mask = aDilSize + 1;
00204 }
00205
00206 if (mask)
00207 {
00208 *behind = 1;
00209 --mask;
00210 }
00211
00212 ++behind;
00213 ++ahead;
00214 }
00215
00216 }
00217 }
00218
00219
00220
00221
00222
00223
00224
00225 void
00226 LinDilatedBinaryImage::dilateVer(BinaryImage* anImg,
00227 unsigned int aDilSize)
00228
00229 throw(QgarErrorDomain)
00230
00231 {
00232 int linSize = (2 * aDilSize) + 1;
00233 int width = anImg->width();
00234 int height = anImg->height();
00235
00236 if (linSize > height)
00237 {
00238 std::ostringstream os;
00239 os << "Vertical dilation size ["
00240 << aDilSize
00241 << " -> "
00242 << linSize
00243 << "] too large for image ["
00244 << width
00245 << " x "
00246 << height
00247 << "]";
00248 throw QgarErrorDomain(__FILE__, __LINE__,
00249 "void qgar::LinDilatedBinaryImage::dilateVer(qgar::BinaryImage*, unsigned int)",
00250 os.str());
00251 }
00252
00253
00254 BinaryImage::value_type* behind;
00255 BinaryImage::value_type* ahead;
00256
00257 int mask;
00258 int i;
00259 int j;
00260
00261
00262
00263 for (i = 0; i < width; ++i)
00264 {
00265
00266
00267 behind = anImg->pColumn(i);
00268
00269
00270 for (j = mask = 0; j < (int)aDilSize; ++j, behind += width)
00271 {
00272
00273 if (*behind)
00274 {
00275 mask = j + 1;
00276 }
00277 }
00278
00279
00280
00281 for (ahead = behind;
00282 (j < linSize - 1) && (j < (height - (int)aDilSize - 1));
00283 ++j, ahead += width)
00284 {
00285
00286 if (*ahead) mask = aDilSize + 1;
00287 if (mask)
00288 {
00289 *ahead = 1;
00290 --mask;
00291 }
00292 }
00293
00294
00295
00296 for (; j < (height - (int)aDilSize); ++j)
00297 {
00298 if (*ahead)
00299 {
00300 mask = aDilSize + 1;
00301 }
00302
00303 if (mask)
00304 {
00305 *behind = 1;
00306 *ahead = 1;
00307 --mask;
00308 }
00309
00310 behind += width;
00311 ahead += width;
00312 }
00313
00314
00315
00316 for (; j < height ; ++j)
00317 {
00318 if (*ahead)
00319 {
00320 mask = aDilSize + 1;
00321 }
00322
00323 if (mask)
00324 {
00325 *behind = 1;
00326 --mask;
00327 }
00328
00329 behind += width;
00330 ahead += width;
00331 }
00332
00333 }
00334 }
00335
00336
00337
00338
00339
00340
00341
00342 void
00343 LinDilatedBinaryImage::dilatePdiag(BinaryImage* anImg,
00344 unsigned int aDilSize)
00345
00346 throw(QgarErrorDomain)
00347
00348 {
00349 int linSize = (2 * aDilSize) + 1;
00350 int width = anImg->width();
00351 int height = anImg->height();
00352
00353 int diagSize = (2 * linSize) / 3;
00354 if ((diagSize > height) || (diagSize > width))
00355 {
00356 std::ostringstream os;
00357 os << "NE-SW dilation size ["
00358 << aDilSize
00359 << " -> "
00360 << linSize
00361 << "] too large for image ["
00362 << width
00363 << " x "
00364 << height
00365 << "]";
00366 throw QgarErrorDomain(__FILE__, __LINE__,
00367 "void qgar::LinDilatedBinaryImage::dilatePDiag(qgar::BinaryImage*, unsigned int)",
00368 os.str());
00369 }
00370
00371
00372 BinaryImage::value_type* behind;
00373 BinaryImage::value_type* ahead;
00374
00375
00376 BinaryImage::value_type* end = anImg->pRow(height - 1) + 1;
00377
00378 int mask;
00379 int i;
00380 int j;
00381
00382 int length;
00383
00384
00385
00386 for (i = linSize; i < height + width - 1 - linSize; ++i)
00387 {
00388
00389
00390
00391 if (i < height)
00392 {
00393 behind = anImg->pRow(i);
00394 length = (width > i + 1 ? i + 1 : width);
00395 }
00396 else
00397 {
00398 behind = end;
00399 ++end;
00400 length = ((width - i + height - 1) > height
00401 ? height
00402 : width - i + height - 1);
00403 }
00404
00405
00406
00407 for (j = mask = 0; j < (int)aDilSize; ++j, behind -= (width - 1))
00408 {
00409
00410 if (*behind)
00411 {
00412 mask = j + 1;
00413 }
00414 }
00415
00416
00417
00418 for (ahead = behind;
00419 (j < linSize - 1) && (j < (length - (int)aDilSize - 1));
00420 ++j, ahead -= (width - 1))
00421 {
00422
00423
00424 if (*ahead)
00425 {
00426 mask = aDilSize + 1;
00427 }
00428
00429 if (mask)
00430 {
00431 *ahead = 1;
00432 --mask;
00433 }
00434 }
00435
00436
00437
00438 for (; j < (length - (int)aDilSize); ++j)
00439 {
00440 if (*ahead)
00441 {
00442 mask = aDilSize + 1;
00443 }
00444
00445 if (mask)
00446 {
00447 *behind = 1;
00448 *ahead = 1;
00449 --mask;
00450 }
00451
00452 behind -= (width - 1);
00453 ahead -= (width - 1);
00454 }
00455
00456
00457 for (; j < length ; ++j)
00458 {
00459 if (*ahead)
00460 {
00461 mask = aDilSize + 1;
00462 }
00463
00464 if (mask)
00465 {
00466 *behind = 1;
00467 --mask;
00468 }
00469
00470 behind -= (width - 1);
00471 ahead -= (width - 1);
00472 }
00473
00474 }
00475 }
00476
00477
00478
00479
00480
00481
00482
00483 void
00484 LinDilatedBinaryImage::dilateNdiag(BinaryImage* anImg,
00485 unsigned int aDilSize)
00486
00487 throw(QgarErrorDomain)
00488
00489 {
00490 int linSize = (2 * aDilSize) + 1;
00491 int width = anImg->width();
00492 int height = anImg->height();
00493
00494 int diagSize = (2 * linSize) / 3;
00495 if ((diagSize > height) || (diagSize > width))
00496 {
00497 std::ostringstream os;
00498 os << "NW-SE dilation size ["
00499 << aDilSize
00500 << " -> "
00501 << linSize
00502 << "] too large for image ["
00503 << width
00504 << " x "
00505 << height
00506 << "]";
00507 throw QgarErrorDomain(__FILE__, __LINE__,
00508 "void qgar::LinDilatedBinaryImage::dilateNDiag(qgar::BinaryImage*, unsigned int)",
00509 os.str());
00510 }
00511
00512
00513 BinaryImage::value_type* behind;
00514 BinaryImage::value_type* ahead;
00515
00516
00517 BinaryImage::value_type* first = anImg->pRow(1) - linSize;
00518
00519 int mask;
00520 int i;
00521 int j;
00522
00523 int length;
00524
00525
00526
00527
00528 for (i = linSize; i < height + width - 1 - linSize; ++i)
00529 {
00530
00531
00532
00533 if (i < width)
00534 {
00535 behind = --first;
00536 length = (i + 1 > height ? height : i + 1);
00537 }
00538 else
00539 {
00540 behind = anImg->pRow(i - width + 1);
00541 length = (height - (i - width + 1) > width ? width : height - (i - width + 1));
00542 }
00543
00544
00545
00546 for (j = mask = 0; j < (int)aDilSize; ++j, behind += (width + 1))
00547 {
00548
00549 if (*behind)
00550 {
00551 mask = j + 1;
00552 }
00553 }
00554
00555
00556
00557 for (ahead = behind;
00558 (j < linSize - 1) && (j < (length - (int)aDilSize - 1));
00559 ++j, ahead += (width + 1))
00560 {
00561
00562 if (*ahead)
00563 {
00564 mask = aDilSize + 1;
00565 }
00566
00567 if (mask)
00568 {
00569 *ahead = 1;
00570 --mask;
00571 }
00572 }
00573
00574
00575
00576 for (; j < (length - (int)aDilSize); ++j)
00577 {
00578 if (*ahead)
00579 {
00580 mask = aDilSize + 1;
00581 }
00582
00583 if (mask)
00584 {
00585 *behind = 1;
00586 *ahead = 1;
00587 --mask;
00588 }
00589
00590 behind += (width + 1);
00591 ahead += (width + 1);
00592 }
00593
00594
00595
00596 for (; j < length ; ++j)
00597 {
00598 if (*ahead)
00599 {
00600 mask = aDilSize + 1;
00601 }
00602
00603 if (mask)
00604 {
00605 *behind = 1;
00606 --mask;
00607 }
00608
00609 behind += (width + 1);
00610 ahead += (width + 1);
00611 }
00612
00613 }
00614 }
00615
00616
00617
00618
00619
00620
00621
00622 void
00623 LinDilatedBinaryImage::dilateAll(BinaryImage* anImg,
00624 unsigned int aDilSize)
00625
00626 throw(QgarErrorDomain)
00627
00628 {
00629 int linsize = (2 * aDilSize) + 1;
00630 int width = anImg->width();
00631 int height = anImg->height();
00632
00633 int diagSize = (2 * linsize) / 3;
00634 if ((diagSize > height) || (diagSize > width))
00635 {
00636 std::ostringstream os;
00637 os << "All-orientations dilation size ["
00638 << aDilSize
00639 << " -> "
00640 << linsize
00641 << "] too large for image ["
00642 << width
00643 << " x "
00644 << height
00645 << "]";
00646 throw QgarErrorDomain(__FILE__, __LINE__,
00647 "void qgar::LinDilatedBinaryImage::dilateAll(qgar::BinaryImage*, unsigned int)",
00648 os.str());
00649 }
00650
00651 BinaryImage img2(*anImg);
00652
00653
00654 BinaryImage::value_type* crow = new BinaryImage::value_type [anImg->width() * linsize];
00655
00656
00657 BinaryImage::value_type* orow = new BinaryImage::value_type [anImg->width()];
00658
00659 BinaryImage::value_type* p;
00660 BinaryImage::value_type* q;
00661
00662
00663
00664
00665 int i = 0;
00666 int l = aDilSize;
00667
00668 for ( ; l < (anImg->height() - (int)aDilSize) ; ++l, ++i)
00669 {
00670
00671 int ii = i;
00672
00673 for (q = crow ; ii < i + linsize ; ++ii, q += anImg->width())
00674 {
00675 anImg->row(ii, q);
00676 }
00677
00678 int j = aDilSize;
00679 anImg->row(l, orow);
00680
00681 for (p = orow + aDilSize, q = crow + aDilSize ;
00682 j < (anImg->width() - (int)aDilSize) ; ++j, ++q)
00683 {
00684
00685 BinaryImage::value_type curhoriz = 0;
00686 BinaryImage::value_type curverti = 0;
00687 BinaryImage::value_type curpdiag = 0;
00688 BinaryImage::value_type curndiag = 0;
00689
00690 BinaryImage::value_type* sl = q;
00691 int k = 0;
00692
00693 for ( ; k < linsize ; ++k, sl += anImg->width())
00694 {
00695 if (*(sl - aDilSize + k) != 0)
00696 {
00697 curndiag = 1;
00698 }
00699
00700 if (*sl != 0)
00701 {
00702 curverti = 1;
00703 }
00704
00705 if (*(sl + aDilSize -k) != 0)
00706 {
00707 curpdiag = 1;
00708 }
00709
00710 if (k == (int)aDilSize)
00711 {
00712 BinaryImage::value_type* ssl = sl - aDilSize;
00713 int kk = 0;
00714 for ( ; kk < linsize ; ++kk, ++ssl)
00715 {
00716 if (*ssl != 0)
00717 {
00718 curhoriz = 1;
00719 break;
00720 }
00721 }
00722 }
00723 }
00724
00725 *p = ((curndiag != 0) && (curpdiag != 0) &&
00726 (curhoriz != 0) && (curverti != 0)) ? 1 : 0;
00727 ++p;
00728 }
00729
00730
00731 img2.setRow(l, orow);
00732
00733 }
00734
00735 for (i = 0; i < anImg->height(); ++i)
00736 {
00737 img2.row(i, orow);
00738 anImg->setRow(i, orow);
00739 }
00740
00741
00742 delete [] crow;
00743 delete [] orow;
00744 }
00745
00746
00747
00748 }