Beatmup
flood_fill.cpp
Go to the documentation of this file.
1 /*
2  Beatmup image and signal processing library
3  Copyright (C) 2019, lnstadrum
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "flood_fill.h"
20 #include "region_filling.h"
21 #include "../bitmap/processing.h"
22 #include "../bitmap/internal_bitmap.h"
23 #include <cstring>
24 
25 using namespace Beatmup;
26 
27 
29  input(nullptr), output(nullptr), maskPos(0, 0), bounds(0,0,0,0), borderMorphology(NONE), tolerance(0), borderHold(0), borderRelease(0), computeContours(false)
30 {}
31 
32 
34  // deleting contours, if any
35  for (IntegerContour2D* contour : contours)
36  delete contour;
37  contours.clear();
38 }
39 
40 
41 void FloodFill::setInput(AbstractBitmap* inputBitmap) {
42  this->input = inputBitmap;
43 }
44 
45 
47  this->output = mask;
48 }
49 
50 
51 void FloodFill::setMaskPos(const IntPoint& pos) {
52  this->maskPos = pos;
53 }
54 
55 
56 void FloodFill::setSeeds(const IntPoint seeds[], int seedCount) {
57  this->seeds.clear();
58  for (int n = 0; n < seedCount; n++)
59  this->seeds.push_back(seeds[n]);
60 }
61 
62 
63 void FloodFill::setSeeds(const int seedsXY[], int seedCount) {
64  this->seeds.clear();
65  for (int n = 0; n < seedCount; n++)
66  this->seeds.push_back(IntPoint(seedsXY[2*n], seedsXY[2*n+1]));
67 }
68 
69 
70 void FloodFill::setComputeContours(bool compute) {
71  this->computeContours = compute;
72 }
73 
74 
76  return validThreadCount((int)seeds.size());
77 }
78 
79 
81  std::vector<IntPoint> border;
82  border.reserve((output->getWidth() + output->getHeight()) * 2);
83 
84  std::vector<IntegerContour2D*> myContours;
86  bounds.a = bounds.b = seeds[thread.currentThread()];
87 
88  for (int n = thread.currentThread(); n < seeds.size(); n += thread.numThreads())
89  if (!thread.isTaskAborted()) {
90  IntPoint seed = seeds[n];
91  if (seed.x >= maskPos.x && seed.y >= maskPos.y && seed.x < maskPos.x + output->getWidth() && seed.y < maskPos.x + output->getHeight()) {
92  BitmapProcessing::pipelineWithMaskOutput<Kernels::FillRegion>(*input, *output, maskPos, seed, tolerance, border, bounds);
93  }
94  }
95 
96  // compute contours
97  if (!thread.isTaskAborted())
98  if (computeContours) {
100  IntegerContour2D::computeBoundary(myContours, *output, border, writer, 0);
101  }
102 
103  if (!thread.isTaskAborted())
104  switch (borderMorphology) {
105  case DILATE:
106  BitmapProcessing::writeToMask<Kernels::CircularDilatation>(*output, border, 255, borderHold, borderRelease);
107  bounds.grow((int) ceilf(borderHold + borderRelease));
109  break;
110  case ERODE:
111  BitmapProcessing::writeToMask<Kernels::CircularErosion>(*output, border, 255, borderHold, borderRelease);
112  bounds.grow(-(int) floorf(borderHold));
113  break;
114  default: break;
115  }
116 
117  // updating bounds and merging contours
118  {
119  std::lock_guard<std::mutex> lock(access);
120  if (bounds.a.x < this->bounds.a.x) this->bounds.a.x = bounds.a.x;
121  if (bounds.a.y < this->bounds.a.y) this->bounds.a.y = bounds.a.y;
122  if (bounds.b.x > this->bounds.b.x) this->bounds.b.x = bounds.b.x;
123  if (bounds.b.y > this->bounds.b.y) this->bounds.b.y = bounds.b.y;
124 
125  if (computeContours) {
126  contours.reserve(contours.size() + myContours.size());
127  for (auto contour : myContours)
128  contours.push_back(contour);
129  }
130  }
131 
132  return true;
133 }
134 
135 
137  NullTaskInput::check(input, "input bitmap");
138  NullTaskInput::check(output, "output bitmap");
139  lock<ProcessingTarget::CPU>(gpu, input, output);
140  for (IntegerContour2D* contour : contours)
141  delete contour;
142  contours.clear();
143  if (computeContours) {
146  std::memset(ignoredSeeds->getData(0, 0), 0, ignoredSeeds->getMemorySize());
147  }
148  bounds.a = bounds.b = seeds[0];
149 }
150 
151 
152 void FloodFill::afterProcessing(ThreadIndex threadCount, GraphicPipeline* gpu, bool aborted) {
153  unlock(input, output);
154  if (computeContours) {
156  delete ignoredSeeds;
157  }
158 }
159 
160 
162  this->tolerance = tolerance;
163 }
164 
165 
166 void FloodFill::setBorderPostprocessing(BorderMorphology operation, float holdRadius, float releaseRadius) {
167  borderMorphology = operation;
168  borderHold = std::max(0.0f, holdRadius);
169  borderRelease = std::max(borderHold, releaseRadius);
170 }
171 
172 
173 const IntegerContour2D& FloodFill::getContour(int contourIndex) const {
174  RuntimeError::check(contourIndex >= 0 && contourIndex < contours.size(),
175  "Contour index is out of range. Contours computation may have been disabled.");
176  return *contours[contourIndex];
177 }
A very basic class for any image.
Context & getContext() const
const ImageResolution getSize() const
Returns the bitmap resolution within ImageResolution object.
virtual const pixbyte * getData(int x, int y) const =0
Returns a pointer to given pixel.
virtual const msize getMemorySize() const =0
Bitmap size in bytes.
static ThreadIndex validThreadCount(int number)
Valid thread count from a given integer value.
Definition: parallelism.cpp:45
void unlock(AbstractBitmap *bitmap)
Drops a lock to the bitmap.
void lock(GraphicPipeline *gpu, AbstractBitmap *input, AbstractBitmap *output)
Definition: content_lock.h:84
void writeLock(GraphicPipeline *gpu, AbstractBitmap *bitmap, ProcessingTarget target)
Locks content of a bitmap for writing using a specific processing target device.
void limit(const CustomRectangle &frame)
Truncates a rectangle to a limiting frame.
Definition: geometry.h:221
CustomPoint< numeric > b
Definition: geometry.h:131
CustomPoint< numeric > a
Definition: geometry.h:131
void grow(numeric r)
Definition: geometry.h:287
std::mutex access
access control assuring internal thread safety
Definition: flood_fill.h:55
void setSeeds(const IntPoint seeds[], int seedCount)
Specifies a set of seeds (starting points)
Definition: flood_fill.cpp:56
BorderMorphology
Morphological postprocessing operation applied to discovered connected components.
Definition: flood_fill.h:41
@ DILATE
apply a dilatation
Definition: flood_fill.h:43
@ ERODE
apply an erosion
Definition: flood_fill.h:44
AbstractBitmap * ignoredSeeds
1-bit bitmap storing flags marking used pixels
Definition: flood_fill.h:51
BorderMorphology borderMorphology
border morphological postprocessing
Definition: flood_fill.h:58
void setComputeContours(bool)
Enables or disables contours computation.
Definition: flood_fill.cpp:70
std::vector< IntegerContour2D * > contours
contours to store borders for each seed
Definition: flood_fill.h:57
void setInput(AbstractBitmap *)
Sets the input bitmap.
Definition: flood_fill.cpp:41
AbstractBitmap * output
resulting mask
Definition: flood_fill.h:50
void setBorderPostprocessing(BorderMorphology operation, float holdRadius, float releaseRadius)
Specifies a morphological operation to apply to the mask border.
Definition: flood_fill.cpp:166
void setMaskPos(const IntPoint &)
Specifies left-top corner position of the mask to compute inside the input bitmap.
Definition: flood_fill.cpp:51
const IntegerContour2D & getContour(int contourIndex) const
Returns a contour by index if computeContours was true, throws an exception otherwise.
Definition: flood_fill.cpp:173
virtual void afterProcessing(ThreadIndex threadCount, GraphicPipeline *gpu, bool aborted) final
Instruction called after the task is executed.
Definition: flood_fill.cpp:152
IntPoint maskPos
left-top corner of the mask to compute over the input bitmap
Definition: flood_fill.h:53
virtual void beforeProcessing(ThreadIndex threadCount, ProcessingTarget target, GraphicPipeline *gpu) final
Instruction called before the task is executed.
Definition: flood_fill.cpp:136
std::vector< IntPoint > seeds
set of starting points (seed points)
Definition: flood_fill.h:56
void setTolerance(float)
Sets the intensity tolerance threshold used to decide on similarity of neighboring pixels.
Definition: flood_fill.cpp:161
float tolerance
intensity tolerance value
Definition: flood_fill.h:60
AbstractBitmap * input
input bitmap
Definition: flood_fill.h:49
IntRectangle bounds
mask bounds
Definition: flood_fill.h:54
virtual bool process(TaskThread &thread) final
Executes the task on CPU within a given thread.
Definition: flood_fill.cpp:80
bool computeContours
if true, border contours will be computed per each seed
Definition: flood_fill.h:64
void setOutput(AbstractBitmap *)
Specifies the bitmap to put the resulting mask to.
Definition: flood_fill.cpp:46
ThreadIndex getMaxThreads() const
Gives the upper limint on the number of threads the task may be performed by.
Definition: flood_fill.cpp:75
virtual const int getHeight() const =0
Height of the texture in pixels.
virtual const int getWidth() const =0
Width of the texture in pixels.
Internal low-level GPU control API.
Definition: pipeline.h:33
IntRectangle closedRectangle() const
A sequence of integer-valued 2D points.
Definition: contours.h:33
static void computeBoundary(std::vector< IntegerContour2D * > &boundary, AbstractBitmap &bitmap, std::vector< IntPoint > &border, BinaryMaskWriter &testedPixels, float level=0.5f)
Discovers an area boundary in a bitmap following a level curve, starting from a given set of points.
Definition: contours.cpp:166
Bitmap whose memory is managed by the Beatmup engine.
A generic to write mask bitmap data lookup tables for masks values.
static void check(const void *pointer, const char *which)
Definition: exception.h:115
static void check(const bool condition, const std::string &message)
Definition: exception.h:64
Thread executing tasks.
Definition: parallelism.h:154
virtual ThreadIndex numThreads() const =0
ThreadIndex currentThread() const
Definition: parallelism.h:165
virtual bool isTaskAborted() const =0
Returns true if the task is asked to stop from outside.
@ NONE
no extension
Definition: program.h:64
unsigned char ThreadIndex
number of threads / thread index
Definition: parallelism.h:68
@ BinaryMask
1 bit per pixel
ProcessingTarget
Definition: basic_types.h:55
CustomPoint< numeric > max(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
Definition: geometry.h:728
jlong jfloat tolerance
int n