Images, Bitmaps, Videos, Sounds: Chapter 8 - Flex 3 Cookbook
Pages: 1, 2, 3, 4
This code returns false when the pixels of the first image at
the given points do not possess alpha values greater than those set in
the hitTest method. In , the two light
blue squares are within a PNG file with alpha transparency. The shake
is a separate image that, at this moment, is not colliding with an
area of the PNG with a high-enough alpha. In , however, the shake
collides with a square and the method returns true.
Section 8.11: Read and Save a User's Webcam Image
Problem
You want to read an image from a user's webcam and save that image to a server.
Solution
Create a Camera object and
attach it to a Video object. Then
create a button that will read a bitmap from the Video object and save the bitmap data to a
server-side script that will save the image.
Discussion
To capture an image from a webcam, create a bitmap from the
Video object that is displaying the
camera image. The Flash Player doesn't provide any access to the
stream of data that is read from the webcam, however, so you need to
render the data as a bitmap before you can use it.
After the image has been captured as a BitmapData object, you can pass that data to
an instance of the JPEGEncoder
class to convert the image into JPEG data. Next, save the JPEG to a
server by adding the data to a URLRequest object and sending it via the
navigateToURL method. For
example:
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="500"
creationComplete="setUpCam()">
<mx:Script>
<![CDATA[
import flash.net.navigateToURL;
import flash.net.sendToURL;
import mx.graphics.codec.JPEGEncoder;
private var cam:Camera;
private function setUpCam():void {
cam = flash.media.Camera.getCamera("2");
vid.attachCamera(cam);
}
private function saveImage():void {
var bitmapData:BitmapData = new BitmapData(vid.width, vid.height);
bitmapData.draw(vid);
var encode:JPEGEncoder = new JPEGEncoder(100);
var ba:ByteArray = encode.encode(bitmapData);
var urlRequest:URLRequest = new URLRequest("/jpg_reader.php");
urlRequest.method = "POST";
var urlVars:URLVariables = new URLVariables();
urlVars.pic = ba;
urlRequest.data = urlVars;
flash.net.navigateToURL(urlRequest, "_blank");
}
]]>
</mx:Script>
<mx:VideoDisplay id="vid" width="360" height="320"/>
<mx:Button label="Take Picture Now" click="saveImage()"/>
</mx:Canvas>
Section 8.12: Use Blend Modes with Multiple Images
Problem
You want to blend multiple images.
Solution
Set the blendMode property of
the images.
Discussion
Every DisplayObject defines a
blendMode property that controls
how that appears, controlling
the alpha and how any DisplayObjects beneath that object in the
DisplayList appear through that
component. The blend modes should be familiar to anyone who has worked
with Adobe Photoshop or After Effects:
BlendMode.ADD ("add")- Creates an animated lightening dissolve effect between two images.
BlendMode.ALPHA ("alpha")- Applies the transparency of the foreground to the background.
BlendMode.DARKEN ("darken")- Superimposes type.
BlendMode.DIFFERENCE ("difference")- Creates more-vibrant colors.
BlendMode.ERASE ("erase")- Erases part of the background by using the foreground alpha.
BlendMode.HARDLIGHT ("hardlight")- Creates shading effects.
BlendMode.INVERT ("invert")- Inverts the background.
BlendMode.LAYER ("layer")- Forces the creation of a temporary buffer for precomposition for a particular display object.
BlendMode.LIGHTEN ("lighten")- Superimposes type.
BlendMode.MULTIPLY ("multiply")- Creates shadows and depth effects.
BlendMode.NORMAL ("normal")- Specifies that the pixel values of the blend image override those of the base image.
BlendMode.OVERLAY ("overlay")- Creates shading effects.
BlendMode.SCREEN ("screen")- Creates highlights and lens flares.
BlendMode.SUBTRACT ("subtract")- Creates an animated darkening dissolve effect between two images.
The following example applies the various blend modes to the two
Image objects:
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="800" height="800">
<mx:Script>
<![CDATA[
import flash.display.BlendMode;
]]>
</mx:Script>
<mx:Image id="img1" mouseDown="img1.startDrag(false, this.getBounds(stage)),
swapChildren(img1, img2)" rollOut="img1.stopDrag()" mouseUp="img2.stopDrag()"
source="../assets/mao.jpg"/>
<mx:Image id="img2" mouseDown="img2.startDrag(false, this.getBounds(stage)),
swapChildren(img2, img1)" rollOut="img2.stopDrag()" mouseUp="img2.stopDrag()"
source="../assets/bigshakey.png"/>
<mx:HBox>
<mx:CheckBox id="chb" label="which one"/>
<mx:ComboBox id="cb" dataProvider="{[BlendMode.ADD, BlendMode.ALPHA, BlendMode
.DARKEN, BlendMode.DIFFERENCE, BlendMode.ERASE, BlendMode.HARDLIGHT, BlendMode.
INVERT,BlendMode.LAYER, BlendMode.LIGHTEN, BlendMode.MULTIPLY, BlendMode.NORMAL,
BlendMode.OVERLAY, BlendMode.SCREEN, BlendMode.SUBTRACT]}"
change="chb.selected ? img1.blendMode = cb.selectedItem as String :
img2.blendMode = cb.selectedItem as String"/>
</mx:HBox>
</mx:Canvas>
Section 8.13: Handle Cue Points in FLV Data
Problem
You need to work with cue points that are embedded in an FLV file while it plays.
Solution
Use the onCuePoint event
of the NetStream
class to create a handler method to be fired whenever a cue point is
encountered.
Discussion
A cue point is a value inserted into an FLV
file at a certain time within a video that contains either simply a
name or a data object with a hash table of values. Usually cue points
are inserted into an FLV when the file is being encoded, and any
values are determined there. The Flex VideoDisplay object uses the mx.controls.videoclasses.CuePoint manager
class to handle detecting and reading any data from a cue point. For a
more-complete understanding of this, consider an example using the
flash.media.Video object.
When the NetConnection object
has connected and the NetStream is
being instantiated, you need to set an object to relay any metadata
and cue point events to handler methods:
var obj:Object = new Object(); obj.onCuePoint = onCuePoint; obj.onMetaData = onMetaData; ns.client = obj;
This needs to occur before the NetStream play method is called. Note in the
following code that both the onMetaData and onCuePoint events accept an object as a
parameter:
import flash.events.NetStatusEvent;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import mx.core.UIComponent;
public class CuePointExample extends UIComponent
{
private var ns:NetStream;
private var nc:NetConnection;
private var obj:Object = {};
private var vid:Video;
public function CuePointExample () {
super();
vid = new Video();
addChild(vid);
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusEventHandler);
nc.connect(null);
}
private function netStatusEventHandler(event:NetStatusEvent):void {
ns = new NetStream(nc);
obj.onCuePoint = onCuePoint;
obj.onMetaData = onMetaData;
ns.client = obj;
ns.play("http://localhost:3001/test2.flv");
vid.attachNetStream(ns);
}
private function onCuePoint(obj:Object):void {
trace(obj.name+" "+obj.time+" "+obj.length+" ");
for each(var o:String in obj.parameters) {
trace(obj[o]+" "+o);
}
}
private function onMetaData(obj:Object):void{
}
}
Using the mx.controls.VideoDisplay simplifies working
with a cue point object quite substantially. When using the CuePointEvent dispatched by the CuePointManager, unlike in the preceding
case, the received event possesses only three properties: cuePointTime, cuePointName, and cuePointType. If you need more or different
information from the cue point, you can write a custom class to return
the cue point data and set it to the cuePointManager property of the VideoDisplay object. The complete code
listing is shown here:
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
<mx:Script>
<![CDATA[
import mx.events.CuePointEvent;
private function onCuePoint(event:CuePointEvent):void {
trace(event.cuePointName+" "+event.cuePointTime+"
"+event.cuePointType+" ");
}
]]>
</mx:Script>
<mx:VideoDisplay id="vid" cuePoint="onCuePoint(event)"/>
</mx:VBox>
Section 8.14: Create a Video Scrubber
Problem
You need to create a control that a user can use to scrub through a video as it plays.
Solution
Create a draggable Sprite
object and listen for any DragEvent events dispatched from it. In the
event handler for the DragEvent,
set the amount to seek forward or backward in the NetStream that is streaming the video to the
Video object.
Discussion
You can use any draggable display object to set the new position
at which the video should be played. In this example, the seek method of the NetStream begins playback from the specified
point in seconds from the beginning of the video:
ns.seek((playhead.x/timeline.width) * length);
To determine which second in the video that the user meant to
seek, divide the position of the dragged Sprite by the width of the timeline area and
multiply by the length of the video. The NetStream will take care of locating the
appropriate frames in the video and restarting the streaming from that
point.
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import mx.core.UIComponent;
public class Scrubber extends UIComponent
{
private var playhead:Sprite;
private var timeline:Sprite;
private var ns:NetStream;
private var nc:NetConnection;
private var obj:Object = {};
private var length:int;
private var vid:Video;
public function Scrubber () {
super();
playhead = new Sprite();
addChild(playhead);
playhead.graphics.beginFill(0x0000ff, 1);
playhead.graphics.drawCircle(0, 0, 5);
playhead.graphics.endFill();
playhead.addEventListener(MouseEvent.MOUSE_DOWN, startSeek);
timeline = new Sprite();
timeline.graphics.beginFill(0xcccccc, 1);
timeline.graphics.drawRect(0, 0, 200, 10);
timeline.graphics.endFill();
addChild(timeline);
timeline.addChild(playhead);
playhead.y = 4;
vid = new Video();
addChild(vid);
vid.y = 100;
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
nc.connect(null);
}
private function netStatus(event:NetStatusEvent):void {
obj.onMetaData = onMetaData;
ns = new NetStream(nc);
ns.client = obj;
vid.attachNetStream(ns);
ns.play("http://localhost:3001/test.flv");
}
private function onMetaData(obj:Object):void {
length = obj.duration;
trace(length);
}
private function startSeek(mouseEvent:MouseEvent):void {
playhead.startDrag(false, timeline.getBounds(this));
addEventListener(MouseEvent.MOUSE_MOVE, seek);
playhead.addEventListener(MouseEvent.ROLL_OUT, endSeek);
playhead.addEventListener(MouseEvent.MOUSE_UP, endSeek);
}
private function seek(mouseEvent:MouseEvent):void {
ns.seek((playhead.x/timeline.width) * length);
}
private function endSeek(mouseEvent:MouseEvent):void {
removeEventListener(MouseEvent.MOUSE_MOVE, seek);
playhead.stopDrag();
}


