The commands from IMAGE TRANSFORMS can be used in Tcl procedure to create more complex visual effects. For example, consider the following Tcl procedure called whirlpool:
proc whirlpool {image1 p} { set image2 [im_scaleC $image1 [expr 1- $p]] set image3 [im_rotateC $image2 [expr 360 * $p]] return $image3 }This procedure takes two arguments: a Rivl image (image1) and a double value between 0 and 1 (p). The call to im_scaleC reduces image1 by a factor of 1 - p, and assigns the result to image2 about its center by an angle proportional to p, and stores the result in image3, which is returned.
Many Rivl procedures, like whirlpool, apply a sequence of operations to an image. Since the operators under IMAGE TRANSFORMS are all non-destructive, these procedures consist of a sequence of statements of the form
set im [im_effect $im params]We found this notation cumbersome, so we borrowed an idiom from Scheme. Any operator with the character "!" appended destructively modifies its first argument. This rule applies to all operators listed under IMAGE TRANSFORMS. Since the operators under IMAGE TRANSFORMS are all non-destructive, these procedures consist of a sequence of statements of the form
set im [im_effect $im params]Taking advantage of this notation, we can write whirlpool as:
proc whirlpool {image p} { im_scaleC! image [expr 1- $p] im_rotateC! image [expr 360 * $p] return $image }Notice that the destructive operation omits the "$" in front of its first argument, whereas the non-destructive form requires the "$". This artifact is caused by the way pass-by-reference is implemented in Tcl.
For consistency, we felt that user defined effects should also have destructive and non-destructive versions. To this end we provide the rvl_proc command, which is similar to Tcl's proc command but also creates a destructive form of the procedure. Thus, if we use rvl_proc in the definition of whirlpool above, two commands, called whirlpool and whirlpool!, are created.
Since the full Tcl language is available, Rivl procedures can be constructed that include looping, branching, and recursion. For example, suppose the following sequence and operations is applied to an image n times:
rvl_proc fractal {image n} { set dx [expr 0.25 * [im_width $image]] set dy [expr 0.25 * [im_height $image]] for {set i 0} {$i < $n} {incr i} { # 1. Shrink to half size. im_scaleC! image 0.5 # 2. Create and move three duplicates. set north [im_trans $image 0 -$dy] set sw [im_trans $image -$dx $dy] set se [im_trans $image $dx $dy] # 3. Merge the three duplicates. set image [im_overlay $north $sw $se] } return $image }The first two lines compute the translation distance dx and dy for the second step as a function of the image size. The rest of the procedure follows from the description given above.