mirror of
https://github.com/SimpleMobileTools/Simple-Draw.git
synced 2025-06-05 21:59:17 +02:00
Optimize flood fill algorithm
- Reduced memory usage. - 20% faster than the original implementation.
This commit is contained in:
@ -96,48 +96,30 @@ class VectorFloodFiller(image: Bitmap) {
|
|||||||
var lFillLoc = x // the location to check/fill on the left
|
var lFillLoc = x // the location to check/fill on the left
|
||||||
var pxIdx = width * y + x
|
var pxIdx = width * y + x
|
||||||
path.moveTo(x.toFloat(), y.toFloat())
|
path.moveTo(x.toFloat(), y.toFloat())
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// fill with the color
|
|
||||||
val newX = (pxIdx % width).toFloat()
|
|
||||||
val newY = (pxIdx - newX) / width
|
|
||||||
path.lineTo(newX, newY)
|
|
||||||
|
|
||||||
// indicate that this pixel has already been checked and filled
|
|
||||||
pixelsChecked[pxIdx] = true
|
pixelsChecked[pxIdx] = true
|
||||||
|
lFillLoc--
|
||||||
// de-increment
|
pxIdx--
|
||||||
lFillLoc-- // de-increment counter
|
|
||||||
pxIdx-- // de-increment pixel index
|
|
||||||
|
|
||||||
// exit loop if we're at edge of bitmap or color area
|
// exit loop if we're at edge of bitmap or color area
|
||||||
if (lFillLoc < 0 || pixelsChecked[pxIdx] || !isPixelColorWithinTolerance(pxIdx)) {
|
if (lFillLoc < 0 || pixelsChecked[pxIdx] || !isPixelColorWithinTolerance(pxIdx)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
vectorFill(pxIdx + 1)
|
||||||
lFillLoc++
|
lFillLoc++
|
||||||
|
|
||||||
// Find Right Edge of Color Area
|
// Find Right Edge of Color Area
|
||||||
var rFillLoc = x // the location to check/fill on the left
|
var rFillLoc = x // the location to check/fill on the left
|
||||||
pxIdx = width * y + x
|
pxIdx = width * y + x
|
||||||
while (true) {
|
while (true) {
|
||||||
// fill with the color
|
|
||||||
val newX = (pxIdx % width).toFloat()
|
|
||||||
val newY = (pxIdx - newX) / width
|
|
||||||
path.lineTo(newX, newY)
|
|
||||||
|
|
||||||
// indicate that this pixel has already been checked and filled
|
|
||||||
pixelsChecked[pxIdx] = true
|
pixelsChecked[pxIdx] = true
|
||||||
|
rFillLoc++
|
||||||
// increment
|
pxIdx++
|
||||||
rFillLoc++ // increment counter
|
|
||||||
pxIdx++ // increment pixel index
|
|
||||||
|
|
||||||
// exit loop if we're at edge of bitmap or color area
|
|
||||||
if (rFillLoc >= width || pixelsChecked[pxIdx] || !isPixelColorWithinTolerance(pxIdx)) {
|
if (rFillLoc >= width || pixelsChecked[pxIdx] || !isPixelColorWithinTolerance(pxIdx)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
vectorFill(pxIdx - 1)
|
||||||
rFillLoc--
|
rFillLoc--
|
||||||
|
|
||||||
// add range to queue
|
// add range to queue
|
||||||
@ -145,6 +127,13 @@ class VectorFloodFiller(image: Bitmap) {
|
|||||||
ranges.offer(r)
|
ranges.offer(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vector fill pixels with color
|
||||||
|
private fun vectorFill(pxIndex: Int) {
|
||||||
|
val x = (pxIndex % width).toFloat()
|
||||||
|
val y = (pxIndex - x) / width
|
||||||
|
path.lineTo(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
// Sees if a pixel is within the color tolerance range.
|
// Sees if a pixel is within the color tolerance range.
|
||||||
private fun isPixelColorWithinTolerance(px: Int): Boolean {
|
private fun isPixelColorWithinTolerance(px: Int): Boolean {
|
||||||
val red = pixels!![px] ushr 16 and 0xff
|
val red = pixels!![px] ushr 16 and 0xff
|
||||||
|
Reference in New Issue
Block a user