Initializing... drag & drop files here
Supports: PPM
PPM files usually arrive in numbered batches. Ray tracers, plotting libraries, simulation codes, scanner drivers and PostScript rasterisers all write Portable Pixmap because it takes about ten lines of code to emit — a two-line ASCII header followed by red, green and blue bytes — and they write one per frame. SWF is what you need when the destination is a Flash-era system: legacy courseware and LMS packages, kiosk and signage players, an Adobe Animate project, or a Flash archive kept playable through the Ruffle emulator.
This page takes the batch and produces the movie. The mechanics are simple but a few of them are not obvious, so this walkthrough covers what happens to each frame on the way in.
P6, ASCII P3 and 16-bit files with a Maxval above 255 are all read. Upload order is playback order, so make sure the filenames sort the way the frames should run — zero-padded numbering (frame0001.ppm) is what you want, not frame1.ppm through frame10.ppm..swf for each file instead. Image Duration opens at 5 seconds per frame, which is a slideshow pace; a rendered animation wants 1/24, 1/30 or 1/60 second.| Stage | What is done | Why it matters to you |
|---|---|---|
| Decode | The PPM header is parsed and the raster read; 16-bit samples are reduced to 8 bits | Video is 8-bit throughout, so extra precision in the source cannot survive |
| Normalise | Each image is rewritten as a clean PNG before it reaches the encoder | Removes odd pixel formats and colour profiles that otherwise trip the encoder up |
| Clamp | The long edge is capped at 4,096 pixels | A render larger than that is reduced before anything else happens |
| Frame the shot | On "Keep original" the movie frame is taken from the first image's dimensions, rounded down to an even number; every later frame is scaled to fit inside it and padded with the Background Color | A batch of identically-sized renders is unaffected. A batch of mixed sizes is letterboxed to match the first one |
| Encode | One frame per second, each image repeated for its Image Duration | A held still costs almost nothing after its first frame on the FLV codec |
The output is silent. On an image source the audio controls are not rendered at all, because there is no audio stream to configure — add a soundtrack in Animate or an editor afterwards.
Image Duration is the only timing control and it applies to every frame equally. Work backwards from the playback rate you want:
If your renderer produced frames at a fixed rate and you want them played back at that rate, the arithmetic is simply one divided by the frame rate. Nothing here resamples or interpolates: every uploaded PPM becomes exactly one frame, and no frames are invented or dropped.
| Symptom | Cause | Fix |
|---|---|---|
| Frames play in the wrong order | Filenames sort as text, so frame10 comes before frame2 |
Re-upload with zero-padded numbering |
| The whole movie is one frame long | Merge strategy was set to "Video per image", producing one file per PPM | Set it back to "Merge images" |
| The animation is far too slow | Image Duration is on the default 5 seconds per frame | Set 1/24, 1/30 or 1/60 second |
| The picture is soft or blocky | Quality Preset was used, which has no effect on a still-image source | Switch File Compression to Constant Quality and set 2 to 4 |
| White bars around the picture | The frame aspect does not match the output frame | Choose a Fixed Resolution matching your render's shape, or change Background Color |
| Later frames are letterboxed but the first is not | The batch has mixed dimensions and the movie frame came from the first image | Render or resize the whole sequence to one size first |
| Colours look washed out and pale | The PPM was written with linear samples rather than gamma-encoded ones | Apply the gamma correction in whatever produced the files |
| The file is enormous | MJPEG was chosen, which stores every frame as a full JPEG | Switch back to FLV unless something specifically needs JPEG frames |
Because it works by scaling the source's own bitrate, and a still image does not have one. On video sources the preset multiplies the input rate to get a target; on an image source that figure is zero, so on the quantiser-based codecs this page offers there is nothing to scale and the setting does not reach the encoder in a meaningful way. Use Constant Quality instead, where the 1-to-31 slider maps straight onto the encoder's quantiser — 1 is nearly lossless, 31 is heavily compressed, and 2 to 4 is the useful range.
FLV in almost every case. It codes each frame as a difference from the previous one, which is a very large saving on any sequence where the picture is similar from frame to frame — and an enormous one on held stills, where a measured test showed a five-second hold at roughly a tenth the size of the MJPEG equivalent. FLV is also what Ruffle's decoder is built for. MJPEG's case is narrow: it stores every frame as an independent JPEG, which helps only if something downstream needs to pull single frames out of the file.
Adobe ended Flash Player support on 31 December 2020 and began blocking Flash content on 12 January 2021, so browsers do not play these natively any more. Ruffle is the practical answer for playback — it runs as a browser extension, a desktop application and a self-hosted web player, and its video support is built on a Rust H.263 decoder written for exactly the Sorenson-flavour streams this page produces. VLC and mpv will also open the video inside a SWF, and Adobe Animate still imports the format.
P3 files?Yes, along with binary P6 and 16-bit files with a Maxval above 255. P3 files write every sample as an ASCII decimal number, so they are typically three to four times larger than the equivalent P6 and slower to upload. If you control the code that writes them, P6 is the better choice for everything except human inspection.
There is no fixed count limit, but PPM is uncompressed — three bytes per pixel at 8-bit, six at 16-bit — so a long sequence becomes a very large upload quickly. A 1920 x 1080 frame is 6.2 MB before compression, so 240 of them is about 1.5 GB. If the sequence is long, either render at the size you actually want to publish or compress the frames to PNG first; the upload is normally the slowest part of the job by a wide margin.
No. Video is 8 bits per channel throughout the encoding chain, so a Maxval above 255 is reduced during the decode step. That is rarely a practical problem for playback, but it does mean a high-dynamic-range render will show banding in smooth gradients that was not visible in the source. If the precision matters, keep the PPMs, or convert the individual frames to PPM to PNG, which stores 16 bits per channel.
Because the movie frame and the image frame do not match. On "Keep original" the movie takes its dimensions from the first image you uploaded, and everything else is fitted inside that with the Background Color filling the difference. If you set a Fixed Resolution, the same fitting happens against that frame instead. The clean fix is to render the whole sequence at the aspect ratio you intend to publish, and to choose a Fixed Resolution that matches it.
Only choose SWF if a Flash-era system is genuinely the destination. For anything with a modern audience — a website, a phone, a television, a media server, a video platform — PPM to MP4 assembles exactly the same sequence with H.264 video that every player decodes, at a better size and without needing an emulator. SWF is the answer to "this legacy system only accepts SWF", not to "I need a video from these renders".
Your PPM files are uploaded over an encrypted connection, processed on our servers, and both the uploads and the finished movie are deleted automatically after a few hours. Nothing is shared or made public, and there is no sign-up, no watermark and no account required.