Krita Source Code Documentation
Loading...
Searching...
No Matches
KisWatershedWorker::Private Struct Reference

Public Member Functions

void calcNumGroupMaps ()
 
QVector< GroupLevelPair > calculateConflictingPairs ()
 
void cleanupForeignEdgeGroups (qreal cleanUpAmount)
 
void dumpGroupInfo (qint32 groupIndex, quint8 levelIndex)
 
void dumpGroupMaps ()
 
void initializeQueueFromGroupMap (const QRect &rc)
 
 Private ()
 
void processQueue (qint32 _backgroundGroupId)
 
QVector< TaskPoint > tryRemoveConflictingPlane (qint32 group, quint8 level)
 
ALWAYS_INLINE void updateGroupLastDistance (FillGroup::LevelData &levelData, int distance)
 
void updateNarrowRegionMetrics ()
 
ALWAYS_INLINE void visitNeighbour (const QPoint &currPt, const QPoint &prevPt, quint8 fromDirection, int prevDistance, quint8 prevLevel, qint32 prevGroupId, FillGroup &prevGroup, FillGroup::LevelData &prevLevelData, qint32 prevPrevGroupId, FillGroup &prevPrevGroup, bool statsOnly=false)
 
void writeColoring ()
 

Public Attributes

int backgroundGroupColor = -1
 
qint32 backgroundGroupId = 0
 
QRect boundingRect
 
KisPaintDeviceSP dstDevice
 
KisRandomAccessorSP groupIt
 
QVector< FillGroup > groups
 
KisPaintDeviceSP groupsMap
 
KisPaintDeviceSP heightMap
 
QVector< KeyStrokekeyStrokes
 
KisRandomConstAccessorSP levelIt
 
quint64 numFilledPixels = 0
 
CompareTaskPoints pointsComparator
 
PointsPriorityQueue pointsQueue
 
KoUpdaterprogressUpdater = 0
 
bool recolorMode = false
 
quint64 totalPixelsToFill = 0
 

Detailed Description

Definition at line 195 of file KisWatershedWorker.cpp.

Constructor & Destructor Documentation

◆ Private()

KisWatershedWorker::Private::Private ( )
inline

Definition at line 197 of file KisWatershedWorker.cpp.

Member Function Documentation

◆ calcNumGroupMaps()

void KisWatershedWorker::Private::calcNumGroupMaps ( )

Definition at line 957 of file KisWatershedWorker.cpp.

958{
961
962 QSet<QPair<qint32, quint8>> groups;
963
964 while (groupIt.nextPixel() && levelIt.nextPixel()) {
965
966 const qint32 group = *reinterpret_cast<const qint32*>(groupIt.rawDataConst());
967 const quint8 level = *reinterpret_cast<const quint8*>(levelIt.rawDataConst());
968
969 groups.insert(qMakePair(group, level));
970 }
971
972 for (auto it = groups.begin(); it != groups.end(); ++it) {
973 dumpGroupInfo(it->first, it->second);
974 }
975
976 ENTER_FUNCTION() << ppVar(groups.size());
977}
#define ENTER_FUNCTION()
Definition kis_debug.h:178
#define ppVar(var)
Definition kis_debug.h:155
KisRandomConstAccessorSP levelIt
void dumpGroupInfo(qint32 groupIndex, quint8 levelIndex)

References ENTER_FUNCTION, KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixel(), ppVar, and KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawDataConst().

◆ calculateConflictingPairs()

QVector< GroupLevelPair > KisWatershedWorker::Private::calculateConflictingPairs ( )

Definition at line 778 of file KisWatershedWorker.cpp.

779{
781
782
783 for (qint32 i = 0; i < groups.size(); i++) {
784 FillGroup &group = groups[i];
785
786 for (auto levelIt = group.levels.begin(); levelIt != group.levels.end(); ++levelIt) {
787 FillGroup::LevelData &l = levelIt.value();
788
789 for (auto conflictIt = l.conflictWithGroup.begin(); conflictIt != l.conflictWithGroup.end(); ++conflictIt) {
790 if (!conflictIt->empty()) {
791 result.append(GroupLevelPair(i, levelIt.key()));
792 break;
793 }
794 }
795 }
796 }
797
798 return result;
799}

