Jitter provides an easy way to rotate and/or zoom an image with an object called jit.rota. Rotation and zoom are common and useful video effects, and by combining them in different ways you can also achieve a variety of kaleidoscopic effects. jit.rota takes a matrix of video data (or any other sort of image) in its inlet, and sends out a version that has been zoomed, rotated, and otherwise distorted based on the settings of the object's attributes.
Open the tutorial patch. The QuickTime video dishes.mov is read into the jit.movie object automatically by a bang from loadbang. To see the video, click on the Displaytoggle to start the metro.
The video is a three-second left-to-right camera pan over a set of dishes. However, the loop attribute of the jit.movie object has been initialized to 2, so the movie loops back and forth, giving the illusion of a back-and-forth pan.
The theta attribute of jit.rota determines the angle of rotation around a central anchor point.
Drag on the Rotation Anglenumber box to rotate the video. Positive (or increasing) values cause counter-clockwise rotation, and negative (or decreasing) values cause clockwise rotation. The angle of rotation—a.k.a. the angle (theta)—is stated in radians. A value of 0—or any multiple of 2π (i.e., 6.283185)—is the normal upright positioning. A value of π (i.e. 3.141593)—or any odd multiple of π—is the fully upside-down position. Experiment until you understand the relationship between the theta values and the behavior of jit.rota.
Automated Rotation
Besides rotating the image by hand, you can also write an automated process in Max that will supply continually changing rotation angles. In the previous chapter we wrote a subpatch called rotate that used the line object to increase the angle of hue rotation continually from 0° to 360°. In this chapter we do something similar, but this time we use the bang from the metro that's displaying the movie to increase the angle of rotation. To keep it "user-friendly" we show the user degrees of angle rotation rather than radians (we convert degrees to radians inside the subpatch), and we also display the rotation speed as "rotations per second."
In the number box labeled Degrees per bang, enter the number 6. This will cause the rotation angle to increase by 6 degrees with each bang from the metro. Since the metro sends out a bang 20 times per second (once every 50 ms), we know that we can calculate the number of rotations per second by the formula d*20/360 —that is, d/18 —where d is the degrees of angle increase per bang. Now click on the toggle marked On/Off to begin the automated rotation.
Double click on the patcherrotate object to see the contents of the subpatch.
We convert what the user specifies as degrees per bang into an amount in radians, by multiplying the degrees by 2π and dividing by –360. (See the Technical Detail sidebar above.) When a bang comes in the left inlet, if rotation is turned on then the bang gets passed through and it causes an increase of angle rotation to be added into the accum object. Note that a negative degrees per bang amount works fine, too, and causes a counter-clockwise rotation of the image. When the total rotation angle exceeds 2π (or -2π), a split sends the value to an expr that uses a modulo operation to bring it back into range (resetting the value in the accum object) before sending it to the outlet. When rotation gets turned off, we detect that fact with a sel0 object, and reset the theta angle to 0.
Close the subpatch window. Click on the On/Offtoggle to stop the automated rotation.
Zoom In or Out
The other main feature of jit.rota is its zooming capability. The amount of zoom is determined by jit.rota 's zoom_x and zoom_y attributes. These permit you to zoom in or out in the horizontal and vertical dimensions independently; or you can zoom both dimensions simultaneously by changing both attributes at once.
Drag on the number box labeled Zoom to zoom in and out. Values greater than 1 expand the image (zoom in), and values less than 1 shrink the image (zoom out). You can change the zoom of the x and y dimensions independently by entering values directly into the x and ynumber boxes. (Negative zoom values flip the image as well as resize it.)
When we zoom in on the image—say, with a zoom value of 2—we still retain reasonably good image quality because we've turned jit.rota 's interp attribute on with an interp 1 message. If you turn interp off, you will get pixelation when you zoom in. When you're zooming out, interp has no appreciable effect, so it's pretty much a waste of the computer's time. (See Jitter Tutorial 14 for a discussion of pixelation and interpolation.) However, interpolation does improve the look of rotated images, even when they've been shrunk by zooming out.
Beyond the Edge
Set the zoom of both dimensions to some small value, such as 0.25.
When the image does not fill the entire display area because of shrinking or rotation, jit.rota has to decide what to do with the rest of the matrix that lies outside the image area. At present jit.rota is setting all the cell values outside the image area to 0, making them all black. The way that jit.rota handles the cells that lie outside the image boundaries is determined by its boundmode attribute. The different available boundmode settings are presented in the popup menu labeled Space outside the image in the upper-right corner of the patch. We initialized the boundmode value to 1, which instructs jit.rota to clear all the outlying cells. Here is the meaning of each of the boundmode settings:
0Ignore: Leave all outlying cells unchanged from their previous values.
1Clear: Set all outlying cell values to 0.
2Wrap: Begin the image again, as many times as necessary to fill the matrix.
3Clip: For all the outlying cells, continue to use the values of the boundary cells of the image.
4Fold: Repeat the image, flipped back in the opposite direction.
For special effects when the image is zoomed out, try setting the boundmode attribute to 2 (wrap) for a "Warhol" duplicate image effect, or 4 (fold) for a kaleidoscope effect.
Now try turning the automated rotation back on, to combine rotation and zoom, and modify the different parameters (Degrees per bang, Zoom, and Space outside the image).
When you have finished experimenting, turn off the automated rotation and return the zoom attributes (zoom_x and zoom_y) to 1.
Some Adjustments—Anchor Point and Offset
Up to now we've been using the center of the image as the anchor point of the rotation. However, you can choose any point for this. The center of rotation is set with the anchor_x and anchor_y attributes. Right now those attributes are set to 160 and 120 (half of the image dimensions), but you can change them in the number boxes labeled Anchor point.
Try different anchor points, and drag on the Rotation Anglenumber box to see the effect. Some anchor point settings you might want to try are 0,0 or 40,30 or 160,–120 or 320,240. You might want to set the boundmode attribute to 1 so that you can see the effects of different rotations more clearly. Note that the anchor_x and anchor_y values are specified relative to the upper-left corner of the matrix, but they may exceed the bounds of the matrix's dimensions.
In addition, you can move the image to a different location in the output matrix after zooming and rotation take place, using the offset_x and offset_y attributes.
To see this most effectively, first click on the message box above the pvar object in the lower right corner of the patch. This will set the rotation angle, boundary mode, zoom, and anchor points back to the settings we used at the outset of this chapter. (We have given names to the relevant user interface objects so that we can communicate with them via pvar.) Now set the Zoom number box to some value between 0 and 1, to zoom out on the image.
Use the Location offsetnumber boxes to move the image around by changing the offset_x and offset_y values. Try this in conjunction with boundmode 4, to see its utility in the "kaleidoscope" mode.
When you have finished, reset the Location offset values to 0.
Mouse control of rotation
We've devised one more way for you to rotate the image.
Click in the jit.pwindow display object and, with the mouse button held down, drag in a small circular motion around the center of the object.
jit.pwindow tracks your mouse movements and, as long the mouse button is down, it sends coordinate information (and other mouse information) out its right outlet in the form of mouse messages. The first two arguments of the mouse message are the x and y coordinates of the mouse, relative to the upper left corner of jit.pwindow. We use those coordinates to calculate the angle of the mouse relative to the center of the jit.pwindow, and we send that angle to jit.rota as the argument to the theta attribute.
Summary
The jit.rota object provides an easy way to rotate an image with its theta attribute, specifying an angle of rotation, in radians. It also provides an easy way to zoom in and out on an image with its zoom_x and zoom_y attributes. You can change the central point of the rotation with the anchor_x and anchor_y attributes, and you can move the resulting image in the output matrix with the offset_x and offset_y attributes. You can change the way that jit.rota treats the matrix cells that lie outside of the resulting image with the boundmode attribute. Using all of these capabilities in combination, you can get image-duplication and kaleidoscope effects in addition to simple zoom and rotation.
Zooming and rotation involve some rather intensive internal calculation by jit.rota, so these operations make substantial demands on the computer's processor. There are additional attributes, not covered in this tutorial, that give you access to virtually every coefficient in the rotation formula, presenting you even more possibilities for distorting and rotating the image. These are shown in jit.rota reference.
To manage the control of so many attributes at once, you can devise automated Max processes to generate attribute values, and/or interactive controls to change the values with gestures.