Home / Articles / Adobe Creative Suite / Tools of the Trade: Flash meets Java with Transform SWF and JFlashPlayer

Tools of the Trade: Flash meets Java with Transform SWF and JFlashPlayer

Contents

  1. Create and update Flash movies with Transform SWF
  2. Play and Control Flash Movies with JFlashPlayer
  3. Conclusion

Article Description

Perhaps some of your Java applications can benefit from supporting Flash. Jeff Friesen introduces two tools that support Flash in a Java context: Transform SWF and JFlashPlayer. Transform SWF is useful for creating new Flash movies and updating existing Flash movies. JFlashPlayer gives you the ability to integrate a Flash movie player into your software. In this article, you're introduced to three Java applications that show you how to use these nifty tools.

Many people believe that Macromedia’s Shockwave Flash (SWF) file format is the best way to present feature-rich and low-bandwidth animated content—Flash movies—over the Web. In light of this belief, it’s not surprising that Macromedia’s Flash movie players have been installed (mainly in Web browser contexts) on millions of computers around the world. This huge potential audience is a great incentive for you to distribute your electronic books, video-based tutorials, and other kinds of multimedia documents as Flash movies.

Java’s combination of power and simplicity has made it a very popular programming language and environment; the amount of Java-based software for the server and desktop continues to grow. Perhaps some of your Java software can benefit from supporting Flash. For example, a Web application creates a user-specific Flash movie and sends that movie to the user’s Web browser when the user contacts the application. Another example: a complex desktop application contains a Flash movie player that plays a tutorial movie when a user requests help.

I have discovered many tools that support Flash in a Java context. This article introduces two of those tools to you: Transform SWF and JFlashPlayer. Transform SWF is useful for creating new Flash movies and updating existing Flash movies. In contrast, JFlashPlayer gives you the ability to integrate a Flash movie player into your software. As you read this article, you’re introduced to three Java applications that show you how to use these tools.

Create and update Flash movies with Transform SWF

Flagstone Software makes available three open-source tools for creating and updating Flash movies. Transform SWF is the foundation tool in this tools suite. Each of the other higher-level tools depends on Transform SWF. Although you can use Transform SWF (and the other tools) without paying a fee, this software is licensed under the BSD license. Make sure you fully understand your responsibilities, as stipulated by this license, before integrating Transform SWF (and the other tools) with your own software.

Before we can explore Transform SWF, we need to download and install that tool. Accomplish the download task by pointing your Web browser to Flagstone Software’s Downloads for Java Web page and clicking the link to the appropriate Transform SWF distribution file. For example, I downloaded transform-java-2.0.4.zip. After downloading the distribution file, you should verify the integrity of that file by also downloading the corresponding PGP or MD5 signature and using the appropriate PGP, GPG, or MD5 tool to perform the verification task. The Downloads for Java Web page provides instructions on how to accomplish this task with PGP.

After downloading and unzipping the Transform SWF distribution file, you need to install that tool. Begin by creating an appropriate directory structure to facilitate project development. For example, I created an fss umbrella directory in the root directory on my C: drive (so that I could accommodate Flagstone’s other open-source tools in the future) and moved Transform SWF’s home directory to fss. I also placed a projects directory in fss to conveniently organize my Transform SWF projects. The following directory structure emerged:

c:\fss\transform-java-2.0.4
c:\fss\projects

Transform SWF’s directory contains a Jar file: transform.jar. To finish installing this tool, add that Jar file to the CLASSPATH environment variable. For Windows 98 SE, the command to set CLASSPATH in the context of the preceding directory structure is set classpath=c:\fss\transform-java-2.0.4\transform.jar;%classpath%;.. If you are using a different version of Windows or a non-Windows operating system, study your OS documentation to find out how to set this environment variable.

Now that Transform SWF has been installed, let’s investigate this tool. For starters, Transform SWF is a collection of Java classes that implement the various tags and other data structures described by Macromedia’s SWF file-format specification. These classes fully support this specification up through Flash MX 2004 (version 7) and are stored in package com.flagstone.transform, which corresponds to the transform.jar Jar file.

Assuming the previously created directory structure, point your Web browser to c:\fss\transform-java-2.0.4\doc\datasheets\index.htm, to explore Javadoc documentation for this package and its classes. Because it is beyond this article’s scope to delve into SWF, I recommend reading the package description, especially if you are new to SWF. That description concisely describes SWF, with emphasis on Flash’s programming model.

The central class in the Transform SWF package is FSMovie. That class describes a Flash movie in terms of header information, such as the size of each movie frame—measured in twips (one twip equals 1/20th of a point or 1/1440th of an inch)—and the number of frames that are shown per second, and a sequence of objects that correspond to the various tags comprising the movie.

The simplest way to create a Flash movie is to first create an FSMovie object (initially empty of tag objects) by invoking the public FSMovie()constructor, then create objects representing various tags and add them to the FSMovie object, and finally invoke FSMovie’s public void encodeToFile(String filename) method to encode the movie to the SWF file identified by filename. (It would be a good idea to ensure that the filename ends with a .swf extension.) Because encodeToFile() is capable of throwing java.io.IOException if it cannot create or write to the file, you’ll need to address this possibility in your code. The following code fragment demonstrates these methods and more as it creates a very simple Flash movie:

FSMovie movie = new FSMovie ();

movie.setFrameSize (new FSBounds (0, 0, 400, 400));
movie.setFrameRate (1.0f);

movie.add (new FSSetBackgroundColor (new FSColor (0, 0, 255)));

try
{
  movie.encodeToFile ("test.swf");
}
catch (Exception e)
{
  System.out.println (e);
}

After creating an FSMovie object devoid of any tag objects, the code fragment invokes FSMovie’s public void setFrameSize(FSBounds bounds) method to set the size (400x400 twips) of all movie frames via an FSBounds object and invokes public void setFrameRate(float fps) to establish the recommended number of frames (1) to play per second. Of course, we would not need to invoke these methods if we created the FSMovie object with the public FSMovie(FSBounds bounds, float fps) constructor.

Moving on, the code fragment introduces a SetBackgroundColor tag into the movie, which identifies the color of each frame’s background (in many movies, the background color might or might not appear, depending on how much of each frame is covered by various shapes). The tag is introduced by first creating an FSColor object representing opaque color blue (there is no transparency information), then passing that object to a newly-created FSSetBackgroundColor tag object, and finally adding that tag object to the FSMovie object by invoking FSMovie’s public void add(FSMovieObject object) method—FSMovieObject is an abstract class that serves as the superclass of tag classes (such as FSSetBackgroundColor).

After adding the FSSetBackgroundColor tag object to the FSMovie object, the code fragment invokes encodeToFile() to create the SWF movie file. That method creates test.swf, encodes FSMovie’s header information and tag objects to the equivalent SWF binary tags, and outputs that binary information to the file. If something goes wrong during file creation or file writing, an IOException throws; the code fragment outputs the exception information to the console.

If you were to view test.swf in a Flash movie player, you would see a very short movie consisting only of a blue background. For a more complex movie, you need to incorporate additional Transform SWF classes into a movie-creation Java application. To that end, I prepared an example that demonstrates a few Transform SWF classes. This example’s CreateSquareCircle.java source code appears in Listing 1.

Listing 1 CreateSquareCircle.java

// CreateSquareCircle.java

import java.util.*;

import com.flagstone.transform.*;

public class CreateSquareCircle
{
  public static void main (String [] args)
  {
   // Create an initially empty movie structure that holds the movie’s
   // header information and tags.

   FSMovie movie = new FSMovie ();

   // Establish the movie’s bounds such that the upper-left corner locates
   // at (0, 0) and the lower-right corner locates at (400, 400).

   movie.setFrameSize (new FSBounds (0, 0, 400, 400));

   // Establish the movie’s frame rate as 24 frames per second.

   movie.setFrameRate (24.0f);

   // Add a SetBackgroundColor tag to the movie. This tag identifies green
   // as the background color.

   movie.add (new FSSetBackgroundColor (new FSColor (0, 255, 0)));

   // Specify the boundaries for a square shape.

   FSBounds bounds = new FSBounds (0, 0, 50, 50);

   // Define the fill- and line-styles for the shape.

   ArrayList<FSFillStyle> fillStyles = new ArrayList<FSFillStyle> ();
   fillStyles.add (new FSSolidFill (new FSColor (255, 0, 0)));

   ArrayList<FSLineStyle> lineStyles = new ArrayList<FSLineStyle> ();
   lineStyles.add (new FSSolidLine (1, new FSColor (0, 0, 0)));

   // Construct the square shape.

   FSShape shape = new FSShape ();

   // FSShapeStyle specifies the 1-based indices into the fill- and line-
   // styles arrays that are passed to FSDefineShape. The final two zeros
   // identify the origin where drawing begins. This origin is the square
   // shape’s upper-left corner.

   shape.add (new FSShapeStyle (1, 1, 0, 0, 0));
   shape.add (new FSLine (50, 0));
   shape.add (new FSLine (0, 50));
   shape.add (new FSLine (-50, 0));
   shape.add (new FSLine (0, -50));

   // Define the square shape in terms of its bounds, fill-style, line-style,
   // and shape.

   FSDefineShape shape2 = new FSDefineShape (movie.newIdentifier (), bounds,
                        fillStyles, lineStyles, shape);

   // Add the DefineShape tag to the movie.

   movie.add (shape2);

   // Animate the square over the background by moving the square in a
   // circle. The animation begins toward the bottom and in the middle of
   // the movie player’s window.

   for (double angle = 0.0; angle <= 3600.0; angle += 1.0)
   {
      double rads = Math.toRadians (angle);

      // Add a PlaceObject tag to the movie. This tag places the square
      // object on layer #1 of the movie player’s display list.

      movie.add (new FSPlaceObject (shape2.getIdentifier (), 1,
                     (int) (175 + Math.sin (rads)*150),
                     (int) (175 + Math.cos (rads)*150)));

      // Add a ShowFrame tag to the movie. This tag causes the entire
      // display list to be viewed in the movie player’s window.

      movie.add (new FSShowFrame ());

      // Add a RemoveObject tag to the movie. This tag removes the square
      // object from layer #1 in the display list. If this tag was not
      // present, the square would not move around the movie player’s
      // window. Once an object has been placed on the display list on a
      // given layer, it must be removed and re-added to place the object
      // in a new position on that layer.

      movie.add (new FSRemoveObject (shape2.getIdentifier (), 1));
   }

   // Attempt to encode, possibly compress (Flash 6+), and output the movie
   // to a SWF file named squarecircle.swf.

   try
   {
     movie.encodeToFile ("squarecircle.swf");
   }
   catch (Exception e)
   {
     System.out.println (e);
   }
  }
}

The most interesting parts of Listing 1 involve the creation and animation of the square shape. That shape is created as an FSShape object, and this object and other relevant objects are stored in an FSDefineShape tag object, which represents a DefineShape tag that is responsible for making the square shape available to the movie.

The FSShape object is a container for FSShapeStyle, FSLine, and FSCurve objects. In Listing 1, only one FSShapeStyle object (which identifies the line-style and fill-style—via one-based indices into arrays passed to FSDefineShape—and initial drawing position of the shape) and four FSLine objects (whose coordinate arguments are relative to the current drawing position) are added to the FSShape object. After the FSShape object has been populated, an FSDefineShape tag object is created with a unique identifier (for later reference by the FSPlaceObject tag object), an FSBounds object that specifies the size of the shape (in twips), previously created java.util.ArrayLists that specify the shape’s line-styles and fill-styles (only one of each style is created), and the FSShape object.

The square is animated by adding a sequence of FSPlaceObject, FSShowFrame, and FSRemoveObject tag objects to the FSMovie object:

  • The FSPlaceObject tag object represents a PlaceObject tag that is responsible for placing the square shape onto the movie player’s display list (a layered data structure that controls the order by which shapes are displayed on the screen). The first argument passed to the constructor identifies the square’s FSDefineShape tag object, the second argument identifies the layer in which the square will be placed (shapes placed at higher-numbered layers are rendered over shapes placed at lower-numbered layers), and the last two arguments identify the location (in twips relative to the upper-left corner of the movie’s frame window) where the shape’s upper-left corner will be placed. Listing 1 calculates this location using sines and cosines, so that the square travels in a circle around the movie player’s window.
  • The FSShowFrame tag object represents a ShowFrame tag that is responsible for rendering the contents of the display list onto the movie player’s window. Lower-numbered layers are rendered first; higher-numbered layers are rendered last.
  • The FSRemoveObject tag object represents a RemoveObject tag that is responsible for removing the square shape from the display list. This shape must be removed before it can be repositioned. The first argument passed to the constructor identifies the square shape; the second argument identifies that shape’s layer.

So what does the movie look like? Figure 1 reveals a single frame in the FireFox Web browser’s integrated movie player’s window that shows the square in transit.

Figure 1

Figure 1 A red square moves in a circle over a green background.

Suppose that you have access only to squarecircle.swf and want to change the square’s fill color to blue. How would you update that movie’s SWF file? Transform SWF provides a solution, which is demonstrated in Listing 2’s UpdateSquareCircle.java source code.

Listing 2 UpdateSquareCircle.java

// UpdateSquareCircle.java

import java.util.*;

import com.flagstone.transform.*;

public class UpdateSquareCircle
{
  public static void main (String [] args)
  {
   // Attempt to load squarecircle.swf into an FSMovie object.

   FSMovie movie = null;

   try
   {
     movie = new FSMovie ("squarecircle.swf");
   }
   catch (Exception e)
   {
     System.out.println (e);
     return;
   }

   // Create a new fill-style based on solid color blue.

   ArrayList<FSFillStyle> fillStyles = new ArrayList<FSFillStyle> ();
   fillStyles.add (new FSSolidFill (new FSColor (0, 0, 255)));

   // Retrieve all movie objects of type DefineShape.

   ArrayList objects = movie.getObjectsOfType (FSMovieObject.DefineShape);

   // There is only one FSDefineShape object in this movie, so we don’t
   // have to worry about iterating over these objects. After retrieving
   // this object, set its fill-styles to the previously-created array.

   FSDefineShape shape = (FSDefineShape) objects.get (0);
   shape.setFillStyles (fillStyles);

   // Attempt to encode, possibly compress (Flash 6+), and output the movie
   // to a SWF file named squarecircle.swf.

   try
   {
     movie.encodeToFile ("squarecircle.swf");
   }
   catch (Exception e)
   {
     System.out.println (e);
   }
  }
}

The FSMovie class provides the public FSMovie(String filename) constructor for reading the contents of the SWF file identified by filename into an FSMovie object. After creating that object, you can call either of FSMovie’s public ArrayList getObjects() or public ArrayList getObjectsOfType(int type) methods to retrieve movie tags as objects—the first method returns an ArrayList of all tag objects, and the latter method returns an ArrayList of only those tag objects that match the specified type, as denoted by the FSMovieObject class (FSMovieObject.DefineShape, for example). After you have the ArrayList, you can iterate through that container object until you find the desired tag object.

Listing 2 invokes getObjectsOfType() to return an ArrayList of all FSDefineShape tag objects. Because there is only one DefineShape tag in squarecircle.swf, Listing 2 doesn’t need to search the array for the appropriate FSDefineShape tag object. Instead, after creating an appropriate ArrayList to store the new solid blue fill-style, the source code invokes FSDefineShape’s public void setFillStyles(ArrayList fillStyles) method to change the fill-styles associated with the ArrayList’s solitary FSDefineShape tag object.

Compile UpdateSquareCircle.java and run the resulting application. Start up a Flash movie player and play squarecircle.swf. You will discover a blue square moving in a circular fashion.

2. Play and Control Flash Movies with JFlashPlayer | Next Section