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.

Example
Figure : hitTest() will return false.
Example
Figure : hitTest() will return 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();
        }

Pages: 1, 2, 3, 4

Next Pagearrow