PFM(5)

πŸ“¦
version 11.13.03 Β· 3 versions
, in arch rolling, centos-stream 10, debian trixie, fedora 43, fedora 44, opensuse-leap 16.0, ubuntu resolute, ubuntu stonking

πŸŽ€ NAME πŸŽ€

PFM β€” the PFM graphic image file format, bestie. that's it, that's the name πŸ’…


✨ DESCRIPTION ✨

okay so this whole doc is describing the PFM graphic image file format exactly the way the Netpbm converters pamtopfm(1) and pfmtopam(1) understand it. those two are the ones doing the actual vibes here.

here's the tea though: there are multiple formats out in the wild all calling themselves PFM, and honestly? none of them are authoritatively documented. not one. the specific one we're describing is the one Bryan Henderson figured out by reverse-engineering a program he found somewhere that dealt with a "PFM" format. and that version is apparently the one Gimp calls PFM. so like, that's the canon now 🫢

now, there's another big-name PFM β€” the one Adobe Photoshop uses β€” and it looks basically identical to this one except rows are ordered from top to bottom in the Adobe version. so if you swap images between systems using these two formats, it'll ~technically~ work, but your image comes out flipped upside down πŸ™ˆ you can fix that with pamflip -topbottom, so it's giving minor inconvenience, not tragedy.

also worth knowing: PFM is inspired by the Netpbm formats, so you're gonna see a LOT of family resemblance. but no cap, it is not an official Netpbm format, and its goals aren't even consistent with the goals of Netpbm formats. cousins, not siblings πŸ’«


πŸ’« The format πŸ’«

a PFM image is literally just a stream of bytes. that stream = a header followed immediately by a raster. two components, described below, and there are no delimiters before or after these sections. none. zero. don't add any 🌸

🌈 PFM header

the header is 3 consecutive "lines" of ASCII text. after each line comes a white space character. that character is typically a newline β€” which is why we even call them "lines" β€” but bestie, it doesn't have to be.

for the record, pamtopfm uses a newline in the PFM it generates. that's the move ✨

πŸ¦‹ Identifier Line

this line contains the characters "PF" or "Pf".

  • PF means it's a color PFM
  • Pf means it's a grayscale PFM

capitalization is literally load-bearing, iykyk πŸ’…

πŸ¦‹ Dimensions Line

two positive decimal integers, separated by a blank.

  1. the first is the width of the image
  2. the second is the height

both in pixels. periodt πŸ“

πŸ¦‹ Scale Factor / Endianness

okay this line is queer (the manpage's word, not mine, but honestly? accurate πŸ’€). it jams endianness info into what would otherwise be a perfectly sane description of a scale.

the line = a nonzero decimal number, not necessarily an integer.

  • if the number is negative β†’ the PFM raster is little endian
  • otherwise β†’ it's big endian</big endian>

and the absolute value of that number is the scale factor for the image.

so what does the scale factor even do? it tells you the units of the samples in the raster. you take it, combine it somehow with some separately-understood unit information, and boom β€” a sample value turns into something meaningful, like watts per square meter. it's giving ✨teamwork✨

🌈 PFM raster

the raster is a sequence of pixels, packed one after another, with no delimiters of any kind. they're grouped by row, with the pixels in each row ordered left to right and the rows ordered bottom to top.

Note: this is the opposite of Netpbm formats, which order rows top to bottom. it's also the opposite of the format Adobe Photoshop calls PFM. see the introduction for more on this disparity. 🫠

each pixel consists of 1 or 3 samples, packed one after another, again with no delimiters of any kind.

  • 1 sample β†’ grayscale PFM
  • 3 samples β†’ color PFM

(see the Identifier Line of the PFM header, we literally just talked about this πŸ’–)

each sample = 4 consecutive bytes. those bytes represent a 32 bit string, in either big endian or little endian format, as determined by the Scale Factor / Endianness line of the PFM header. and that string is an IEEE 32 bit floating point number code.

here's the cute part: since that's the same format most CPUs and compilers use, you can usually just make a program use the bytes directly as a floating point number β€” after taking care of the endianness variation, obviously. slay 🧚


πŸ“œ DOCUMENT SOURCE πŸ“œ

this manual page was generated by the Netpbm tool makeman from HTML source. the master documentation lives at

http://netpbm.sourceforge.net/doc/pfm.html

and that's the whole page bestie, we ate and left no crumbs πŸ‘‘ this was netpbm documentation, dated 27 February 2024, and if you made it this far you are genuinely the main character of reading manpages πŸ’œ

πŸ“¦ where this page comes from