topical media & game development

talk show tell print

#graphic-flex-image-effects-12-Flex-Kaleidoscope.ax

#graphic-flex-image-effects-12-Flex-Kaleidoscope.ax [swf] [flash] flex


  package {
  
          import aether.utils.ImageUtil;
          import aether.utils.MathUtil;
  
          import flash.display.Bitmap;
          import flash.display.BitmapData;
          import flash.display.Loader;
          import flash.display.LoaderInfo;
          import flash.display.Shape;
          import flash.display.Sprite;
          import flash.events.Event;
          import flash.events.MouseEvent;
          import flash.geom.Matrix;
          import flash.geom.Point;
          import flash.net.FileFilter;
          import flash.net.FileReference;
  
          [SWF(width=500, height=500, backgroundColor=0xCCCCCC)]
  
          
Demonstrates how a kaleidoscope effect can be achieved by copying and rotating portions of an image. This class also shows how to allow user to load local image, as well as how to transform the effect based on mouse movement, where they can click and drag image to alter angle of kaleidoscope.

  
          public class @ax-graphic-flex-image-effects-12-Flex-Kaleidoscope extends Sprite {
  
                  // number of segments in kaleidoscope
                  private static const NUM_SEGMENTS:uint = 8;
  
                  private var _file:FileReference;
                  private var _originalImage:BitmapData;
                  private var _kaleidoscope:Bitmap;
                  private var _startAngle:Number;
                  private var _angle:Number;
                  private var _center:Point;
  
                  
Constructor. This sets up a listener for when the stage is clicked.

  
                  public function @ax-graphic-flex-image-effects-12-Flex-Kaleidoscope() {
                          stage.addEventListener(MouseEvent.CLICK, onStageClick);
                  }
  
                  
Creates a new Bitmap for the bitmap data passed in. This bitmap is rotated and flipped based on the index, which is its index in the total number of segments. This allows for segments to be placed around a central point, with every other segment mirrored, to create the effect.
parameter: index The index of the segment in the total number of segments.
parameter: segment The bitmap data to display.
parameter: center The center of the effect around which the segments are placed.
parameter: angle The angle that each segment will be placed at, based on total number of segments.
returns: The bitmap created.

  
                  private function drawSegment(index:uint, segment:BitmapData, center:Point, angle:Number):Bitmap {
                          var bitmap:Bitmap = new Bitmap(segment);
                          // odd segments are flipped vertically
                          if (index % 2 > 0) {
                                  bitmap.scaleY = -1;
                                  // add one to the index because the segment was flipped
                                  bitmap.rotation = (index+1)*angle;
                          } else {
                                  bitmap.rotation = index*angle;
                          }
                          bitmap.x = center.x;
                          bitmap.y = center.y;
                          return bitmap;
                  }
  
                  
Creates the different segments that make up the total kaleidoscope effect.

  
                  private function draw@ax-graphic-flex-image-effects-12-Flex-Kaleidoscope():void {
                          var width:Number = _originalImage.width;
                          var height:Number = _originalImage.height;
                          // radius of effect will be half of image size
                          var radius:Number = Math.min(width, height)/2;
                          // find difference in angle of each segment based on total number of segments
                          var segmentAngle:Number = 360/NUM_SEGMENTS;
                          // these values will be used to draw triangle shape out of original image
                          var theta:Number = MathUtil.degreesToRadians(segmentAngle);
                          var x:Number = Math.cos(theta)*radius;
                          var y:Number = Math.sin(theta)*radius;
                          // translate image so it is centered on registration point
                          var matrix:Matrix = new Matrix();
                          matrix.translate(-width/2, -height/2);
                          // rotate so that the visible pixel in the positive quadrant of image are from the current angle
                          matrix.rotate(_angle);
                          // draw pixels from positive image quadrant into triangular shape
                          var shape:Shape = new Shape();
                          shape.graphics.beginBitmapFill(_originalImage, matrix, false);
                          shape.graphics.lineTo(radius, 0);
                          shape.graphics.lineTo(x, y);
                          shape.graphics.lineTo(0, 0);
                          shape.graphics.endFill();
                          // draw shape data into bitmap data
                          var segment:BitmapData = ImageUtil.getBitmapData(shape);
                          var sprite:Sprite = new Sprite();
                          var center:Point = new Point(width/2, height/2);
                          // run through total number of segments and place drawn segment into rotated bitmaps
                          for (var i:uint; i < NUM_SEGMENTS; i++) {
                                  sprite.addChild(drawSegment(i, segment, center, segmentAngle));
                          }
                          _kaleidoscope.bitmapData.dispose();
                          // draw new kaleidoscope contents from drawn segments
                          _kaleidoscope.bitmapData = ImageUtil.getBitmapData(sprite);
                          segment.dispose();
                  }
  
                  
Handler for when stage is clicked. This opens file browse dialog.
parameter: event Event dispatched by stage.

  
                  private function onStageClick(event:MouseEvent):void {
                          _file = new FileReference();
                          _file.addEventListener(Event.SELECT, onFileSelect);
                          _file.browse([new FileFilter("Images", "*.jpg;*.jpeg;*.gif;*.png")]);
                  }
  
                  
Handler for when a file is selected. Loads file.
parameter: event Event dispatched by FileReference.

  
                  private function onFileSelect(event:Event):void {
                          stage.removeEventListener(MouseEvent.CLICK, onStageClick);
                          _file.addEventListener(Event.COMPLETE, onImageLoadComplete);
                          _file.load();
                  }
  
                  
Handler for when local image completes loading. This loads bytes into Loader for access.
parameter: event Event dispatched by FileReference.

  
                  private function onImageLoadComplete(event:Event):void {
                          var loader:Loader = new Loader();
                          loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLocalFileRead);
                          loader.loadBytes(_file.data);
                  }
  
                  
Handler for when bytes from local file are read into Loader. This kicks off the effect with the loaded image and sets up an ENTER_FRAME listener so that the effect may be animated.
parameter: event Event dispatched by LoaderInfo.

  
                  private function onLocalFileRead(event:Event):void {
                          var loaderInfo:LoaderInfo = event.target as LoaderInfo;
                          // add initial image to stage
                          _kaleidoscope = loaderInfo.content as Bitmap;
                          addChild(_kaleidoscope);
                          var width:Number = stage.stageWidth;
                          var height:Number = stage.stageHeight;
                          // will be used to save reference to original image, scaled to stage
                          _originalImage = new BitmapData(width, height);
                          var bitmapData:BitmapData = _kaleidoscope.bitmapData;
                          var matrix:Matrix = new Matrix();
                          // scale loaded image to stage size
                          matrix.scale(width/bitmapData.width, height/bitmapData.height);
                          _originalImage.draw(bitmapData, matrix);
                          _kaleidoscope.bitmapData = _originalImage.clone();
                          _angle = 0;
                          // will be used to determine angle of drag
                          _center = new Point(stage.stageWidth/2, stage.stageHeight/2);
                          // apply initial effect
                          draw@ax-graphic-flex-image-effects-12-Flex-Kaleidoscope();
                          stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown);
                  }
  
                  
Handler for when user clicks stage. Thissets up listeners for movement and release, and records start angle of click in relation to center of effect.
parameter: event Event dispatched by stage.

  
                  private function onStageMouseDown(event:MouseEvent):void {
                          var position:Point = new Point(stage.mouseX-_center.x, stage.mouseY-_center.y);
                          _startAngle = _angle - Math.atan2(position.y, position.x);
                          stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);
                          stage.addEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove);
                  }
  
                  
Handler for then mouse is released after clicking stage. This removes listeners.
parameter: event Event dispatched by stage.

  
                  private function onStageMouseUp(event:MouseEvent):void {
                          stage.removeEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);
                          stage.removeEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove);
                  }
  
                  
Handler for then mouse is moved after clicking stage. This redraws kaleidoscope based on mouse's current position.
parameter: event Event dispatched by stage.

  
                  private function onStageMouseMove(event:MouseEvent):void {
                          var position:Point = new Point(stage.mouseX-_center.x, stage.mouseY-_center.y);
                          // determine new angle based on angle at start of click and new mouse position
                          _angle = _startAngle + Math.atan2(position.y, position.x);
                          draw@ax-graphic-flex-image-effects-12-Flex-Kaleidoscope();
                  }
  
          }
  
  }


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.