summaryrefslogtreecommitdiff
path: root/webcam/com/neave
diff options
context:
space:
mode:
authordumpfmprod <dumpfmprod@ubuntu.(none)>2010-03-26 18:38:20 -0400
committerdumpfmprod <dumpfmprod@ubuntu.(none)>2010-03-26 18:38:20 -0400
commit5650b9a43736f191dd13b4ec5fdc11f18a9e96d6 (patch)
tree7ed88e7d3a920923f3945216c0e8cd8b761c3e88 /webcam/com/neave
parentfc36a314e47c755da5056b33e0349545acc664dd (diff)
Added webcam effects
Diffstat (limited to 'webcam/com/neave')
-rwxr-xr-xwebcam/com/neave/media/NeaveCamera.as81
-rwxr-xr-xwebcam/com/neave/media/NeaveMicrophone.as104
-rwxr-xr-xwebcam/com/neave/webcam/NeaveWebcam.as196
-rwxr-xr-xwebcam/com/neave/webcam/effects/AbstractEffect.as81
-rwxr-xr-xwebcam/com/neave/webcam/effects/EffectEvent.as23
-rwxr-xr-xwebcam/com/neave/webcam/effects/EffectType.as1
-rwxr-xr-xwebcam/com/neave/webcam/effects/EffectsManager.as1
-rwxr-xr-xwebcam/com/neave/webcam/effects/NormalEffect.as38
-rwxr-xr-xwebcam/com/neave/webcam/effects/color/GlowEffect.as68
-rwxr-xr-xwebcam/com/neave/webcam/effects/color/MonochromeEffect.as61
-rwxr-xr-xwebcam/com/neave/webcam/effects/color/RainbowEffect.as90
-rwxr-xr-xwebcam/com/neave/webcam/effects/color/SepiaDirt.as31
-rwxr-xr-xwebcam/com/neave/webcam/effects/color/SepiaEffect.as90
-rwxr-xr-xwebcam/com/neave/webcam/effects/color/WarholEffect.as99
-rwxr-xr-xwebcam/com/neave/webcam/effects/color/XRayEffect.as62
-rwxr-xr-xwebcam/com/neave/webcam/effects/delay/DivideEffect.as99
-rwxr-xr-xwebcam/com/neave/webcam/effects/delay/FilmstripEffect.as91
-rwxr-xr-xwebcam/com/neave/webcam/effects/delay/GhostEffect.as89
-rwxr-xr-xwebcam/com/neave/webcam/effects/delay/SlitScanEffect.as178
-rwxr-xr-xwebcam/com/neave/webcam/effects/delay/TrailEffect.as68
-rwxr-xr-xwebcam/com/neave/webcam/effects/displace/AbstractDisplaceEffect.as64
-rwxr-xr-xwebcam/com/neave/webcam/effects/displace/BulgeEffect.as74
-rwxr-xr-xwebcam/com/neave/webcam/effects/displace/DentEffect.as75
-rwxr-xr-xwebcam/com/neave/webcam/effects/displace/FishbowlEffect.as72
-rwxr-xr-xwebcam/com/neave/webcam/effects/displace/FisheyeEffect.as72
-rwxr-xr-xwebcam/com/neave/webcam/effects/displace/FragmentEffect.as101
-rwxr-xr-xwebcam/com/neave/webcam/effects/displace/SqueezeEffect.as87
-rwxr-xr-xwebcam/com/neave/webcam/effects/displace/WaterEffect.as76
-rwxr-xr-xwebcam/com/neave/webcam/effects/mirror/AbstractMirrorEffect.as68
-rwxr-xr-xwebcam/com/neave/webcam/effects/mirror/BottomMirrorEffect.as41
-rwxr-xr-xwebcam/com/neave/webcam/effects/mirror/InverseMirrorEffect.as41
-rwxr-xr-xwebcam/com/neave/webcam/effects/mirror/LeftMirrorEffect.as41
-rwxr-xr-xwebcam/com/neave/webcam/effects/mirror/QuadMirrorEffect.as97
-rwxr-xr-xwebcam/com/neave/webcam/effects/mirror/RightMirrorEffect.as44
-rwxr-xr-xwebcam/com/neave/webcam/effects/mirror/TopMirrorEffect.as44
-rwxr-xr-xwebcam/com/neave/webcam/effects/mirror/UpsideDownEffect.as54
-rwxr-xr-xwebcam/com/neave/webcam/effects/motion/AbstractMotionEffect.as138
-rwxr-xr-xwebcam/com/neave/webcam/effects/motion/FireEffect.as129
-rwxr-xr-xwebcam/com/neave/webcam/effects/motion/SnowEffect.as154
-rwxr-xr-xwebcam/com/neave/webcam/effects/motion/Snowflake.as66
-rwxr-xr-xwebcam/com/neave/webcam/effects/motion/SteamEffect.as73
-rwxr-xr-xwebcam/com/neave/webcam/effects/motion/SwarmEffect.as106
-rwxr-xr-xwebcam/com/neave/webcam/effects/motion/SwarmFly.as122
-rwxr-xr-xwebcam/com/neave/webcam/effects/pixel/ASCIIEffect.as225
-rwxr-xr-xwebcam/com/neave/webcam/effects/pixel/HalftoneDot.as33
-rwxr-xr-xwebcam/com/neave/webcam/effects/pixel/HalftoneEffect.as135
-rwxr-xr-xwebcam/com/neave/webcam/effects/pixel/PixelateEffect.as75
-rwxr-xr-xwebcam/com/neave/webcam/effects/pixel/RGBEffect.as126
-rwxr-xr-xwebcam/com/neave/webcam/effects/pixel/RGBPixel.as34
49 files changed, 4018 insertions, 0 deletions
diff --git a/webcam/com/neave/media/NeaveCamera.as b/webcam/com/neave/media/NeaveCamera.as
new file mode 100755
index 0000000..f401af8
--- /dev/null
+++ b/webcam/com/neave/media/NeaveCamera.as
@@ -0,0 +1,81 @@
+/**
+ * Neave Camera
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.media
+{
+ import flash.events.*;
+ import flash.media.*;
+ import flash.system.*;
+
+ public class NeaveCamera
+ {
+ /**
+ * The requested width of the camera object
+ */
+ static public var CAMERA_WIDTH:int = 320;
+
+ /**
+ * The requested height of the camera object
+ */
+ static public var CAMERA_HEIGHT:int = 240;
+
+ static private var cam:Camera;
+
+ public function NeaveCamera() { }
+
+ /**
+ * Sets up and returns the camera object
+ *
+ * @return A camera object
+ */
+ static public function getCamera():Camera
+ {
+ // Return the same camera if it has been successfully requested before
+ if (cam != null)
+ {
+ if (cam.muted) Security.showSettings(SecurityPanel.PRIVACY);
+ return cam;
+ }
+
+ // Get the camera
+ cam = Camera.getCamera();
+ if (cam != null)
+ {
+ // Set properties if a camera was found
+ cam.setMode(CAMERA_WIDTH, CAMERA_HEIGHT, 30, true);
+ cam.addEventListener(StatusEvent.STATUS, NeaveCamera.statusListener);
+ return cam;
+ }
+ else
+ {
+ // No camera found
+ Security.showSettings(SecurityPanel.CAMERA);
+ return new Camera();
+ }
+ }
+
+ /**
+ * Whether the camera object is available or not
+ */
+ static public function get muted():Boolean
+ {
+ return cam == null || cam.muted || cam.name == null || cam.width == 0;
+ }
+
+ /**
+ * Camera status response
+ */
+ static private function statusListener(e:StatusEvent):void
+ {
+ if (e.code == "Camera.Unmuted") Security.showSettings(SecurityPanel.CAMERA);
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/media/NeaveMicrophone.as b/webcam/com/neave/media/NeaveMicrophone.as
new file mode 100755
index 0000000..6a46ee7
--- /dev/null
+++ b/webcam/com/neave/media/NeaveMicrophone.as
@@ -0,0 +1,104 @@
+/**
+ * Neave Microphone
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.media
+{
+ import flash.events.*;
+ import flash.media.*;
+ import flash.system.*;
+ import flash.utils.*;
+
+ public class NeaveMicrophone
+ {
+ static private var mic:Microphone;
+ static private var gainTimer:Timer;
+
+ public function NeaveMicrophone() { }
+
+ /**
+ * Sets up and returns the microphone object
+ *
+ * @return A microphone object
+ */
+ static public function getMicrophone():Microphone
+ {
+ // Return the same microphone if it has been successfully requested before
+ if (mic != null)
+ {
+ if (mic.muted) Security.showSettings(SecurityPanel.PRIVACY);
+ else NeaveMicrophone.startAutoGain();
+ return mic;
+ }
+
+ gainTimer = new Timer(100);
+
+ // Get the microphone
+ mic = Microphone.getMicrophone();
+ if (mic != null)
+ {
+ // Set properties if a microphone was found
+ mic.setLoopBack(true);
+ mic.rate = 44;
+ mic.gain = 25;
+ mic.setSilenceLevel(0);
+ mic.setUseEchoSuppression(true);
+ mic.soundTransform = new SoundTransform(0); // Mute microphone from sounding on speakers
+ mic.addEventListener(StatusEvent.STATUS, NeaveMicrophone.statusListener);
+
+ return mic;
+ }
+ else
+ {
+ // No microphone found
+ Security.showSettings(SecurityPanel.MICROPHONE);
+ return new Microphone();
+ }
+ }
+
+ /**
+ * Microphone status response
+ */
+ static private function statusListener(e:StatusEvent):void
+ {
+ if (e.code == "Microphone.Unmuted") NeaveMicrophone.startAutoGain();
+ else NeaveMicrophone.stopAutoGain();
+ }
+
+ /**
+ * Set up gain control
+ */
+ static public function startAutoGain():void
+ {
+ gainTimer.start();
+ if (!gainTimer.hasEventListener(TimerEvent.TIMER)) gainTimer.addEventListener(TimerEvent.TIMER, setGain);
+ }
+
+ /**
+ * Stop gain control
+ */
+ static public function stopAutoGain():void
+ {
+ gainTimer.stop();
+ gainTimer.reset();
+ gainTimer.removeEventListener(TimerEvent.TIMER, setGain);
+ }
+
+ /**
+ * Dynamically adjust the microphone's gain value
+ */
+ static private function setGain(e:TimerEvent):void
+ {
+ if (mic.activityLevel < 15) mic.gain = 30;
+ else if (mic.activityLevel > 90) mic.gain = 20;
+ else mic.gain = 25;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/NeaveWebcam.as b/webcam/com/neave/webcam/NeaveWebcam.as
new file mode 100755
index 0000000..811446b
--- /dev/null
+++ b/webcam/com/neave/webcam/NeaveWebcam.as
@@ -0,0 +1,196 @@
+/**
+ * Neave Webcam ...play with webcam effects
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * @author Paul Neave
+ * @version 1.0.0
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam
+{
+ import flash.display.*;
+ import flash.events.*;
+ import flash.media.*;
+ import flash.ui.*;
+ import com.neave.media.*;
+ import com.neave.webcam.effects.*;
+
+ public class NeaveWebcam extends Sprite
+ {
+ // Main variables
+ private var camera:Camera;
+ private var video:Video;
+ private var videoBitmap:Bitmap;
+ private var videoContainer:Sprite;
+ private var uiEnabled:Boolean;
+
+ /**
+ * Manages the webcam effects
+ */
+ public var effects:EffectsManager;
+
+ /**
+ * Creates a new instance of Neave Webcam
+ *
+ * @param camera The camera object to use to create the webcam effects
+ * @param interactive Enable mouse click or arrow keys to change the webcam effect
+ */
+ public function NeaveWebcam(camera:Camera, interactive:Boolean = true)
+ {
+ this.camera = camera;
+
+ initVideo();
+ initEffects();
+
+ this.interactive = interactive;
+ }
+
+ /**
+ * Sets up the main video object
+ */
+ private function initVideo():void
+ {
+ // Video dimensions must be 320x240 or higher
+ var w:int = camera.width < NeaveCamera.CAMERA_WIDTH ? NeaveCamera.CAMERA_WIDTH : camera.width;
+ var h:int = camera.height < NeaveCamera.CAMERA_HEIGHT ? NeaveCamera.CAMERA_HEIGHT : camera.height;
+
+ // Attach the camera object a video object
+ video = new Video(w, h);
+ video.attachCamera(camera);
+
+ // Create a bitmap object for the video effect, flipping to create a mirror image
+ videoBitmap = new Bitmap(new BitmapData(w, h, false, 0xFF000000), PixelSnapping.AUTO, false);
+ videoBitmap.scaleX = -1;
+ videoBitmap.x = w;
+
+ // Create a sprite to hold the bitmap
+ videoContainer = new Sprite();
+ videoContainer.addChild(videoBitmap);
+ addChild(videoContainer);
+ }
+
+ /**
+ * Sets up the webcam effects for the video object
+ */
+ private function initEffects():void
+ {
+ // Set up the effects manager for this video object
+ effects = new EffectsManager(video, videoBitmap.bitmapData);
+ paused = false;
+ }
+
+ /**
+ * Enable mouse click or arrow keys to change the webcam effect
+ */
+ public function set interactive(i:Boolean):void
+ {
+ uiEnabled = i;
+
+ if (uiEnabled)
+ {
+ // Arrow keys select previous or next webcam effect
+ addEventListener(KeyboardEvent.KEY_DOWN, keyDownListener);
+
+ // Clicking on the video selects the next webcam effect
+ videoContainer.addEventListener(MouseEvent.CLICK, videoClickListener);
+ videoContainer.buttonMode = true;
+ }
+ else
+ {
+ // Remove interactivity
+ removeEventListener(KeyboardEvent.KEY_DOWN, keyDownListener);
+ videoContainer.removeEventListener(MouseEvent.CLICK, videoClickListener);
+ videoContainer.buttonMode = false;
+ }
+ }
+
+ /**
+ * Moves to the next webcam effect on mouse click
+ */
+ private function videoClickListener(e:MouseEvent):void
+ {
+ if (paused || camera.muted || camera.width == 0) return;
+
+ effects.nextEffect();
+ }
+
+ /**
+ * Moves to the next or previous webcam effect when the arrow keys are pressed
+ */
+ private function keyDownListener(e:KeyboardEvent):void
+ {
+ if (paused || camera.muted || camera.width == 0) return;
+
+ switch (e.keyCode)
+ {
+ case Keyboard.LEFT:
+ effects.previousEffect();
+ break;
+
+ case Keyboard.RIGHT:
+ effects.nextEffect();
+ break;
+ }
+ }
+
+ /**
+ * The bitmap data containing the current webcam effect
+ */
+ public function get effectBitmap():BitmapData
+ {
+ return videoBitmap.bitmapData;
+ }
+
+ /**
+ * Pause or resume the current webcam effect
+ */
+ public function set paused(p:Boolean):void
+ {
+ if (p == paused) return;
+
+ // Pause or resume updating the current webcam effect every frame
+ if (p) removeEventListener(Event.ENTER_FRAME, update);
+ else addEventListener(Event.ENTER_FRAME, update);
+ }
+
+ /**
+ * Pause or resume the current webcam effect
+ */
+ public function get paused():Boolean
+ {
+ return !hasEventListener(Event.ENTER_FRAME);
+ }
+
+ /**
+ * Removes the webcam and all other referenced objects
+ */
+ public function destroy():void
+ {
+ interactive = false;
+ paused = true;
+ effects.destroy();
+ videoContainer.removeChild(videoBitmap);
+ videoBitmap.bitmapData.dispose();
+ videoBitmap.bitmapData = null;
+ videoBitmap = null;
+ removeChild(videoContainer);
+ videoContainer = null;
+ video = null;
+ camera = null;
+ }
+
+ /**
+ * Updates the current webcam effect
+ */
+ private function update(e:Event):void
+ {
+ effects.update();
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/AbstractEffect.as b/webcam/com/neave/webcam/effects/AbstractEffect.as
new file mode 100755
index 0000000..a0fb241
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/AbstractEffect.as
@@ -0,0 +1,81 @@
+/**
+ * Neave Webcam // Abstract Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects
+{
+ import flash.display.*;
+ import flash.geom.*;
+
+ public class AbstractEffect
+ {
+ protected var source:IBitmapDrawable;
+ protected var targetBitmap:BitmapData;
+ protected var name:String;
+ protected var sourceBitmap:BitmapData;
+ protected var sourceMatrix:Matrix;
+ protected var rect:Rectangle;
+ protected var point:Point;
+ protected var color:ColorTransform;
+
+ /**
+ * An abstract effect class, not to be instantiated
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param name The proper name of the effect
+ */
+ public function AbstractEffect(source:IBitmapDrawable, targetBitmap:BitmapData, name:String = "")
+ {
+ this.source = source;
+ this.targetBitmap = targetBitmap;
+ this.name = name;
+
+ createEffect();
+ }
+
+ /**
+ * Sets up the effect
+ */
+ private function createEffect():void
+ {
+ sourceBitmap = targetBitmap.clone();
+ sourceMatrix = new Matrix();
+ rect = targetBitmap.rect;
+ point = new Point();
+ color = new ColorTransform();
+ }
+
+ /**
+ * The proper name of the effect
+ */
+ public function get effectName():String
+ {
+ return name;
+ }
+
+ /**
+ * Draws the effect
+ */
+ public function draw():void
+ {
+ sourceBitmap.draw(source, sourceMatrix, color);
+ }
+
+ /**
+ * Removes the effect and all other referenced objects
+ */
+ public function destroy():void
+ {
+ sourceBitmap.dispose();
+ sourceBitmap = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/EffectEvent.as b/webcam/com/neave/webcam/effects/EffectEvent.as
new file mode 100755
index 0000000..134b792
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/EffectEvent.as
@@ -0,0 +1,23 @@
+package com.neave.webcam.effects
+{
+ import flash.events.*;
+
+ public class EffectEvent extends Event
+ {
+ public static const NEW_EFFECT:String = "newEffect";
+
+ private var _effectType:int;
+
+ public function EffectEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false, effectType:int = 0)
+ {
+ super(type, bubbles, cancelable);
+
+ _effectType = effectType;
+ }
+
+ public function get effectType():int
+ {
+ return _effectType;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/EffectType.as b/webcam/com/neave/webcam/effects/EffectType.as
new file mode 100755
index 0000000..217dcb5
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/EffectType.as
@@ -0,0 +1 @@
+/** * Neave Webcam // Effects Type * * Copyright (C) 2008 Paul Neave * http://www.neave.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html */ package com.neave.webcam.effects { final public class EffectType { static public const NORMAL :int = 0; static public const RAINBOW :int = 1; //static public const MIRROR_RIGHT :int = 2; //static public const MIRROR_TOP :int = 3; //static public const MIRROR_BOTTOM :int = 2; static public const MIRROR_INVERSE :int = 2; //static public const MIRROR_QUAD :int = 6; static public const UPSIDE_DOWN :int = 3; //static public const DIVIDE :int = 8; //static public const FILMSTRIP :int = 9; static public const FRAGMENT :int = 4; static public const SEPIA :int = 5; //static public const TRAIL :int = 12; //static public const BULGE :int = 13; //static public const FISHEYE :int = 14; //static public const FISHBOWL :int = 15; //static public const DENT :int = 16; ///static public const SQUEEZE :int = 17; static public const WATER :int = 6; static public const FIRE :int = 7; static public const SNOW :int = 8; //static public const STEAM :int = 21; static public const SWARM :int = 9; //static public const PIXELATE :int = 23; //static public const RGB :int = 24; //static public const HALFTONE :int = 25; static public const MONOCHROME :int = 10; static public const GHOST :int = 11; static public const MIRROR_LEFT :int = 12; //static public const ASCII :int = 14; //static public const X_RAY :int = 30; //static public const WARHOL :int = 31; static public const GLOW :int = 13; static public const SLIT_SCAN :int = 14; static public const TOTAL_EFFECTS :int = 14; public function EffectType() { } } } \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/EffectsManager.as b/webcam/com/neave/webcam/effects/EffectsManager.as
new file mode 100755
index 0000000..a5fa050
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/EffectsManager.as
@@ -0,0 +1 @@
+/** * Neave Webcam // Effects Manager * * Copyright (C) 2008 Paul Neave * http://www.neave.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html */ package com.neave.webcam.effects { import flash.display.*; import flash.events.*; import com.neave.webcam.effects.color.*; import com.neave.webcam.effects.delay.*; import com.neave.webcam.effects.displace.*; import com.neave.webcam.effects.mirror.*; import com.neave.webcam.effects.motion.*; import com.neave.webcam.effects.pixel.*; public class EffectsManager extends EventDispatcher { private var source:IBitmapDrawable; private var targetBitmap:BitmapData; private var effect:AbstractEffect; private var chosenEffect:int; /** * Manages all of the webcam effects * * @param source The source object to use for the effect * @param targetBitmap The target bitmap data to draw the resulting effect into */ public function EffectsManager(source:IBitmapDrawable, targetBitmap:BitmapData) { this.source = source; this.targetBitmap = targetBitmap; // Start with the normal effect effectType = EffectType.NORMAL; } /** * Sets the effect to the next effect in the EffectType class */ public function nextEffect():void { effectType = chosenEffect + 1; } /** * Sets the effect to the previous effect in the EffectType class */ public function previousEffect():void { effectType = chosenEffect - 1; } /** * An integer representing the current effect in the EffectType class */ public function set effectType(type:int):void { // Remove the previous effect if (effect != null) effect.destroy(); // Wrap the chosen effect within the total effects available if (type > EffectType.TOTAL_EFFECTS) type = 0; if (type < 0) type = EffectType.TOTAL_EFFECTS; // Set the effect switch (type) { case EffectType.MIRROR_LEFT: effect = new LeftMirrorEffect (source, targetBitmap); break; //case EffectType.MIRROR_RIGHT: effect = new RightMirrorEffect (source, targetBitmap); break; //case EffectType.MIRROR_TOP: effect = new TopMirrorEffect (source, targetBitmap); break; //case EffectType.MIRROR_BOTTOM: effect = new BottomMirrorEffect (source, targetBitmap); break; case EffectType.MIRROR_INVERSE: effect = new InverseMirrorEffect (source, targetBitmap); break; //case EffectType.MIRROR_QUAD: effect = new QuadMirrorEffect (source, targetBitmap); break; case EffectType.UPSIDE_DOWN: effect = new UpsideDownEffect (source, targetBitmap); break; //case EffectType.DIVIDE: effect = new DivideEffect (source, targetBitmap); break; //case EffectType.FILMSTRIP: effect = new FilmstripEffect (source, targetBitmap); break; case EffectType.FRAGMENT: effect = new FragmentEffect (source, targetBitmap); break; case EffectType.GHOST: effect = new GhostEffect (source, targetBitmap); break; //case EffectType.TRAIL: effect = new TrailEffect (source, targetBitmap); break; //case EffectType.BULGE: effect = new BulgeEffect (source, targetBitmap); break; //case EffectType.FISHEYE: effect = new FisheyeEffect (source, targetBitmap); break; //case EffectType.FISHBOWL: effect = new FishbowlEffect (source, targetBitmap); break; //case EffectType.DENT: effect = new DentEffect (source, targetBitmap); break; //case EffectType.SQUEEZE: effect = new SqueezeEffect (source, targetBitmap); break; case EffectType.WATER: effect = new WaterEffect (source, targetBitmap); break; case EffectType.FIRE: effect = new FireEffect (source, targetBitmap); break; case EffectType.SNOW: effect = new SnowEffect (source, targetBitmap); break; //case EffectType.STEAM: effect = new SteamEffect (source, targetBitmap); break; case EffectType.SWARM: effect = new SwarmEffect (source, targetBitmap); break; //case EffectType.PIXELATE: effect = new PixelateEffect (source, targetBitmap); break; //case EffectType.RGB: effect = new RGBEffect (source, targetBitmap); break; //case EffectType.HALFTONE: effect = new HalftoneEffect (source, targetBitmap); break; case EffectType.MONOCHROME: effect = new MonochromeEffect (source, targetBitmap); break; case EffectType.SEPIA: effect = new SepiaEffect (source, targetBitmap); break; case EffectType.RAINBOW: effect = new RainbowEffect (source, targetBitmap); break; //case EffectType.ASCII: effect = new ASCIIEffect (source, targetBitmap); break; //case EffectType.X_RAY: effect = new XRayEffect (source, targetBitmap); break; //case EffectType.WARHOL: effect = new WarholEffect (source, targetBitmap); break; case EffectType.GLOW: effect = new GlowEffect (source, targetBitmap); break; case EffectType.SLIT_SCAN: effect = new SlitScanEffect (source, targetBitmap); break; case EffectType.NORMAL: default: // Use a normal effect if the passed effect type is not valid type = EffectType.NORMAL; effect = new NormalEffect(source, targetBitmap); break; } // Remember the chosen effect chosenEffect = type; // Tell anything listening that a new effect has been chosen dispatchEvent(new EffectEvent(EffectEvent.NEW_EFFECT, false, false, chosenEffect)); } /** * An integer representing the current effect in the EffectType class */ public function get effectType():int { return chosenEffect; } /** * The proper name of the current effect */ public function get effectName():String { return effect.effectName; } /** * Updates the appearance of the current effect */ public function update():void { effect.draw(); } /** * Removes the current effect */ public function destroy():void { effect.destroy(); } } } \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/NormalEffect.as b/webcam/com/neave/webcam/effects/NormalEffect.as
new file mode 100755
index 0000000..b97e896
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/NormalEffect.as
@@ -0,0 +1,38 @@
+/**
+ * Neave Webcam // Normal Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects
+{
+ import flash.display.*;
+
+ public class NormalEffect extends AbstractEffect
+ {
+ /**
+ * Creates a normal effect for copying the source object into the target bitmap data without modification
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function NormalEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Normal");
+ }
+
+ /**
+ * Draws the normal effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+ targetBitmap.copyPixels(sourceBitmap, rect, point);
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/color/GlowEffect.as b/webcam/com/neave/webcam/effects/color/GlowEffect.as
new file mode 100755
index 0000000..5c96e71
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/color/GlowEffect.as
@@ -0,0 +1,68 @@
+/**
+ * Neave Webcam // Glow Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.color
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class GlowEffect extends AbstractEffect
+ {
+ private var edge:ConvolutionFilter;
+ private var blur:BlurFilter;
+
+ /**
+ * Creates a high constrast glow effect around surface edges
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function GlowEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Glow");
+
+ createGlow();
+ }
+
+ /**
+ * Sets up the glow effect
+ */
+ private function createGlow():void
+ {
+ // Increase contrast
+ color = new ColorTransform(2, 2, 2, 1, -100, -100, -100);
+
+ // Set up a large horizontal edge convoluton filter
+ var m:Array =
+ [
+ -100, -100, -100,
+ 100, 100, 100,
+ 0, 0, 0
+ ];
+ edge = new ConvolutionFilter(3, 3, m, 9);
+
+ // Blur the edges to create a smooth glow
+ blur = new BlurFilter(8, 8, 2);
+ }
+
+ /**
+ * Draws the glow effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+ sourceBitmap.applyFilter(sourceBitmap, rect, point, blur);
+ targetBitmap.applyFilter(sourceBitmap, rect, point, edge);
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/color/MonochromeEffect.as b/webcam/com/neave/webcam/effects/color/MonochromeEffect.as
new file mode 100755
index 0000000..ed14de9
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/color/MonochromeEffect.as
@@ -0,0 +1,61 @@
+/**
+ * Neave Webcam // Monochrome (Black & White) Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+package com.neave.webcam.effects.color
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class MonochromeEffect extends AbstractEffect
+ {
+ private var monochrome:ColorMatrixFilter;
+
+ /**
+ * Creates a high contrast black and white monochrome effect
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function MonochromeEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Black & White");
+
+ createMonochrome();
+ }
+
+ /**
+ * Sets up the monochrome effect
+ */
+ private function createMonochrome():void
+ {
+ // Add punch with more contrast
+ color = new ColorTransform(2, 2, 2, 1, -100, -100, -100);
+
+ // Monochrome colour matrix
+ var m:Array = new Array();
+ m = m.concat([0.3, 0.59, 0.11, 0, 0]); // Red
+ m = m.concat([0.3, 0.59, 0.11, 0, 0]); // Green
+ m = m.concat([0.3, 0.59, 0.11, 0, 0]); // Blue
+ m = m.concat([0, 0, 0, 1, 0]); // Alpha
+ monochrome = new ColorMatrixFilter(m);
+ }
+
+ /**
+ * Draws the monochrome effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+ targetBitmap.applyFilter(sourceBitmap, rect, point, monochrome);
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/color/RainbowEffect.as b/webcam/com/neave/webcam/effects/color/RainbowEffect.as
new file mode 100755
index 0000000..3b5b70b
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/color/RainbowEffect.as
@@ -0,0 +1,90 @@
+/**
+ * Neave Webcam // Rainbow Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.color
+{
+ import flash.display.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class RainbowEffect extends AbstractEffect
+ {
+ private var red:Array;
+ private var green:Array;
+ private var blue:Array;
+
+ /**
+ * Creates a psychedelic colour-cycling effect
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function RainbowEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Rainbow");
+
+ createRainbow();
+ }
+
+ /**
+ * Sets up the rainbow effect
+ */
+ private function createRainbow():void
+ {
+ // Add punch with more contrast
+ color = new ColorTransform(2, 2, 2, 1, -100, -100, -100);
+
+ // Set up colour arrays
+ red = new Array(256);
+ green = new Array(256);
+ blue = new Array(256);
+
+ // Populate colour arrays with a curved gradient
+ for (var i:int = 0; i < 256; i++)
+ {
+ red[i] = Math.sin(i / 0xFF * Math.PI) * 0xFF << 16;
+ green[i] = Math.sin(i / 0xFF * Math.PI) * 0xFF << 8;
+ blue[i] = Math.sin(i / 0xFF * Math.PI) * 0xFF;
+ }
+ }
+
+ /**
+ * Draws the rainbow effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+
+ red.push(red.splice(0, 1));
+ green.unshift(green.pop());
+ green.unshift(green.pop());
+ if (Math.random() < 0.5) green.unshift(green.pop());
+ blue.unshift(blue.pop());
+ blue.unshift(blue.pop());
+ blue.unshift(blue.pop());
+ if (Math.random() < 0.5) blue.unshift(blue.pop());
+ if (Math.random() < 0.5) blue.unshift(blue.pop());
+
+ targetBitmap.paletteMap(sourceBitmap, rect, point, red, green, blue);
+ }
+
+ /**
+ * Removes the rainbow effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+ red = null;
+ green = null;
+ blue = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/color/SepiaDirt.as b/webcam/com/neave/webcam/effects/color/SepiaDirt.as
new file mode 100755
index 0000000..4b03f65
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/color/SepiaDirt.as
@@ -0,0 +1,31 @@
+/**
+ * Neave Webcam // Sepia Dirt
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.color
+{
+ import flash.display.*;
+
+ final internal class SepiaDirt extends Shape
+ {
+ /**
+ * Creates a black circular shape to be used with the sepia effect
+ *
+ * @param x The position of the dirt on the x-axis
+ * @param y The position of the dirt on the y-axis
+ * @param radius The radius of the dirt
+ */
+ public function SepiaDirt(x:Number = 0, y:Number = 0, radius:Number = 1)
+ {
+ graphics.beginFill(0x000000);
+ graphics.drawCircle(x, y, radius);
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/color/SepiaEffect.as b/webcam/com/neave/webcam/effects/color/SepiaEffect.as
new file mode 100755
index 0000000..f7d2ebe
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/color/SepiaEffect.as
@@ -0,0 +1,90 @@
+/**
+ * Neave Webcam // Sepia Movie Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.color
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class SepiaEffect extends AbstractEffect
+ {
+ private var frameStep:int;
+ private var sepia:ColorMatrixFilter;
+ private var count:uint;
+ private var linePos:Number;
+
+ /**
+ * Creates an animated sepia effect like an old projector movie
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param frameStep The number of frames to step over to create a jittery movie effect
+ */
+ public function SepiaEffect(source:IBitmapDrawable, targetBitmap:BitmapData, frameStep:int = 3)
+ {
+ super(source, targetBitmap, "Sepia Movie");
+ this.frameStep = frameStep < 1 ? 1 : frameStep;
+
+ createSepia();
+ }
+
+ /**
+ * Sets up the sepia effect
+ */
+ private function createSepia():void
+ {
+ // Reset variables
+ count = linePos = 0;
+
+ // Sepia colour matrix
+ var m:Array = new Array();
+ m = m.concat([0.3, 0.59, 0.11, 0, 0]); // Red
+ m = m.concat([0.246, 0.4838, 0.0902, 0, 10]); // Green
+ m = m.concat([0.15, 0.295, 0.055, 0, 10]); // Blue
+ m = m.concat([0, 0, 0, 1, 0]); // Alpha
+ sepia = new ColorMatrixFilter(m);
+ }
+
+ /**
+ * Draws the sepia effect
+ */
+ override public function draw():void
+ {
+ if (count == 0)
+ {
+ super.draw();
+
+ // Tint source bitmap sepia
+ sourceBitmap.applyFilter(sourceBitmap, rect, point, sepia);
+
+ // Create old movie style black vertical line on one side
+ linePos += (Math.random() * rect.width * 0.25 - linePos) * 0.04;
+ if (Math.random() < 0.05) linePos = rect.width;
+ if (Math.random() < 0.05) linePos = rect.width * 0.2;
+ if (Math.random() < 0.5) sourceBitmap.fillRect(new Rectangle(Math.round(linePos), 0, 1, rect.height), 0xFF000000);
+
+ // Create random dirt with one big spot every so often
+ for (var i:int = 4; i--; ) sourceBitmap.draw(new SepiaDirt(Math.random() * rect.width, Math.random() * rect.height, Math.random() < 0.995 ? Math.random() + 0.5 : Math.random() * 10 + 15));
+
+ // Draw source bitmap into target bitmap with a slight flicker
+ var mult:uint = Math.random() * 64 + (255 - 64);
+ targetBitmap.lock();
+ targetBitmap.fillRect(rect, 0xFF000000);
+ targetBitmap.merge(sourceBitmap, rect, point, mult, mult, mult, 0);
+ targetBitmap.unlock();
+ }
+ count++;
+ count %= frameStep;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/color/WarholEffect.as b/webcam/com/neave/webcam/effects/color/WarholEffect.as
new file mode 100755
index 0000000..81f8289
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/color/WarholEffect.as
@@ -0,0 +1,99 @@
+/**
+ * Neave Webcam // Andy Warhol Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.color
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class WarholEffect extends AbstractEffect
+ {
+ private var smallBitmap:BitmapData;
+ private var pos1:Point;
+ private var pos2:Point;
+ private var pos3:Point;
+ private var pos4:Point;
+
+ /**
+ * Creates an Andy Warhol-style Pop Art effect with four highly constrasted tricolour images
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function WarholEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Andy Warhol");
+
+ createWarhol();
+ }
+
+ /**
+ * Sets up the Warhol effect
+ */
+ private function createWarhol():void
+ {
+ // Create a bitmap quarter the size of the original
+ smallBitmap = new BitmapData(Math.round(rect.width / 2), Math.round(rect.height / 2), false, 0xFF000000);
+ sourceMatrix.scale(0.5, 0.5);
+
+ // Positions of each image
+ pos1 = new Point(0, 0);
+ pos2 = new Point(smallBitmap.width, 0);
+ pos3 = new Point(0, smallBitmap.height);
+ pos4 = new Point(smallBitmap.width, smallBitmap.height);
+ }
+
+ /**
+ * Draws a tricolour (three colour) image from the passed bitmap into the target bitmap data
+ *
+ * @param bitmapData The source bitmap data to draw the tricolour from
+ * @param pos The position to draw tricolour
+ * @param color1 The background colour
+ * @param color2 The middle colour
+ * @param color3 The highlight colour
+ */
+ private function drawTricolor(bitmapData:BitmapData, pos:Point, color1:uint, color2:uint, color3:uint):void
+ {
+ // Limit the pixels in the bitmap data to three colours only
+ targetBitmap.threshold(bitmapData, rect, pos, "<=", 0xFFAAAAAA, color2);
+ targetBitmap.threshold(bitmapData, rect, pos, ">", 0xFFAAAAAA, color3);
+ targetBitmap.threshold(bitmapData, rect, pos, "<", 0xFF555555, color1);
+ }
+
+ /**
+ * Draws the Warhol effect
+ */
+ override public function draw():void
+ {
+ smallBitmap.draw(source, sourceMatrix);
+
+ targetBitmap.lock();
+ drawTricolor(smallBitmap, pos1, 0xFF0080FF, 0xFFFFFF00, 0xFFFF0080);
+ drawTricolor(smallBitmap, pos2, 0xFF202020, 0xFFFF0000, 0xFFFFFFFF);
+ drawTricolor(smallBitmap, pos3, 0xFFA040A0, 0xFFFF9900, 0xFF80C0FF);
+ drawTricolor(smallBitmap, pos4, 0xFF40A000, 0xFFFFFFA0, 0xFFFFA0FF);
+ targetBitmap.unlock();
+ }
+
+ /**
+ * Removes the Warhol effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+ smallBitmap.dispose();
+ smallBitmap = null;
+ pos1 = pos2 = pos3 = pos4 = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/color/XRayEffect.as b/webcam/com/neave/webcam/effects/color/XRayEffect.as
new file mode 100755
index 0000000..06067bd
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/color/XRayEffect.as
@@ -0,0 +1,62 @@
+/**
+ * Neave Webcam // X-Ray Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.color
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class XRayEffect extends AbstractEffect
+ {
+ private var cyanWash:ColorMatrixFilter;
+
+ /**
+ * Creates a mock x-ray effect by inverting the image
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function XRayEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "X-Ray");
+
+ createXRay();
+ }
+
+ /**
+ * Sets up the x-ray effect
+ */
+ private function createXRay():void
+ {
+ // Invert the image
+ color = new ColorTransform(-1.5, -1.5, -1.5, 1, 0xFF, 0xFF, 0xFF);
+
+ // Monochrome colour matrix with a cyan tint
+ var m:Array = new Array();
+ m = m.concat([0.3, 0.59, 0.11, 0, 0]); // Red
+ m = m.concat([0.3, 0.59, 0.11, 0, 40]); // Green
+ m = m.concat([0.3, 0.59, 0.11, 0, 50]); // Blue
+ m = m.concat([0, 0, 0, 1, 0]); // Alpha
+ cyanWash = new ColorMatrixFilter(m);
+ }
+
+ /**
+ * Draws the x-ray effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+ targetBitmap.applyFilter(sourceBitmap, rect, point, cyanWash);
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/delay/DivideEffect.as b/webcam/com/neave/webcam/effects/delay/DivideEffect.as
new file mode 100755
index 0000000..5e9cfee
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/delay/DivideEffect.as
@@ -0,0 +1,99 @@
+/**
+ * Neave Webcam // Delayed Divide Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.delay
+{
+ import flash.display.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class DivideEffect extends AbstractEffect
+ {
+ private var frames:int;
+ private var divideBitmaps:Array;
+ private var divideRect:Rectangle;
+ private var dividePoint:Point;
+
+ /**
+ * Creates a split screen effect where the lower half of the image is delayed
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param frames The number of frames to delay the lower half of the image by
+ */
+ public function DivideEffect(source:IBitmapDrawable, targetBitmap:BitmapData, frames:int = 30)
+ {
+ super(source, targetBitmap, "Delayed Divide");
+ this.frames = frames < 2 ? 2 : frames;
+
+ createDivide();
+ }
+
+ /**
+ * Sets up the divide effect
+ */
+ private function createDivide():void
+ {
+ // Define the lower half area and its top left position
+ divideRect = new Rectangle(0, rect.height / 2, rect.width, rect.height / 2);
+ dividePoint = new Point(0, rect.height / 2);
+
+ // Draw the delayed bitmap into the lower half
+ var m:Matrix = sourceMatrix.clone();
+ m.translate(0, -rect.height / 2);
+
+ // Create an array of bitmaps to store the delayed frames
+ divideBitmaps = new Array();
+ for (var i:int = frames; i--; )
+ {
+ var b:BitmapData = new BitmapData(rect.width, rect.height / 2, false, 0xFF000000);
+ b.draw(source, m, color, null, rect, true); // Start with the current source image
+ divideBitmaps.push(b);
+ }
+ }
+
+ /**
+ * Draws the divide effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+
+ // Loop through all the delayed frames
+ for (var i:int = frames; i--; )
+ {
+ var b:BitmapData = divideBitmaps[i];
+ if (i == 0) b.copyPixels(sourceBitmap, divideRect, point); // Draw the current source image into frame 0
+ else b.copyPixels(divideBitmaps[i - 1], b.rect, point); // Move the other frames along the array
+ }
+
+ // Draw the final delayed frame into the lower half with the current source image
+ sourceBitmap.copyPixels(divideBitmaps[frames - 1], divideBitmaps[0].rect, dividePoint);
+ targetBitmap.copyPixels(sourceBitmap, rect, point);
+ }
+
+ /**
+ * Removes the divide effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+
+ // Remove all the frame bitmaps
+ for (var i:int = frames; i--; )
+ {
+ divideBitmaps[i].dispose();
+ divideBitmaps[i] = null;
+ }
+ divideBitmaps = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/delay/FilmstripEffect.as b/webcam/com/neave/webcam/effects/delay/FilmstripEffect.as
new file mode 100755
index 0000000..ce324b1
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/delay/FilmstripEffect.as
@@ -0,0 +1,91 @@
+/**
+ * Neave Webcam // Filmstrip Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.delay
+{
+ import flash.display.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class FilmstripEffect extends AbstractEffect
+ {
+ private var scale:int;
+ private var total:int;
+ private var filmstrip:Array;
+
+ /**
+ * Creates a grid of delayed images, each delayed by one frame after the previous frame
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param scale The number of images to use along the width and height of the grid
+ */
+ public function FilmstripEffect(source:IBitmapDrawable, targetBitmap:BitmapData, scale:int = 8)
+ {
+ super(source, targetBitmap, "Filmstrip");
+ this.scale = scale < 2 ? 2 : scale;
+
+ createFilmstrip();
+ }
+
+ /**
+ * Sets up the filmstrip effect
+ */
+ private function createFilmstrip():void
+ {
+ // Resize the source to the set scale
+ sourceMatrix.scale(1 / scale, 1 / scale);
+
+ // Create an array of bitmaps to store the delayed frames
+ total = scale * scale;
+ filmstrip = new Array();
+ for (var i:int = total; i--; )
+ {
+ var b:BitmapData = new BitmapData(rect.width / scale, rect.height / scale, false, 0xFF000000);
+ b.draw(source, sourceMatrix, color, null, null, true);
+ filmstrip.push(b);
+ }
+ }
+
+ /**
+ * Draws the filmstrip effect
+ */
+ override public function draw():void
+ {
+ // Loop through all the delayed frames
+ targetBitmap.lock();
+ for (var i:int = total; i--; )
+ {
+ var b:BitmapData = filmstrip[i];
+ if (i == 0) b.draw(source, sourceMatrix, color); // Draw the source at a smaller size into frame 0
+ else b.copyPixels(filmstrip[i - 1], b.rect, point); // Move the other frames along the array
+ targetBitmap.copyPixels(b, b.rect, new Point((scale - (i % scale) - 1) * rect.width / scale, int(i / scale) * rect.height / scale)); // Draw this frame in position
+ }
+ targetBitmap.unlock();
+ }
+
+ /**
+ * Removes the divide effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+
+ // Remove all the filmstrip bitmaps
+ for (var i:int = total; i--; )
+ {
+ filmstrip[i].dispose();
+ filmstrip[i] = null;
+ }
+ filmstrip = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/delay/GhostEffect.as b/webcam/com/neave/webcam/effects/delay/GhostEffect.as
new file mode 100755
index 0000000..35c5787
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/delay/GhostEffect.as
@@ -0,0 +1,89 @@
+/**
+ * Neave Webcam // Ghost Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.delay
+{
+ import flash.display.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class GhostEffect extends AbstractEffect
+ {
+ private var frames:int;
+ private var ghostBitmaps:Array;
+
+ /**
+ * Creates a ghost effect where the source image is delayed then blended with the current image
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param frames The number of frames to delay the ghost image by
+ */
+ public function GhostEffect(source:IBitmapDrawable, targetBitmap:BitmapData, frames:int = 30)
+ {
+ super(source, targetBitmap, "Ghost");
+ this.frames = frames < 2 ? 2 : frames;
+
+ createGhost();
+ }
+
+ /**
+ * Sets up the ghost effect
+ */
+ private function createGhost():void
+ {
+ // Create an array of bitmaps to store the delayed frames
+ ghostBitmaps = new Array();
+ for (var i:int = frames; i--; )
+ {
+ var b:BitmapData = sourceBitmap.clone();
+ b.draw(source, null, color, null, null, true); // Start with the current source image
+ ghostBitmaps.push(b);
+ }
+ }
+
+ /**
+ * Draws the ghost effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+
+ // Loop through all the delayed frames
+ for (var i:int = frames; i--; )
+ {
+ var b:BitmapData = ghostBitmaps[i];
+ if (i == 0) b.copyPixels(sourceBitmap, rect, point); // Draw the current source image into frame 0
+ else b.copyPixels(ghostBitmaps[i - 1], rect, point); // Move the other frames along the array
+ }
+
+ // Blend the final delayed frame with the current source image
+ sourceBitmap.merge(ghostBitmaps[frames - 1], rect, point, 128, 128, 128, 0);
+ targetBitmap.copyPixels(sourceBitmap, rect, point);
+ }
+
+ /**
+ * Removes the ghost effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+
+ // Remove all the frame bitmaps
+ for (var i:int = frames; i--; )
+ {
+ ghostBitmaps[i].dispose();
+ ghostBitmaps[i] = null;
+ }
+ ghostBitmaps = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/delay/SlitScanEffect.as b/webcam/com/neave/webcam/effects/delay/SlitScanEffect.as
new file mode 100755
index 0000000..37eb00c
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/delay/SlitScanEffect.as
@@ -0,0 +1,178 @@
+/**
+ * Neave Webcam // Slit Scan Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.delay
+{
+ import flash.display.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class SlitScanEffect extends AbstractEffect
+ {
+ private const MAX_SLITS:int = 60;
+
+ private var slitHeight:int;
+ private var slitScale:Number;
+ private var initScale:Number;
+ private var total:int;
+ private var slitBitmaps:Array;
+ private var slitMatrix:Matrix;
+ private var slitRect:Rectangle;
+ private var halfBitmap:BitmapData;
+ private var topMatrix:Matrix;
+ private var bottomPoint:Point;
+ private var moveUp:Boolean;
+ private var midX:Number;
+
+ /**
+ * Creates a slit scan effect, similar to the final scene in 2001: A Space Odyssey
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param slitHeight The height of the slit to capture in pixels
+ * @param slitScale How much to increase the size of each slit by
+ * @param initScale The scale of the first slit
+ */
+ public function SlitScanEffect(source:IBitmapDrawable, targetBitmap:BitmapData, slitHeight:int = 1, slitScale:Number = 1.125, initScale:Number = 0.25)
+ {
+ super(source, targetBitmap, "Slit Scan");
+ this.slitHeight = slitHeight < 1 ? 1 : slitHeight;
+ this.slitScale = slitScale < 0.1 ? 0.1 : slitScale;
+ this.initScale = initScale < 0.1 ? 0.1 : initScale;
+
+ createSlitScan();
+ }
+
+ /**
+ * Sets up the slit scan effect
+ */
+ private function createSlitScan():void
+ {
+ // Slit dimensions
+ slitMatrix = new Matrix();
+ slitRect = new Rectangle(0, 0, rect.width, slitHeight);
+
+ // Create a half-sized bitmap to contain all the slit scans
+ halfBitmap = new BitmapData(rect.width, Math.round(rect.height / 2), false, 0xFF000000);
+ topMatrix = new Matrix(1, 0, 0, -1, 0, halfBitmap.height);
+ bottomPoint = new Point(0, halfBitmap.height);
+
+ // Create an array of bitmaps to store the slits
+ slitBitmaps = new Array();
+ setTotal();
+ for (var i:int = total; i--; )
+ {
+ var b:BitmapData = new BitmapData(rect.width, slitHeight, false, 0xFF000000);
+ b.draw(source, null, color, null, slitRect, true); // Start with the current source image
+ slitBitmaps.push(b);
+ }
+
+ // Other variables
+ moveUp = false;
+ midX = rect.width / 2 / initScale - rect.width / 2;
+ }
+
+ /**
+ * Calculates the total number of slits needed to cover the half-sized bitmap
+ */
+ private function setTotal():void
+ {
+ total = 0;
+ var size:Number = slitHeight * initScale;
+ var lastSize:Number = size;
+
+ // Loop through the slit sizes, increasing in height until the size is bigger than the bitmap height
+ while (size < halfBitmap.height && total < MAX_SLITS)
+ {
+ var nextSize:Number = lastSize * slitScale;
+ lastSize = nextSize;
+ size += nextSize;
+ total++;
+ }
+ }
+
+ /**
+ * Moves the slit position up or down the source image
+ */
+ private function moveSlit():void
+ {
+ if (moveUp)
+ {
+ // Moving up or reversing direction
+ if (slitRect.top > 1) slitRect.offset(0, -slitHeight);
+ else moveUp = false;
+ }
+ else
+ {
+ // Moving down or reversing direction
+ if (slitRect.top < rect.height - slitHeight - 1) slitRect.offset(0, slitHeight);
+ else moveUp = true;
+ }
+ }
+
+ /**
+ * Draw the slit scan effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+
+ // Move the slit up or down
+ moveSlit();
+
+ // Set slit to initial position and size
+ slitMatrix.identity();
+ slitMatrix.tx = midX;
+ slitMatrix.scale(initScale, initScale);
+
+ // Draw each slit
+ for (var i:int = total; i--; )
+ {
+ // Draw or move each slit along the array
+ var b:BitmapData = slitBitmaps[i];
+ if (i == 0) b.copyPixels(sourceBitmap, slitRect, point); // Draw the current source image into slit 0
+ else b.copyPixels(slitBitmaps[i - 1], b.rect, point); // Move the other slits along the array
+
+ // Scale each slit up and position in the middle
+ slitMatrix.scale(slitScale, slitScale);
+ slitMatrix.translate(rect.width / 2 * (1 - slitScale), slitHeight * initScale);
+
+ // Draw this new slit into the main half-size bitmap
+ halfBitmap.draw(slitBitmaps[total - i - 1], slitMatrix, null, null, null, true);
+ }
+
+ // Draw the half-size bitmaps into the top and bottom
+ targetBitmap.lock();
+ targetBitmap.draw(halfBitmap, topMatrix);
+ targetBitmap.copyPixels(halfBitmap, halfBitmap.rect, bottomPoint);
+ targetBitmap.unlock();
+ }
+
+ /**
+ * Removes the slit scan effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+
+ // Remove all the frame bitmaps
+ for (var i:int = total; i--; )
+ {
+ slitBitmaps[i].dispose();
+ slitBitmaps[i] = null;
+ }
+ slitBitmaps = null;
+
+ halfBitmap.dispose();
+ halfBitmap = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/delay/TrailEffect.as b/webcam/com/neave/webcam/effects/delay/TrailEffect.as
new file mode 100755
index 0000000..41a9c91
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/delay/TrailEffect.as
@@ -0,0 +1,68 @@
+/**
+ * Neave Webcam // Trail Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.delay
+{
+ import flash.display.*;
+ import com.neave.webcam.effects.*;
+
+ public class TrailEffect extends AbstractEffect
+ {
+ private var fade:uint;
+ private var whiteBitmap:BitmapData;
+
+ /**
+ * Creates a trail effect by smearing and fading out movement
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param fade The amount to fade out the trail by each frame, the higher the faster
+ */
+ public function TrailEffect(source:IBitmapDrawable, targetBitmap:BitmapData, fade:uint = 8)
+ {
+ super(source, targetBitmap, "Trail");
+ this.fade = fade > 0xFF ? 0xFF: fade;
+
+ createTrail();
+ }
+
+ /**
+ * Sets up the trail effect
+ */
+ private function createTrail():void
+ {
+ whiteBitmap = new BitmapData(rect.width, rect.height, false, 0xFFFFFFFF); // White bitmap for fading out the trail
+ targetBitmap.draw(source, null, color, null, null, true); // Start with the current source image
+ }
+
+ /**
+ * Draws the trail effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+ targetBitmap.lock();
+ targetBitmap.merge(whiteBitmap, rect, point, fade, fade, fade, 0); // Repeatedly fade out the image
+ targetBitmap.draw(sourceBitmap, null, null, BlendMode.DARKEN); // Blend the new source image with the old one
+ targetBitmap.unlock();
+ }
+
+ /**
+ * Removes the divide effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+ whiteBitmap.dispose();
+ whiteBitmap = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/displace/AbstractDisplaceEffect.as b/webcam/com/neave/webcam/effects/displace/AbstractDisplaceEffect.as
new file mode 100755
index 0000000..89458ac
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/displace/AbstractDisplaceEffect.as
@@ -0,0 +1,64 @@
+/**
+ * Neave Webcam // Abstract Displace Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.displace
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import com.neave.webcam.effects.*;
+
+ internal class AbstractDisplaceEffect extends AbstractEffect
+ {
+ protected var displace:DisplacementMapFilter;
+
+ /**
+ * An abstract displacement effect class, not to be instantiated
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param name The proper name of the effect
+ */
+ public function AbstractDisplaceEffect(source:IBitmapDrawable, targetBitmap:BitmapData, name:String = "")
+ {
+ super(source, targetBitmap, name);
+
+ createAbstractDisplace();
+ }
+
+ /**
+ * Sets up the displacement effect
+ */
+ private function createAbstractDisplace():void
+ {
+ // Create a displacement map filter with grey bitmap data, using red to distort horizontally, green to distort vertically
+ displace = new DisplacementMapFilter(new BitmapData(rect.width, rect.height, false, 0xFF808080), point, BitmapDataChannel.RED, BitmapDataChannel.GREEN, 0, 0, DisplacementMapFilterMode.CLAMP);
+ }
+
+ /**
+ * Draws the displacement effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+ targetBitmap.applyFilter(sourceBitmap, rect, point, displace);
+ }
+
+ /**
+ * Removes the displacement effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+ displace.mapBitmap.dispose();
+ displace = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/displace/BulgeEffect.as b/webcam/com/neave/webcam/effects/displace/BulgeEffect.as
new file mode 100755
index 0000000..d2c1ac2
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/displace/BulgeEffect.as
@@ -0,0 +1,74 @@
+/**
+ * Neave Webcam // Bulge Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.displace
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+
+ public class BulgeEffect extends AbstractDisplaceEffect
+ {
+ /**
+ * Creates a bulge effect that pushes the centre of the image outwards
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function BulgeEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Bulge");
+
+ createBulge();
+ }
+
+ /**
+ * Sets up the bulge effect
+ */
+ private function createBulge():void
+ {
+ // The size of the bulge, one quarter the size of the source image
+ var w:int = rect.width;
+ var h:int = rect.height;
+ var size:int = Math.round((w + h) / 4);
+
+ // The displacement gradient matrix
+ var m:Matrix = new Matrix();
+ m.createGradientBox(size, size);
+
+ // Grey radial gradient to smooth the edges of the distortion
+ var cover:Shape = new Shape();
+ cover.graphics.beginGradientFill(GradientType.RADIAL, [0x808080, 0x808080], [0, 1], [0x00, 0xFF], m);
+ cover.graphics.drawRect(0, 0, size, size);
+
+ // Red gradient to distort pixels horizontally
+ var red:Shape = new Shape();
+ red.graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0x000000], [1, 1], [0x00, 0xFF], m);
+ red.graphics.drawRect(0, 0, size, size);
+
+ // Green gradient to distort pixels vertically
+ var green:Shape = new Shape();
+ m.rotate(Math.PI / 2);
+ green.graphics.beginGradientFill(GradientType.LINEAR, [0x00FF00, 0x000000], [1, 1], [0x00, 0xFF], m);
+ green.graphics.drawRect(0, 0, size, size);
+
+ // Draw all the gradients into one displacement map bitmap
+ var mapMatrix:Matrix = new Matrix();
+ mapMatrix.translate(w / 2 - size / 2, h / 2 - size / 2);
+ displace.mapBitmap.draw(red, mapMatrix);
+ displace.mapBitmap.draw(green, mapMatrix, null, BlendMode.ADD);
+ displace.mapBitmap.draw(cover, mapMatrix);
+
+ // Set the size of the displacement
+ displace.scaleX = displace.scaleY = size;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/displace/DentEffect.as b/webcam/com/neave/webcam/effects/displace/DentEffect.as
new file mode 100755
index 0000000..c701146
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/displace/DentEffect.as
@@ -0,0 +1,75 @@
+/**
+ * Neave Webcam // Dent Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.displace
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+
+ public class DentEffect extends AbstractDisplaceEffect
+ {
+ /**
+ * Creates a dent effect that pinches the centre of the image inwards
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function DentEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Dent");
+
+ createDent();
+ }
+
+ /**
+ * Sets up the dent effect
+ */
+ private function createDent():void
+ {
+ // The size of the dent, one quarter the size of the source image
+ var w:int = rect.width;
+ var h:int = rect.height;
+ var size:int = Math.round((w + h) / 4);
+
+ // The displacement gradient matrix
+ var m:Matrix = new Matrix();
+ m.createGradientBox(size, size);
+
+ // Grey radial gradient to smooth the edges of the distortion
+ var cover:Shape = new Shape();
+ cover.graphics.beginGradientFill(GradientType.RADIAL, [0x808080, 0x808080], [0, 1], [0x00, 0xFF], m);
+ cover.graphics.drawRect(0, 0, size, size);
+
+ // Red gradient to distort pixels horizontally
+ var red:Shape = new Shape();
+ red.graphics.beginGradientFill(GradientType.LINEAR, [0x000000, 0xFF0000], [1, 1], [0x00, 0xFF], m);
+ red.graphics.drawRect(0, 0, size, size);
+
+ // Green gradient to distort pixels vertically
+ var green:Shape = new Shape();
+ m.rotate(Math.PI / 2);
+ green.graphics.beginGradientFill(GradientType.LINEAR, [0x000000, 0x00FF00], [1, 1], [0x00, 0xFF], m);
+ green.graphics.drawRect(0, 0, size, size);
+
+ // Draw all the gradients into one displacement map bitmap
+ var mapMatrix:Matrix = new Matrix();
+ mapMatrix.translate(w / 2 - size / 2, h / 2 - size / 2);
+ displace.mapBitmap.draw(red, mapMatrix);
+ displace.mapBitmap.draw(green, mapMatrix, null, BlendMode.ADD);
+ displace.mapBitmap.draw(cover, mapMatrix);
+
+ // Double up the grey cover for a greater dent size
+ displace.mapBitmap.draw(cover, mapMatrix);
+ displace.scaleX = displace.scaleY = size * 2;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/displace/FishbowlEffect.as b/webcam/com/neave/webcam/effects/displace/FishbowlEffect.as
new file mode 100755
index 0000000..08f5d08
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/displace/FishbowlEffect.as
@@ -0,0 +1,72 @@
+/**
+ * Neave Webcam // Fishbowl Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.displace
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+
+ public class FishbowlEffect extends AbstractDisplaceEffect
+ {
+ /**
+ * Creates a fishbowl effect like looking into a fishbowl, the opposite of the fisheye effect
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function FishbowlEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Fishbowl");
+
+ createFishbowl();
+ }
+
+ /**
+ * Sets up the fishbowl effect
+ */
+ private function createFishbowl():void
+ {
+ // The size of the fishbowl effect
+ var w:int = rect.width;
+ var h:int = rect.height;
+ var size:int = Math.round(Math.sqrt((w / 2) * (w / 2) + (h / 2) * (h / 2)) * 2);
+
+ // The displacement gradient matrix
+ var m:Matrix = new Matrix();
+ m.createGradientBox(size, size, 0, w / 2 - size / 2, h / 2 - size / 2);
+
+ // Grey radial gradient to smooth the edges of the distortion
+ var cover:Shape = new Shape();
+ cover.graphics.beginGradientFill(GradientType.RADIAL, [0x808080, 0x808080], [1, 0], [0x00, 0xFF], m);
+ cover.graphics.drawRect(0, 0, w, h);
+
+ // Red gradient to distort pixels horizontally
+ var red:Shape = new Shape();
+ red.graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0x000000], [1, 1], [0x00, 0xFF], m);
+ red.graphics.drawRect(0, 0, w, h);
+
+ // Green gradient to distort pixels vertically
+ var green:Shape = new Shape();
+ m.rotate(Math.PI / 2);
+ green.graphics.beginGradientFill(GradientType.LINEAR, [0x00FF00, 0x000000], [1, 1], [0x00, 0xFF], m);
+ green.graphics.drawRect(0, 0, w, h);
+
+ // Draw all the gradients into one displacement map bitmap
+ displace.mapBitmap.draw(red);
+ displace.mapBitmap.draw(green, null, null, BlendMode.ADD);
+ displace.mapBitmap.draw(cover);
+
+ // Set the size of the displacement
+ displace.scaleX = displace.scaleY = size;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/displace/FisheyeEffect.as b/webcam/com/neave/webcam/effects/displace/FisheyeEffect.as
new file mode 100755
index 0000000..1d4cf4a
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/displace/FisheyeEffect.as
@@ -0,0 +1,72 @@
+/**
+ * Neave Webcam // Fisheye Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.displace
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+
+ public class FisheyeEffect extends AbstractDisplaceEffect
+ {
+ /**
+ * Creates a fisheye (wide-angle) lens effect
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function FisheyeEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Fisheye");
+
+ createFisheye();
+ }
+
+ /**
+ * Sets up the fisheye effect
+ */
+ private function createFisheye():void
+ {
+ // The size of the fisheye effect
+ var w:int = rect.width;
+ var h:int = rect.height;
+ var size:int = (w + h) / 2;
+
+ // The displacement gradient matrix
+ var m:Matrix = new Matrix();
+ m.createGradientBox(size, size, 0, w / 2 - size / 2, h / 2 - size / 2);
+
+ // Grey radial gradient to smooth the edges of the distortion
+ var cover:Shape = new Shape();
+ cover.graphics.beginGradientFill(GradientType.RADIAL, [0x808080, 0x808080], [0, 1], [0x00, 0xFF], m, SpreadMethod.REFLECT);
+ cover.graphics.drawRect(0, 0, w, h);
+
+ // Red gradient to distort pixels horizontally
+ var red:Shape = new Shape();
+ red.graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0x000000], [1, 1], [0x00, 0xFF], m);
+ red.graphics.drawRect(0, 0, w, h);
+
+ // Green gradient to distort pixels vertically
+ var green:Shape = new Shape();
+ m.rotate(Math.PI / 2);
+ green.graphics.beginGradientFill(GradientType.LINEAR, [0x00FF00, 0x000000], [1, 1], [0x00, 0xFF], m);
+ green.graphics.drawRect(0, 0, w, h);
+
+ // Draw all the gradients into one displacement map bitmap
+ displace.mapBitmap.draw(red);
+ displace.mapBitmap.draw(green, null, null, BlendMode.ADD);
+ displace.mapBitmap.draw(cover);
+
+ // Set the size of the displacement
+ displace.scaleX = displace.scaleY = size;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/displace/FragmentEffect.as b/webcam/com/neave/webcam/effects/displace/FragmentEffect.as
new file mode 100755
index 0000000..e058dd9
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/displace/FragmentEffect.as
@@ -0,0 +1,101 @@
+/**
+ * Neave Webcam // Fragment Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.displace
+{
+ import flash.display.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class FragmentEffect extends AbstractEffect
+ {
+ private var fragmentsWide:int;
+ private var scale:Number;
+ private var total:int;
+ private var fragmentBitmap:BitmapData;
+ private var fragmentMatrix:Matrix;
+ private var fragmentRects:Array;
+ private var fragmentPoints:Array;
+
+ /**
+ * Creates a fragmentary effect where the image is divided into a grid of smaller zoomed areas
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param fragmentsWide The number of fragments in width to use
+ * @param scale The size of the zoom for each fragment
+ */
+ public function FragmentEffect(source:IBitmapDrawable, targetBitmap:BitmapData, fragmentsWide:int = 10, scale:Number = 0.5)
+ {
+ super(source, targetBitmap, "Fragment");
+ this.fragmentsWide = fragmentsWide < 1 ? 1 : fragmentsWide;
+ this.scale = scale;
+ if (scale > 2) this.scale = 2;
+ if (scale < 0.5) this.scale = 0.5;
+
+ createFragment();
+ }
+
+ /**
+ * Sets up the fragment effect
+ */
+ private function createFragment():void
+ {
+ // The fragment dimensions
+ var w:Number = rect.width / fragmentsWide;
+ var h:Number = rect.height / fragmentsWide;
+
+ // Set up the main fragment bitmap data and scaling properties
+ fragmentBitmap = new BitmapData(rect.width * scale, rect.height * scale, false, 0xFF000000);
+ fragmentMatrix = new Matrix();
+ fragmentMatrix.scale(1 / scale, 1 / scale);
+ fragmentRects = new Array();
+ fragmentPoints = new Array();
+
+ // Set up each fragment's area and position
+ for (var y:int = 0; y < fragmentsWide; y++)
+ {
+ for (var x:int = 0; x < fragmentsWide; x++)
+ {
+ fragmentRects.push(new Rectangle(x * w, y * h, w * scale, h * scale));
+ fragmentPoints.push(new Point(x * w * scale, y * h * scale));
+ }
+ }
+ total = fragmentsWide * fragmentsWide;
+ }
+
+ /**
+ * Draws the fragment effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+
+ // Loop through each fragment and draw the zoomed area
+ for (var i:int = total; i--; ) fragmentBitmap.copyPixels(sourceBitmap, fragmentRects[i], fragmentPoints[i]);
+
+ // Draw the fragment bitmap data into the target bitmap data but scaled to fit
+ targetBitmap.draw(fragmentBitmap, fragmentMatrix, null, null, null, true);
+ }
+
+ /**
+ * Removes the fragment effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+ fragmentBitmap.dispose();
+ fragmentBitmap = null;
+ fragmentRects = null;
+ fragmentPoints = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/displace/SqueezeEffect.as b/webcam/com/neave/webcam/effects/displace/SqueezeEffect.as
new file mode 100755
index 0000000..e702dc1
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/displace/SqueezeEffect.as
@@ -0,0 +1,87 @@
+/**
+ * Neave Webcam // Squeeze Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.displace
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+
+ public class SqueezeEffect extends AbstractDisplaceEffect
+ {
+ /**
+ * Creates a squeezing distortion effect where the middle is squeezed and the edges are stretched
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function SqueezeEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Squeeze");
+
+ createSqueeze();
+ }
+
+ /**
+ * Sets up the squeeze effect
+ */
+ private function createSqueeze():void
+ {
+ // The size of the squeeze effect
+ var w:int = rect.width;
+ var h:int = rect.height;
+
+ // The displacement gradient matrix
+ var m:Matrix = new Matrix();
+
+ // Grey radial gradient to smooth the edges of the distortion
+ var cover:Shape = new Shape();
+ m.createGradientBox(w, w);
+ cover.graphics.beginGradientFill(GradientType.LINEAR, [0x808080, 0x808080], [1, 0], [0x00, 0xFF], m);
+ cover.graphics.drawRect(0, 0, w, w);
+
+ // Red gradient to distort pixels horizontally
+ var red:Shape = new Shape();
+ m.createGradientBox(h, h, 0, (w - h) / 2, 0);
+ red.graphics.beginGradientFill(GradientType.LINEAR, [0x000000, 0xFF0000], [1, 1], [0x00, 0xFF], m);
+ red.graphics.drawRect(0, 0, w, w);
+
+ // Green gradient to distort pixels vertically
+ var green:Shape = new Shape();
+ m.createGradientBox(h, h, Math.PI / 2, (w - h) / 2, 0);
+ green.graphics.beginGradientFill(GradientType.LINEAR, [0x000000, 0x00FF00], [1, 1], [0x00, 0xFF], m);
+ green.graphics.drawRect(0, 0, w, w);
+
+ // Draw red and green gradients into one displacement map bitmap
+ displace.mapBitmap.draw(red);
+ displace.mapBitmap.draw(green, null, null, BlendMode.ADD);
+
+ // Fade out the edges of the distorion linearly in each direction, up, down, left and right
+ m.identity();
+ m.scale(0.5, 1);
+ displace.mapBitmap.draw(cover, m);
+ m.rotate(Math.PI);
+ m.translate(w, h);
+ displace.mapBitmap.draw(cover, m);
+ m.identity();
+ m.scale(h / w / 2, 1);
+ m.rotate(Math.PI / 2);
+ m.translate(w, 0);
+ displace.mapBitmap.draw(cover, m);
+ m.rotate(Math.PI);
+ m.translate(w, h);
+ displace.mapBitmap.draw(cover, m);
+
+ // Set the size of the displacement
+ displace.scaleX = displace.scaleY = w;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/displace/WaterEffect.as b/webcam/com/neave/webcam/effects/displace/WaterEffect.as
new file mode 100755
index 0000000..4f45d72
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/displace/WaterEffect.as
@@ -0,0 +1,76 @@
+/**
+ * Neave Webcam // Water Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.displace
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+
+ public class WaterEffect extends AbstractDisplaceEffect
+ {
+ private var seed:int;
+ private var offsets:Array;
+ private var blue:ColorMatrixFilter;
+
+ /**
+ * Creates a water effect as if you were looking into a pool of waving water
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function WaterEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Water");
+
+ createWater();
+ }
+
+ /**
+ * Sets up the water effect
+ */
+ private function createWater():void
+ {
+ // Set up the displacement
+ displace.scaleX = rect.width * 0.25;
+ displace.scaleY = rect.height * 0.25;
+ seed = Math.floor(Math.random() * 256);
+ offsets = new Array(new Point(), new Point());
+
+ // Blue colour matrix
+ var m:Array = new Array();
+ m = m.concat([0.3, 0.59, 0.11, 0, -10]); // Red
+ m = m.concat([0.3, 0.59, 0.11, 0, 30]); // Green
+ m = m.concat([0.3, 0.59, 0.11, 0, 70]); // Blue
+ m = m.concat([0, 0, 0, 1, 0]); // Alpha
+ blue = new ColorMatrixFilter(m);
+ }
+
+ /**
+ * Draws the water effect
+ */
+ override public function draw():void
+ {
+ // Wave the water by moving the displacement map's offsets
+ offsets[0].x += rect.width * 0.06;
+ offsets[1].x += rect.height * 0.06;
+
+ // Generate perlin noise as a displacement map to make water waves
+ displace.mapBitmap.perlinNoise(rect.width * 0.5, rect.height * 0.5, 1, seed, false, true, BitmapDataChannel.RED | BitmapDataChannel.GREEN, false, offsets);
+
+ // Draw the displaced image and tint it blue
+ targetBitmap.lock();
+ super.draw();
+ targetBitmap.applyFilter(targetBitmap, rect, point, blue);
+ targetBitmap.unlock();
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/mirror/AbstractMirrorEffect.as b/webcam/com/neave/webcam/effects/mirror/AbstractMirrorEffect.as
new file mode 100755
index 0000000..57008f7
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/mirror/AbstractMirrorEffect.as
@@ -0,0 +1,68 @@
+/**
+ * Neave Webcam // Abstract Mirror Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.mirror
+{
+ import flash.display.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ internal class AbstractMirrorEffect extends AbstractEffect
+ {
+ protected var mirrorBitmap:BitmapData;
+ protected var mirrorMatrix:Matrix;
+ protected var mirrorPoint:Point;
+
+ /**
+ * An abstract mirror effect class, not to be instantiated
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param name The proper name of the effect
+ */
+ public function AbstractMirrorEffect(source:IBitmapDrawable, targetBitmap:BitmapData, name:String = "")
+ {
+ super(source, targetBitmap, name);
+
+ createAbstractMirror();
+ }
+
+ /**
+ * Sets up the mirror effect
+ */
+ private function createAbstractMirror():void
+ {
+ mirrorMatrix = new Matrix();
+ mirrorPoint = new Point();
+ }
+
+ /**
+ * Draws the mirror effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+ mirrorBitmap.draw(sourceBitmap, mirrorMatrix);
+ targetBitmap.copyPixels(sourceBitmap, rect, point);
+ targetBitmap.copyPixels(mirrorBitmap, rect, mirrorPoint);
+ }
+
+ /**
+ * Removes the mirror effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+ mirrorBitmap.dispose();
+ mirrorBitmap = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/mirror/BottomMirrorEffect.as b/webcam/com/neave/webcam/effects/mirror/BottomMirrorEffect.as
new file mode 100755
index 0000000..4bb7b07
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/mirror/BottomMirrorEffect.as
@@ -0,0 +1,41 @@
+/**
+ * Neave Webcam // Bottom Mirror Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.mirror
+{
+ import flash.display.*;
+
+ public class BottomMirrorEffect extends AbstractMirrorEffect
+ {
+ /**
+ * Creates a mirror effect where the bottom half of the image is reflected into the top half
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function BottomMirrorEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Bottom Mirror");
+
+ createMirror();
+ }
+
+ /**
+ * Sets up the mirror effect
+ */
+ private function createMirror():void
+ {
+ mirrorMatrix.scale(1, -1);
+ mirrorMatrix.translate(0, rect.height);
+ mirrorBitmap = new BitmapData(rect.width, Math.round(rect.height / 2), false, 0xFF000000);
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/mirror/InverseMirrorEffect.as b/webcam/com/neave/webcam/effects/mirror/InverseMirrorEffect.as
new file mode 100755
index 0000000..8f0da4c
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/mirror/InverseMirrorEffect.as
@@ -0,0 +1,41 @@
+/**
+ * Neave Webcam // Inverse Mirror Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.mirror
+{
+ import flash.display.*;
+
+ public class InverseMirrorEffect extends AbstractMirrorEffect
+ {
+ /**
+ * Creates a mirror effect where the top half of the image is inversed
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function InverseMirrorEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Inverse Mirror");
+
+ createMirror();
+ }
+
+ /**
+ * Sets up the mirror effect
+ */
+ private function createMirror():void
+ {
+ mirrorMatrix.scale(-1, 1);
+ mirrorMatrix.translate(rect.width, 0);
+ mirrorBitmap = new BitmapData(rect.width, Math.round(rect.height / 2), false, 0xFF000000);
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/mirror/LeftMirrorEffect.as b/webcam/com/neave/webcam/effects/mirror/LeftMirrorEffect.as
new file mode 100755
index 0000000..31cc510
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/mirror/LeftMirrorEffect.as
@@ -0,0 +1,41 @@
+/**
+ * Neave Webcam // Left Mirror Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.mirror
+{
+ import flash.display.*;
+
+ public class LeftMirrorEffect extends AbstractMirrorEffect
+ {
+ /**
+ * Creates a mirror effect where the left side of the image is reflected into the right side (when using a flipped image)
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function LeftMirrorEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Left Mirror");
+
+ createMirror();
+ }
+
+ /**
+ * Sets up the mirror effect
+ */
+ private function createMirror():void
+ {
+ mirrorMatrix.scale(-1, 1);
+ mirrorMatrix.translate(rect.width, 0);
+ mirrorBitmap = new BitmapData(Math.round(rect.width / 2), rect.height, false, 0xFF000000);
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/mirror/QuadMirrorEffect.as b/webcam/com/neave/webcam/effects/mirror/QuadMirrorEffect.as
new file mode 100755
index 0000000..d4e84a4
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/mirror/QuadMirrorEffect.as
@@ -0,0 +1,97 @@
+/**
+ * Neave Webcam // Quad Mirror Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.mirror
+{
+ import flash.display.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class QuadMirrorEffect extends AbstractEffect
+ {
+ private var quadBitmap:BitmapData;
+ private var halfBitmap:BitmapData;
+ private var quadMatrix:Matrix;
+ private var rightMatrix:Matrix;
+ private var topMatrix:Matrix;
+ private var bottomMatrix:Matrix;
+
+ /**
+ * Creates a mirror effect where the source image is reflected vertically and horizontally
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function QuadMirrorEffect(source:IBitmapDrawable, targetBitmapData:BitmapData)
+ {
+ super(source, targetBitmapData, "Quad Mirror");
+
+ createQuadMirror();
+ }
+
+ /**
+ * Sets up the mirror effect
+ */
+ private function createQuadMirror():void
+ {
+ // Mirror dimensions
+ var midW:int = Math.round(rect.width / 2);
+ var midH:int = Math.round(rect.height / 2);
+
+ // Reflected bitmap data
+ quadBitmap = new BitmapData(midW, midH, false, 0xFF000000);
+ halfBitmap = new BitmapData(rect.width, midH, false, 0xFF000000);
+
+ // Half size matrix
+ quadMatrix = new Matrix();
+ quadMatrix.scale(0.5, 0.5);
+
+ // Right side matrix
+ rightMatrix = new Matrix();
+ rightMatrix.scale(-1, 1);
+ rightMatrix.translate(rect.width, 0);
+
+ // Top half matrix
+ topMatrix = new Matrix();
+ topMatrix.scale(1, -1);
+ topMatrix.translate(0, midH);
+
+ // Bottom half matrix
+ bottomMatrix = new Matrix();
+ bottomMatrix.translate(0, midH);
+ }
+
+ /**
+ * Draws the quad mirror effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+ quadBitmap.draw(sourceBitmap, quadMatrix); // Draw quarter image
+ halfBitmap.draw(quadBitmap); // Draw quarter into left
+ halfBitmap.draw(quadBitmap, rightMatrix); // Draw quarter into right
+ targetBitmap.draw(halfBitmap, bottomMatrix); // Draw half into bottom
+ targetBitmap.draw(halfBitmap, topMatrix); // Draw half into top
+ }
+
+ /**
+ * Removes the quad mirror effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+ quadBitmap.dispose();
+ quadBitmap = null;
+ halfBitmap.dispose();
+ halfBitmap = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/mirror/RightMirrorEffect.as b/webcam/com/neave/webcam/effects/mirror/RightMirrorEffect.as
new file mode 100755
index 0000000..d469226
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/mirror/RightMirrorEffect.as
@@ -0,0 +1,44 @@
+/**
+ * Neave Webcam // Right Mirror Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.mirror
+{
+ import flash.display.*;
+
+ public class RightMirrorEffect extends AbstractMirrorEffect
+ {
+ /**
+ * Creates a mirror effect where the right side of the image is reflected into the left side (when using a flipped image)
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function RightMirrorEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Right Mirror");
+
+ createMirror();
+ }
+
+ /**
+ * Sets up the mirror effect
+ */
+ private function createMirror():void
+ {
+ var midW:int = Math.round(rect.width / 2);
+
+ mirrorMatrix.scale(-1, 1);
+ mirrorMatrix.translate(midW, 0);
+ mirrorPoint.x = midW;
+ mirrorBitmap = new BitmapData(midW, rect.height, false, 0xFF000000);
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/mirror/TopMirrorEffect.as b/webcam/com/neave/webcam/effects/mirror/TopMirrorEffect.as
new file mode 100755
index 0000000..af69612
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/mirror/TopMirrorEffect.as
@@ -0,0 +1,44 @@
+/**
+ * Neave Webcam // Top Mirror Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.mirror
+{
+ import flash.display.*;
+
+ public class TopMirrorEffect extends AbstractMirrorEffect
+ {
+ /**
+ * Creates a mirror effect where the top half of the image is reflected into the bottom half
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function TopMirrorEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Top Mirror");
+
+ createMirror();
+ }
+
+ /**
+ * Sets up the mirror effect
+ */
+ private function createMirror():void
+ {
+ var midH:int = Math.round(rect.height / 2);
+
+ mirrorMatrix.scale(1, -1);
+ mirrorMatrix.translate(0, midH);
+ mirrorPoint.y = midH;
+ mirrorBitmap = new BitmapData(rect.width, midH, false, 0xFF000000);
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/mirror/UpsideDownEffect.as b/webcam/com/neave/webcam/effects/mirror/UpsideDownEffect.as
new file mode 100755
index 0000000..71e08d8
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/mirror/UpsideDownEffect.as
@@ -0,0 +1,54 @@
+/**
+ * Neave Webcam // Upside-Down Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.mirror
+{
+ import flash.display.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class UpsideDownEffect extends AbstractEffect
+ {
+ private var flipMatrix:Matrix;
+
+ /**
+ * Creates a mirror effect where the source image is flipped vertically
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function UpsideDownEffect(source:IBitmapDrawable, targetBitmapData:BitmapData)
+ {
+ super(source, targetBitmapData, "Upside-Down");
+
+ createUpsideDown();
+ }
+
+ /**
+ * Sets up the upside-down effect
+ */
+ private function createUpsideDown():void
+ {
+ flipMatrix = new Matrix();
+ flipMatrix.scale(1, -1);
+ flipMatrix.translate(0, rect.height);
+ }
+
+ /**
+ * Draws the upside-down effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+ targetBitmap.draw(sourceBitmap, flipMatrix);
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/motion/AbstractMotionEffect.as b/webcam/com/neave/webcam/effects/motion/AbstractMotionEffect.as
new file mode 100755
index 0000000..3301a8a
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/motion/AbstractMotionEffect.as
@@ -0,0 +1,138 @@
+/**
+ * Neave Webcam // Abstract Motion Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.motion
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ internal class AbstractMotionEffect extends AbstractEffect
+ {
+ private var motionScale:int;
+ private var motionFrames:int;
+ private var contrast:ColorTransform;
+ private var frames:Array;
+ private var frameBitmap:BitmapData;
+ protected var monochrome:ColorMatrixFilter;
+ protected var motionBitmap:BitmapData;
+ protected var motionRect:Rectangle;
+ protected var motionMatrix:Matrix;
+
+ /**
+ * An abstract motion detection effect class, not to be instantiated
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param name The proper name of the effect
+ * @param motionScale The scale of the motion bitmap data to use for detection
+ * @param motionFrames The number of frames to capture for the motion bitmap data
+ */
+ public function AbstractMotionEffect(source:IBitmapDrawable, targetBitmap:BitmapData, name:String = "", motionScale:int = 1, motionFrames:int = 4)
+ {
+ super(source, targetBitmap, name);
+ this.motionScale = motionScale < 1 ? 1 : motionScale;
+ this.motionFrames = motionFrames < 1 ? 1 : motionFrames;
+
+ createAbstractMotion();
+ }
+
+ /**
+ * Sets up the motion effect
+ */
+ private function createAbstractMotion():void
+ {
+ // Increase contrast
+ contrast = new ColorTransform(2, 2, 2, 1, -100, -100, -100);
+
+ // Motion bitmap dimensions
+ var w:int = Math.round(rect.width / motionScale);
+ var h:int = Math.round(rect.height / motionScale);
+
+ // Main motion bitmap data
+ motionBitmap = new BitmapData(w, h, false, 0xFF000000);
+ motionRect = motionBitmap.rect;
+ motionMatrix = new Matrix();
+ motionMatrix.scale(1 / motionScale, 1 / motionScale);
+
+ // The previous frame to use when comparing with the current image
+ frameBitmap = motionBitmap.clone();
+ frameBitmap.draw(source, motionMatrix, contrast);
+
+ // Create the delayed motion frames
+ frames = new Array();
+ for (var i:int = motionFrames; i--; ) frames.push(new BitmapData(w, h, false, 0xFF000000));
+
+ // Monochrome colour matrix
+ var m:Array = new Array();
+ m = m.concat([0.3, 0.59, 0.11, 0, 0]); // Red
+ m = m.concat([0.3, 0.59, 0.11, 0, 0]); // Green
+ m = m.concat([0.3, 0.59, 0.11, 0, 0]); // Blue
+ m = m.concat([0, 0, 0, 1, 0]); // Alpha
+ monochrome = new ColorMatrixFilter(m);
+ }
+
+ /**
+ * Draws the motion effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+
+ // Clear old motion bitmap
+ motionBitmap.fillRect(motionRect, 0xFF000000);
+
+ // Do motion detection
+ for (var i:int = motionFrames; i--; )
+ {
+ var b:BitmapData = frames[i];
+ if (i == 0)
+ {
+ // Detect motion by taking the difference between this source image to the previous source image
+ b.copyPixels(frameBitmap, motionRect, point); // Get the old image
+ frameBitmap.draw(sourceBitmap, motionMatrix, contrast); // Draw the new image
+ frameBitmap.applyFilter(frameBitmap, motionRect, point, monochrome); // Convert the new image to greyscale
+ b.draw(frameBitmap, null, null, BlendMode.DIFFERENCE); // Draw the difference
+ }
+ else b.copyPixels(frames[i - 1], motionRect, point); // Move the motion frames along the array
+
+ // Add all the motion frames into a single bitmap
+ motionBitmap.draw(b, null, null, BlendMode.ADD);
+ }
+
+ // Separate the motion bitmap data into only black and white pixels
+ motionBitmap.threshold(motionBitmap, motionRect, point, ">", 0xFF808080, 0xFFFFFFFF);
+ motionBitmap.threshold(motionBitmap, motionRect, point, "<=", 0xFF808080, 0xFF000000);
+ }
+
+ /**
+ * Removes the motion effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+
+ // Remove all the motion frames
+ for (var i:int = motionFrames; i--; )
+ {
+ frames[i].dispose();
+ frames[i] = null;
+ }
+ frames = null;
+
+ frameBitmap.dispose();
+ frameBitmap = null;
+ motionBitmap.dispose();
+ motionBitmap = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/motion/FireEffect.as b/webcam/com/neave/webcam/effects/motion/FireEffect.as
new file mode 100755
index 0000000..33dcfe2
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/motion/FireEffect.as
@@ -0,0 +1,129 @@
+/**
+ * Neave Webcam // Fire Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.motion
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+
+ public class FireEffect extends AbstractMotionEffect
+ {
+ private const MOTION_SCALE:int = 2;
+
+ private var fireSourceBitmap:BitmapData;
+ private var fireBitmap:BitmapData;
+ private var darkenBitmap:BitmapData;
+ private var edge:ConvolutionFilter;
+ private var fireColor:ColorMatrixFilter;
+ private var displace:DisplacementMapFilter;
+ private var blur:BlurFilter;
+ private var targetMatrix:Matrix;
+
+ /**
+ * Creates a fire effect which animates along edges and as motion is detected
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function FireEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Fire", MOTION_SCALE, 5);
+
+ createFire();
+ }
+
+ /**
+ * Sets up the fire effect
+ */
+ private function createFire():void
+ {
+ // Set up fire bitmap data and scaling
+ fireSourceBitmap = motionBitmap.clone();
+ fireBitmap = motionBitmap.clone();
+ targetMatrix = new Matrix();
+ targetMatrix.scale(MOTION_SCALE, MOTION_SCALE);
+
+ // Edge detection convolution array
+ var m:Array =
+ [
+ 0, 0, 0,
+ 16, 16, 16,
+ -16, -16, -16
+ ];
+ edge = new ConvolutionFilter(3, 3, m, 9);
+
+ // Fire colour matrix
+ m = new Array();
+ m = m.concat([0.8, 0.05, 0, 0, 0]); // Red
+ m = m.concat([0, 0.65, 0, 0, 0]); // Green
+ m = m.concat([0, 0, 0.5, 0, 0]); // Blue
+ m = m.concat([0, 0, 0, 1, 0]); // Alpha
+ fireColor = new ColorMatrixFilter(m);
+
+ // Fire displacement map
+ displace = new DisplacementMapFilter(new BitmapData(rect.width, rect.height, false, 0xFF808080), point, BitmapDataChannel.RED, BitmapDataChannel.GREEN, 7, -35, DisplacementMapFilterMode.CLAMP);
+
+ // Fire blurring
+ blur = new BlurFilter(8, 8, 1);
+
+ // Darken the fire
+ darkenBitmap = new BitmapData(rect.width, rect.height, false, 0xFFFF8000);
+ }
+
+ /**
+ * Draws the fire effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+
+ // Get the source image's edges
+ fireSourceBitmap.draw(sourceBitmap, motionMatrix);
+ fireBitmap.applyFilter(fireSourceBitmap, motionRect, point, edge);
+ fireBitmap.applyFilter(fireBitmap, motionRect, point, monochrome);
+
+ // Add motion bitmap to edge bitmap and turn pixels into orange and black only
+ fireBitmap.draw(motionBitmap, null, null, BlendMode.ADD);
+ fireBitmap.threshold(fireBitmap, motionRect, point, ">", 0xFF808080, 0xFFFF8000);
+ fireBitmap.threshold(fireBitmap, motionRect, point, "<=", 0xFF808080, 0xFF000000);
+
+ // Blur to make motion bitmap look more like fire
+ fireBitmap.applyFilter(fireBitmap, motionRect, point, blur);
+
+ // Displace the image with perlin noise to animate the fire
+ displace.mapBitmap.perlinNoise(14, 10, 1, Math.floor(Math.random() * 256), false, true, BitmapDataChannel.RED | BitmapDataChannel.GREEN, false);
+ displace.mapBitmap.draw(darkenBitmap, null, null, BlendMode.DARKEN);
+ fireBitmap.applyFilter(fireBitmap, motionRect, point, displace);
+ fireBitmap.applyFilter(fireBitmap, motionRect, point, fireColor);
+
+ // Draw the fire bitmap on top of the current source image
+ targetBitmap.lock();
+ targetBitmap.copyPixels(sourceBitmap, rect, point);
+ targetBitmap.draw(fireBitmap, targetMatrix, null, BlendMode.ADD);
+ targetBitmap.unlock();
+ }
+
+ /**
+ * Removes the fire effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+ fireSourceBitmap.dispose();
+ fireSourceBitmap = null;
+ fireBitmap.dispose();
+ fireBitmap = null;
+ darkenBitmap.dispose();
+ darkenBitmap = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/motion/SnowEffect.as b/webcam/com/neave/webcam/effects/motion/SnowEffect.as
new file mode 100755
index 0000000..30468d9
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/motion/SnowEffect.as
@@ -0,0 +1,154 @@
+/**
+ * Neave Webcam // Snow Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.motion
+{
+ import flash.display.*;
+ import flash.events.*;
+ import flash.filters.*;
+ import flash.geom.*;
+ import flash.utils.*;
+ import com.neave.webcam.effects.*;
+
+ public class SnowEffect extends AbstractEffect
+ {
+ private const SNOWFLAKE_DELAY:int = 20;
+ private const MELT_SPEED:Number = 0.0025;
+
+ private var totalFlakes:int;
+ private var snowSourceBitmap:BitmapData;
+ private var edgeBitmap:BitmapData;
+ private var edge:ConvolutionFilter;
+ private var blur:BlurFilter;
+ private var snowflakes:Sprite;
+ private var snowTimer:Timer;
+ private var snowMatrix:Matrix;
+ private var contrast:ColorTransform;
+
+ /**
+ * Creates a snow effect where falling snowflakes settle and build up along edges
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param totalFlakes The total number of snowflakes to use
+ */
+ public function SnowEffect(source:IBitmapDrawable, targetBitmap:BitmapData, totalFlakes:int = 200)
+ {
+ super(source, targetBitmap, "Snow");
+ this.totalFlakes = totalFlakes < 1 ? 1 : totalFlakes;
+
+ createSnow();
+ }
+
+ /**
+ * Sets up the snow effect
+ */
+ private function createSnow():void
+ {
+ // Increase contrast to better detect edges
+ //contrast = new ColorTransform(2, 2, 2, 1, -100, -100, -100);
+
+ // Create bitmaps to hold edge detection
+ snowSourceBitmap = new BitmapData(Math.round(rect.width / 2), Math.round(rect.height / 2), false, 0xFF000000);
+ edgeBitmap = snowSourceBitmap.clone();
+ snowMatrix = new Matrix();
+ snowMatrix.scale(0.5, 0.5);
+
+ // Add a new snowflake to the snowflakes sprite every so often
+ snowflakes = new Sprite();
+ snowTimer = new Timer(SNOWFLAKE_DELAY);
+ snowTimer.addEventListener(TimerEvent.TIMER, makeNewSnowflake);
+ snowTimer.start();
+
+ // Edge detection convolution array
+ var m:Array =
+ [
+ 0, 50, 0,
+ 0, -60, 0,
+ 0, 10, 0
+ ];
+ edge = new ConvolutionFilter(3, 3, m, 5);
+ }
+
+ /**
+ * Creates a new snowflake inside the snowflakes sprite
+ */
+ private function makeNewSnowflake(e:TimerEvent = null):void
+ {
+ // Only add another random snowflake if the maximum amount has not been reached
+ if (snowflakes.numChildren < totalFlakes) snowflakes.addChild(new Snowflake(Math.random() * rect.width, -4, Math.random() * 2 + 1, Math.random() * 2 - 1));
+ }
+
+ /**
+ * Draws the snow effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+
+ // Loop through each snowflake
+ for (var i:int = snowflakes.numChildren; i--; )
+ {
+ var flake:Snowflake = snowflakes.getChildAt(i) as Snowflake;
+
+ // Only move the snowflake if it is not hitting an edge
+ if (edgeBitmap.getPixel(Math.round(flake.x / 2), Math.round(flake.y / 2)) == 0x000000)
+ {
+ // Animate the snowflake
+ flake.fall();
+ flake.alpha += 0.1;
+ if (flake.alpha > 1) flake.alpha = 1;
+
+ // Wrap the snowflake to within the bounds of the image
+ if (flake.x > rect.width + flake.width) flake.x -= rect.width + flake.width;
+ if (flake.x < -flake.width) flake.x += rect.width + flake.width;
+
+ // Remove this snowflake if it has fallen off the bottom of the image
+ if (flake.y > rect.height + flake.height) snowflakes.removeChildAt(i);
+ }
+ else
+ {
+ // Melt this snowflake by fading out it
+ if (flake.alpha > 0.1) flake.alpha -= MELT_SPEED;
+ else snowflakes.removeChildAt(i);
+ }
+ }
+
+ // Find the edges for the snow to settle on
+ snowSourceBitmap.draw(sourceBitmap, snowMatrix, contrast);
+ edgeBitmap.applyFilter(snowSourceBitmap, edgeBitmap.rect, point, edge);
+ edgeBitmap.threshold(edgeBitmap, edgeBitmap.rect, point, "<", 0xFF808080, 0xFF000000);
+
+ // Draw the snow over the current source image
+ targetBitmap.lock();
+ targetBitmap.copyPixels(sourceBitmap, rect, point);
+ targetBitmap.draw(snowflakes);
+ targetBitmap.unlock();
+ }
+
+ /**
+ * Removes the snow effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+
+ // Stop making new snowflakes
+ snowTimer.removeEventListener(TimerEvent.TIMER, makeNewSnowflake);
+
+ // Remove bitmap data
+ snowSourceBitmap.dispose();
+ snowSourceBitmap = null;
+ edgeBitmap.dispose();
+ edgeBitmap = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/motion/Snowflake.as b/webcam/com/neave/webcam/effects/motion/Snowflake.as
new file mode 100755
index 0000000..fc943f5
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/motion/Snowflake.as
@@ -0,0 +1,66 @@
+/**
+ * Neave Webcam // Snowflake
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.motion
+{
+ import flash.display.*;
+ import flash.geom.*;
+
+ final internal class Snowflake extends Shape
+ {
+ private const SIDEWAYS_DAMPEN:Number = 0.995;
+
+ private var size:Number;
+ private var vx:Number;
+
+ /**
+ * Draws a snowflake shape to be used with the snow effect
+ *
+ * @param x The position of the snowflake on the x-axis
+ * @param y The position of the snowflake on the y-axis
+ * @param size The size of the snowflake
+ * @param vx The sideways velocity of the snowflake
+ */
+ public function Snowflake(x:Number = 0, y:Number = 0, size:Number = 1, vx:Number = 0)
+ {
+ this.x = x;
+ this.y = y;
+ this.size = size;
+ this.vx = vx;
+
+ createSnowflake();
+ }
+
+ /**
+ * Sets up the snowflake shape, a white oval gradient
+ */
+ private function createSnowflake():void
+ {
+ var m:Matrix = new Matrix();
+ m.createGradientBox(size * 2, size * 2);
+ m.translate(-size, -size);
+ graphics.beginGradientFill(GradientType.RADIAL, [0xFFFFFF, 0xFFFFFF], [1, 0], [0x66, 0xFF], m);
+ graphics.drawCircle(0, 0, size);
+ width *= 1.5;
+ cacheAsBitmap = true;
+ }
+
+ /**
+ * Animates the snowflake downwards
+ */
+ internal function fall():void
+ {
+ vx *= SIDEWAYS_DAMPEN;
+ x += vx;
+ y += size;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/motion/SteamEffect.as b/webcam/com/neave/webcam/effects/motion/SteamEffect.as
new file mode 100755
index 0000000..0b55ca2
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/motion/SteamEffect.as
@@ -0,0 +1,73 @@
+/**
+ * Neave Webcam // Steamy Window Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.motion
+{
+ import flash.display.*;
+
+ public class SteamEffect extends AbstractMotionEffect
+ {
+ private var steamBitmap:BitmapData;
+ private var blackBitmap:BitmapData;
+ private var wipedBitmap:BitmapData;
+
+ /**
+ * Creates a steamy window effect where detected motion wipes away areas of the steamed-up image
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ */
+ public function SteamEffect(source:IBitmapDrawable, targetBitmap:BitmapData)
+ {
+ super(source, targetBitmap, "Steamy Window");
+
+ createSteam();
+ }
+
+ /**
+ * Sets up the steam effect
+ */
+ private function createSteam():void
+ {
+ steamBitmap = new BitmapData(rect.width, rect.height, false, 0xFF808080);
+ blackBitmap = new BitmapData(rect.width, rect.height, false, 0xFF000000);
+ wipedBitmap = blackBitmap.clone();
+ }
+
+ /**
+ * Draws the steam effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+ wipedBitmap.draw(motionBitmap, null, null, BlendMode.ADD); // Build up a wiped area by repeatedly adding the motion bitmap
+ wipedBitmap.merge(blackBitmap, rect, point, 2, 2, 2, 0); // Gradually fade away the wiped areas
+ steamBitmap.fillRect(rect, 0xFF808080); // Create some steam
+ steamBitmap.draw(wipedBitmap, null, null, BlendMode.SUBTRACT); // Remove the wiped areas from the steam
+ sourceBitmap.merge(steamBitmap, rect, point, 0x80, 0x80, 0x80, 0); // Merge the steam with the source image
+ targetBitmap.copyPixels(sourceBitmap, rect, point); // Draw into the target bitmap
+ }
+
+ /**
+ * Removes the steam effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+ steamBitmap.dispose();
+ steamBitmap = null;
+ blackBitmap.dispose();
+ blackBitmap = null;
+ wipedBitmap.dispose();
+ wipedBitmap = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/motion/SwarmEffect.as b/webcam/com/neave/webcam/effects/motion/SwarmEffect.as
new file mode 100755
index 0000000..f22a6bd
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/motion/SwarmEffect.as
@@ -0,0 +1,106 @@
+/**
+ * Neave Webcam // Swarm Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.motion
+{
+ import flash.display.*;
+ import flash.geom.*;
+
+ public class SwarmEffect extends AbstractMotionEffect
+ {
+ private const MOTION_SCALE:int = 4;
+
+ private var flies:int;
+ private var swarm:Sprite;
+
+ /**
+ * Creates a swarming flies effect where the flies are attracted to detected motion
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param flies The number of flies to use in the swarm
+ */
+ public function SwarmEffect(source:IBitmapDrawable, targetBitmap:BitmapData, flies:int = 150)
+ {
+ super(source, targetBitmap, "Swarm", MOTION_SCALE);
+ this.flies = flies < 1 ? 1 : flies;
+
+ createSwarm();
+ }
+
+ /**
+ * Sets up the swarm effect
+ */
+ private function createSwarm():void
+ {
+ // Draw the flies into the swarm sprite in random positions
+ swarm = new Sprite();
+ for (var i:int = flies; i--; ) swarm.addChild(new SwarmFly(Math.random() * rect.width, Math.random() * rect.height, (i / flies) * 0.75 + 0.75));
+ }
+
+ /**
+ * Draws the swarm effect
+ */
+ override public function draw():void
+ {
+ super.draw();
+
+ // Loop through each pixel in the motion bitmap data
+ var flyX:int = -1;
+ var flyY:int = -1;
+ for (var y:int = motionBitmap.height; y--; )
+ {
+ for (var x:int = motionBitmap.width; x--; )
+ {
+ // If this pixel has motion set this as a point for the flies to move to
+ if (motionBitmap.getPixel(x, y) == 0xFFFFFF)
+ {
+ flyX = x * MOTION_SCALE;
+ flyY = y * MOTION_SCALE;
+ break;
+ }
+ }
+ }
+
+ // Loop through each fly in the swarm
+ for (var i:int = flies; i--; )
+ {
+ // Fly the fly towards the motion point
+ var fly:SwarmFly = swarm.getChildAt(i) as SwarmFly;
+ fly.flyTo(flyX, flyY);
+
+ // Limit the fly to within bounds of the source image
+ if (fly.x < 0) fly.x = 0;
+ if (fly.y < 0) fly.y = 0;
+ if (fly.x > rect.width) fly.x = rect.width;
+ if (fly.y > rect.height) fly.y = rect.height;
+ }
+
+ // Draw the swarm over the source image
+ targetBitmap.lock();
+ targetBitmap.copyPixels(sourceBitmap, rect, point);
+ targetBitmap.draw(swarm);
+ targetBitmap.unlock();
+ }
+
+ /**
+ * Removes the swarm effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+
+ // Remove all the flies from the swarm sprite
+ for (var i:int = flies; i--; ) swarm.removeChildAt(i);
+ swarm = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/motion/SwarmFly.as b/webcam/com/neave/webcam/effects/motion/SwarmFly.as
new file mode 100755
index 0000000..a7cfe62
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/motion/SwarmFly.as
@@ -0,0 +1,122 @@
+/**
+ * Neave Webcam // Swarm Fly
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.motion
+{
+ import flash.display.*;
+ import flash.filters.*;
+
+ final internal class SwarmFly extends Shape
+ {
+ private const MAX_BOREDOM:int = 10;
+ private const BOREDOM_TIME:int = 20;
+ private const MAX_DIST:int = 8000;
+ private const BORED_DIST:int = 30;
+
+ private var x0:Number;
+ private var y0:Number;
+ private var size:Number;
+ private var speed:Number;
+ private var boredom:int;
+ private var wobbleAngle:Number;
+ private var wobbleDist:Number;
+ private var wobbleStep:Number;
+
+ /**
+ * Creates a fly graphic to be used with the swarm effect
+ *
+ * @param x The starting position of the fly on the x-axis
+ * @param y The starting position of the fly on the y-axis
+ */
+ public function SwarmFly(x:Number = 0, y:Number = 0, size:Number = 1)
+ {
+ this.x = x0 = x;
+ this.y = y0 = y;
+ this.size = size;
+
+ createFly();
+ }
+
+ /**
+ * Sets up the fly and its initial properties
+ */
+ private function createFly():void
+ {
+ // This fly's movement speed and initial boredom threshold
+ speed = Math.random() * 20 + 10;
+ boredom = Math.floor(Math.random() * (MAX_BOREDOM + BOREDOM_TIME));
+
+ // This fly's wobbling amount as it flies
+ wobbleAngle = Math.random() * Math.PI;
+ wobbleDist = Math.random() * 2.5 + 0.5;
+ wobbleStep = evenRandom() * 2;
+
+ // Draw the fly shape, a black circle with a black glow
+ graphics.beginFill(0x000000);
+ graphics.drawCircle(0, 0, size);
+ filters = [ new GlowFilter(0x000000, 1, 6, 6, 2, 2, false, false) ];
+ cacheAsBitmap = true;
+ }
+
+ /**
+ * Generates a random number between -0.5 and 0.5
+ */
+ private function evenRandom():Number
+ {
+ return Math.random() - 0.5;
+ }
+
+ /**
+ * Moves the fly towards the specified position
+ *
+ * @param x The position to move to on the x-axis
+ * @param y The position to move to on the y-axis
+ */
+ internal function flyTo(x:int, y:int):void
+ {
+ var dx:int = this.x - x;
+ var dy:int = this.y - y;
+ if (boredom > MAX_BOREDOM || dx * dx + dy * dy > MAX_DIST)
+ {
+ // Fly around if the fly is too bored or too far away
+ this.x += (x0 - this.x) / speed;
+ this.y += (y0 - this.y) / speed;
+
+ // Flying around reduces boredom
+ if (boredom > 0) boredom--;
+
+ // Not bored any more, reset boredom threshold
+ if (boredom == MAX_BOREDOM) boredom = 0;
+ }
+ else if (x >=0 || y >= 0)
+ {
+ // Fly isn't bored yet so moves towards the motion
+ this.x += (x - this.x) / speed / 2;
+ this.y += (y - this.y) / speed / 2;
+
+ // Boredom increases until the fly is totally bored and flies off
+ if (boredom < MAX_BOREDOM) boredom++;
+ else
+ {
+ // Bored now, so fly away somewhere for a time
+ x0 = x + evenRandom() * BORED_DIST;
+ y0 = y + evenRandom() * BORED_DIST;
+ boredom = MAX_BOREDOM + Math.ceil(evenRandom() * BOREDOM_TIME);
+ }
+ }
+
+ // Wobble the fly's movement
+ wobbleAngle += wobbleStep;
+ this.x += Math.sin(wobbleAngle) * wobbleDist;
+ this.y += Math.cos(wobbleAngle / 3) * wobbleDist;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/pixel/ASCIIEffect.as b/webcam/com/neave/webcam/effects/pixel/ASCIIEffect.as
new file mode 100755
index 0000000..cd8e8d8
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/pixel/ASCIIEffect.as
@@ -0,0 +1,225 @@
+/**
+ * Neave Webcam // ASCII Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.pixel
+{
+ import flash.display.*;
+ import flash.filters.*;
+ import flash.geom.*;
+ import flash.system.*;
+ import flash.text.*;
+ import com.neave.webcam.effects.*;
+
+ public class ASCIIEffect extends AbstractEffect
+ {
+ private const FONT_NAME:String = "_typewriter";
+ private const FONT_SIZE:int = 10;
+ private const FONT_COLOR:int = 0x33FF33;
+ private const FONT_SPACING:int = 2;
+ private const FONT_WIN_LEADING:int = -8;
+ private const FONT_MAC_LEADING:int = -6;
+ private const CHARS_WIDE:int = 39;
+ private const MIN_ASCII_CHAR:uint = 32;
+ private const MAX_ASCII_CHAR:uint = 126;
+
+ private var flipChars:Boolean;
+ private var smallBitmap:BitmapData;
+ private var smallMatrix:Matrix;
+ private var textBitmap:BitmapData;
+ private var textfield:TextField;
+ private var textMatrix:Matrix;
+ private var flipMatrix:Matrix;
+ private var charsX:int;
+ private var charsY:int;
+ private var total:int;
+ private var textFormat:TextFormat;
+ private var chars:Array;
+ private var blur:BlurFilter;
+
+ /**
+ * Creates a text-based effect where each pixel is drawn as a letter from the ASCII character table
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param flipChars Flips the ASCII characters horizontally, useful if using a mirrored webcam as the source object
+ */
+ public function ASCIIEffect(source:IBitmapDrawable, targetBitmap:BitmapData, flipChars:Boolean = true)
+ {
+ super(source, targetBitmap, "ASCII");
+ this.flipChars = flipChars;
+
+ createASCII();
+ }
+
+ /**
+ * Sets up the ASCII effect
+ */
+ private function createASCII():void
+ {
+ // Increase contrast
+ color = new ColorTransform(2, 2, 2, 1, -100, -100, -100);
+
+ // Create the main textfield
+ var fmt:TextFormat = new TextFormat(FONT_NAME, FONT_SIZE, FONT_COLOR);
+ fmt.letterSpacing = FONT_SPACING;
+ fmt.leading = Capabilities.version.substr(0, 3) == "MAC" ? FONT_MAC_LEADING : FONT_WIN_LEADING;
+ textfield = new TextField();
+ textfield.defaultTextFormat = fmt;
+ textfield.autoSize = TextFieldAutoSize.LEFT;
+
+ // Get the ASCII characters in order of brightness
+ chars = getOrderedChars();
+ total = chars.length - 1;
+
+ // Create a bitmap to hold the textfield
+ textBitmap = targetBitmap.clone();
+ textMatrix = new Matrix();
+ textMatrix.translate(3, 0);
+
+ // Create a smaller, lower resolution bitmap to sample pixels from
+ smallBitmap = new BitmapData(CHARS_WIDE, Math.round(CHARS_WIDE * rect.height / rect.width), false, 0xFF000000);
+ charsX = smallBitmap.width;
+ charsY = smallBitmap.height;
+ smallMatrix = new Matrix();
+ smallMatrix.scale(charsX / rect.width, charsY / rect.height);
+
+ // If flip flag is true, reverse the bitmaps horizontally
+ flipMatrix = new Matrix();
+ flipMatrix.scale(rect.width / 320, rect.height / 240);
+ if (flipChars)
+ {
+ flipMatrix.scale(-1, 1);
+ flipMatrix.translate(rect.width, 0);
+ smallMatrix.scale(-1, 1);
+ smallMatrix.translate(charsX, 0);
+ }
+
+ // Use a blur filter to add a slight glow behind the characters
+ blur = new BlurFilter(4, 4, 1);
+ }
+
+ /**
+ * Generates an array of ASCII characters in order of pixel brightness
+ *
+ * @return An array of characters ordered by pixel brightness
+ */
+ private function getOrderedChars():Array
+ {
+ // Create an array containing character and its brightness
+ var order:Array = new Array();
+ for (var i:int = MIN_ASCII_CHAR; i < MAX_ASCII_CHAR; i++)
+ {
+ var c:String = String.fromCharCode(i);
+ order.push( { char:c, level:getCharBrightness(c) } );
+ }
+
+ // Sort the characters in order of descending brightness
+ order.sortOn("level", Array.NUMERIC | Array.DESCENDING);
+
+ // Return a new array containing only the characters in order
+ var list:Array = new Array();
+ for (i = order.length; i--; ) list.push(order[i].char);
+ return list;
+ }
+
+ /**
+ * Calculates the pixel brightness a character
+ *
+ * @param char The single ASCII character to test for brightness level
+ * @return A number between 0 and 1 indicating the amount of brightness
+ */
+ private function getCharBrightness(char:String):Number
+ {
+ // Create a temporary textfield to hold this character
+ var tf:TextField = new TextField();
+ tf.defaultTextFormat = new TextFormat(FONT_NAME, FONT_SIZE, 0x000000);
+ tf.text = char.charAt();
+ tf.autoSize = TextFieldAutoSize.LEFT;
+
+ // Determine the width and height of this character
+ var charWidth:int = Math.ceil(tf.width);
+ var charHeight:int = Math.ceil(tf.height);
+
+ // Create a temporary bitmap data to draw this character into
+ var charBitmap:BitmapData = new BitmapData(charWidth, charHeight, false, 0xFFFFFFFF);
+ charBitmap.draw(tf);
+
+ // Loop through each pixel in this character's bitmap data
+ var level:int = 0;
+ for (var y:int = charHeight; y--; )
+ {
+ for (var x:int = charWidth; x--; )
+ {
+ // If this pixel is bright enough, add it to the overall brightness level
+ if (charBitmap.getPixel(x, y) > 0x808080) level++;
+ }
+ }
+
+ // Return the brightness level as a percentage of the whole character area
+ return level / (charWidth * charHeight);
+ }
+
+ /**
+ * Converts a colour value to an averaged monochrome (greyscale) value
+ *
+ * @param col The colour to convert to monochrome
+ * @return The averaged monochrome value
+ */
+ private function getMonochrome(col:uint):uint
+ {
+ // Add the red, green and blue components together and return the average
+ return 0xFF - (((col >> 16) & 0xFF) + ((col >> 8) & 0xFF) + (col & 0xFF)) / 3;
+ }
+
+ /**
+ * Draws the ASCII effect
+ */
+ override public function draw():void
+ {
+ // Generate a lower resolution bitmap data to sample pixels from
+ smallBitmap.draw(source, smallMatrix, color);
+
+ // Create the ASCII textfield from each pixel
+ var str:String = "";
+ for (var y:int = 0; y < charsY; y++)
+ {
+ for (var x:int = 0; x < charsX; x++)
+ {
+ // Get the monochrome pixel value and convert it to an ASCII character
+ str += chars[int(getMonochrome(smallBitmap.getPixel(x, y)) / 0xFF * total)];
+ }
+ str += "\r\n"; // New line
+ }
+
+ // Draw the new ASCII textfield into the text bitmap data with a blurred background glow
+ textfield.text = str;
+ textBitmap.fillRect(rect, 0xFF000000);
+ textBitmap.draw(textfield, textMatrix);
+ sourceBitmap.applyFilter(textBitmap, rect, point, blur);
+ sourceBitmap.draw(textBitmap, null, null, BlendMode.ADD);
+ targetBitmap.draw(sourceBitmap, flipMatrix);
+ }
+
+ /**
+ * Removes the ASCII effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+ smallBitmap.dispose();
+ smallBitmap = null;
+ textBitmap.dispose();
+ textBitmap = null;
+ textfield = null;
+ chars = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/pixel/HalftoneDot.as b/webcam/com/neave/webcam/effects/pixel/HalftoneDot.as
new file mode 100755
index 0000000..4f4fb40
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/pixel/HalftoneDot.as
@@ -0,0 +1,33 @@
+/**
+ * Neave Webcam // Halftone Dot
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.pixel
+{
+ import flash.display.*;
+
+ final internal class HalftoneDot extends Shape
+ {
+ /**
+ * Draws a halftone dot shape to be used with the halftone effect
+ *
+ * @param x The position of the dot on the x-axis
+ * @param y The position of the dot on the y-axis
+ * @param radius The radius of the dot
+ */
+ public function HalftoneDot(x:Number = 0, y:Number = 0, radius:Number = 1)
+ {
+ this.x = x;
+ this.y = y;
+ graphics.beginFill(0x000000);
+ graphics.drawCircle(0, 0, radius);
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/pixel/HalftoneEffect.as b/webcam/com/neave/webcam/effects/pixel/HalftoneEffect.as
new file mode 100755
index 0000000..0b9cf3c
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/pixel/HalftoneEffect.as
@@ -0,0 +1,135 @@
+/**
+ * Neave Webcam // Halftone Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.pixel
+{
+ import flash.display.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class HalftoneEffect extends AbstractEffect
+ {
+ private var dotsWide:int;
+ private var invert:Boolean;
+ private var smallBitmap:BitmapData;
+ private var smallMatrix:Matrix;
+ private var halftone:Sprite;
+ private var dotsX:int;
+ private var dotsY:int;
+ private var size:Number;
+
+ /**
+ * Creates a halftone effect where each pixel is drawn as a variably-sized black dot, as used in the printing process
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param dotsWide The number of dots to use in width
+ * @param invert Inverts the halftone effect so bright pixels create large dots
+ */
+ public function HalftoneEffect(source:IBitmapDrawable, targetBitmap:BitmapData, dotsWide:int = 40, invert:Boolean = false)
+ {
+ super(source, targetBitmap, "Halftone");
+ this.dotsWide = dotsWide < 1 ? 1: dotsWide;
+ this.invert = invert;
+
+ createHalftone();
+ }
+
+ /**
+ * Sets up the halftone effect
+ */
+ private function createHalftone():void
+ {
+ // Increase contrast
+ color = new ColorTransform(1.5, 1.5, 1.5, 1, -50, -50, -50);
+
+ // Create a smaller, lower resolution bitmap to sample pixels from
+ smallBitmap = new BitmapData(dotsWide, Math.round(dotsWide * rect.height / rect.width), false, 0xFF000000);
+ dotsX = smallBitmap.width;
+ dotsY = smallBitmap.height;
+ smallMatrix = new Matrix();
+ smallMatrix.scale(dotsX / rect.width, dotsY / rect.height);
+ size = rect.width / dotsX;
+
+ // Create a sprite containing all the halftone dots needed
+ halftone = new Sprite();
+ for (var y:int = dotsY; y--; )
+ {
+ for (var x:int = dotsX; x--; )
+ {
+ // Position each halftone dot, alternating the y-axis position between on pixel and halfway between pixels
+ halftone.addChild(new HalftoneDot((x + 0.25 + (y % 2) * 0.5) * size, (y + 0.5) * size, size));
+ }
+ }
+ }
+
+ /**
+ * Converts a colour value to an averaged monochrome (greyscale) value
+ *
+ * @param col The colour to convert to monochrome
+ * @param inv Whether to invert the monochrome value
+ * @return The averaged monochrome value
+ */
+ private function getMonochrome(col:uint, inv:Boolean):uint
+ {
+ // Add the red, green and blue components together and return the average
+ var mono:uint = (((col >> 16) & 0xFF) + ((col >> 8) & 0xFF) + (col & 0xFF)) / 3;
+ if (inv) return mono;
+ else return 0xFF - mono;
+ }
+
+ /**
+ * Draws the halftone effect
+ */
+ override public function draw():void
+ {
+ // Generate a lower resolution bitmap data to sample pixels from
+ smallBitmap.draw(source, smallMatrix, color);
+
+ // Create the halftone dots from each pixel
+ var n:int = 0;
+ for (var y:int = dotsY; y--; )
+ {
+ for (var x:int = dotsX; x--; )
+ {
+ // Average this pixel's colour to a greyscale value
+ var w:Number = getMonochrome(smallBitmap.getPixel(x, y), invert) / 0xFF * Math.SQRT2 * size;
+
+ // Set this dot's size, alternating the y-axis position between on pixel and halfway between pixels
+ var d:HalftoneDot = halftone.getChildAt(n) as HalftoneDot;
+ d.width = d.height = (y % 2 == 0 || n == 0) ? w : (w + halftone.getChildAt(n - 1).width) / 2; // Average pixel values if this y-axis position is between pixels
+ n++;
+ }
+ }
+
+ // Draw the new halftone dots
+ targetBitmap.lock();
+ targetBitmap.fillRect(rect, 0xFFFFFFFF);
+ targetBitmap.draw(halftone);
+ targetBitmap.unlock();
+ }
+
+ /**
+ * Removes the halftone effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+
+ // Remove all the halftone dots
+ for (var i:int = dotsX * dotsY; i--; ) halftone.removeChildAt(i);
+ halftone = null;
+
+ smallBitmap.dispose();
+ smallBitmap = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/pixel/PixelateEffect.as b/webcam/com/neave/webcam/effects/pixel/PixelateEffect.as
new file mode 100755
index 0000000..8ff94d5
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/pixel/PixelateEffect.as
@@ -0,0 +1,75 @@
+/**
+ * Neave Webcam // Pixelate Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.pixel
+{
+ import flash.display.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class PixelateEffect extends AbstractEffect
+ {
+ private var pixelsWide:int;
+ private var smallBitmap:BitmapData;
+ private var targetMatrix:Matrix;
+
+ /**
+ * Creates a low-resolution effect where pixels appear large
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param pixelsWide The number of pixels to use in width
+ */
+ public function PixelateEffect(source:IBitmapDrawable, targetBitmap:BitmapData, pixelsWide:int = 20)
+ {
+ super(source, targetBitmap, "Pixelate");
+ this.pixelsWide = pixelsWide < 1 ? 1 : pixelsWide;
+
+ createPixelate();
+ }
+
+ /**
+ * Sets up the pixelate effect
+ */
+ private function createPixelate():void
+ {
+ // Create a low resolution bitmap data
+ smallBitmap = new BitmapData(pixelsWide, Math.round(pixelsWide * rect.height / rect.width), false, 0xFF000000);
+
+ // Set up scaling of bitmaps from large to small to large again
+ var sx:Number = smallBitmap.width / rect.width;
+ var sy:Number = smallBitmap.height / rect.height;
+ sourceMatrix.scale(sx, sy);
+ targetMatrix = new Matrix();
+ targetMatrix.scale(1 / sx, 1 / sy);
+ }
+
+ /**
+ * Draws the pixelate effect
+ */
+ override public function draw():void
+ {
+ // Resize small then resize large
+ smallBitmap.draw(source, sourceMatrix);
+ targetBitmap.draw(smallBitmap, targetMatrix);
+ }
+
+ /**
+ * Removes the pixelate effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+ smallBitmap.dispose();
+ smallBitmap = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/pixel/RGBEffect.as b/webcam/com/neave/webcam/effects/pixel/RGBEffect.as
new file mode 100755
index 0000000..4d2b2ff
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/pixel/RGBEffect.as
@@ -0,0 +1,126 @@
+/**
+ * Neave Webcam // Red Green Blue Effect
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.pixel
+{
+ import flash.display.*;
+ import flash.geom.*;
+ import com.neave.webcam.effects.*;
+
+ public class RGBEffect extends AbstractEffect
+ {
+ private const COLORS:Array = [0xFF0000, 0x00FF00, 0x0000FF];
+
+ private var pixelsWide:int;
+ private var smallBitmap:BitmapData;
+ private var smallMatrix:Matrix;
+ private var pixels:Sprite;
+ private var pixelsX:int;
+ private var pixelsY:int;
+ private var size:Number;
+
+ /**
+ * Creates a low-resolution effect where each pixel is split into its red, green and blue components
+ *
+ * @param source The source object to use for the effect
+ * @param targetBitmap The target bitmap data to draw the resulting effect into
+ * @param pixelsWide The number of pixels to use in width
+ */
+ public function RGBEffect(source:IBitmapDrawable, targetBitmap:BitmapData, pixelsWide:int = 40)
+ {
+ super(source, targetBitmap, "RGB");
+ this.pixelsWide = pixelsWide < 3 ? 3 : pixelsWide;
+
+ createRGB();
+ }
+
+ /**
+ * Sets up the RGB effect
+ */
+ private function createRGB():void
+ {
+ // Create a smaller, lower resolution bitmap to sample pixels from
+ smallBitmap = new BitmapData(pixelsWide, Math.round(pixelsWide * rect.height / rect.width), false, 0xFF000000);
+ pixelsX = smallBitmap.width;
+ pixelsY = smallBitmap.height;
+ smallMatrix = new Matrix();
+ smallMatrix.scale(pixelsX / rect.width, pixelsY / rect.height);
+ size = rect.width / pixelsX;
+
+ // Create a sprite containing all the RGB pixels needed
+ pixels = new Sprite();
+ for (var y:int = pixelsY; y--; )
+ {
+ for (var x:int = pixelsX; x--; )
+ {
+ // Position each RGB pixel and set its colour to either red, green or blue
+ pixels.addChild(new RGBPixel((x + 0.5) * size, (y + 0.5) * size, COLORS[x % 3], size));
+ }
+ }
+ }
+
+ /**
+ * Draws the RGB effect
+ */
+ override public function draw():void
+ {
+ // Generate a lower resolution bitmap data to sample pixels from
+ smallBitmap.draw(source, smallMatrix, color);
+
+ // Create the RGB pixels from each pixel
+ var n:int = 0;
+ for (var y:int = pixelsY; y--; )
+ {
+ for (var x:int = pixelsX; x--; )
+ {
+ // Set the brightness of this RGB pixel
+ var c:uint = smallBitmap.getPixel(x, y);
+ var p:RGBPixel = pixels.getChildAt(n++) as RGBPixel;
+ switch (x % 3)
+ {
+ case 0: // Red
+ p.alpha = ((c >> 16) & 0xFF) / 0xFF;
+ break;
+
+ case 1: // Green
+ p.alpha = ((c >> 8) & 0xFF) / 0xFF;
+ break;
+
+ case 2: // Blue
+ p.alpha = (c & 0xFF) / 0xFF;
+ break;
+ }
+ }
+ }
+
+ // Draw the new RGB pixels
+ targetBitmap.lock();
+ targetBitmap.fillRect(rect, 0xFF000000);
+ targetBitmap.draw(pixels);
+ targetBitmap.unlock();
+ }
+
+ /**
+ * Removes the RGB effect and all other referenced objects
+ */
+ override public function destroy():void
+ {
+ super.destroy();
+
+ // Remove all the pixels
+ for (var i:int = pixelsX * pixelsY; i--; ) pixels.removeChildAt(i);
+ pixels = null;
+
+ smallBitmap.dispose();
+ smallBitmap = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/webcam/com/neave/webcam/effects/pixel/RGBPixel.as b/webcam/com/neave/webcam/effects/pixel/RGBPixel.as
new file mode 100755
index 0000000..ababb10
--- /dev/null
+++ b/webcam/com/neave/webcam/effects/pixel/RGBPixel.as
@@ -0,0 +1,34 @@
+/**
+ * Neave Webcam // Red Green Blue Pixel
+ *
+ * Copyright (C) 2008 Paul Neave
+ * http://www.neave.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html
+ */
+
+package com.neave.webcam.effects.pixel
+{
+ import flash.display.*;
+
+ final internal class RGBPixel extends Shape
+ {
+ /**
+ * Draws a simple square graphic to be used with the RGB effect
+ *
+ * @param x The position of the pixel on the x-axis
+ * @param y The position of the pixel on the y-axis
+ * @param color The colour of the pixel
+ * @param size The size (width and height) of the pixel
+ */
+ public function RGBPixel(x:int = 0, y:int = 0, color:uint = 0, size:Number = 1)
+ {
+ this.x = x - size / 2;
+ this.y = y - size / 2;
+ graphics.beginFill(color);
+ graphics.drawRect(0, 0, size, size);
+ }
+ }
+} \ No newline at end of file