Anatomy of a SWF File
Patrick has developed Flash content for major industry heavyweights like Disney, Mitsubishi, and Viacom. He's developed Rapid Application Development libraries, 128-bit encryption, and other useful stuff for Flash. Patrick currently runs Bay New Media, his Toronto, Canada based Flash and web application development company, and still gets a kick our of coding ActionScript each and every day. Check out his tutorial site http://www.peabee.com/ for extended content and great ActionScript tutorials.View all articles by Patrick Bay
We won't be looking into the bit-by-bit format of the SWF file (you can request that information here if you're interested). Rather, we'll be looking at how SWF files are formed in general, how they are used and transmitted over the web, and how they go about producing all that neat Flash content.
The abbreviation "SWF" (pronounced "swiff") stands for "ShockWave Flash". This stems from the days when Macromedia was still developing the Flash technology and they had a more powerful star in their software lineup called ShockWave.
In many ways, ShockWave is still more powerful than Flash. It comes with a built-in 3D graphics engine, and can interact with the user's operating system without any extensions. In many ways Flash has caught up to, and in some ways surpassed ShockWave, but it's still a powerful format.
There were a few mitigating factors that forced ShockWave to a far second position. First, the programming language wasn't based on any standards and was difficult to use even for experienced developers. Unlike Flash, the ShockWave editor (called Director) was also difficult to use by casual users. Finally, Flash caught up to most of ShockWave's capabilities relatively quickly while maintaining a much easier, standards-based programming language, and an easy to use editor.
Production on the Director software was essentially (though unofficially) halted in version MX2004, which is about the same as Flash version 7. It is still used in CDROM startup screens and kiosks, but Flash has far outstripped ShockWave in popularity. You can still experience ShockWave on the site initially developed for it: www.shockwave.com
Standards, once established, are often difficult to break, so the content name "ShockWave Flash" stuck. This is used by web servers to identify the content to web browsers (also called the MIME type), and has become the default file extension for the Flash-format output file. The two technologies are very loosely related; ShockWave can load and display Flash content; but that's about where the commonalities end.
The All-In-One Solution
The SWF file is really an amazing solution for content delivery. It can contain graphics, audio, programming, and data in a single package that can be delivered over a standard web connection to just about any browser out there.
Image 1.1.1 - The SWF file with content inside, and loaded from external sources
The file is a binary file. This means that it's almost entirely data that's meant to be interpreted by the Flash player/AIR runtime and not intended to be read directly by humans. If you were to open a Flash file in a program like the Windows Notepad, you wouldn't see anything but gibberish. This gibberish is meaningful to the Flash player/AIR runtime, but not to you.
That's not to say that, with the specification document available, you couldn't actually read this. If you learned what each symbol in the file represents and you were able to recognize how the file is structured, in theory you could read it. However, that would be extremely tedious and it wouldn't really offer any more insight into the SWF file than running it in the player/runtime would. Plus, because the file is compressed to make it small, you would probably have to read it numerous times in various formats in order to get at the final, meaningful information.
Viewing the binary data directly isn't really useful except for the first three letters that appear right at the beginning. These are "CWS" and typically indicate that the content is a compressed Flash SWF file. However, this isn't necessarily limited to Flash content so if you do happen to see "CWS" at the start of a binary file, it is probably but not necessarily a SWF file.
SWF files are streaming. This means that they are intended to be played back as they are being delivered over a network, like the Internet. There are many other streaming formats out there like video and audio files. As soon as the player on your computer has enough data to start playing *something*, it starts doing so. This is the same with SWF files.
The reason for this is because Flash started it's life as an animation tool. Flash version 1 was mostly designed to deliver live animation and audio over a network connection. Because animations could be quite long, waiting for them to fully download would sometimes require a lot of patience. Instead, the Flash player begins playing back the content as soon as it has enough information to generate the first frame of animation. The rest of the content can continue to "stream" into the player in the background while playback continues.
This is also sometimes referred to as "progressive download" and is also used for one type of Flash video playback to be discussed in a future article. Because a Flash file is required to stream, it must be structured in a very specific sequence so that, for example, the first frame of animation isn't added to the end of the file. In other words, SWF files are stored sequentially so that if the end of a SWF file is damaged it is likely that the last frames of the animation will also be damaged. Not all files are stored in sequence like this.
Because network bandwidth is always at a premium, the SWF file is also compressed so that there is simply less data to deliver. A compression system similar to the ubiquitous ZIP file called Lempel-Ziv-Welch (or LZW) is used to compress the SWF data before it is finally output to a file. This produces the tightest possible package without losing any of the contents.
There do exist many other compression systems like the JPEG system for images which are "lossy", meaning that some of the original information is lost (crisp edges on a picture, for example). When we're dealing with programmatic instructions, however, any losses could be absolutely disastrous, so lossy compression methods simply don't enter into the picture. Because the SWF file is also a streaming format, extra work is required by the Flash editor to ensure that the compressed data stays in the correct order when the SWF file is being produced.
Now we have a properly formatted, compressed, streaming SWF file. So what does it actually contain?
A SWF file contains a few standard things and many optional things.
Some of the standard information found in all Flash files includes the frame rate at which to play animation at, the number of frames found on the "main timeline" (discussed in section 2.x), and the content dimensions like width and height. Remember how I mentioned that Flash started out as an animation tool? Well, this legacy has been maintained all throughout the life of Flash and still dominates much of the structure of Flash today. For this reason, frame rates (how many frames of animation play per second), animation timelines (like the frames of a film reel), and dimensions are all core information that the Flash player needs to know before running anything.
As a result, SWF files can never be exactly 0 bytes. The smallest SWF file you can generate (one with absolutely nothing in it) will be 36 bytes. Small, but not completely empty. The frame rate, dimensions, and other information must be included even when there is nothing to show or do.
Beyond this, however, a Flash file cannot be assumed to have anything present (though most usually have more than just a blank screen).
Keep in mind that in the SWF file, the following items will not be present in the order in which they're shown, so the order in which they're listed here is not representative of any SWF standard. Rather, a SWF file may incorporate any of these elements in various numbers and assorted orders.
SWF Contents: Graphics
In the world of computers, there are only two types of graphics: vectors and bitmaps (sometimes called rasters).
Bitmap images are stored by the computer pixel by pixel, left to right, up to down. This is exactly the same as a television set where the image you see is actually composed of millions of tiny phosphorescent dots. If you look up close, you can see these dots clearly, but from afar they blend together to form a single image. In the TV, the electron gun that creates the image shoots at the dot in the upper left-hand corner of the screen to illuminate it. It then zips across from left to right (from the viewer's perspective), illuminating all the other dots along the way. At the end of the line, the electron gun zips back to the left side and moves one row down. It continues this process until all of the dots are illuminated.
This is a fairly amazing process when you stop to consider that the whole screen of dots is refreshed like this 30 times every second. Bitmap images are assembled in much the same way; the information for them is stored in lines and re-assembled in the same way that a TV paints its picture. Each dot on a computer monitor is called a pixel (a slightly strange abbreviation for "picture element"), and is comprised of three values: Red, Green, and Blue (or RGB). Each value tells the computer's monitor how much intensity to light up that pixel's colour at so that when Red is at a maximum and Blue/Green are minimum, the pixel is pure red. Combining these colour values, any colour can be produced. For example, pure Red and pure Blue create pure purple. Pure Red, Green, and Blue produce pure white.
An extra value is also often added in computer graphics called the "alpha blending" value which specifies how opaque the pixel is. Full alpha means the pixel is fully opaque. A 50% alpha means that the pixel is blended, 50/50, with any image that appears "beneath" it in the computer's memory. This is a bit of a trick since a monitor doesn't have layers to store images; rather, the graphics hardware combines what are called "logical layers" which essentially means "data blended together as though there are layers". So a bitmap image is made up of RGBa values, stored in sequential rows to produce an entire image.
This is a pretty simple format for the computer to handle because there are no heavy computations. In most cases, the computer will simply dump the entire image into a special section of memory called "video memory" where the graphics card will simply pick it up an display it on the monitor. It's fast, efficient, and simple.
Unfortunately, bitmaps are also quite memory hungry. Each colour element in a pixel consumes one byte of memory so that a single pixel, or RGBa element, consumes 4 bytes in the computer's memory. For an image that's 800 pixels wide by 600 pixels tall, this requires 1,920,000 bytes, or almost 2 Megabytes of memory. If we create an animation that's 800x600, 30 frames of animation (or one second at 30 frames per second) would result in close to 60 Megabytes of data! Even on a DSL connection, this amount of data for a single second of animation is absurd, so a different approach must be considered. Enter vector graphics.
Vector graphics have been around since the early days of digital computing so they're nothing new. However, they are generally calculation-heavy so they require faster computers that can compute and draw quickly enough to be able to produce 30 frame per second animations.
Vectors are different from bitmaps in that, rather than storing an image bit by bit sequentially, an image is "described" using points, lines, fills, and shapes. For example, a line drawn in a bitmap image still requires all the pixels in the rectangular image to be stored in memory, even if the pixels are blank or just white. In a vector, however, the line is described using a start point, end point, line thickness, line colour, and style (dashed, for example), and the computer must then generate that line as a bitmap in the computer's memory.
Consider that the image is, once again, 800 by 600 pixels. In vector images, this is mostly irrelevant because the line is not stored pixel by pixel. Instead, we use 2 bytes to describe the X position of the start point and end point (total of 4 bytes), and 2 more bytes to describe the Y position of both points (up to 8 bytes). Now we use an RGBa value to describe the colour (12 bytes), and maybe 4 more bytes to describe thickness and style. Grand total: 16 bytes. Compared to 1,920,000 bytes for the same line as a bitmap, that's quite a savings.
Unfortunately, there is a trade-off in processing speed. Whereas the bitmap can simply be "dumped" into video memory, here the computer must build the line, pixel by pixel, based on the information provided. This includes computing angles between the start and end point, calculating where the coloured pixels should appear and where they shouldn't appear, and other information. For a single line, the computing power may be negligible, but when the vector image becomes very complex, the computer can really start to struggle.
Luckily, the creators of Flash wrote some very fast routines for drawing vector shapes so that for most applications, performance usually isn't a factor. Besides this, new optimizations have been added to Flash 8 and 9 to keep a bitmap version of a vector graphic in memory and use that for animation instead of re-drawing the vector on each frame. As long as the vector is static (doesn't change between frames), the bitmap version can be used instead of the vector version, and Flash can run quickly.
SWF Contents: Audio
The SWF file can also contain audio information. This information can be stored nestled in the SWF (in correct streaming position, of course) as either MP3-formatted audio, Adaptive Pulse Code Modulation (ADPCM), raw (not compressed), or speech (compressed and filtered). Sounds in a SWF file may be stored on the timeline so that they synchronize with the playback of the "movie", or they may be bound to events (such as when you click on a button). Regardless of where they're used, the SWF file format ensures that the audio data is ready before any playback is attempted.
Most people are at least partially familiar with the MP3 format. This audio compression format is the jack of all trades that can produce good quality sound with good compression. Many tricks are used to create MP3 compression, much of them having to do with the way we hear. MP3 is, ultimately, a lossy format, meaning the sound that you create will sound a little less crispy once you compress it. With MP3s, however, you can control how much compression to apply and therefore how much of the original sound information remains intact.
ADPCM is a non-lossy form of audio compression that compresses data based on differences between subsequent sections of the sound data, or samples. This format is still compressed, but not nearly to the extent that MP3 can compress data.
The "raw" audio format, as the name suggests, stores the sound data in the SWF file uncompressed and raw. The quality is perfect but the size is bulky.
Finally, the "speech" format depends on the qualities of the human voice for its compression. Unlike the rich tapestry of sounds frequencies that can be found in a full classical orchestra, for example, the human voice has a fairly narrow range. If the audio is indeed speech, many of the extraneous frequencies can be eliminated by a process called "band filtering". This process, which is incidentally used in standard phone systems, can eliminate audio data by as much as half simply because it's assumed not to be needed.
SWF Contents: Video
Video can be embedded in SWF files, although this practice is usually avoided since this can bulk up the file size significantly. Because SWF files can load other other SWF files, they are occasionally used as content "wrappers". A video file, along with video controls and the ActionScript instructions to control it all can be packaged into a SWF. This SWF can then be loaded as part of a bigger project such as a video player with multiple pieces of content.
Video in SWFs is stored in one of only two formats.
The first format is simply embedded bitmap images, placed on a timeline along with its audio track. The bitmaps are compressed using JPEG compression, but the format is still quite bulky and so usually reserved for shorter clips.
The second video format that may be embedded in SWFs is the FLV (FLash Video) format initially developed by Sorenson Media, and later by ON2 Technologies. One of the newest additions to Flash is the H.264/MP4 video format which is a more open format capable of full screen, great quality video. This last format was added in the latest update to Flash CS3 and Flash Player 9.0.115 so it's not officially part of the standard Flash distribution.
Regardless of this, data compression for video is by far the most advanced data compression available today. Many tricks such as delta frames and area sampling (discussed in a future article) are used to shrink video data. Despite this, video tends to require the most storage space and so it's often kept in its own file and loaded into the SWF programmatically.
SWF Contents: Data
Data stored in a SWF can take many forms. We'll be discussing these in greater detail in sections like 4.x, but for now it suffices to say that data of almost any kind can be stored in a SWF. Technically speaking, graphics, audio, and video are types of data, but they have a very specific purpose. Other types of data like XML are generic and may be used in any number of ways. This is the data being described here.
A SWF file can contain data such as the on-screen locations of buttons, scroll bars, and graphics, and also more specific information like the name of the application's author and its version number.
Just like other content, data is compressed and arranged so that it is available when needed.
SWF Contents: ActionScript
This entire series is about learning ActionScript, so why is it left to the bottom of the list? Simply, without content like graphics, audio, and video, programming would have nothing to control. Ultimately, ActionScript is the glue that holds it all together and makes it dance (if you'll pardon a bad analogy).
ActionScript has a history as long as Flash and was present in the very first version. It started, as the name suggests, as a way to script actions of the Flash "movie". This included controlling graphics on the screen and playback in the timeline through commands like "stop", "play", and "gotoAndPlay" (which is usually coupled with a frame number).
ActionScript is currently in version 3.0 and this is the version we will be focusing on. ActionScript 2.0 can be found in Flash 8, 7, and 6. Previous versions used ActionScript 1.0.
These previous versions are still broadly used, but they have a limited shelf life. ActionScript 3.0 is the window to the future, and its capabilities are *much* broader than anything that Flash could previously do. Besides simply having more functionality available, ActionScript 3.0 and Flash Player 9 mark the first major departure from the core Flash technology.
Up until Flash 9/ActionScript 3.0, the Flash player was updated by simply lumping new features on top of old functionality. This lumpy construct is currently called AVM1, or the "Adobe Virtual Machine 1" (though it was really developed by Macromedia before Adobe, and by a company named Future Splash before that).
Flash 9 and ActionScript 3.0, in comparison, are a complete re-write of the technology from the ground up. The tools used to construct SWF files are written in the Java language, and the Flash 9 player is also closer to Java in the way it executes instructions (usually called "code"). This brand new incarnation of Flash is known internally as "AVM2" or "Adobe Virtual Machine 2". We'll discuss the "virtual machine" concept in section 1.1 when we talk about the Flash player and the AIR runtime.
ActionScript 2.0 is useful to know, but increasingly less so, and once you've gotten a grasp of ActionScript 3.0, stepping backwards is easier if need be.
ActionScript in a SWF file isn't directly recognizable. The reason is because it's converted to a format called "bytecode" by the Flash editor as part of the SWF creation process.
We humans have a tendency to need multiple letters and words to describe what we want to do. For example, to draw a line in ActionScript "source code" (the instructions we can read) we would write "lineTo(100,200)".
The Flash player, however, would have to process all these letters, numbers, and punctuation, ensure extra spaces and line feeds are accounted for, and this ultimately slows down the process of actually displaying the line.
Instead, a byte representation of the "lineTo" command is used (hence "bytecode") so that processing time can be used to perform commands and not try to understand quirky English text. Bytecode, like all other content, must be prepared for streaming (if certain ActionScript commands must run on frame 1, it must already be in memory before frame 1 is displayed). Furthermore, it's compressed to make the entire SWF file smaller.
A note about the word "script"; it comes from an older style of programming where source code would directly be translated to machine code, or instructions that would be read and understood by the computer hardware directly. Older languages like BASIC and Turing, and even newer languages like PHP and a flavour of Java work this way.
This type of programming differs from "compiled" languages where the source code is converted to machine code only once, and then that machine code is executed directly every time a program runs. Scripts run slower than compiled programs because of all of the extra work required to understand the source code, but it does make them more flexible because they can be changed on the fly.
So why is ActionScript a "script" language? Isn't it really compiled? The answer to the second question is, "sort of". It's true that ActionScript doesn't stay as source code when it's put into the SWF. However, the bytecode instructions aren't understood by the computer either. If you tried to execute them like an "EXE" file, your computer would crash. This is because the bytecode instructions are "virtual" instructions. They describe the type of action to take, but the way that this action is accomplished on various computer system can vary widely.
On a Windows PC, for example, drawing a line can be quite different from a Mac PC. The same bytecode instruction is interpreted into machine code by the Flash player for each individual machine (which we will discuss in greater detail in section 1.1), so technically it's still a "script" language. The only difference is that the instruction isn't stored as human-readable source code but in more compact, portable format.
Putting it All Together
Now we have a good overview of the type of content that can be embedded, or included with a SWF file. It is structured and compressed in a way that makes it ready for streaming and this makes it ideal for delivery over networks like the Internet. That doesn't necessarily mean that all this type of content is always embedded in every SWF file, but it is certainly capable of containing it.
That being said, the type of ActionScript development we'll be focusing on will try to avoid cramming everything together into one file. Why? Because Flash has for quite some time been able to load many types of content like graphics, audio, video, data, and other SWF files from external locations that are outside the SWF (locations like web servers, databases, and the file system).
This is advantageous in that external content can be updated without ever needing to re-create the SWF file. It also allows a great deal of separation between "design", the visual/audio aspect of the application, and code...your programming. In other words, designers and developers don't need to be joined at the hip. In fact, modern Flash development techniques can allow you to create a SWF file that has only ActionScript and has *all* content stored outside and loaded in at "runtime", or when the Flash player is playing the SWF.
Flash 9 and ActionScript offer unparalleled options for creating "modular" applications; applications that are loaded and assembled in pieces. For example, a Flash application can be comprised of a number of scroll bars, buttons, and text input fields. All of these can be generated using ActionScript, included within a single SWF, or loaded into a "container" SWF as external content and ultimately controlled by ActionScript. This type of loosely coupled programming is called "event driven" programming, and it's what we will look at in advanced sections.
With the powerful yet tiny package of the SWF file, the remarkable power of ActionScript 3.0, running in the new AVM2 available in Flash 9, the sky's the limit.
Where the SWF Lives
To wrap up section 1.0, I should offer a few tips and warnings about the SWF file.
First of all, SWFs don't inherently have any version information that can be seen by the user. Only the Flash player (and software that can read the SWF format file) can determine the Flash version. As a general rule SWFs created for, say, Flash 8, won't run in Flash 7. This is simply because some of the bytecode instructions (and perhaps other content) may not be understood by Flash 7. This is true for all older versions as well. This is called "no downward compatibility", and it's common among most software.
SWFs are also not inherently secure. Although the Flash editor has a password option for SWF file creation, this really only applies when you try to open the SWF in the Flash editor. There are decompilers like SoThink's that can, quite literally, re-construct your source code and extract any other content found in the SWF.
There are some products called Flash "obfuscators" which attempt to scramble the bytecode into forms that are readable by the Flash player only, but these have very limited effect. You must assume that content is not secure and move forward by finding other solutions, some of which will be discussed in later sections.
And if you thought that grabbing SWF files was difficult or required fancy web browser plugins, you may be shocked to find out that you can grab them right from your browser cache.
In Internet Explorer 7, for example, you can use the menu options "Tools"->"Internet Options" and under the "General" tab, click the Browsing History "Settings" button, then "View Files" in the popup dialog. In the file list that appears, simply look for files with the extension ".swf" (these will also have a round gray icon with a big "F" through it if you have the standalone Flash player installed).
These are the SWF files that you saw displayed on any website you may have visited. Pop these into a Flash decompiler and everything is there for you to see. The procedure isn't glaringly obvious, but once you know how to do it, it's easy.
Fancy programming techniques can, to a certain extent, overcome some of these limitations, but nothing is ever 100% secure. Java applications, and even EXE files can be decompiled by specialized software so that other techniques must be found to secure important information.
We'll leave those details to a future article.
In the next part of this section we'll be looking at how the SWF file is loaded and used by the Flash player and AIR runtime.