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