Just another update

This commit is contained in:
Ingy döt Net 2015-02-20 00:35:01 -05:00
parent a25938f123
commit 00a190b0a6
6591 changed files with 94363 additions and 23227 deletions

View file

@ -2,7 +2,7 @@ import std.array, bitmap;
void floodFill(Color)(Image!Color img, in uint x, in uint y,
in Color color)
pure nothrow in {
/*pure*/ nothrow in {
assert (y < img.ny && x < img.nx);
} body {
immutable target = img[x, y];
@ -22,7 +22,8 @@ pure nothrow in {
}
void main() {
auto img = loadPPM6(null, "unfilled_circ.ppm");
Image!RGB img;
loadPPM6(img, "unfilled_circ.ppm");
img.floodFill(200, 200, RGB(127, 0, 0));
img.savePPM6("unfilled_circ_flooded.ppm");
}

View file

@ -0,0 +1,43 @@
import java.awt.Color
import scala.collection.mutable
object Flood {
def floodFillStack(bm:RgbBitmap, x: Int, y: Int, targetColor: Color): Unit = {
// validate
if (bm.getPixel(x,y) == targetColor) return
// vars
val oldColor = bm.getPixel(x,y)
val pixels = new mutable.Stack[(Int,Int)]
// candy coating methods
def paint(fx: Int, fy:Int) = bm.setPixel(fx,fy,targetColor)
def old(cx: Int, cy: Int): Boolean = bm.getPixel(cx,cy) == oldColor
def push(px: Int, py: Int) = pixels.push((px,py))
// starting point
push(x,y)
// work
while (pixels.nonEmpty) {
val (x, y) = pixels.pop()
var y1 = y
while (y1 >= 0 && old(x, y1)) y1 -= 1
y1 += 1
var spanLeft = false
var spanRight = false
while (y1 < bm.height && old(x, y1)) {
paint(x,y1)
if (x > 0 && spanLeft != old(x-1,y1)) {
if (old(x - 1, y1)) push(x - 1, y1)
spanLeft = !spanLeft
}
if (x < bm.width - 1 && spanRight != old(x+1,y1)) {
if (old(x + 1, y1)) push(x + 1, y1)
spanRight = !spanRight
}
y1 += 1
}
}
}
}

View file

@ -0,0 +1,49 @@
(* For simplicity, we're going to fill black-and-white images. Nothing
* fundamental would change if we used more colors. *)
datatype color = Black | White
(* Represent an image as a 2D mutable array of pixels, since flood-fill
* is naturally an imperative algorithm. *)
type image = color array array
(* Helper functions to construct images for testing. Map 0 -> White
* and 1 -> Black so we can write images concisely as lists. *)
fun intToColor 0 = White
| intToColor _ = Black
fun listToImage (LL : int list list) : image =
Array.tabulate(List.length LL,
fn i => Array.tabulate (List.length (hd LL),
fn j => intToColor(List.nth(List.nth(LL,i),j))))
(* Is the given pixel within the image ? *)
fun inBounds (img : image) ((x,y) : int * int) : bool =
x >= 0 andalso y >= 0 andalso y < Array.length img
andalso x < Array.length (Array.sub(img, y))
(* Return an option containing the neighbors we should explore next, if any.*)
fun neighbors (img : image) (c : color) ((x,y) : int * int) : (int * int) list option =
if inBounds img (x,y) andalso Array.sub(Array.sub(img,y),x) <> c
then SOME [(x-1,y),(x+1,y),(x,y-1),(x,y+1)]
else NONE
(* Update the given pixel of the image. *)
fun setPixel (img : image) ((x,y) : int * int) (c : color) : unit =
Array.update (Array.sub(img,y),x,c)
(* Recursive fill around the given point using the given color. *)
fun fill (img : image) (c : color) ((x,y) : int * int) : unit =
case neighbors img c (x,y) of
SOME xys => (setPixel img (x,y) c; List.app (fill img c) xys)
| NONE => ()
val test = listToImage
[[0,0,1,1,0,1,0],
[1,0,1,0,1,0,0],
[1,0,0,0,0,0,1],
[0,1,0,0,0,1,0],
[1,0,0,0,0,0,1],
[0,0,1,1,1,0,0],
[0,1,0,0,0,1,0]]
(* Fill the image with black starting at the center. *)
val () = fill test Black (3,3)