[Part 5 of 8]
While the image property is pretty handy, and allows you to access full images, it's not enough for manipulating images. For that we have three more functions: copyPixels, getPixel and setPixel. We don't use the getPixel and setPixel functions here, but they allow full access to individual pixels in an image. That's high-power functionality, but at a cost-they are very processor intensive, and modifying an image one pixel at a time can result in a serious degradation in performance. The copyPixels function, on the other hand, works with rectangles and is pretty fast. Using copyPixels, you can copy a specified rectangle (all or a portion) from one image into a specified rectangle of another image, with appropriate resizing. For our mosaic transition, that's what we need. Our rectangles are full size of the image, rather than a portion, but we need the resizing to make it work. The syntax is
imageObject.copyPixels(sourceImage, destinationRect, sourceRect {,propList})
The optional fourth parameter is a property list using typical Director properties to modify the copy. We don't use any, but they allow you to specify such modifications as ink, blend and dithering. One command we use is
imSmall.copyPixels(imSource, imSmall.rect, imSource.rect)
which copies into imSmall from imSource using the full-size rect of both.
That's it! If you give this movie a try, each mouse click should result in an increasingly boxy image.
Next, we want to make some small changes to our code so that the modifications to the images happen within an exitFrame handler. The button will only initiate the transition. This is one step in the process of converting to a reusable behavior.
This next version of the mosaic transformation really isn't a whole lot different than the previous version. The major difference is that the exitFrame handler is a behavior that is attached to the sprite. In the final version, this is what we want, a behavior for a transition that can be dropped onto any bitmap sprite. The behavior is only for one direction, getting boxier. Eventually, we will need to supply the reverse so that the "from" image gets boxier, then the "to" image starts boxy and gets less boxy. Here is the second version for download:
Getting weird characters when you try to download? Right-Click (Win) or Ctrl-Click (Mac) and use SAVE THIS LINK AS... and select SOURCE in the dialogue box
The mosaic2 movie uses identical images, the same movie script (startMovie and stopMovie) and the same exitFrame handler (for looping) in the behavior channel. The mouseUp script is changed since it only needs to start the transition (the final behavior will be automatic and won't need a button). Most of the previous functionality of the mouseUp handler has been transferred to an exitFrame handler.
on mouseUp global stepNumber global isTransforming -- Image modified while TRUE isTransforming = TRUE stepNumber = 1 end
The new exitFrame behavior contains the code to perform the modifications to the image. Since a "boxy" step is implemented at each exitFrame, a test is added (with an if construct) to see if enough steps have passed. I chose ten steps as a reasonable number, and it's hard-coded into the behavior, but a well-written behavior would allow the user to determine this number (and we'll implement that later). Also, a well-written behavior would probably loop on the first frame while the transition takes place. Since this is a simplified version, we're holding off on those improvements for now. Here is the source for the behavior. To be implemented, the behavior is dragged onto the image sprite (sprite 1 in our example source).
on exitFrame global stepNumber, gSourceImage, gSourceMember, isTransforming if isTransforming = TRUE then w = gSourceImage.width h = gSourceImage.height -- Create an image object imSource = image(w, h, the colorDepth) -- Each modification starts with the -- original image, otherwise you are -- modifying a modification. imSource = gSourceMember.image.duplicate() -- Create an image object that is -- smaller imSmall = image(w/(stepNumber*4), h/(stepNumber*4), the colorDepth) -- Copy the original image into the -- small image imSmall.copyPixels(imSource, imSmall.rect, imSource.rect) -- Copy the small image back into the -- larger, resulting in the desired -- modification imSource.copyPixels(imSmall, imSource.rect, imSmall.rect) -- Put the modified image in the -- sprite's member gSourceImage.image = imSource -- Get ready for the next, greater, -- modification stepNumber = stepNumber + 1 if stepNumber > 10 then isTransforming = FALSE end if end
When you give this movie a try you should see the image transform each time a frame passes. To be effective, your image needs to span at least eleven frames.