Turn Split YUV Files into a PPM Image with yuvsplittoppm
yuvsplittoppm stitches three raw Netpbm component files back into one viewable PPM image. It reads BASE.Y, BASE.U and BASE.V, and writes the image to standard output. The examples use Netpbm 11.5.2, installed here as Debian package netpbm 2:11.05.02-1.1build1.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes if the files already exist. You need a shell, the Netpbm package, the common basename for the three files, and the exact image width and height. This workflow only creates a new output file; it does not alter the YUV inputs or require elevated privileges.
1. Confirm the command and the three inputs
Check the executable and list the component files before converting, an ordinary read-only check:
$ command -v yuvsplittoppm
/usr/bin/yuvsplittoppm
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1
$ ls -l /path/to/frame.Y /path/to/frame.U /path/to/frame.V
For a basename of /path/to/frame, the command looks for exactly /path/to/frame.Y, /path/to/frame.U and /path/to/frame.V. The suffixes are part of the contract: a similarly named file, different capitalisation, or a missing component stops the conversion or hands you an unusable result.
Checkpoint
Record the dimensions from whatever produced the files. Raw data carries no header, so yuvsplittoppm cannot discover the width or height on its own.
2. Check the raw file sizes
The usual Netpbm split-YUV layout stores one byte per pixel in the Y file, and one byte per four-pixel square in each of the U and V files. For a 2 by 2 image that means four bytes in Y and one byte in each chroma file:
$ wc -c /path/to/frame.Y /path/to/frame.U /path/to/frame.V
4 /path/to/frame.Y
1 /path/to/frame.U
1 /path/to/frame.V
6 total
This size relationship is a useful sanity check, not a substitute for knowing the file's actual format. It applies to the subsampled raw files produced by the related ppmtoyuvsplit tool; if your files came from another encoder, confirm its sampling and byte layout first. Do not pad or truncate files to make the numbers fit, since that changes image data and cannot recover anything missing.
3. Convert using the default JPEG-style scaling
Pass the basename, width and height, then redirect standard output to a new PPM path:
$ yuvsplittoppm /path/to/frame 1920 1080 > /path/to/frame.ppm
The default assumes the YUV triplets use the JFIF (JPEG) range. Standard output is the image itself, with no progress report mixed in, so keep that redirection in place.
Redirection can silently overwrite an existing destination. If the output matters, check first:
$ test ! -e /path/to/frame.ppm && yuvsplittoppm /path/to/frame 1920 1080 > /path/to/frame.ppm
$ file /path/to/frame.ppm
/path/to/frame.ppm: Netpbm image data, size = 1920 x 1080, rawbits, pixmap
If that test fails, nothing is overwritten. Remove or rename the existing file only once you have confirmed it is disposable, which is the only state-changing step here and needs no sudo.
4. Use CCIR 601 scaling when the source requires it
Some video and MPEG-oriented YUV data uses the narrower CCIR 601 range instead of the full JPEG range. Select it with -ccir601:
$ yuvsplittoppm /path/to/frame 1920 1080 -ccir601 > /path/to/frame-601.ppm
$ file /path/to/frame-601.ppm
/path/to/frame-601.ppm: Netpbm image data, size = 1920 x 1080, rawbits, pixmap
This option only changes how component values convert to RGB. It does not repair wrong dimensions, reorder bytes, or touch the source files. If the image looks washed out, crushed or unexpectedly bright, revisit the source encoder's documented range before reaching for other options, and keep the two output names separate while you compare them.
Checkpoint
Compare the two PPM files with an image viewer or a downstream Netpbm converter. A valid PPM header proves the conversion ran; it cannot prove the colour range you chose matches the source.
5. Diagnose the common failures
If the command says an input file cannot be opened, run ls -l on the exact three names and check the basename spelling. A short read, or a distorted lower edge in the output, usually means the width, height or expected byte counts are wrong. Raw files carry no metadata, so a plausible-looking command can still be wrong.
- Keep dimensions as separate arguments:
1920 1080, never1920x1080. - Match the installed synopsis order for where
-ccir601goes relative to the positional arguments. - Never add an input filename: yuvsplittoppm always reads the three basename-derived files.
For a quick structural check, inspect the PPM header without opening the full image:
$ head -n 3 /path/to/frame.ppm
P6
1920 1080
255
The first line should be the binary PPM marker P6, the second should match the requested width and height, and the third should normally read 255. Do not open the file in a text editor: everything after the header is binary pixel data.
Done means
- Resolved the basename to matching
.Y,.Uand.Vfiles. - Matched the supplied dimensions to the source, with plausible raw file sizes.
- Chose the JPEG or CCIR 601 range to match the source documentation.
- Confirmed a PPM at the requested dimensions with
file. - Kept the output path separate from the inputs, protecting any existing output before conversion.