◆ cleanupForeignEdgeGroups()

void KisWatershedWorker::Private::cleanupForeignEdgeGroups ( qreal cleanUpAmount)

Definition at line 806 of file KisWatershedWorker.cpp.

807{
808 KIS_SAFE_ASSERT_RECOVER_NOOP(cleanUpAmount > 0.0);
809
810 // convert into the threshold range [0.05...0.5]
811 const qreal foreignEdgePortionThreshold = 0.05 + 0.45 * (1.0 - qBound(0.0, cleanUpAmount, 1.0));
812
814
815 // sort the pairs by the total edge size
816 QMap<qreal, GroupLevelPair> sortedPairs;
817 Q_FOREACH (const GroupLevelPair &pair, conflicts) {
818 const qint32 groupIndex = pair.first;
819 const quint8 levelIndex = pair.second;
820 FillGroup::LevelData &level = groups[groupIndex].levels[levelIndex];
821
822 sortedPairs.insert(level.totalEdgeSize(), pair);
823 }
824
825 // remove sequentially from the smallest to the biggest
826 for (auto pairIt = sortedPairs.begin(); pairIt != sortedPairs.end(); ++pairIt) {
827 const qint32 groupIndex = pairIt->first;
828 const quint8 levelIndex = pairIt->second;
829 FillGroup::LevelData &level = groups[groupIndex].levels[levelIndex];
830
831 const int thisLength = pairIt.key();
832 const qreal thisForeignPortion = qreal(level.foreignEdgeSize) / thisLength;
833
834 using namespace boost::accumulators;
835 accumulator_set<int, stats<tag::count, tag::mean, tag::min>> lengthStats;
836
837 for (auto it = level.conflictWithGroup.begin(); it != level.conflictWithGroup.end(); ++it) {
838 const FillGroup::LevelData &otherLevel = groups[it.key()].levels[levelIndex];
839 lengthStats(otherLevel.totalEdgeSize());
840 }
841
842 KIS_SAFE_ASSERT_RECOVER_BREAK(count(lengthStats));
843
844 const qreal minMetric = min(lengthStats) / qreal(thisLength);
845 const qreal meanMetric = mean(lengthStats) / qreal(thisLength);
846
847// qDebug() << "G" << groupIndex
848// << "L" << levelIndex
849// << "con" << level.conflictWithGroup.size()
850// << "FRP" << thisForeignPortion
851// << "S" << level.numFilledPixels
852// << ppVar(thisLength)
853// << ppVar(min(lengthStats))
854// << ppVar(mean(lengthStats))
855// << ppVar(minMetric)
856// << ppVar(meanMetric);
857
858 if (!(thisForeignPortion > foreignEdgePortionThreshold)) continue;
859
860 if (minMetric > 1.0 && meanMetric > 1.2) {
861// qDebug() << " * removing...";
862
863 QVector<TaskPoint> taskPoints =
864 tryRemoveConflictingPlane(groupIndex, levelIndex);
865
866 if (!taskPoints.isEmpty()) {
867 // dump before
868 // dumpGroupInfo(groupIndex, levelIndex);
869
870 Q_FOREACH (const TaskPoint &pt, taskPoints) {
871 pointsQueue.push(pt);
872 }
873 processQueue(groupIndex);
874
875 // dump after: should become empty!
876 // dumpGroupInfo(groupIndex, levelIndex);
877
878 // the areas might be disjoint, so that removing one "conflicting"
879 // part will not remove the whole group+level pair
880
881 // KIS_SAFE_ASSERT_RECOVER_NOOP(level.totalEdgeSize() == 0);
882 }
883
884 //dumpGroupMaps();
885 //calcNumGroupMaps();
886
887 }
888 }
889
890}
#define KIS_SAFE_ASSERT_RECOVER_BREAK(cond)
Definition kis_assert.h:127
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
T min(T a, T b, T c)
QVector< GroupLevelPair > calculateConflictingPairs()
void processQueue(qint32 _backgroundGroupId)
QVector< TaskPoint > tryRemoveConflictingPlane(qint32 group, quint8 level)

References KIS_SAFE_ASSERT_RECOVER_BREAK, and KIS_SAFE_ASSERT_RECOVER_NOOP.

◆ dumpGroupInfo()

