I wrote the last time about simple ways to "just get something onto the screen", and I ended by exploring a simple Top Draw program. I hinted at the ease with which Top Draw allows compositing a complex "painting", taking more or less by fiat the examples included with the program. I since took advantage of the basic rosette drawing subroutine to make a wallpaper that I could actually install:
In my opinion there are two advantages to using Top Draw:
- It abstracts the compositing paradigm with a Photoshop-like
Layer
object, - It allows to interleave procedural drawing with arbitrary Core Image filters,
thus leveraging the built-in capabilities of Mac OS X Quartz subsystem.
I first refactored my script so that the drawing code is independent of the global transform being applied:
function wheel(m, n) { if (m < 1 || n < 5) return; var color = new Color(); color.alpha = 0.3; var a = Math.PI / n; var k = Math.cos(a), s = Math.sin(a); var t = (k + s) / (k - s); var d = k + s * t; var r = Math.pow(k - s, m); for (var e = 0; e != m; e++) { color.saturation = 0.5*(1 + e/m); // 0.5 -- 1.0 color.brightness = 0.5*(2 - e/m); // 1.0 -- 0.5 for (var i = 0; i != n; i++) { var b = (2*i + e) * a; var x = r * Math.cos(b), y = r * Math.sin(b); color.hue = i / n; desktop.fillStyle = color; desktop.beginPath(); desktop.moveTo(x, y); desktop.lineTo(d * (k * x - s * y), d * (k * y + s * x)); desktop.lineTo(t * x, t * y); desktop.lineTo(d * (k * x + s * y), d * (k * y - s * x)); desktop.lineTo(x, y); desktop.fill(); } r /= k - s; } }
Gone are centers and offsets in each parameter to the drawing commands, as gone is the global scaling of the drawing. Then, I use random number generators to place the rosettes all over the screen:
desktop.fillLayer(new Color(0)); var db = desktop.bounds; var xrnd = new Randomizer(0, db.width ); var yrnd = new Randomizer(0, db.height);
In order to give some depth to the final result, I'll blur each drawing a bit so that newer rosettes are sharper than older ones:
var f = new Filter("CIGaussianBlur"); f.setKeyValue("inputRadius", 2);
I'll draw a number of rosettes, four in this case, in random places:
for (var i = 1; i <= 4; i++) { var cx = xrnd.intValue; var cy = yrnd.intValue;
I make sure that the rosette fits the screen with the given center:
var sz = Math.max(cx, cy, db.width - cx, db.height - cy);
In order to isolate each drawing from the modifications to the global transform, I save the drawing context prior to changing scale and center:
desktop.save(); desktop.translate(db.x + cx, db.y + cy); desktop.scale(sz, sz);
I then draw the rosette and restore the context. I could easily give random parameters to the drawing routine, but I find that by having uniform shapes the rosettes nicely stack one over another:
wheel(8, 10); desktop.restore();
Finally, I apply the prepared filter to the resulting image:
desktop.applyFilter(f); }
As you can see, it's really easy to get good results with remarkably little code. Keep hitting Command-R until you find a result you like, and install it on your desktop.
1 comment:
Nice wallpaper!
Yet another nifty (command line) utility to apply Core Image filters is CoreImageTool!
http://codesnippets.joyent.com/posts/show/1731
Post a Comment