Engauge Digitizer  2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GridHealerAbstractBase.cpp
Go to the documentation of this file.
1 /******************************************************************************************************
2  * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
3  * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
5  ******************************************************************************************************/
6 
8 #include "EngaugeAssert.h"
10 #include "GridLog.h"
11 #include "GridTriangleFill.h"
12 #include "Logger.h"
13 #include "Pixels.h"
14 #include <QFile>
15 #include <QImage>
16 #include <qmath.h>
17 #include <QRgb>
18 #include <QTextStream>
19 
21  const DocumentModelGridRemoval &modelGridRemoval) :
22  m_modelGridRemoval (modelGridRemoval),
23  m_maxPointSeparation (0),
24  m_gridLog (gridLog)
25 {
26 }
27 
29 {
30 }
31 
33  int y0,
34  int x1,
35  int y1)
36 {
37  m_mutualPairHalvesBelow.push_back (QPoint (x0, y0));
38  m_mutualPairHalvesAbove.push_back (QPoint (x1, y1));
39 }
40 
42  int xBL, int yBL,
43  int xBR, int yBR,
44  int xTR, int yTR,
45  int xTL, int yTL)
46 {
47  // Sanity checks
48  if (xBL == 0 || yBL == 0 || xBR == 0 || yBR == 0 || xTR == 0 || yTR == 0 || xTL == 0 || yTL == 0) {
49  LOG4CPP_ERROR_S ((*mainCat)) << "GridHealerAbstractBase::fillTrapezoid received undefined corner coordinate "
50  << "xBL=" << xBL << " yBL=" << yBL << " xBR=" << xBR << " yBR=" << yBR
51  << "xTR=" << xTR << " yTR=" << yTR << " xTL=" << xTL << " yTL=" << yTL;
52  }
53 
54  if (!Pixels::pixelIsBlack(image, xBL, yBL)) {
55  LOG4CPP_ERROR_S ((*mainCat)) << "GridHealerAbstractBase::fillTrapezoid has bad bottom left point";
56  }
57  if (!Pixels::pixelIsBlack(image, xBR, yBR)) {
58  LOG4CPP_ERROR_S ((*mainCat)) << "GridHealerAbstractBase::fillTrapezoid has bad bottom right point";
59  }
60  if (!Pixels::pixelIsBlack(image, xTR, yTR)) {
61  LOG4CPP_ERROR_S ((*mainCat)) << "GridHealerAbstractBase::fillTrapezoid has bad top right point";
62  }
63  if (!Pixels::pixelIsBlack(image, xTL, yTL)) {
64  LOG4CPP_ERROR_S ((*mainCat)) << "GridHealerAbstractBase::fillTrapezoid has bad top left point";
65  }
66 
67  // Any quadrilateral (including this trapezoid) can be considered the union of two triangles
68  GridTriangleFill triangleFill;
69  triangleFill.fill (m_gridLog,
70  image,
71  QPoint (xBL, yBL),
72  QPoint (xBR, yBR),
73  QPoint (xTR, yTR));
74  triangleFill.fill (m_gridLog,
75  image,
76  QPoint (xBL, yBL),
77  QPoint (xTL, yTL),
78  QPoint (xTR, yTR));
79 }
80 
82 {
83  return m_gridLog;
84 }
85 
86 void GridHealerAbstractBase::healed (QImage &image)
87 {
88  applyMutualPairs (image);
89  doHealingAcrossGaps (image);
90 }
91 
93 {
94  return m_maxPointSeparation;
95 }
96 
98 {
99  return m_modelGridRemoval;
100 }
101 
103 {
104  return m_mutualPairHalvesAbove;
105 }
106 
108 {
109  return m_mutualPairHalvesBelow;
110 }
111 
113 {
114  // For now we will use the close distance as the minimum pixel count
115  return qFloor (modelGridRemoval.closeDistance());
116 }
117 
118 bool GridHealerAbstractBase::pointsAreGood (const QImage &image,
119  int x0,
120  int y0,
121  int x1,
122  int y1) const
123 {
124  Pixels pixels;
125 
126  int stopCountAt = pixelCountInRegionThreshold (m_modelGridRemoval);
127 
128  // Skip if either endpoint is an unwanted artifact. Look at start point below (since it is connected
129  // to the end point below), and the start point above (which is connected to the end point above)
130  return ((pixels.countBlackPixelsAroundPoint (image, x0, y0, stopCountAt) >= stopCountAt) &&
131  (pixels.countBlackPixelsAroundPoint (image, x1, y1, stopCountAt) >= stopCountAt));
132 }
133 
134 void GridHealerAbstractBase::saveGapSeparation (double gapSeparation)
135 {
136  // Right triangle with one edge crossing the gap (separation value) and hypotenuse giving
137  // maximum point separation (closest distance) gives the maximum horizontal separation
138  m_maxPointSeparation = qFloor (qSqrt (qPow (modelGridRemoval().closeDistance(), 2) -
139  qPow (gapSeparation, 2)));
140 }
Class that does special logging for GridLog and GridRemoval classes.
Definition: GridLog.h:16
void fill(GridLog &gridLog, QImage &image, const QPoint &p0, const QPoint &p1, const QPoint &p2)
Fill triangle between these three points.
double closeDistance() const
Get method for close distance.
void saveGapSeparation(double gapSeparation)
Gap separation set method.
Utility class for pixel manipulation.
Definition: Pixels.h:31
virtual void doHealingAcrossGaps(QImage &image)=0
Guts of the algorithm in which sequences of black pixels across the gap from each other are filled in...
void healed(QImage &image)
Return healed image after grid removal.
bool pointsAreGood(const QImage &image, int x0, int y0, int x1, int y1) const
Apply blackPixelRegionIsBigEnough to regions around each of two points.
#define LOG4CPP_ERROR_S(logger)
Definition: convenience.h:12
GridHealerAbstractBase(GridLog &gridLog, const DocumentModelGridRemoval &modelGridRemoval)
Single constructor.
GridLog & gridLog()
Logging get method.
double maxPointSeparation() const
Max point separation get method.
virtual void applyMutualPairs(const QImage &image)=0
Apply mutual pair points after all grid removal is done.
static int pixelCountInRegionThreshold(const DocumentModelGridRemoval &modelGridRemoval)
Threshold number of pixels in a region to be considered too-small or big-enough.
const MutualPairHalves & mutualPairHalvesBelow() const
Mutual pair halves for above grid line.
int countBlackPixelsAroundPoint(const QImage &image, int x, int y, int stopCountAt)
Fill triangle between these three points.
Definition: Pixels.cpp:16
QList< QPoint > MutualPairHalves
Save one half of a mutual pair.
log4cpp::Category * mainCat
Definition: Logger.cpp:14
const MutualPairHalves & mutualPairHalvesAbove() const
Mutual pair halves for below grid line.
Class that does raster-line fill of a triangle, with logging customizations for GridHealer (and there...
static bool pixelIsBlack(const QImage &image, int x, int y)
Return true if pixel is black in black and white image.
Definition: Pixels.cpp:286
void addMutualPair(int x0, int y0, int x1, int y1)
Add two points on either side of a gap. Later, after removal, the black points will be processed...
Model for DlgSettingsGridRemoval and CmdSettingsGridRemoval. The settings are unstable until the user...
DocumentModelGridRemoval & modelGridRemoval()
DocumentModelGridRemoval get method.
void fillTrapezoid(QImage &image, int xBL, int yBL, int xBR, int yBR, int xTR, int yTR, int xTL, int yTL)
Fill trapezoid with bottom left, bottom right, top right, and top left points.