Images, Bitmaps, Videos, Sounds: Chapter 8 - Flex 3 Cookbook

by Joshua Noble and Todd Anderson

This excerpt is from Flex 3 Cookbook. This highly practical book contains more than 300 proven recipes for developing interactive Rich Internet Applications and Web 2.0 sites. You'll find everything from Flex basics and working with menus and controls, to methods for compiling, deploying, and configuring Flex applications. Each recipe features a discussion of how and why it works, and many of them offer sample code that you can put to use immediately.

buy button

Images, bitmaps, videos, and sounds is a mouthful and a far wider range of topics than could be adequately covered in a single chapter, so this one concentrates on answering the most common questions. As Flash becomes the primary method of delivering video over the Internet and the use of the Flex Framework in creating photo and MP3 applications increases, understanding how to work with all of these elements becomes more and more important.

The Flash Player offers multiple levels of tools for dealing with images and sound. The first avenue of control contains the Image and VideoDisplay classes, MXML classes that simplify much of dealing with images and video and enable you to quickly integrate these assets into your application. The next step down is the flash.media package, which houses the Video, Sound, SoundTransform, Camera, and Microphone classes; their corollaries, Loader, NetConnection, and NetStream, are in the flash.net package. These classes provide much finer control over the integration of sound, video, and images into an application and require slightly more time to perfect. Finally, you can reach down to the bytes of data in the Flash Player: the BitmapData classes and the ByteArray classes. These classes enable you not only to manipulate the bitmap data of the images that you load into the Flash Player, but they also let you create new bitmaps and stream the data out.

Many of the examples in this chapter manipulate images and videos as bitmap data. This is not nearly as difficult as it sounds, because the Flash Player provides numerous convenience methods for working with the BitmapData class, and manipulating the bitmap data directly greatly increases the efficiency of your application. You'll also be working extensively with the NetStream class, for handling video and users' microphones and cameras. NetStream is an effective way of streaming information both to and from server-side applications.

Section 8.1: Load and Display an Image

Problem

You need to display an image in a Flex component.

Solution

Use either an Embed statement to compile the image into the SWF file or load the image at runtime.

Discussion

Flex supports importing GIF, JPEG, PNG, and SWF files at runtime or at compile time, and SVG files at compile time through embedding. The method you choose depends on the file types of your images and your application parameters. Any embedded images are already part of the SWF file and so don't require any time to load. The trade-off is the size that they add to your application, which slows the application initialization process. Extensive use of embedded images also requires you to recompile your applications whenever your image files change.

Alternatively, you can load the resource at runtime by either setting the source property of an image to a URL or by using URLRequest objects and making the result of the load operation a BitmapAsset object. You can load a resource from the local file system in which the SWF file runs, or you can access a remote resource, typically through an HTTP request over a network. These images are independent of your application; you can change them without needing to recompile as long as the names of the modified images remain the same.

Any SWF file can access only one type of external resource, either local or over a network; it cannot access both types. You determine the type of access allowed by the SWF file by using the use-network flag when you compile your application. When the use-network flag is set to false, you can access resources in the local file system, but not over the network. The default value is true, which allows you to access resources over the network, but not in the local file system.

To embed an image file, use the Embed metadata property:

            [Embed(source="../assets/flag.png")]
            private var flag:Class;

Now this Class object can be set as the source for an image:

                var asset:BitmapAsset = new flag() as BitmapAsset;
                img3rd.source = asset;

Alternatively, you can set the property of the source to a local or external file system:

<mx:Image source="http://server.com/beach.jpg"/>

The full example follows:

<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
    <mx:Script>
        <![CDATA[
            import mx.core.BitmapAsset;

            [Embed(source="../assets/flag.png")]
            private var flag:Class;

            private function imgMod():void
            {
                var asset:BitmapAsset = new flag() as BitmapAsset;
                img3rd.source = asset;
            }

        ]]>
    </mx:Script>
    <mx:Image source="../assets/flag.png"/>
    <mx:Image source="{flag}"/>
    <mx:Image id="img3rd" creationComplete="imgMod()"/>
</mx:VBox>

Section 8.2: Create a Video Display

Problem

You need to display an FLV file in your application.

Solution

Use the VideoDisplay class in your application and use Button instances to play and pause the application if desired.

Discussion

The VideoDisplay class wraps a flash.media.Video object and simplifies adding video to that object considerably. The source attribute of the VideoDisplay is set to the URL of an FLV file, and the autoplay parameter is set to true so that when the NetStream has been properly instantiated and the video information begins streaming to the player, the video will begin playing:

<mx:VideoDisplay source="http://localhost:3001/Trailer.flv" id="vid" autoplay="true"/>

In the following example, buttons are set up to play, pause, and stop the video by using the methods defined by the VideoDisplay class:

<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
    <mx:VideoDisplay source="http://localhost:3001/Trailer.flv" id="vid" autoPlay=
"false" autoRewind="true"/>
    <mx:HBox>
            <mx:Button label="Play" click="vid.play();"/>
            <mx:Button label="Pause" click="vid.pause();"/>
            <mx:Button label="Stop" click="vid.stop();"/>
        </mx:HBox>
</mx:VBox>

Section 8.3: Play and Pause an MP3 File

Problem

You want to allow a user to play a series of MP3 files.

Solution

Use the Sound and SoundChannel classes and load new files by using progressive download when the user selects a new MP3 file.

Discussion

The play method of the Sound class returns a SoundChannel object that provides access to methods and properties that control the balance or right and left volume of the sound, as well as methods to pause and resume a particular sound.

For example, let's say your code loads and plays a sound file like this:

var snd:Sound = new Sound(new URLRequest("sound.mp3"));
var channel:SoundChannel = snd.play();

You cannot literally pause a sound during playback in ActionScript; you can only stop it by using the SoundChannel stop method. You can, however, play a sound starting from any point. You can record the position of the sound at the time it was stopped, and then replay the sound starting at that position later.

While the sound plays, the SoundChannel.position property indicates the point in the sound file that's currently being played. Store the position value before stopping the sound from playing:

var pausePosition:int = channel.position;
channel.stop();

To resume the sound, pass the previously stored position value to restart the sound from the same point it stopped at before:

channel = snd.play(pausePosition);

The following complete code listing provides a combo box to allow the user to select different MP3 files, pause, and stop playback by using the SoundChannel class:

<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
    <mx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;

            public var sound:Sound;
            public var chan:SoundChannel;
            public var pausePos:int = 0;

            private const server:String = "http://localhost:3001/"

            private var dp:ArrayCollection = new ArrayCollection(["Plans.mp3", 
"Knife.mp3", "Marla.mp3", "On a Neck, On a Spit.mp3", "Colorado.mp3"])

            private function loadSound():void {
                if(chan != null) {
                    //make sure we stop the sound; otherwise, they'll overlap
                    chan.stop();
                }
                //re-create sound object, flushing the buffer, and readd the event 
listener
                sound = new Sound();
                sound.addEventListener(Event.SOUND_COMPLETE, soundComplete);
                var req:URLRequest = new URLRequest(server + cb.selectedItem as 
String);
                sound.load(req);
                pausePos = 0;
                chan = sound.play();
            }
            //
            private function soundComplete(event:Event):void {
                cb.selectedIndex++;
                sound.load(new URLRequest(server + cb.selectedItem as String));
                chan = sound.play();
            }

            private function playPauseHandler():void
            {
                if(pausePlayBtn.selected){
                    pausePos = chan.position;
                    chan.stop();
                } else {
                    chan = sound.play(pausePos);
                }
            }

        ]]>
    </mx:Script>
    <mx:ComboBox creationComplete="cb.dataProvider=dp" id="cb" change="loadSound()"/>
    <mx:Button label="start" id="pausePlayBtn" toggle="true" click=
"playPauseHandler()"/>
    <mx:Button label="stop" click="chan.stop()"/>
</mx:HBox>

Section 8.4: Create a Seek Bar for a Sound File

Problem

You need to create a seek control for a user to seek different parts of an MP3 file and a volume control to change the volume of the MP3 playback.

Solution

Pass a time parameter to the Sound play method to begin playing the file from that point. This creates a new SoundTransform object that should be set as the soundTransform of the SoundChannel.

Discussion

The play method of the sound file accepts a start-point parameter:

public function play(startTime:Number = 0, loops:int = 0, sndTransform: SoundTransform
= null):SoundChannel

This creates a new SoundChannel object to play the sound returns that object, which you access to stop the sound and monitor the volume. (To control the volume, panning, and balance, access the SoundTransform object assigned to the SoundChannel.)

To control the volume of the sound, pass the SoundTransform object to the . We create a new SoundTransform object with the desired values and pass it to the SoundChannel that is currently playing:

var trans:SoundTransform = new SoundTransform(volumeSlider.value);
chan.soundTransform = trans;

The SoundTransform class accepts the following parameters:

SoundTransform(vol:Number = 1, panning:Number = 0)

The panning values range from -1.0, indicating a full pan left (no sound coming out of the right speaker) to 1.0, indicating a full pan right. A full code listing is shown here:

<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" 
creationComplete="loadSound()">
    <mx:Script>
        <![CDATA[

            private var sound:Sound;
            private var chan:SoundChannel;

            private function loadSound():void {
                sound = new Sound(new URLRequest("http://localhost:3001/Plans.mp3"));
                chan = sound.play();
            }

            private function scanPosition():void {
                chan.stop();
                //divide by 10 because the Slider values go from 0 - 10 and we want 
a value
                //between 0 - 1.0
                chan = sound.play(positionSlider.value/10 * sound.length);
            }

            private function scanVolume():void
            {
                var trans:SoundTransform = new SoundTransform(volumeSlider.value, 
(panSlider.value - 5)/10);
                chan.soundTransform = trans;
            }

        ]]>
    </mx:Script>
    <mx:Label text="Position"/>
    <mx:HSlider change="scanPosition()" id="positionSlider"/>
    <mx:Label text="Volume"/>
    <mx:HSlider change="scanVolume()" id="volumeSlider"/>
    <mx:Label text="Pan"/>
    <mx:HSlider change="scanVolume()" id="panSlider"/>
</mx:VBox>

Section 8.5: Blend Two Images

Problem

You want to manipulate and combine multiple images at runtime and use filters to alter those images.

Solution

Cast the images as BitmapData objects and use the combine method of the BitmapData class to combine all the data in the two bitmaps into a new image.

Discussion

The BitmapData and Bitmap classes are powerful tools for manipulating images at runtime and creating new effects. The two classes are frequently used in tandem but are quite different. BitmapData encapsulates the actual data of the image, and Bitmap is a display object that can be added to the display list. The BitmapData object is created and drawn into as shown here:

var bitmapAsset:BitmapAsset = new BitmapAsset(img1.width, img1.height);
bitmapAsset.draw(img1);

First, set the height and width of the BitmapAsset, ensuring that the object is the correct size, and then draw all the data from an image. This captures all the data in the image as a bitmap and allows you to manipulate that data. In the following example, the colorTransform method manipulates the color data of the BitmapData object, and the two bitmaps are merged via the merge method. The colorTransform method applies the data from a ColorTransform object to the BitmapData object. The ColorTransform object modifies the color of a display object or BitmapData according to the values passed in to the constructor:

ColorTransform(redMultiplier:Number = 1.0, greenMultiplier:Number = 1.0, 
blueMultiplier:Number = 1.0, alphaMultiplier:Number = 1.0, redOffset:Number = 0,
greenOffset:Number = 0, blueOffset:Number = 0, alphaOffset:Number = 0)

When a ColorTransform object is applied to a display object, a new value for each color channel is calculated like this:

  • New red value = (old red value * redMultiplier) + redOffset
  • New green value = (old green value * greenMultiplier) + greenOffset
  • New blue value = (old blue value * blueMultiplier) + blueOffset
  • New alpha value = (old alpha value * alphaMultiplier) + alphaOffset

The merge method of the BitmapData class has the following signature:

merge(sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, redMultiplier
:uint, greenMultiplier:uint, blueMultiplier:uint, alphaMultiplier:uint):void

Pages: 1, 2, 3, 4

Next Pagearrow