Created
April 2, 2013 21:09
-
-
Save dyoo/5296212 to your computer and use it in GitHub Desktop.
Flood fill example; submitted to Rosetta Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang racket | |
(require racket/draw) | |
;; flood-fill: bitmap<%> number number color color -> void | |
;; An example of flood filling a bitmap. | |
;; | |
;; We'll use a raw, byte-oriented interface here for demonstration | |
;; purposes. Racket does provide get-pixel and set-pixel functions | |
;; which work on color% structures rather than bytes, but it's useful | |
;; to see that the byte approach works as well. | |
(define (flood-fill bm start-x start-y target-color replacement-color) | |
;; The main loop. | |
;; http://en.wikipedia.org/wiki/Flood_fill | |
(define (iter x y) | |
(when (and (in-bounds? x y) (target-color-at? x y)) | |
(replace-color-at! x y) | |
(iter (add1 x) y) | |
(iter (sub1 x) y) | |
(iter x (add1 y)) | |
(iter x (sub1 y)))) | |
;; With auxillary definitions below: | |
(define width (send bm get-width)) | |
(define height (send bm get-height)) | |
(define buffer (make-bytes (* width height 4))) | |
(send bm get-argb-pixels 0 0 width height buffer) | |
(define-values (target-red target-green target-blue) | |
(values (send target-color red) | |
(send target-color green) | |
(send target-color blue))) | |
(define-values (replacement-red replacement-green replacement-blue) | |
(values (send replacement-color red) | |
(send replacement-color green) | |
(send replacement-color blue))) | |
(define (offset-at x y) (* 4 (+ (* y width) x))) | |
(define (target-color-at? x y) | |
(define offset (offset-at x y)) | |
(and (= (bytes-ref buffer (+ offset 1)) target-red) | |
(= (bytes-ref buffer (+ offset 2)) target-green) | |
(= (bytes-ref buffer (+ offset 3)) target-blue))) | |
(define (replace-color-at! x y) | |
(define offset (offset-at x y)) | |
(bytes-set! buffer (+ offset 1) replacement-red) | |
(bytes-set! buffer (+ offset 2) replacement-green) | |
(bytes-set! buffer (+ offset 3) replacement-blue)) | |
(define (in-bounds? x y) | |
(and (<= 0 x) (< x width) (<= 0 y) (< y height))) | |
;; Finally, let's do the fill, and then store the | |
;; result back into the bitmap: | |
(iter start-x start-y) | |
(send bm set-argb-pixels 0 0 width height buffer)) | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;; Example: flood fill a hole shape. | |
(define bm (make-bitmap 100 100)) | |
(define dc (send bm make-dc)) | |
;; We intentionally set the smoothing of the dc to | |
;; aligned so that there are no gaps in the shape for the | |
;; flood to leak through. | |
(send dc set-smoothing 'aligned) | |
(send dc draw-rectangle 10 10 80 80) | |
(send dc draw-rounded-rectangle 20 20 50 50) | |
;; In DrRacket, we can print the bm to look at it graphically, | |
;; before the flood fill: | |
bm | |
(flood-fill bm 50 50 | |
(send the-color-database find-color "white") | |
(send the-color-database find-color "DarkSeaGreen")) | |
;; ... and after: | |
bm |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment