Newsgroups: comp.lang.smalltalk
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!cam-news-feed3.bbnplanet.com!news.bbnplanet.com!cam-news-hub1.bbnplanet.com!howland.erols.net!blackbush.xlink.net!ins.net!heeg.de!hmm
From: hmm@heeg.de (Hans-Martin Mosner)
Subject: Re: "flood fill" for smalltalk (visualworks 2.5)
Message-ID: <E25Cor.IMr@heeg.de>
Sender: uucp@heeg.de
Organization: Georg Heeg Objektorientierte Systeme, Dortmund, FRG
X-Newsreader: TIN [version 1.2 PL2]
References: <01bbe466$c4349c80$0bd07e82@srh0002.urh.uiuc.edu>
Date: Mon, 9 Dec 1996 12:43:38 GMT
Lines: 73

SL Tong (s-tong@uiuc.edu) wrote:
: Hi! Is there a "floodfill" for smalltalk? I have tried
: looking in the graphicsContext methods but came up with nil.
: Can anyone help?

Look into the Image methods. The fillShapeAround:to: method
does mostly what you want. One catch is that it works for
images of depth one only. Applying it to deeper images is
a bit tricky. One course of action would be this:

"original is the original image, insidePoint is the point 
 around which flood filling should take place,
 and fillColor is the color with which to fill.
 For everything you don't understand, read the sources
 in the image; you will learn quite a bit!" 

| gc original insidePoint monoImage shape insidePixel row fillColor xorPixel xorImage |
gc := ScheduledControllers activeController view graphicsContext.
original := Image fromUser.
insidePoint := original extent//2.
fillColor := ColorValue darkGray.

insidePixel := original atPoint: insidePoint. 

"convert to a mono image mapping the inside color to white
 and all other colors to black"
monoImage := Image extent: original extent depth: 1 palette: MappedPalette whiteBlack.
row := original pixelArraySpecies new: original width.
0 to: original height-1 do: [:rowIndex |
	original rowAt: rowIndex into: row.
	1 to: row size do: [:x |
		row at: x put: ((row at: x) = insidePixel ifTrue: [0] ifFalse: [1])].
	monoImage rowAt: rowIndex putAll: row].

"test output"
monoImage displayOn: gc.

"fill the shape, then extract just the newly-filled area"
shape := monoImage filledShapeAround: insidePoint.
shape
	copy: shape bounds
	from: Point zero
	in: monoImage
	rule: RasterOp erase.

"test output"
shape displayOn: gc at: monoImage width+2 @0.

"convert the shape image into an image with which to xor the original"
xorPixel := (original palette indexOfPaintNearest: fillColor) bitXor: insidePixel.
xorImage := original copyEmpty: original extent.
0 to: original height-1 do: [:rowIndex |
	shape rowAt: rowIndex into: row.
	1 to: row size do: [:x |
		row at: x put: ((row at: x) = 1 ifTrue: [xorPixel] ifFalse: [0])].
	xorImage rowAt: rowIndex putAll: row].

"apply the xor"
original
	copy: original bounds
	from: Point zero
	in: xorImage
	rule: RasterOp reverse.

"test output"
original displayOn: gc at: 0@(original height+2)

Hans-Martin
--
+--- Hans-Martin Mosner ---- Senior Smalltalk Guru :-) ---+
| These opinions are entirely ficticious.  Any similarity |
| to real opinions is purely coincidental and unintended. |
+--- <hmm@heeg.de> ------ URL:http://www.heeg.de/~hmm/ ---+
