48 auto b = SBlock(
new Block(src, nam));
63 child(std::make_shared<
Map>()),
71 buffGradient(nullptr),
73 grad_diffusemaxiter(0),
74 grad_diffusemaxdiv(std::numeric_limits<double>::max())
82 srcRGB = std::dynamic_pointer_cast<
ImageRGB>(src);
85 srcGray = std::dynamic_pointer_cast<
ImageGray>(src);
88 srcBW = std::dynamic_pointer_cast<
ImageBW>(src);
93 if (!srcRGB && !srcGray && !srcBW && !srcGradient)
95 _(
"unsupported image type."));
97 bbox =
Rect(0, 0,
int(src->GetWidth()) - 1,
int(src->GetHeight()) - 1);
116 auto b = SBlock(
new Block(ifname, xfname, nam));
120 if ((!b->bbox.IsValid()) || (b->bbox.GetWidth() == 0) || (b->bbox.GetHeight() == 0))
122 auto irgb = b->GetRGB();
125 b->bbox.SetWidth(
int(irgb->GetWidth()));
126 b->bbox.SetHeight(
int(irgb->GetHeight()));
147 child(std::make_shared<
Map>()),
151 srcGradient(nullptr),
155 buffGradient(nullptr),
157 grad_diffusemaxiter(0),
158 grad_diffusemaxdiv(std::numeric_limits<double>::max())
162 image_is_open =
false;
163 imagefilename = ifname;
177 SBlock Block::create(
const WBlock &par,
const String &tree,
const Rect &clip,
const String &nam)
179 auto b = SBlock(
new Block(par, tree, clip, nam));
197 child(std::make_shared<
Map>()),
204 buffGradient(nullptr),
206 grad_diffusemaxiter(0),
207 grad_diffusemaxdiv(std::numeric_limits<double>::max())
214 srcRGB = par.lock()->srcRGB;
215 srcGray = par.lock()->srcGray;
216 srcBW = par.lock()->srcBW;
217 srcGradient = par.lock()->srcGradient;
218 image_is_open = par.lock()->image_is_open;
227 else if (srcGradient)
229 bbox = bbox & par.lock()->GetAbsoluteBBox();
236 if (bbox.
GetRight() >= int(src->GetWidth()))
237 bbox.
SetRight(
int(src->GetWidth()) - 1);
238 if (bbox.
GetBottom() >= int(src->GetHeight()))
239 bbox.
SetBottom(
int(src->GetHeight()) - 1);
256 if (parent.expired())
258 _(
"this is a topmost block. Its bounding box cannot be changed."));
261 _(
"Uninitialized bounding box."));
262 Rect nr = parent.lock()->GetAbsoluteBBox();
266 _(
"bounding box out of parent's bounding box."));
268 if ((nr & bbox).GetArea() < bbox.GetArea())
269 for (
auto & elem : *child)
271 SVector v(std::static_pointer_cast<Vector>(elem.second));
272 for (
long j =
long(v->Size()) - 1 ; j >= 0 ; --j)
274 SBlock b(std::static_pointer_cast<Block>((*v)[
size_t(j)]));
275 Rect newChildBox(nr & b->GetAbsoluteBBox());
276 if (newChildBox.GetArea() > 0)
277 b->SetAbsoluteBBox(newChildBox);
302 if (parent.expired())
304 _(
"this is a topmost block. Its bounding box cannot be changed."));
307 _(
"Uninitialized bounding box."));
308 newbox.
Translate(parent.lock()->GetAbsoluteBBox().GetLeft(), parent.lock()->GetAbsoluteBBox().GetTop());
318 if (parent.expired())
321 r.
Translate(-parent.lock()->GetAbsoluteBBox().GetLeft(), -parent.lock()->GetAbsoluteBBox().GetTop());
336 if (child->Find(tree) != child->end())
342 _(
"tree not found."));
356 if (child->Find(tree) != child->end())
360 _(
"tree not found."));
374 if (child->Find(tree) != child->end())
376 SCVector v = std::static_pointer_cast<
const Vector>(child->Get(tree));
381 _(
"tree not found."));
395 if (child->Find(tree) != child->end())
397 SCVector v = std::static_pointer_cast<
const Vector>(child->Get(tree));
402 _(
"tree not found."));
411 void Block::openImage(
void)
417 if (!parent.expired())
419 parent.lock()->openImage();
434 _(
"Cannot open image."));
436 srcRGB = std::dynamic_pointer_cast<
ImageRGB>(src);
437 srcGray = std::dynamic_pointer_cast<
ImageGray>(src);
438 srcBW = std::dynamic_pointer_cast<
ImageBW>(src);
439 bbox =
Rect(0, 0,
int(src->GetWidth()) - 1,
int(src->GetHeight()) - 1);
440 image_is_open =
true;
452 SImageRGB Block::get_srcRGB(
void)
454 if (!parent.expired())
455 return parent.lock()->get_srcRGB();
469 SImageGray Block::get_srcGray(
void)
471 if (!parent.expired())
472 return parent.lock()->get_srcGray();
486 SImageBW Block::get_srcBW(
void)
488 if (!parent.expired())
489 return parent.lock()->get_srcBW();
503 SImageGradient Block::get_srcGradient(
void)
505 if (!parent.expired())
506 return parent.lock()->get_srcGradient();
530 SVector Block::getChildList(
const String &name)
532 if (child->Find(name) == child->end())
533 child->Set(name, std::make_shared<Vector>());
534 return std::static_pointer_cast<
Vector>(child->Get(name));
552 _(
"Uninitialized clipping rectangle."));
553 SBlock nb = create(
self, tree, clip, tree);
554 if (!nb->GetAbsoluteBBox().IsValid())
557 _(
"Clipping rectangle out of bounds."));
559 getChildList(tree)->PushBack(nb);
579 _(
"Uninitialized clipping rectangle."));
580 SBlock nb = create(
self, tree, clip, name);
581 if (!nb->GetAbsoluteBBox().IsValid())
583 throw ExceptionDomain(
StringUTF8(
"SBlock Block::AddChildAbsolute(const String &tree, Rect clip, const String &name): ") +
584 _(
"Clipping rectangle out of bounds."));
586 getChildList(tree)->PushBack(nb);
606 _(
"Uninitialized clipping rectangle."));
607 if (child->Find(tree) == child->end())
609 else if (pos >= getChildList(tree)->Size())
613 SBlock nb = create(
self, tree, clip, tree.
CStr());
614 if (!nb->GetAbsoluteBBox().IsValid())
617 _(
"Clipping rectangle out of bounds."));
619 getChildList(tree)->Insert(nb, pos);
641 _(
"Uninitialized clipping rectangle."));
642 if (child->Find(tree) == child->end())
644 else if (pos >= getChildList(tree)->Size())
648 SBlock nb = create(
self, tree, clip, name);
649 if (!nb->GetAbsoluteBBox().IsValid())
651 throw ExceptionDomain(
StringUTF8(
"SBlock Block::AddChildAbsoluteAt(const String &tree, Rect clip, const String &name, size_t pos): ") +
652 _(
"Clipping rectangle out of bounds."));
654 getChildList(tree)->Insert(nb, pos);
674 _(
"Uninitialized clipping rectangle."));
675 clip.
Translate(bbox.GetLeft(), bbox.GetTop());
676 SBlock nb = create(
self, tree, clip, tree);
677 if (!nb->GetAbsoluteBBox().IsValid())
680 _(
"Clipping rectangle out of bounds."));
682 getChildList(tree)->PushBack(nb);
702 _(
"Uninitialized clipping rectangle."));
703 clip.
Translate(bbox.GetLeft(), bbox.GetTop());
704 SBlock nb = create(
self, tree, clip, name);
705 if (!nb->GetAbsoluteBBox().IsValid())
707 throw ExceptionDomain(
StringUTF8(
"SBlock Block::AddChildRelative(const String &tree, Rect clip, const String &name): ") +
708 _(
"Clipping rectangle out of bounds."));
710 getChildList(tree)->PushBack(nb);
730 _(
"Uninitialized clipping rectangle."));
731 if (child->Find(tree) == child->end())
733 else if (pos >= getChildList(tree)->Size())
737 clip.
Translate(bbox.GetLeft(), bbox.GetTop());
738 SBlock nb = create(
self, tree, clip, tree.
CStr());
739 if (!nb->GetAbsoluteBBox().IsValid())
742 _(
"Clipping rectangle out of bounds."));
744 getChildList(tree)->Insert(nb, pos);
766 _(
"Uninitialized clipping rectangle."));
767 if (child->Find(tree) == child->end())
769 else if (pos >= getChildList(tree)->Size())
773 clip.
Translate(bbox.GetLeft(), bbox.GetTop());
774 SBlock nb = create(
self, tree, clip, name);
775 if (!nb->GetAbsoluteBBox().IsValid())
777 throw ExceptionDomain(
StringUTF8(
"SBlock Block::AddChildRelativeAt(const String &tree, Rect clip, const String &name, size_t pos): ") +
778 _(
"Clipping rectangle out of bounds."));
780 getChildList(tree)->Insert(nb, pos);
802 buffRGB = std::make_shared<ImageRGB>(*get_srcRGB(), bbox);
806 if (!parent.expired())
808 if (parent.lock()->GetRGB())
810 Rect localbbox(bbox.GetLeft() - parent.lock()->GetAbsoluteBBox().GetLeft(),
811 bbox.GetTop() - parent.lock()->GetAbsoluteBBox().GetTop(),
812 bbox.GetRight() - parent.lock()->GetAbsoluteBBox().GetLeft(),
813 bbox.GetBottom() - parent.lock()->GetAbsoluteBBox().GetTop());
814 buffRGB = std::make_shared<ImageRGB>(*parent.lock()->GetRGB(), localbbox);
821 buffRGB = std::make_shared<ImageRGB>(*buffGray);
827 buffRGB = std::make_shared<ImageRGB>(*buffBW);
833 buffRGB = std::make_shared<ImageRGB>(*get_srcGray());
839 buffRGB = std::make_shared<ImageRGB>(*get_srcBW());
869 buffGray = std::make_shared<ImageGray>(*get_srcGray(), bbox);
873 if (!parent.expired())
875 if (parent.lock()->GetGray(create))
877 Rect localbbox(bbox.GetLeft() - parent.lock()->GetAbsoluteBBox().GetLeft(),
878 bbox.GetTop() - parent.lock()->GetAbsoluteBBox().GetTop(),
879 bbox.GetRight() - parent.lock()->GetAbsoluteBBox().GetLeft(),
880 bbox.GetBottom() - parent.lock()->GetAbsoluteBBox().GetTop());
881 buffGray = std::make_shared<ImageGray>(*parent.lock()->GetGray(
false), localbbox);
886 if (buffRGB && create)
892 if (get_srcRGB() && create)
900 buffGray = std::make_shared<ImageGray>(*buffBW);
906 buffGray = std::make_shared<ImageGray>(*get_srcBW());
913 _(
"Cannot access to any source or buffer."));
939 buffBW = std::make_shared<ImageBW>(*get_srcBW(), bbox);
943 if (!parent.expired())
945 if (parent.lock()->GetBW(create))
947 Rect localbbox(bbox.GetLeft() - parent.lock()->GetAbsoluteBBox().GetLeft(),
948 bbox.GetTop() - parent.lock()->GetAbsoluteBBox().GetTop(),
949 bbox.GetRight() - parent.lock()->GetAbsoluteBBox().GetLeft(),
950 bbox.GetBottom() - parent.lock()->GetAbsoluteBBox().GetTop());
951 buffBW = std::make_shared<ImageBW>(*parent.lock()->GetBW(
false), localbbox);
958 SImageGray tmp =
GetGray(
true);
973 _(
"Cannot access to any source or buffer."));
988 std::vector<String> list;
991 list.push_back(it->first);
1010 _(
"No filename given."));
1027 eb.SetAttribute(
"top", bbox.GetTop());
1028 eb.SetAttribute(
"right", bbox.GetRight());
1029 eb.SetAttribute(
"bottom", bbox.GetBottom());
1034 SVector v = std::static_pointer_cast<
Vector>(it->second);
1035 for (
size_t tmp = 0; tmp < v->Size(); tmp++)
1037 std::static_pointer_cast<
Block>(v->At(tmp))->addToXml(el);
1052 eb.SetAttribute(
"top", bbox.GetTop());
1053 eb.SetAttribute(
"right", bbox.GetRight());
1054 eb.SetAttribute(
"bottom", bbox.GetBottom());
1059 SVector v = std::static_pointer_cast<
Vector>(it->second);
1060 for (
size_t tmp = 0; tmp < v->Size(); tmp++)
1062 std::static_pointer_cast<
Block>(v->At(tmp))->addToXml(el);
1087 _(
"No filename given."));
1103 if ((l != bbox.GetLeft()) || (t != bbox.GetTop()) ||
1104 (r != bbox.GetRight()) || (b != bbox.GetBottom()))
1107 _(
"Saved block do not have the same size."));
1117 addTreeFromXml(root);
1134 if (tree.GetName() !=
"BlockTree")
1137 for (
xml::Element block = tree.BeginElement(); block != tree.EndElement(); ++block)
1139 if (block.GetName() !=
"Block")
1141 int l = block.GetAttribute<
int>(
"left",
false);
1142 int t = block.GetAttribute<
int>(
"top",
false);
1143 int b = block.GetAttribute<
int>(
"bottom",
false);
1144 int r = block.GetAttribute<
int>(
"right",
false);
1147 bn = block.GetAttribute<
StringUTF8>(
"blockname");
1148 Rect rec(l, t, r, b);
1151 _(
"Wrong content."));
1153 newblock->addTreeFromXml(block);
1174 if (child->Find(tname) == child->end())
1189 child->Remove(tname);
1205 SImageGradient
Block::GetGradient(
bool create,
double sigma,
size_t diffusemaxiter,
double diffusemaxdiv)
1208 return buffGradient;
1213 grad_diffusemaxiter = diffusemaxiter;
1214 grad_diffusemaxdiv = diffusemaxdiv;
1217 if (get_srcGradient())
1220 buffGradient = std::make_shared<ImageGradient>(*get_srcGradient(), bbox);
1221 buffGradient->SetMinModule(get_srcGradient()->GetMinModule());
1222 return buffGradient;
1233 sigma = double(sw) / 6.0;
1238 if (parent.expired())
1242 diff.Diffuse(diffusemaxiter, diffusemaxdiv);
1244 buffGradient =
MoveShared(diff.MakeImageGradient());
1245 return buffGradient;
1250 WBlock gpar = parent;
1251 while (!gpar.expired())
1253 if (gpar.lock()->GetGradient(
false) && (gpar.lock()->grad_sigma == grad_sigma) && (gpar.lock()->grad_diffusemaxiter == grad_diffusemaxiter) && (gpar.lock()->grad_diffusemaxdiv == grad_diffusemaxdiv))
1255 gpar = gpar.lock()->parent;
1257 if (!gpar.expired())
1260 b.
Translate(-gpar.lock()->GetAbsoluteBBox().GetLeft(),
1261 -gpar.lock()->GetAbsoluteBBox().GetTop());
1262 SImageGradient topgrad(gpar.lock()->GetGradient(
true, sigma, diffusemaxiter, diffusemaxdiv));
1263 buffGradient = std::make_shared<ImageGradient>(*topgrad, b);
1264 buffGradient->SetMinModule(topgrad->GetMinModule());
1266 return buffGradient;
1270 Rect clip =
GetTop().lock()->GetAbsoluteBBox();
1273 clip.
SetTop(
Max(0, bbox.GetTop() - 10));
1276 int offsetx = bbox.GetLeft() - clip.
GetLeft();
1277 int offsety = bbox.GetTop() - clip.
GetTop();
1281 diff.Diffuse(diffusemaxiter, diffusemaxdiv);
1283 auto tmpGradient = diff.MakeImageGradient();
1287 r.
SetRight((
int)(offsetx + bbox.GetWidth() - 1));
1288 r.
SetBottom((
int)(offsety + bbox.GetHeight() - 1));
1289 buffGradient = std::make_shared<ImageGradient>(tmpGradient, r);
1290 buffGradient->SetMinModule(tmpGradient.GetMinModule());
1292 return buffGradient;
1306 if (!parent.expired())
1307 parent.lock()->ReloadImage();
1311 image_is_open =
false;
1315 srcGradient =
nullptr;
1348 SVector l(std::static_pointer_cast<Vector>(p.second));
1370 SVector l(std::static_pointer_cast<Vector>(p.second));
1392 SVector l(std::static_pointer_cast<Vector>(p.second));
1409 buffGradient =
nullptr;
1414 SVector l(std::static_pointer_cast<Vector>(p.second));
1444 if ((
int(img->GetWidth()) != w) || (int(img->GetHeight()) != h))
1447 _(
"Wrong image dimensions."));
1474 if ((
int(img->GetWidth()) != w) || (int(img->GetHeight()) != h))
1477 _(
"Wrong image dimensions."));
1504 if ((
int(img->GetWidth()) != w) || (int(img->GetHeight()) != h))
1507 _(
"Wrong image dimensions."));
1534 if ((
int(img->GetWidth()) != w) || (int(img->GetHeight()) != h))
1537 _(
"Wrong image dimensions."));
1547 void Add(
int a,
int b)
1551 for (
int tmp = 0; tmp < int(inter.size()); ++tmp)
1553 if (inter[tmp].count(a))
1555 inter[tmp].insert(b);
1560 if (inter[tmp].count(b))
1562 inter[tmp].insert(a);
1570 inter.push_back(std::set<int>());
1571 inter.back().insert(a);
1572 inter.back().insert(b);
1576 if (foundwhat == -1)
1578 for (
int tmp = 0; tmp < int(inter.size()); ++tmp)
1582 if (inter[tmp].count(b))
1584 inter[found].insert(inter[tmp].begin(), inter[tmp].end());
1585 inter.erase(inter.begin() + tmp);
1592 for (
int tmp = 0; tmp < int(inter.size()); ++tmp)
1596 if (inter[tmp].count(a))
1598 inter[found].insert(inter[tmp].begin(), inter[tmp].end());
1599 inter.erase(inter.begin() + tmp);
1607 std::vector<std::set<int> > inter;
1612 for (std::set<int> &s : inter)
1614 auto it = s.begin();
1617 for (; it != s.end(); ++it)
1621 std::map<int,int> corresp;
1642 SImageBW bwi =
GetBW(
true);
1645 size_t w = bwi->GetWidth();
1646 size_t h = bwi->GetHeight();
1647 UImageIntGray imap = std::make_unique<ImageIntGray>(w, h, 0);
1653 if (bwi->At(0) == pixel::BWBlack)
1659 for (
size_t x = 1; x < w; ++x)
1661 if (bwi->At(x) == pixel::BWBlack)
1663 int pv = imap->At(x - 1);
1677 for (
size_t y = 1; y < h; ++y)
1681 if (bwi->At(yoffset) == pixel::BWBlack)
1684 size_t c3 = yoffset - w;
1685 int cval = imap->At(c3);
1688 imap->At(yoffset) = cval;
1693 cval = imap->At(c3 + 1);
1696 imap->At(yoffset) = cval;
1701 imap->At(yoffset) = num;
1707 for (
size_t x = 1; x < w - 1; ++x)
1709 size_t offset = x + yoffset;
1710 if (bwi->At(offset) == pixel::BWBlack)
1713 size_t c3 = offset - w;
1714 int cval = imap->At(c3);
1717 imap->At(offset) = cval;
1721 size_t c1 = offset - 1;
1723 cval = imap->At(c1);
1724 int cval4 = imap->At(c4);
1727 imap->At(offset) = cval;
1728 if ((cval4 != 0) && (cval4 != cval))
1729 ir.Add(cval, cval4);
1734 cval = imap->At(c2);
1737 imap->At(offset) = cval;
1738 if ((cval4 != 0) && (cval4 != cval))
1739 ir.Add(cval, cval4);
1745 imap->At(offset) = cval4;
1749 imap->At(offset) = num;
1754 size_t offset = w - 1 + yoffset;
1755 if (bwi->At(offset) == pixel::BWBlack)
1758 size_t c3 = offset - w;
1759 int cval = imap->At(c3);
1762 imap->At(offset) = cval;
1766 size_t c1 = offset - 1;
1767 cval = imap->At(c1);
1770 imap->At(offset) = cval;
1775 cval = imap->At(c2);
1778 imap->At(offset) = cval;
1782 imap->At(offset) = num;
1787 std::map<int, Rect> bboxes;
1791 int v = imap->At(x, y);
1794 auto it = ir.corresp.find(v);
1795 if (it != ir.corresp.end())
1800 if (bboxes.find(v) == bboxes.end())
1803 bboxes.insert(std::make_pair(v,
Rect(
int(x),
int(y),
int(x),
int(y))));
1807 Rect &r = bboxes[v];
1820 for (
const auto &bbox : bboxes)
1822 if (!bbox.second.IsValid())
1829 return std::forward<UImageIntGray>(imap);
1849 "double *mwidth, double *mheight, double *marea) const: ") +
_(
"tree not found."));
1850 long w = 0, h = 0, a = 0;
1854 w += b->GetAbsoluteBBox().GetWidth();
1855 h += b->GetAbsoluteBBox().GetHeight();
1856 a += b->GetAbsoluteBBox().GetArea();
1860 *mwidth = double(w) / tot;
1862 *mheight = double(h) / tot;
1864 *marea = double(a) / tot;
1879 if (child->Find(tree) == child->end())
1881 const SVector v = std::static_pointer_cast<
Vector>(child->Get(tree));
1899 if (child->Find(tree) == child->end())
1901 else if (num >= getChildList(tree)->Size())
1904 return std::static_pointer_cast<
Block>(getChildList(tree)->At(num));
1921 if (child->Find(tree) == child->end())
1925 SCVector v = std::static_pointer_cast<
const Vector>(child->Get(tree));
1926 if (num >= v->Size())
1927 throw ExceptionDomain(
StringUTF8(
"SCBlock Block::GetChild(const String &tree, size_t num) const: ") +
_(
"index out of bounds."));
1929 return std::static_pointer_cast<
const Block>(v->At(num));
1946 if (child->Find(tree) == child->end())
1948 SVector v = std::static_pointer_cast<
Vector>(child->Get(tree));
1949 for (SObject ob : v)
1951 SBlock b(std::static_pointer_cast<Block>(ob));
1952 if (b->GetName() == name)
1971 if (child->Find(tree) == child->end())
1973 SCVector v = std::static_pointer_cast<
const Vector>(child->Get(tree));
1974 for (SCObject ob : v)
1976 SCBlock b(std::static_pointer_cast<const Block>(ob));
1977 if (b->GetName() == name)
1980 throw ExceptionNotFound(
StringUTF8(
"SCBlock Block::GetChild(const String &tree, const String &name) const: ") +
_(
"block not found."));
1997 if (child->Find(tree) == child->end())
1999 _(
"tree not found."));
2001 if (num >= getChildList(tree)->Size())
2003 _(
"index out of bounds."));
2004 SBlock b(std::static_pointer_cast<Block>((*getChildList(tree))[num]));
2005 b->parent = WBlock();
2006 getChildList(tree)->Remove(num);
2036 if (child->Find(tree) == child->end())
2038 _(
"tree not found."));
2040 if (getChildList(tree)->Contains(b))
2042 b->parent = WBlock();
2043 getChildList(tree)->Remove(b);
2047 _(
"block not found."));
2060 if (child->Find(tree) == child->end())
2062 _(
"tree not found."));
2063 SVector lst(getChildList(tree));
2065 [&toremove](
const SObject &b)
2066 {
return toremove.find(std::static_pointer_cast<Block>(b)) != toremove.end(); }
2082 if (child->Find(tree) == child->end())
2085 _(
"tree not found."));
2090 for (Vector::iterator it = getChildList(tree)->begin(); it != getChildList(tree)->end(); ++it)
2092 SBlock b(std::static_pointer_cast<Block>(*it));
2093 if ((b->GetAbsoluteBBox().GetWidth() < int(minw)) && (b->GetAbsoluteBBox().GetHeight() < int(minh)))
2115 if (child->Find(tree) == child->end())
2117 _(
"tree not found."));
2119 for (Vector::iterator it = getChildList(tree)->begin(); it != getChildList(tree)->end(); ++it)
2121 SBlock b(std::static_pointer_cast<Block>(*it));
2122 if ((b->GetAbsoluteBBox().GetWidth() < int(minw)) || (b->GetAbsoluteBBox().GetHeight() < int(minh)))
2140 if (child->Find(tree) == child->end())
2142 _(
"tree not found."));
2144 for (Vector::iterator it = getChildList(tree)->begin(); it != getChildList(tree)->end(); ++it)
2146 SBlock b(std::static_pointer_cast<Block>(*it));
2147 if ((b->GetAbsoluteBBox().GetWidth() > int(maxw)) && (b->GetAbsoluteBBox().GetHeight() > int(maxh)))
2165 if (child->Find(tree) == child->end())
2167 _(
"tree not found."));
2169 for (Vector::iterator it = getChildList(tree)->begin(); it != getChildList(tree)->end(); ++it)
2171 SBlock b(std::static_pointer_cast<Block>(*it));
2172 if ((b->GetAbsoluteBBox().GetWidth() > int(maxw)) || (b->GetAbsoluteBBox().GetHeight() > int(maxh)))
2189 if (child->Find(tree) == child->end())
2191 _(
"tree not found."));
2193 for (Vector::iterator it = getChildList(tree)->begin(); it != getChildList(tree)->end(); ++it)
2195 SBlock b(std::static_pointer_cast<Block>(*it));
2196 if ((b->GetAbsoluteBBox().GetLeft() < int(
GetAbsoluteBBox().GetLeft() + margin)) ||
2198 (b->GetAbsoluteBBox().GetRight() > int(
GetAbsoluteBBox().GetRight() - margin)) ||
2199 (b->GetAbsoluteBBox().GetBottom() > int(
GetAbsoluteBBox().GetBottom() - margin)))
2217 if (child->Find(tree) == child->end())
2219 _(
"tree not found."));
2222 "const String &tree, double ratio): ") +
2223 _(
"ratio is null or negative."));
2225 getChildList(tree)->RemoveIf(
2226 [ratio](
const SObject &b)
2246 if (child->Find(tree) == child->end())
2248 _(
"tree not found."));
2251 "const String &tree, double ratio): ") +
2252 _(
"ratio is null or negative."));
2254 getChildList(tree)->RemoveIf(
2255 [ratio](
const SObject &b)
2281 if (child->Find(tree) == child->end())
2283 _(
"tree not found."));
2285 throw ExceptionDomain(
StringUTF8(
"void Block::MergeChildren(const String &tree, double overlap, ImageIntGray *imap): ") +
2286 _(
"overlap is negative."));
2288 std::map<size_t, std::map<size_t, size_t> > overlaps;
2290 for (
size_t b1 = 0; b1 < vtree->Size(); ++b1)
2292 SBlock cb1(std::static_pointer_cast<Block>((*vtree)[b1]));
2293 Rect bb1(cb1->GetAbsoluteBBox());
2294 double ov1 = bb1.
GetArea() * overlap;
2295 for (
size_t b2 = b1 + 1; b2 < vtree->Size(); ++b2)
2297 SBlock cb2(std::static_pointer_cast<Block>((*vtree)[b2]));
2298 Rect bb2(cb2->GetAbsoluteBBox());
2299 Rect rov = bb1 & bb2;
2303 double ov2 = bb2.GetArea() * overlap;
2304 size_t dist =
Min(
Abs(bb1.GetCenterX() - bb2.GetCenterX()),
Abs(bb1.GetCenterY() - bb2.GetCenterY()));
2305 if ((rova >= ov1) && (rova >= ov2))
2309 overlaps[b2][dist] = b1;
2313 overlaps[b1][dist] = b2;
2317 else if (rova >= ov1)
2319 overlaps[b1][dist] = b2;
2322 else if (rova >= ov2)
2324 overlaps[b2][dist] = b1;
2329 if (overlaps.empty())
2333 std::map<size_t, size_t> change;
2334 for (
auto it = overlaps.begin(); it != overlaps.end(); ++it)
2336 size_t from = it->first;
2337 size_t to = it->second.begin()->second;
2338 auto next = overlaps.find(to);
2339 while (next != overlaps.end())
2341 to = next->second.begin()->second;
2342 next = overlaps.find(to);
2347 std::set<SBlock> toremove;
2348 SVector lst(getChildList(tree));
2349 for (
auto & elem : change)
2351 SBlock bfrom(std::static_pointer_cast<Block>((*vtree)[elem.first]));
2352 SBlock bto(std::static_pointer_cast<Block>((*vtree)[elem.second]));
2353 int f = bfrom->GetName().ToInt();
2354 int t = bto->GetName().ToInt();
2356 toremove.insert(std::static_pointer_cast<Block>((*lst)[elem.first]));
2357 bto->SetAbsoluteBBox(bto->GetAbsoluteBBox() | bfrom->GetAbsoluteBBox());
2360 for (
const Point2DInt &p : bfrom->GetAbsoluteBBox())
2362 if (imap->
At(p.X, p.Y) == f)
2363 imap->
At(p.X, p.Y) = t;
2390 "const String &tree, size_t index1, size_t index1, "
2391 "ImageIntGray *imap): ") +
_(
"Tree not found."));
2393 if (index1 == index2)
2396 "const String &tree, size_t index1, size_t index1, "
2397 "ImageIntGray *imap): ") +
_(
"Identical indexes."));
2402 "const String &tree, size_t index1, size_t index1, "
2403 "ImageIntGray *imap): ") +
_(
"Index out of bounds."));
2409 v1 = (int)
GetChild(tree, index1)->GetName().ToInt();
2410 v2 = (int)
GetChild(tree, index2)->GetName().ToInt();
2412 it !=
GetChild(tree, index2)->GetAbsoluteBBox().end(); ++it)
2414 if (imap->
At(it->X, it->Y) == v2)
2415 imap->
At(it->X, it->Y) = v1;
2421 const std::vector<String> child2TreeNames =
GetChild(tree, index2)->GetTreeNames();
2422 for (
const auto & child2TreeName : child2TreeNames)
2423 for (
size_t i = 0 ; i <
GetChild(tree, index2)->GetNbChildren(child2TreeName) ; ++i)
2425 SBlock child =
GetChild(tree, index2)->GetChild(child2TreeName, i);
2426 child->parent =
GetChild(tree, index1);
2427 GetChild(tree, index1)->getChildList(child2TreeName)->PushBack(child);
2451 "const String &tree, Block &sb1, Block &sb2, "
2452 "ImageIntGray *imap): ") +
_(
"Tree not found."));
2455 int index1 = -1, index2 = -1;
2458 if (
GetChild(tree, tmp).get() == &sb1)
2460 if (
GetChild(tree, tmp).get() == &sb2)
2462 if ((index1 != -1) && (index2 != -1))
2465 if ((index1 == -1) || (index2 == -1))
2468 "const String &tree, Block &sb1, Block &sb2, "
2469 "ImageIntGray *imap): ") +
_(
"Cannot find subblock."));
2482 if (parent.expired())
2485 return parent.lock()->GetTop();
2497 if (parent.expired())
2499 if (parent.lock().get() == &b)
2501 return parent.lock()->IsParent(b);
2517 if (child->Find(tree) == child->end())
2519 _(
"tree not found."));
2520 const SVector v = std::static_pointer_cast<
Vector>(child->Get(tree));
2521 if (num >= v->Size())
2523 _(
"index out of bounds."));
2524 const SBlock b(std::static_pointer_cast<Block>(v->At(num)));
2525 Rect r = b->GetAbsoluteBBox();
2526 r.
Translate(-bbox.GetLeft(), -bbox.GetTop());
2540 if (!b || !b->IsParent(*
this))
2542 _(
"null block or block is not a child."));
2543 Rect r = b->GetAbsoluteBBox();
2544 r.
Translate(-bbox.GetLeft(), -bbox.GetTop());
2560 if (child->Find(tree) == child->end())
2562 _(
"tree not found."));
2563 const SVector v = std::static_pointer_cast<
Vector>(child->Get(tree));
2564 if (num >= v->Size())
2566 _(
"index out of bounds."));
2580 if (!b || !b->IsParent(*
this))
2582 _(
"null block or block is not a child."));
2602 if (child->Find(tree) == child->end())
2604 _(
"tree not found."));
2605 SVector v = std::static_pointer_cast<
Vector>(child->Get(tree));
2606 if (num >= v->Size())
2607 throw ExceptionDomain(
StringUTF8(
"Block::masked_pixel_iterator Block::MaskedPixelBegin(const String &tree, size_t num, pixel::BW mask_value): ") +
2608 _(
"index out of bounds."));
2609 SBlock b(std::static_pointer_cast<Block>(v->At(num)));
2610 Rect r = b->GetAbsoluteBBox();
2611 r.
Translate(-bbox.GetLeft(), -bbox.GetTop());
2629 if (!b || !b->IsParent(*
this))
2631 _(
"tree not found."));
2632 Rect r = b->GetAbsoluteBBox();
2633 r.
Translate(-bbox.GetLeft(), -bbox.GetTop());
2651 if (child->Find(tree) == child->end())
2653 _(
"tree not found."));
2654 SCVector v = std::static_pointer_cast<
Vector>(child->Get(tree));
2655 if (num >= v->Size())
2656 throw ExceptionDomain(
StringUTF8(
"Block::masked_pixel_iterator Block::MaskedPixelEnd(const String &tree, size_t num, pixel::BW mask_value): ") +
2657 _(
"index out of bounds."));
2673 if (!b || !b->IsParent(*
this))
2675 _(
"null block or block is not a child."));
2696 +
_(
"Tree not found."));
2737 +
_(
"Wrong direction."));
2742 void Block::refreshSources()
2744 if (!parent.expired())
2746 srcRGB = parent.lock()->srcRGB;
2747 srcGray = parent.lock()->srcGray;
2748 srcBW = parent.lock()->srcBW;
2749 srcGradient = parent.lock()->srcGradient;
2753 SVector l(std::static_pointer_cast<Vector>(p.second));
2756 std::static_pointer_cast<
Block>(b)->refreshSources();
block_iterator BlockBegin(const String &tree)
Returns an iterator on the first block of a tree.
bool Append(const Path &fname)
Appends child trees from a file.
void Save()
Saves the child trees into the default file.
Abstract class for images.
SBlock AddChildRelativeAt(const String &tree, Rect clip, size_t pos)
Adds a child to current block.
SVector GetTree(const String &name)
Returns a list of children. Can be used with CRN_FOREACH.
void FilterMaxOr(const String &tree, size_t maxw, size_t maxh)
Filters a child tree.
void FilterHeightRatio(const String &tree, double ratio)
Filters a child tree.
void FlushGray(bool recursive=false)
Frees the local gray buffer.
Comment PushBackComment(const StringUTF8 &text)
Adds a comment at the end of the children list.
ImageBW MakeImageBW(const ImageGray &img)
SBlock AddChildRelative(const String &tree, Rect clip)
Adds a child to current block.
Iterator on the blocks of a child tree.
void RemoveChildren(const String &tree, const std::set< SBlock > &toremove)
Removes a set of blocks from a child tree.
void FilterBorders(const String &tree, size_t margin)
Filters a child tree.
complex base abstract class
block_iterator BlockEnd(const String &tree)
Returns an iterator after the last block of a tree.
void FilterMinOr(const String &tree, size_t minw, size_t minh)
Filters a child tree.
std::vector< pixel_type >::reference At(size_t x, size_t y) noexcept
Returns a reference to a pixel.
void SetAbsoluteBBox(const Rect &newbox)
Sets the absolute bounding box of the block.
std::vector< String > GetTreeNames() const
Gets the list of the tree names.
const T & Max(const T &a, const T &b)
Returns the max of two values.
WBlock GetTop()
Gets a reference to the topmost parent of the block.
Image< pixel::RGB< uint8_t >> ImageRGB
Color image class.
const char * CStr() const
Conversion to UTF8 cstring.
int GetBottom() const
Returns the bottommost coordinate.
Element GetRoot()
Gets the first element.
void MergeSiblings(const String &tree, size_t index1, size_t index2, ImageIntGray *imap=nullptr)
Merges two subblocks.
Direction
An enumeration of directions.
Element PushBackElement(const StringUTF8 &name)
Adds an element at the end of the children list.
virtual ~Block() override
Destructor.
void FilterMinAnd(const String &tree, size_t minw, size_t minh)
Filters a child tree.
bool IsNotEmpty() const noexcept
Checks if the string is not empty.
const String & GetName() const
Returns the name of the object.
Element BeginElement()
Gets the first child element.
#define FOREACHPIXEL(x, y, img)
Convenience macro to sweep an image.
int GetTop() const
Returns the topmost coordinate.
void serialize_internal_data(xml::Element &el) const
Dumps some internal data to an XML element.
ImageGray MakeImageGray(const ImageRGB &img)
int GetLeft() const
Returns the leftmost coordinate.
Rect::iterator pixel_iterator
Iterator on the pixels the block.
bool IsParent(const Block &b) const
Checks if a block is a parent of current.
static std::mutex & GetMutex(const Path &fname)
Gets the mutex associated to a file.
A UTF32 character string class.
int SetBottom(int endY) noexcept
Changes the bottommost coordinate.
SImageBW GetBW(bool create=true)
Returns a pointer to the local b&w buffer.
pixel_iterator PixelEnd(const String &tree, size_t num) const
Returns an iterator after the last pixel of the block.
bool MergeChildren(const String &tree, double overlap, ImageIntGray *imap=nullptr)
Merges overlapping children in a tree.
void SubstituteGradient(const SImageGradient &img)
Substitutes the Gradient buffer with a new one.
SImageGray GetGray(bool create=true)
Returns a pointer to the local gray buffer.
static SBlock New(const SImage &src, const String &nam=U"")
Top block creator.
static Differential NewGaussian(const ImageRGB &src, RGBProjection proj, double sigma)
Convolution with Gaussian derivatives.
const char * CStr() const noexcept
Conversion to UTF8 cstring.
const Rect & GetAbsoluteBBox() const noexcept
Gets the absolute bounding box of the block.
A convenience class for file paths.
masked_pixel_iterator MaskedPixelBegin(const String &tree, size_t num, pixel::BW mask_value=pixel::BWBlack)
Returns a masked iterator on the first pixel of the block.
unsigned int GetArea() const noexcept
Returns the area of the rectangle.
void SetAttribute(const StringUTF8 &name, const StringUTF8 &value)
Sets the value of an attribute.
std::map< String, SObject >::const_iterator const_iterator
const_iterator on the contents of the container
SBlock AddChildAbsoluteAt(const String &tree, Rect clip, size_t pos)
Adds a child to current block.
void SortTree(const String &name, Direction direction)
Sorts a child tree.
void Save(const Path &fname)
Saves to file.
void FlushBW(bool recursive=false)
Frees the local b&w buffer.
bool IsValid() const noexcept
Returns whether the rect is valid.
Rect GetRelativeBBox() const
Gets the relative bounding box of the block.
iterator begin() const
Returns an iterator to the first point of the rectangle.
SImageGradient GetGradient(bool create=true, double sigma=-1, size_t diffusemaxiter=0, double diffusemaxdiv=std::numeric_limits< double >::max())
Returns a pointer to the local gradient buffer.
T GetAttribute(const StringUTF8 &name, bool silent=true) const
Gets an attribute.
Gradient image in polar form.
const Path & GetFilename() const noexcept
Returns the file name of the object.
SBlock GetChild(const String &tree, size_t num)
Gets a block of a child tree.
void SubstituteBW(const SImageBW &img)
Substitutes the BW buffer with a new one.
void RemoveChild(const String &tree, size_t num)
Removes a block of a child tree.
void Translate(int x, int y)
Translates the rectangle.
int GetHeight() const
Returns the height of the rectangle.
void setFilename(const Path &fname)
Overwrites the filename.
void Abs(Image< T > &img, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr) noexcept
Replaces each pixel by its absolute value.
UImage NewImageFromFile(const Path &fname)
Loads an image from a file.
void FlushGradient(bool recursive=false)
Frees the local gradient buffer.
const T & Min(const T &a, const T &b)
Returns the min of two values.
void FilterMaxAnd(const String &tree, size_t maxw, size_t maxh)
Filters a child tree.
void SetName(const String &s)
Sets the name of the object.
void GetTreeMeans(const String &tree, double *mwidth, double *mheight, double *marea) const
Returns the mean width, height and area of the subblocks.
int SetRight(int endX) noexcept
Changes the rightmost coordinate.
bool HasTree(const String &tname) const
Checks if a child tree exists.
UImageIntGray ExtractCC(const String &tree)
Creates a child tree with connected components.
int SetTop(int begY) noexcept
Changes the topmost coordinate.
std::shared_ptr< T > MoveShared(T &&v)
int GetWidth() const
Returns the width of the rectangle.
Path & ToLocal()
Converts the path to the local format.
std::pair< const crn::String, SObject > pair
A (key, value) pair.
void FlushRGB(bool recursive=false)
Frees the local RGB buffer.
static bool Access(const Path &name, int mode)
Checks rights on a file.
SImageRGB GetRGB()
Returns a pointer to the local RGB buffer.
void RemoveTree(const String &tname)
Deletes a child tree.
size_t StrokesWidth(const Image< T > &img, size_t maxval=50, size_t defaultval=0, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr)
std::shared_ptr< ImageBase > SImage
SBlock AddChildAbsolute(const String &tree, Rect clip)
Adds a child to current block.
A character string class.
void SubstituteRGB(const SImageRGB &img)
Substitutes the RGB buffer with a new one.
size_t GetNbChildren(const String &tree) const
Gets the number of blocks in a child tree.
void ReloadImage()
Reloads the image.
Iterator on the pixels the block with BW buffer as mask.
masked_pixel_iterator MaskedPixelEnd(const String &tree, size_t num, pixel::BW mask_value=pixel::BWBlack)
Returns a masked iterator on the first pixel of the block.
const Iterator on the blocks of a child tree
void FilterWidthRatio(const String &tree, double ratio)
Filters a child tree.
int GetRight() const
Returns the rightmost coordinate.
pixel_iterator PixelBegin(const String &tree, size_t num) const
Returns an iterator on the first pixel of the block.
Element PushBackElement(const StringUTF8 &name)
Adds an element at the end of the children list.
Block(const Block &)=delete
void SubstituteGray(const SImageGray &img)
Substitutes the Gray buffer with a new one.
Element EndElement()
Gets a null node.
size_t Size() const noexcept
Returns the number of data objects in the vector.
void SetRelativeBBox(Rect newbox)
Sets the absolute bounding box of the block.
void deserialize_internal_data(xml::Element &el)
Initializes some internal data from an XML element.
Invalid argument error (e.g.: nullptr pointer)
int SetLeft(int begX) noexcept
Changes the leftmost coordinate.
An item was not found in a container.
void FlushAll(bool recursive=false)
Frees the local buffers.