Command line application for converting SWF files to PDF or SVG. This program differs from existing alternatives by the fact that it's explicitly meant to convert back files that were originally in PDF (or other vector formats) and have been converted to SWF using programs such as swf-tools' pdf2swf or Adobe InDesign.
As such, only a subset of the SWF specification is supported, with no support for animations. See limitations for more details. Only static files can be converted. For example, this program could be be used to convert a book composed of one SWF file per page.
To reduce output file size, several features are available:
The latest release can be found under the Releases section. Java 8 or later is required to run this program. The same build should be able to run on all desktop platforms.
The JAR file can be run using the following command:
java -jar swf-convert.jar [main options] <output format> <input files> [output options]
It can also take a configuration file:
java -jar swf-convert.jar @config.txt
Multiple input files or folders can be specified. A file collection is created for each file or folder specified. Some arguments will require to have the same number of arguments as there are input collections.
It is recommended to use -Xmx
to increase heap size when converting large input collections (>1000 files) since
the program uses a lot of memory, particularly for PDF frame rasterization. As much as 10 GB has been required in my
case...
For use in place of [main options]
in the above command.
-h
, --help
: Show help message for the program.-v
, --version
: Show version name.
--log <level>
: Set minimum log level to show in stdout (off: 0, fatal: 1, error: 2, warn: 3, info: 4, debug: 5,
all: 6). Logs of all levels are also written to ~/swfconvert/logs
.-s
, --silent
: Don't display progress during conversion.For use in place of [output options]
in the above command. Shared by all output formats.
-h
, --help
: Show help message for the output format.
-o
, --output <path> [paths]
: Output files or directories. There must be as many as input file collections. By
default, output is written to the same path as input. If specifying files, they must have the same extension as the
desired output format.-t
, --tempdir <path>
: Temp directory used for intermediate files. Default temp directory is the same as
input directory. Temp files are automatically removed after conversion, unless specified otherwise.
-e
, --ignore-empty
: Ignore empty frames, not generating output for them.-g
, --dont-group-fonts
: Used to disable font grouping (merging compatible fonts in a single font).--keep-font-names
: Used to keep original font names instead of using generic names.--keep-duplicate-images
: Used to keep duplicate images with same binary data.--image-format <format>
: Format to use for images, can be one of default
, jpg
or png
. Default is default
,
in which case PNG format will be used for DefineBitsLossless tags and JPEG format will be used for DefineBitsJPEG tags.
tags.--jpeg-quality <quality>
: JPEG image quality between 0 and 100. Default is 75.--downsample-images
: Used to downsample images to limit output density.--downsample-filter <name>
: Filter used to downsample images, can be one of fast
, bell
, bicubic
, bicubichf
,
box
, bspline
, hermite
, lanczos3
, mitchell
or triangle
. Default is lanczos3
.--downsample-min-size <size>
: Minimum size in pixels that images can be downsampled to or from. Must be at least 3
px, default is 10 px.--max-dpi <dpi>
: If downsampling images, the maximum allowed image density. Default is 200 DPI.For use in place of [output options]
in the above command, with the pdf
output format.
PDF output will produce one page per frame. The frames of all files in a collection are written to the same output file.
--no-compress
: Used to disable output PDF compression.
--metadata <file> [files]
: Metadata JSON files used for each input file collection. Use underscore _
to apply no metadata
for a particular collection. There must be as many values as there are input collections. See
this section for more information on JSON schema.--dont-optimize-page-labels
: Used to disable page labels optimization (if set in metadata).--rasterization-enabled
: Used to enable rasterization of complex frames.--rasterization-threshold <threshold>
: Minimum input file complexity required to perform rasterization, in
(somewhat) arbitrary units. Default is 100,000. Should be tuned manually to see which at which point rasterization
produces smaller files.--rasterization-dpi <dpi>
: Density in DPI to use to rasterize frames if rasterization is enabled. Default is 200
DPI.--rasterization-format
: Image format to use for rasterized frames, either jpg
or png
. Default is jpg
.--rasterization-jpeg-quality
: JPEG image quality for rasterization, between 0 and 100. Default is 75.For use in place of [output options]
in the above command, with the svg
output format.
SVG will produce one file per input frame.
-p
, --pretty
: Used to pretty print output SVG. This also disables a number of optimizations to increase
readability.--svgz
: Used to output in SVGZ format (gzip compression).--no-prolog
: Used to omit the XML prolog.
--precision
: Precision of SVG path, position, and dimension values. Default is 1.--transform-precision
: Precision of SVG transform values. Default is 2.--percent-precision
: Precision of SVG percentage values. Default is 2.
--images-mode <mode>
: Controls how images are included in SVG, can one of external
(as files) or base64
(embedded as base64 encoded URLs). Default is external
.--fonts-mode <mode>
: Controls how fonts are included in SVG, can be one of external
(as TTF files), base64
(embedded as base64 encoded URLs) or none
(no fonts, use paths).When images and fonts are not embedded, the files are placed in the same directory as the output.
For use in place of [output options]
in the above command, with the ir
output format.
IR will produce one JSON file per input frame.
When converting SWF to the chosen output format, the program first converts the SWF toa SVG-like intermediate representation in order to abstract the difficulties presented by the SWF format. For debugging purposes, it's possible to output this IR as JSON structures. Images and fonts are written as files.
-p
, --pretty
: Used to pretty print output JSON.--indent-size <size>
: Indent size used if pretty printing.
--y-direction
: Y axis direction, either up
or down
. Default is up.For use in place of [output options]
in the above command.
-DkeepFonts
, -DkeepImages
: used to keep temp image and font files.-DparallelSwfDecoding
: SWF file decoding.-DparallelSwfConversion
: conversion to intermediate representation.-DparallelImageCreation
: creation of image files.-DparallelFrameRendering
: rendering from IR to output format.-DdrawShapeBounds
: for DefineShape tags.-DdrawTextBounds
: for DefineText tags.-DdrawClipBounds
: for PlaceObject tags with clipping depth.-DdebugLineWidth=<width>
: bounds line width in twips, default is 20 twips.-DdebugLineColor=<color>
: bounds line color, default is green. (color is a #rrggbb
or #aarrggbb
hex color)-DdisableClipping
: disable clipping.-DdisableBlending
: disable blending except alpha blend mode.-DdisableMasking
: disable alpha blend mode.-DframePadding
: padding to add around frames in inches.-DfontScale2=[<sx>,<sy>,<usx>,<usy>]
: for DefineFont2 tags.-DfontScale3=[<sx>,<sy>,<usx>,<usy>]
: for DefineFont3 tags.-DframeSize=[<width>,<height>]
: if set, overrides frame size defined in SWF, for all frames. Dimensions are in inches.-DbitmapMatrixOffset
: additional offset to use for bitmap fill matrix on shape tags. Default is [0, 0].-DignoreGlyphOffsetsThreshold=<threshold>
: threshold under which custom glyph advances are ignore for DefineText
tags, in glyph space units (1 em = 1024 glyph space units). Used to reduce output file size. Default is 32.-DrecursiveFrames
: if set, frames contained in sprites become top-level frames, recursively.
Otherwise, only top-level frames are used (default).Keep in mind that these options are meant for advanced use or for debugging purposes. Otherwise common uses include:
-DignoreGlyphOffsetsThreshold=0
: keep all original glyph advances.-DfontScale2=[0.05, 0.05, 20, -20]
: font scale used for converting files made with swf-tools.-DkeepFonts
and -DkeepImages
: extracting fonts or images.1. PDF to SWF and back.
Here an arbitrary PDF with 92 pages is converted to SWF files with swf-tools' pdf2swf:
pdf2swf -o pages/%.swf -z input.pdf
The result is 92 SWF files named 1.swf to 92.swf in the pages
directory.
Now let's convert them back to a single PDF file using swf-convert:
java -jar swfconvert.jar pdf pages/ -o report.pdf
--image-format jpg --ignore-empty
-DfontScale2=[0.05,0.05,20,-20]
Additionally we'll ignore empty frames, use only JPG images, and we'll use the special font scale option needed
for swf-tools. In a few seconds, the report.pdf
file is created. 40 fonts were created out of the 719 contained in all
input files, and 333 duplicate images were removed out of 344 images!
2. Self-contained SVG
A SWF file with a single frame is converted to a SVG:
java -jar swfconvert.jar --log 4
svg input.swf -o output.svg
--downsample-images --max-dpi 30 --image-format jpg
--images-mode base64 --fonts-mode none
--transform-precision 2 --no-prolog
Images are embedded and paths are used instead of fonts. Precision for the transform
attribute is also increased to
avoid rounding issues with fonts-mode none
. To avoid making the SVG too big, images are also downsampled.
swf-convert can only convert static files, with no support for animations or actions. Most other limitations arise from the fact that I had no test data to test some features with, so I opted for a lazy implementation. Here's a detailed list of current limitations.
Nearly all of these limitations will result in an exception being thrown, and the conversion will fail. If you ever have an use case needing support for one of the above, please open an issue and provide the required test data, I'll do my best to implement it. Again, this tool was implemented lazily as to cover my own use case and nothing more. More test data will surely allow to fill the holes.
When I say test data, I mean SWF files that can be converted and the result is visually compared with the original. I unfortunately didn't spend the time implementing automated testing that would do that.
The project is built with Gradle, which can be run with:
./gradlew <tasks> [options]
Useful tasks are:
clean
: clean build resultsbuild
: build projectdetekt
: run detekt analysis on projectapp:dist
: output fat jar to app/build/libs
app:run
: run program, using properties from dev.properties
file:
app-test-working-dir
: working dir to useapp-test-args
: options to useAll contributions are welcome. Please read contribution guidelines.
View the CHANGELOG.md
file for detailed release notes.
This program is licensed under LGPL v3, see the license file for more details. It uses modified code
for the following libraries, which can be found in the libsrc
directory:
Other libraries are also used: