From VisualWorks®, Release 5i.1 of January 3, 2000 on November 13, 2004 at 3:06:03 am
Colours
Smalltalk
Core.Object
false
none
mySize image palette
As yet unclassified
Colours class random
midpoint: aRandom from: end1 to: end2
"Pick a random number between two end values (inclusive)."
| small big |
(end1 < end2) ifTrue: [
small := end1.
big := end2.
] ifFalse: [
small := end2.
big := end1.
].
^ (aRandom next * (big - small + 1)) floor + small.
Colours class instance creation
x: xInteger y: yInteger c: cInteger
"Answer a new colours object of the specified size."
| coloursObject |
coloursObject := self new.
coloursObject make_palette: cInteger.
coloursObject make_image: (Point x: xInteger y: yInteger).
^coloursObject
Colours creation
fillRand: aRandom col: col from: endtop to: endbottom
"Recursively fill one column."
"Used to bootstrap the recursive area fill."
"Also used to fudge our way out of ?x2 rectangles."
| middleY |
(endtop + 1 = endbottom) ifFalse: [
"Set the dot in the middle."
middleY := ((endbottom - endtop) / 2 + endtop) floor.
self x: col y: middleY put: (Colours midpoint: aRandom from: (self x: col y: endtop) to: (self x: col y: endbottom)).
"Go fill the two new sub-columns."
self fillRand: aRandom col: col from: endtop to: middleY.
self fillRand: aRandom col: col from: middleY to: endbottom.
]
fillRand: aRandom row: row from: endleft to: endright
"Recursively fill one row."
"Used to bootstrap the recursive area fill."
"Also used to fudge our way out of ?x2 rectangles."
| middleX |
(endleft + 1 = endright) ifFalse: [
"Set the dot in the middle."
middleX := ((endright - endleft) / 2 + endleft) floor.
self x: middleX y: row put: (Colours midpoint: aRandom from: (self x: endleft y: row) to: (self x: endright y: row)).
"Go fill the two new sub-rows."
self fillRand: aRandom row: row from: endleft to: middleX.
self fillRand: aRandom row: row from: middleX to: endright.
]
fillRand: aRandom top: endtop bottom: endbottom left: endleft right: endright
"Recursively fill the area."
| middleY middleX centre1 centre2 |
((endleft + 1 = endright) & (endtop + 1 = endbottom)) ifTrue: [
"This is just a 2x2 square. Nothing to do."
] ifFalse: [ (endleft + 1 = endright) ifTrue: [
"This is just a 2x? rectangle. Fill in some vertical space."
self fillRand: aRandom col: endright from: endtop to: endbottom.
] ifFalse: [ (endtop + 1 = endbottom) ifTrue: [
"This is just a ?x2 rectangle. Fill in some horizontal space."
self fillRand: aRandom row: endbottom from: endleft to: endright.
] ifFalse: [
"Wide open space; something to sink our recursive teeth into..."
"Set the dot half way along the bottom row."
middleX := ((endright - endleft) / 2 + endleft) floor.
self x: middleX y: endbottom put: (Colours midpoint: aRandom from: (self x: endleft y: endbottom) to: (self x: endright y: endbottom)).
"Set the dot half way along the right column."
middleY := ((endbottom - endtop) / 2 + endtop) floor.
self x: endright y: middleY put: (Colours midpoint: aRandom from: (self x: endright y: endtop) to: (self x: endright y: endbottom)).
"Set the dot in the middle (midpoint of two midpoints)."
centre1 := Colours midpoint: aRandom from: (self x: middleX y: endtop) to: (self x: middleX y: endbottom).
centre2 := Colours midpoint: aRandom from: (self x: endright y: middleY) to: (self x: endleft y: middleY).
self x: middleX y: middleY put: (Colours midpoint: aRandom from: centre1 to: centre2).
"Go fill the four new quadrants."
self fillRand: aRandom top: endtop bottom: middleY left: endleft right: middleX.
self fillRand: aRandom top: middleY bottom: endbottom left: endleft right: middleX.
self fillRand: aRandom top: endtop bottom: middleY left: middleX right: endright.
self fillRand: aRandom top: middleY bottom: endbottom left: middleX right: endright.
] ] ]
make_image: aPoint
"Compute a grid of recursive colours of the specified size."
| randomGenerator |
self setSize: aPoint.
randomGenerator := Random new.
"Flip a coin to determine which diagonally opposite corners get the master colours."
randomGenerator next > 0.5
ifTrue: [
self x: 0 y: 0 put: 0.
self x: self cols - 1 y: self rows - 1 put: palette size - 1.
self x: self cols - 1 y: 0 put: (Colours midpoint: randomGenerator from: 0 to: palette size - 1).
self x: 0 y: self rows - 1 put: (Colours midpoint: randomGenerator from: 0 to: palette size - 1).
]
ifFalse: [
self x: 0 y: self rows - 1 put: 0.
self x: self cols - 1 y: 0 put: palette size - 1.
self x: 0 y: 0 put: (Colours midpoint: randomGenerator from: 0 to: palette size - 1).
self x: self cols - 1 y: self rows - 1 put: (Colours midpoint: randomGenerator from: 0 to: palette size - 1).
].
"Draw the top row and left column."
self fillRand: randomGenerator row: 0 from: 0 to: self cols - 1.
self fillRand: randomGenerator col: 0 from: 0 to: self rows - 1.
"Now we have the top edge, the left edge, and the bottom/right dot."
"We are all setup to fill the remaining area."
self fillRand: randomGenerator top: 0 bottom: self rows - 1 left: 0 right: self cols - 1.
make_palette: n
"Create a palette of n equidistant colours spanning a range between"
"two randomly picked master colours."
| c1r c1g c1b c2r c2g c2b r g b colourList count ratio aColour randomGenerator |
randomGenerator := Random new.
c1r := c1b := c1g := 0.
c2r := c2b := c2g := 0.
[(c1r-c2r) abs + (c1b-c2b) abs + (c1g-c2g) abs >= 1] whileFalse: [
c1r := randomGenerator next.
c1g := randomGenerator next.
c1b := randomGenerator next.
c2r := randomGenerator next.
c2g := randomGenerator next.
c2b := randomGenerator next.
].
colourList := Array new: n.
count := 0.
n timesRepeat: [
ratio := count/(n-1).
r := c1r * ratio + (c2r * (1 - ratio)).
g := c1g * ratio + (c2g * (1 - ratio)).
b := c1b * ratio + (c2b * (1 - ratio)).
aColour := ColorValue red: r green: g blue: b.
count := count + 1.
colourList at: count put: aColour.
].
palette := MappedPalette withColors: colourList.
open
"Open the image in a window."
ScheduledWindow new
component: image;
minimumSize: mySize;
open
Colours accessing
cols
"Answer the number of columns."
^mySize x
rows
"Answer the number of rows."
^mySize y
setSize: aPoint
"Set the X/Y size of this object."
mySize := aPoint.
image := Image extent: aPoint depth: 8 bitsPerPixel: 8 palette: palette.
"grid := ByteArray new: (self cols) * (self rows) withAll: 0."
x: xInt y: yInt
"Get the pixel at point X/Y."
^image atPoint: (Point x: xInt y: yInt).
x: xInt y: yInt put: newPixel
"Set a pixel at point X/Y."
image atPoint: (Point x: xInt y: yInt) put: newPixel.