void KisWatershedWorker::Private::dumpGroupInfo ( qint32 groupIndex,
quint8 levelIndex )

Definition at line 979 of file KisWatershedWorker.cpp.

980{
981 FillGroup::LevelData &level = groups[groupIndex].levels[levelIndex];
982
983 qDebug() << "G" << groupIndex << "L" << levelIndex << "CI" << this->groups[groupIndex].colorIndex;
984 qDebug() << " P" << level.positiveEdgeSize;
985 qDebug() << " N" << level.negativeEdgeSize;
986 qDebug() << " F" << level.foreignEdgeSize;
987 qDebug() << " A" << level.allyEdgeSize;
988 qDebug() << " (S)" << level.numFilledPixels;
989
990 auto &c = level.conflictWithGroup;
991
992 for (auto cIt = c.begin(); cIt != c.end(); ++cIt) {
993 qDebug() << " C" << cIt.key() << cIt.value().size();
994 }
995}

◆ dumpGroupMaps()

void KisWatershedWorker::Private::dumpGroupMaps ( )

Definition at line 892 of file KisWatershedWorker.cpp.

893{
899
902 KisSequentialIterator dstGroupIt(groupDevice, boundingRect);
903 KisSequentialIterator dstColorIt(colorDevice, boundingRect);
904 KisSequentialIterator dstPedgeIt(pedgeDevice, boundingRect);
905 KisSequentialIterator dstNedgeIt(nedgeDevice, boundingRect);
906 KisSequentialIterator dstFedgeIt(fedgeDevice, boundingRect);
907
908
909 QVector<KoColor> colors;
910 for (auto it = keyStrokes.begin(); it != keyStrokes.end(); ++it) {
911 KoColor color = it->color;
912 color.convertTo(colorDevice->colorSpace());
913 colors << color;
914 }
915 const int colorPixelSize = colorDevice->pixelSize();
916
917
918
919 while (dstGroupIt.nextPixel() &&
920 heightIt.nextPixel() &&
921 srcIt.nextPixel() &&
922 dstColorIt.nextPixel() &&
923 dstPedgeIt.nextPixel() &&
924 dstNedgeIt.nextPixel() &&
925 dstFedgeIt.nextPixel()) {
926
927 const qint32 *srcPtr = reinterpret_cast<const qint32*>(srcIt.rawDataConst());
928
929 *dstGroupIt.rawData() = quint8(*srcPtr);
930 memcpy(dstColorIt.rawData(), colors[groups[*srcPtr].colorIndex].data(), colorPixelSize);
931
932 quint8 level = *heightIt.rawDataConst();
933
934 if (groups[*srcPtr].levels.contains(level)) {
935 const FillGroup::LevelData &l = groups[*srcPtr].levels[level];
936
937 const int edgeLength = l.totalEdgeSize();
938
939 *dstPedgeIt.rawData() = 255.0 * qreal(l.positiveEdgeSize) / (edgeLength);
940 *dstNedgeIt.rawData() = 255.0 * qreal(l.negativeEdgeSize) / (edgeLength);
941 *dstFedgeIt.rawData() = 255.0 * qreal(l.foreignEdgeSize) / (edgeLength);
942 } else {
943 *dstPedgeIt.rawData() = 0;
944 *dstNedgeIt.rawData() = 0;
945 *dstFedgeIt.rawData() = 0;
946 }
947 }
948
949
950 KIS_DUMP_DEVICE_2(groupDevice, boundingRect, "01_groupMap", "dd");
951 KIS_DUMP_DEVICE_2(colorDevice, boundingRect, "02_colorMap", "dd");
952 KIS_DUMP_DEVICE_2(pedgeDevice, boundingRect, "03_pedgeMap", "dd");
953 KIS_DUMP_DEVICE_2(nedgeDevice, boundingRect, "04_nedgeMap", "dd");
954 KIS_DUMP_DEVICE_2(fedgeDevice, boundingRect, "05_fedgeMap", "dd");
955}
quint32 pixelSize() const
const KoColorSpace * colorSpace() const
void convertTo(const KoColorSpace *cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
Definition KoColor.cpp:136
#define KIS_DUMP_DEVICE_2(device, rc, suffix, prefix)
static KoColorSpaceRegistry * instance()

References KisPaintDevice::colorSpace(), KoColor::convertTo(), KoColorSpaceRegistry::instance(), KIS_DUMP_DEVICE_2, KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixel(), KisPaintDevice::pixelSize(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawData(), and KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawDataConst().

◆ initializeQueueFromGroupMap()

void KisWatershedWorker::Private::initializeQueueFromGroupMap ( const QRect & rc)

Definition at line 373 of file KisWatershedWorker.cpp.

374{
375 KisSequentialIterator groupMapIt(groupsMap, rc);
376 KisSequentialConstIterator heightMapIt(heightMap, rc);
377
378 while (groupMapIt.nextPixel() &&
379 heightMapIt.nextPixel()) {
380
381 qint32 *groupPtr = reinterpret_cast<qint32*>(groupMapIt.rawData());
382 const quint8 *heightPtr = heightMapIt.rawDataConst();
383
384 if (*groupPtr > 0) {
385 TaskPoint pt;
386 pt.x = groupMapIt.x();
387 pt.y = groupMapIt.y();
388 pt.group = *groupPtr;
389 pt.level = *heightPtr;
390
391 pointsQueue.push(pt);
392
393 // we must clear the pixel to make sure foreign metric is calculated correctly
394 *groupPtr = 0;
395 }
396
397 }
398}

References groupsMap, heightMap, KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixel(), pointsQueue, KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawData(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawDataConst(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::x(), and KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::y().

◆ processQueue()

void KisWatershedWorker::Private::processQueue ( qint32 _backgroundGroupId)

Definition at line 623 of file KisWatershedWorker.cpp.

624{
625 QElapsedTimer tt; tt.start();
626
627
628 // TODO: lazy initialization of the iterator's position
629 // TODO: reuse iterators if possible!
632 backgroundGroupId = _backgroundGroupId;
635
636 totalPixelsToFill = qint64(boundingRect.width()) * boundingRect.height();
637 numFilledPixels = 0;
638 const int progressReportingMask = (1 << 18) - 1; // report every 512x512 patch
639
640
641 if (recolorMode) {
643 }
644
645 while (!pointsQueue.empty()) {
646 TaskPoint pt = pointsQueue.top();
647 pointsQueue.pop();
648
649 groupIt->moveTo(pt.x, pt.y);
650 qint32 *groupPtr = reinterpret_cast<qint32*>(groupIt->rawData());
651
652 const qint32 prevGroupId = *groupPtr;
653 FillGroup &prevGroup = groups[prevGroupId];
654
655 if (prevGroupId == backgroundGroupId ||
656 (recolorMode &&
657 prevGroup.colorIndex == backgroundGroupColor)) {
658
659 FillGroup &currGroup = groups[pt.group];
660 FillGroup::LevelData &currLevelData = currGroup.levels[pt.level];
661 currLevelData.numFilledPixels++;
662
663 if (prevGroupId > 0) {
664 FillGroup::LevelData &prevLevelData = prevGroup.levels[pt.level];
665 prevLevelData.numFilledPixels--;
666 } else {
668 }
669
670 const NeighbourStaticOffset *offsets = staticOffsets[pt.prevDirection];
671 const QPoint currPt(pt.x, pt.y);
672
673 for (int i = 0; i < 4; i++) {
674 const NeighbourStaticOffset &offset = offsets[i];
675
676 const QPoint nextPt = currPt + offset.offset;
677 visitNeighbour(nextPt, currPt,
678 offset.from, pt.distance, pt.level,
679 pt.group, currGroup, currLevelData,
680 prevGroupId, prevGroup,
681 offset.statsOnly);
682 }
683
684 *groupPtr = pt.group;
685
686 if (progressUpdater && !(numFilledPixels & progressReportingMask)) {
687 const int progressPercent =
688 qBound(0, qRound(100.0 * numFilledPixels / totalPixelsToFill), 100);
689 progressUpdater->setProgress(progressPercent);
691 break;
692 }
693
694 }
695
696 } else {
697 // nothing to do?
698 }
699
700 }
701
702 // cleanup iterators
703 groupIt.clear();
704 levelIt.clear();
707 recolorMode = false;
708
709// ENTER_FUNCTION() << ppVar(tt.elapsed());
710}
virtual quint8 * rawData()=0
KisRandomConstAccessorSP createRandomConstAccessorNG() const
KisRandomAccessorSP createRandomAccessorNG()
virtual void moveTo(qint32 x, qint32 y)=0
bool interrupted() const
Definition KoUpdater.cpp:54
void setProgress(int percent)
Definition KoUpdater.cpp:38
ALWAYS_INLINE void visitNeighbour(const QPoint &currPt, const QPoint &prevPt, quint8 fromDirection, int prevDistance, quint8 prevLevel, qint32 prevGroupId, FillGroup &prevGroup, FillGroup::LevelData &prevLevelData, qint32 prevPrevGroupId, FillGroup &prevPrevGroup, bool statsOnly=false)

References KisPaintDevice::createRandomConstAccessorNG().

◆ tryRemoveConflictingPlane()

QVector< TaskPoint > KisWatershedWorker::Private::tryRemoveConflictingPlane ( qint32 group,
quint8 level )

Definition at line 737 of file KisWatershedWorker.cpp.

738{
739 QVector<TaskPoint> result;
740
741 FillGroup &g = groups[group];
742 FillGroup::LevelData &l = g.levels[level];
743
744 for (auto conflictIt = l.conflictWithGroup.begin(); conflictIt != l.conflictWithGroup.end(); ++conflictIt) {
745
746 std::vector<QPoint> uniquePoints;
747 std::unique_copy(conflictIt->begin(), conflictIt->end(), std::back_inserter(uniquePoints));
748
749 for (auto pointIt = uniquePoints.begin(); pointIt != uniquePoints.end(); ++pointIt) {
750 TaskPoint pt;
751 pt.x = pointIt->x();
752 pt.y = pointIt->y();
753 pt.group = conflictIt.key();
754 pt.level = level;
755
756 result.append(pt);
757 // no writing to the group map!
758 }
759 }
760
761 return result;
762}

◆ updateGroupLastDistance()

ALWAYS_INLINE void KisWatershedWorker::Private::updateGroupLastDistance ( FillGroup::LevelData & levelData,
int distance )

◆ updateNarrowRegionMetrics()

void KisWatershedWorker::Private::updateNarrowRegionMetrics ( )

Definition at line 764 of file KisWatershedWorker.cpp.

765{
766 for (qint32 i = 0; i < groups.size(); i++) {
767 FillGroup &group = groups[i];
768
769 for (auto levelIt = group.levels.begin(); levelIt != group.levels.end(); ++levelIt) {
770 FillGroup::LevelData &l = levelIt.value();
771
772 const qreal areaToPerimeterRatio = qreal(l.numFilledPixels) / l.totalEdgeSize();
773 l.narrowRegion = areaToPerimeterRatio < 2.0;
774 }
775 }
776}

◆ visitNeighbour()

void KisWatershedWorker::Private::visitNeighbour ( const QPoint & currPt,
const QPoint & prevPt,
quint8 fromDirection,
int prevDistance,
quint8 prevLevel,
qint32 prevGroupId,
FillGroup & prevGroup,
FillGroup::LevelData & prevLevelData,
qint32 prevPrevGroupId,
FillGroup & prevPrevGroup,
bool statsOnly = false )

Definition at line 487 of file KisWatershedWorker.cpp.

492{
493 if (!boundingRect.contains(currPt)) {
494 prevLevelData.positiveEdgeSize++;
495
496 if (prevPrevGroupId > 0) {
497 FillGroup::LevelData &prevPrevLevelData = prevPrevGroup.levels[prevLevel];
498 prevPrevLevelData.positiveEdgeSize--;
499 }
500 return;
501 }
502
504
505 groupIt->moveTo(currPt.x(), currPt.y());
506 levelIt->moveTo(currPt.x(), currPt.y());
507
508 const qint32 currGroupId = *reinterpret_cast<const qint32*>(groupIt->rawDataConst());
509 const quint8 newLevel = *levelIt->rawDataConst();
510
511 FillGroup &currGroup = groups[currGroupId];
512 FillGroup::LevelData &currLevelData = currGroup.levels[newLevel];
513
514 const bool needsAddTaskPoint =
515 !currGroupId ||
516 (recolorMode &&
517 ((newLevel == prevLevel &&
518 currGroupId == backgroundGroupId) ||
519 (newLevel >= prevLevel &&
520 currGroup.colorIndex == backgroundGroupColor &&
521 currLevelData.narrowRegion)));
522
523 if (needsAddTaskPoint && !statsOnly) {
524 TaskPoint pt;
525 pt.x = currPt.x();
526 pt.y = currPt.y();
527 pt.group = prevGroupId;
528 pt.level = newLevel;
529 pt.distance = newLevel == prevLevel ? prevDistance + 1 : 0;
530 pt.prevDirection = fromDirection;
531
532 pointsQueue.push(pt);
533 }
534
535 // we can never clear the pixel!
536 KIS_SAFE_ASSERT_RECOVER_RETURN(prevGroupId > 0);
537 KIS_SAFE_ASSERT_RECOVER_RETURN(prevGroupId != prevPrevGroupId);
538
539 if (currGroupId) {
540 const bool isSameLevel = prevLevel == newLevel;
541
542
543 if ((!prevPrevGroupId ||
544 prevPrevGroupId == currGroupId) &&
545 prevGroupId != currGroupId) {
546
547 // we have added a foreign/ally group
548
549 FillGroup::LevelData &currLevelData = currGroup.levels[newLevel];
550
551 addForeignAlly(currGroupId, prevGroupId,
552 currGroup, prevGroup,
553 currLevelData, prevLevelData,
554 currPt, prevPt,
555 isSameLevel);
556
557 } else if (prevPrevGroupId &&
558 prevPrevGroupId != currGroupId &&
559 prevGroupId == currGroupId) {
560
561 // we have removed a foreign/ally group
562
563 FillGroup::LevelData &currLevelData = currGroup.levels[newLevel];
564 FillGroup::LevelData &prevPrevLevelData = prevPrevGroup.levels[prevLevel];
565
566 removeForeignAlly(currGroupId, prevPrevGroupId,
567 currGroup, prevPrevGroup,
568 currLevelData, prevPrevLevelData,
569 currPt, prevPt,
570 isSameLevel);
571
572 } else if (prevPrevGroupId &&
573 prevPrevGroupId != currGroupId &&
574 prevGroupId != currGroupId) {
575
576 // this pixel has become an foreign/ally pixel of a different group
577
578 FillGroup::LevelData &currLevelData = currGroup.levels[newLevel];
579
580 FillGroup &prevPrevGroup = groups[prevPrevGroupId];
581 FillGroup::LevelData &prevPrevLevelData = prevPrevGroup.levels[prevLevel];
582
583 removeForeignAlly(currGroupId, prevPrevGroupId,
584 currGroup, prevPrevGroup,
585 currLevelData, prevPrevLevelData,
586 currPt, prevPt,
587 isSameLevel);
588
589 addForeignAlly(currGroupId, prevGroupId,
590 currGroup, prevGroup,
591 currLevelData, prevLevelData,
592 currPt, prevPt,
593 isSameLevel);
594 }
595
596 if (!isSameLevel) {
597
598 if (prevGroupId == currGroupId) {
599 // we connected with our own disjoint area
600
601 FillGroup::LevelData &currLevelData = currGroup.levels[newLevel];
602
603 incrementLevelEdge(currLevelData, prevLevelData,
604 newLevel, prevLevel);
605 }
606
607 if (prevPrevGroupId == currGroupId) {
608 // we removed a pixel for the borderline
609 // (now it is registered as foreign/ally pixel)
610
611 FillGroup::LevelData &currLevelData = currGroup.levels[newLevel];
612 FillGroup::LevelData &prevPrevLevelData = currGroup.levels[prevLevel];
613
614 decrementLevelEdge(currLevelData, prevPrevLevelData,
615 newLevel, prevLevel);
616 }
617 }
618 }
619}
ALWAYS_INLINE void removeForeignAlly(qint32 currGroupId, qint32 prevGroupId, FillGroup &currGroup, FillGroup &prevGroup, FillGroup::LevelData &currLevelData, FillGroup::LevelData &prevLevelData, const QPoint &currPt, const QPoint &prevPt, bool sameLevel)
ALWAYS_INLINE void addForeignAlly(qint32 currGroupId, qint32 prevGroupId, FillGroup &currGroup, FillGroup &prevGroup, FillGroup::LevelData &currLevelData, FillGroup::LevelData &prevLevelData, const QPoint &currPt, const QPoint &prevPt, bool sameLevel)
ALWAYS_INLINE void decrementLevelEdge(FillGroup::LevelData &currLevelData, FillGroup::LevelData &prevLevelData, quint8 currLevel, quint8 prevLevel)
ALWAYS_INLINE void incrementLevelEdge(FillGroup::LevelData &currLevelData, FillGroup::LevelData &prevLevelData, quint8 currLevel, quint8 prevLevel)
virtual const quint8 * rawDataConst() const =0
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128

References addForeignAlly(), decrementLevelEdge(), incrementLevelEdge(), KIS_SAFE_ASSERT_RECOVER_RETURN, and removeForeignAlly().

◆ writeColoring()

void KisWatershedWorker::Private::writeColoring ( )

Definition at line 712 of file KisWatershedWorker.cpp.

713{
716
717 QVector<KoColor> colors;
718 for (auto it = keyStrokes.begin(); it != keyStrokes.end(); ++it) {
719 KoColor color = it->color;
721 colors << color;
722 }
723 const int colorPixelSize = dstDevice->pixelSize();
724
725
726 while (srcIt.nextPixel() && dstIt.nextPixel()) {
727 const qint32 *srcPtr = reinterpret_cast<const qint32*>(srcIt.rawDataConst());
728
729 const int colorIndex = groups[*srcPtr].colorIndex;
730 if (colorIndex >= 0) {
731 memcpy(dstIt.rawData(), colors[colorIndex].data(), colorPixelSize);
732 }
733
734 }
735}

References KoColor::convertTo(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixel(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawData(), and KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawDataConst().

Member Data Documentation

◆ backgroundGroupColor

int KisWatershedWorker::Private::backgroundGroupColor = -1

Definition at line 215 of file KisWatershedWorker.cpp.

◆ backgroundGroupId

qint32 KisWatershedWorker::Private::backgroundGroupId = 0

Definition at line 214 of file KisWatershedWorker.cpp.

◆ boundingRect

QRect KisWatershedWorker::Private::boundingRect

Definition at line 202 of file KisWatershedWorker.cpp.

◆ dstDevice

KisPaintDeviceSP KisWatershedWorker::Private::dstDevice

Definition at line 200 of file KisWatershedWorker.cpp.

◆ groupIt

KisRandomAccessorSP KisWatershedWorker::Private::groupIt

Definition at line 212 of file KisWatershedWorker.cpp.

◆ groups

QVector<FillGroup> KisWatershedWorker::Private::groups

Definition at line 205 of file KisWatershedWorker.cpp.

◆ groupsMap

KisPaintDeviceSP KisWatershedWorker::Private::groupsMap

Definition at line 206 of file KisWatershedWorker.cpp.

◆ heightMap

KisPaintDeviceSP KisWatershedWorker::Private::heightMap

Definition at line 199 of file KisWatershedWorker.cpp.

◆ keyStrokes

QVector<KeyStroke> KisWatershedWorker::Private::keyStrokes

Definition at line 203 of file KisWatershedWorker.cpp.

◆ levelIt

KisRandomConstAccessorSP KisWatershedWorker::Private::levelIt

Definition at line 213 of file KisWatershedWorker.cpp.

◆ numFilledPixels

quint64 KisWatershedWorker::Private::numFilledPixels = 0

Definition at line 219 of file KisWatershedWorker.cpp.

◆ pointsComparator

CompareTaskPoints KisWatershedWorker::Private::pointsComparator

Definition at line 208 of file KisWatershedWorker.cpp.

◆ pointsQueue

PointsPriorityQueue KisWatershedWorker::Private::pointsQueue

Definition at line 209 of file KisWatershedWorker.cpp.

◆ progressUpdater

KoUpdater* KisWatershedWorker::Private::progressUpdater = 0

Definition at line 221 of file KisWatershedWorker.cpp.

◆ recolorMode

bool KisWatershedWorker::Private::recolorMode = false

Definition at line 216 of file KisWatershedWorker.cpp.

◆ totalPixelsToFill

quint64 KisWatershedWorker::Private::totalPixelsToFill = 0

Definition at line 218 of file KisWatershedWorker.cpp.


The documentation for this struct was generated from the following file: