Goal of this article
This article's main goal is to show how to transform a JPEG file into a SWF animation on the fly, with a few code lines.
Using the SwfDotNet library
SwfDotNet library is a C# open source framework available at:
This library offers some good stuff to read about, and allows to write SWF format files in any version from 1 to 7. SwfDotNet.IO.dll is compatible with .NET framework 1.1, 2.0 or +, and Mono. This library respects the MacromediaTM SWF format specifications. You can read and download the Macromedia official specifications here.
Theory
First of all, I recommend you read my other article about SwfDotNet on CodeProject, "How to create a simple SWF decompiler with the SwfDotNet library". In this article, you can find generic information about how to use this library, and it's a good introduction to understand this article.
The SWF tags sequence
An SWF file is a sequence of specific tags which are used, for example, to embed data, to describe how to display library elements, add a frame, place an object, remove an object, etc.
Every tag describes a character on the screen, and has a character ID, which is composed of a unique number.
Tags used in this sample
Here is the list of tags which are necessary for this example:
SetBackgroundColorTag
: to define the background color.
DefineBitsJpeg2Tag
: to embed JPEG data in the SWF.
DefineShapeTag
: to create a shape on the screen that will describe the way to display the DefineBitsJpeg2Tag
data. Thanks to it, we can, for example, apply a transformation, etc.
PlaceObject2Tag
: to place the DefineShapeTag
object on the screen, with a location, a size, etc.
ShowFrameTag
: to finally add a frame.
Creating the sample application
First, include the SwfDotNet library in your class:
using SwfDotNet.IO;
using SwfDotNet.IO.Tags;
using SwfDotNet.IO.Tags.Types;
We will use the System.Drawing.Image
class to load the JPEG file, and then we can transform BMP, GIF, PNG with the same code too:
Image img = Image.FromFile(jpegFileName);
int posX = 0;
int posY = 0;
int imgWidth = img.Width;
int imgHeight = img.Height;
Now, we create a Swf
object and fill the header information. Don't forget that the SWF format uses inches as unit, not pixels! (1 pixel = 20 inches.) To decrease the bandwidth, we choose to compress our final animation. To do so, add the following specific "CWS" signature:
Swf swf = new Swf();
swf.Size = new Rect(0, 0, (posX + imgWidth) * 20, (posY + imgHeight) * 20);
swf.Version = 7;
swf.Header.Signature = "CWS";
swf.Tags.Add(new SetBackgroundColorTag(255, 255, 255));
We can now import the JPEG data in our animation. It's really simple to do this with the SwfDotNet library, thanks to the FromImage
static method on the DefineBitsJpeg2Tag
object.
You can notice that a DefineBitsJpeg2
tag is a "character tag". Then, we must set a unique ID to this object. To do so, you can use the method GetNewDefineId
on the swf
object.
ushort jpegId = swf.GetNewDefineId();
swf.Tags.Add(DefineBitsJpeg2Tag.FromImage(jpegId, img));
Now comes the most difficult part of this sample: we're going to create the defineShape
that will describe the way to display JPEG data.
First, we must create a new unique ID for this tag. Then, we specify the fill style of our shape, and use the FillStyleType.ClippedBitmapFill
to fill the shape with the JPEG data. We must now define the drawing process in the ShapeRecordCollection
object. The StyleChangeRecord
class specifies that we will set the pen position at the upper left point of the bitmap. StraightEdgeRecord
objects specify the bitmap rect co-ords, and finally, the EndShapeRecord
closes the drawing process.
To conclude, we add a PlaceObject2Tag
object to place the shape on the screen.
DefineShapeTag shapeTag = new DefineShapeTag();
shapeTag.CharacterId = swf.GetNewDefineId();
shapeTag.Rect = new Rect(posX * 20 - 1, posY * 20 - 1,
(posX + imgWidth) * 20 - 1, (posY + imgHeight) * 20 - 1);
FillStyleCollection fillStyles = new FillStyleCollection();
fillStyles.Add(new BitmapFill(FillStyleType.ClippedBitmapFill,
ushort.MaxValue, new Matrix(0, 0, 20, 20)));
fillStyles.Add(new BitmapFill(FillStyleType.ClippedBitmapFill,
jpegId, new Matrix(posX * 20 - 1, posY * 20 - 1,
(20.0 * imgWidth) / img.Width,
(20.0 * imgHeight) / img.Height)));
LineStyleCollection lineStyles = new LineStyleCollection();
ShapeRecordCollection shapes = new ShapeRecordCollection();
shapes.Add(new StyleChangeRecord(posX * 20 - 1, posY * 20 - 1, 2));
shapes.Add(new StraightEdgeRecord(imgWidth * 20, 0));
shapes.Add(new StraightEdgeRecord(0, imgHeight * 20));
shapes.Add(new StraightEdgeRecord(-imgWidth * 20, 0));
shapes.Add(new StraightEdgeRecord(0, -imgHeight * 20));
shapes.Add(new EndShapeRecord());
shapeTag.ShapeWithStyle =
new ShapeWithStyle(fillStyles, lineStyles, shapes);
swf.Tags.Add(shapeTag);
swf.Tags.Add(new PlaceObject2Tag(shapeTag.CharacterId, 1, 0, 0));
At last, we will add a frame to display, and save our Swf
object to a file, thanks to the SwfWriter
class. You wan notice that the SwfWriter
can write in a file or in a stream (for web applications, for example).
swf.Tags.Add(new ShowFrameTag());
swf.Tags.Add(new EndTag());
SwfWriter writer = new SwfWriter(outputSwfFileName);
writer.Write(swf);
writer.Close();
img.Dispose();
Conclusion
As you can see, thanks to the SwfDotNet library, you can easily create a JPEG to SWF program. Thanks to this code, it's easy to create a WebForm component, which creates a Flash slideshow from JPEG files and always on the fly.
We have seen how to draw a simple shape in an SWF file, but it's really only an introduction. We will further develop this topic in a future article.
History
- 19/12/2006: First article version. Special thanks to Nicolas Guary and Pierre Cleaud for helping me with the translation.