File types · Explainer

The PFM file (.pfm)

A PFM file is usually a Portable FloatMap: a high-dynamic-range image in the spirit of the Netpbm PPM format, with a three-line text header followed by uncompressed 32-bit floating-point pixels. This guide explains the header and its sign trick for byte order, why the rows run bottom to top, how to open and convert one, and how to tell it apart from the unrelated Printer Font Metrics .pfm.

At a glance

Full name
Portable FloatMap, also written Portable Float Map
Extensions
.pfm
MIME type
None registered; servers usually send application/octet-stream
Kind
Binary raster image after a short ASCII header; uncompressed 32-bit IEEE floats, high dynamic range
Standard or owner
None. Documented informally (on Paul Debevec's website and in the Netpbm manual), which notes that several similar formats called PFM exist
First released
Not precisely documented; used by USC's HDRShop, and supported by Netpbm since April 2004
Channels
3 (RGB, PF) or 1 (greyscale, Pf); no alpha
Byte order
Set by the sign of the third header line: negative for little-endian, positive for big-endian
Magic number
50 46 ("PF") or 50 66 ("Pf"), then a whitespace character, usually 0A
Opens with
ImageMagick, Netpbm, OpenImageIO, GIMP; Pillow for greyscale only; browsers can't display it
Not to be confused with
Printer Font Metrics (.pfm), the Windows metrics file of a PostScript Type 1 font, which starts with 00 01

The basics

What is a PFM file?

A Portable FloatMap is the simplest way to store an image whose pixels are floating-point numbers. It follows the spirit of the Netpbm PPM format: a few lines of text say what the image is, and the pixels follow with nothing in between. The difference is that each sample is a 32-bit float rather than a whole number from 0 to a maximum, so a pixel can hold 0.0001 or 5,000. That makes PFM a high-dynamic-range format, like Radiance HDR and OpenEXR, but with none of their packing or compression.

No standards body owns PFM. Its best-known description is a short page on Paul Debevec's website, and USC's HDRShop program used it. Netpbm added converters in April 2004 and documents a version of the format, but calls it unofficial: its manual says there are several similar formats known as PFM, none of them authoritatively documented. In practice the variants agree on almost everything except the row order (see below).

Where you'll meet PFM files:

  • Computer vision. The Middlebury stereo benchmark distributes its ground-truth disparity maps as PFM, and expects results in the same format, so PFM is common in stereo-matching and depth-estimation code.
  • HDR research and teaching. A program can write one with a printf and a single fwrite, with no library.
  • Pipelines and tests. As a lossless go-between for floating-point data, and as test input for image libraries.

Two different .pfm formats

A .pfm file in a fonts folder is almost certainly a Printer Font Metrics file, part of a PostScript Type 1 font on Windows. It has nothing to do with images. The section on fonts below explains how to tell them apart.

Anatomy

What's inside a PFM file

A PFM file is three lines of ASCII text, then the pixels as raw 4-byte floating-point numbers. Below is every byte of a 60-byte file we wrote for this page: 2 × 2 pixels, one of them brighter than white. ImageMagick, Netpbm and OpenImageIO all read it as the picture shown at the bottom. It isn't offered for download.

tiny.pfm (hex, 60 bytes)
tiny.pfm: 2 × 2 pixels, colour, little-endian, 60 bytes

offset  bytes                                   part
0       50 46 0A                                "PF" + newline: colour
3       32 20 32 0A                             "2 2": width, height
7       2D 31 2E 30 0A                          "-1.0": little-endian, scale 1
12      00 00 00 00 00 00 00 00 00 00 00 00     bottom row, pixel 1
24      EC 51 38 3E EC 51 38 3E EC 51 38 3E     bottom row, pixel 2
36      00 00 80 3F 00 00 00 3F 00 00 80 3E     top row, pixel 1
48      00 00 80 40 00 00 00 40 00 00 80 3F     top row, pixel 2
60                                              end of file

the picture, as (red, green, blue):
  top row     (1.0, 0.5, 0.25)    (4.0, 2.0, 1.0)
  bottom row  (0.0, 0.0, 0.0)     (0.18, 0.18, 0.18)
  1. 150 46 0A

    The identifier

    PF means a colour image with three samples per pixel; Pf, with a lower-case f, a greyscale image with one. The case of one letter is the only difference, so a reader must compare both bytes exactly.

  2. 232 20 32 0A

    Width and height

    Two positive decimal integers separated by a space: 2 pixels wide, 2 rows high. Unlike PPM, there's no maximum value line: floats need none.

  3. 32D 31 2E 30 0A

    Scale and byte order

    A non-zero decimal number. Its sign gives the byte order of the floats: negative means little-endian (as on x86 and ARM computers), positive means big-endian. Its absolute value is a scale factor that, according to Netpbm, tells the units of the samples. Most files use -1.0 or 1.0.

  4. 400 00 00 00 …

    The bottom row comes first

    The pixel data starts with the bottom row of the image and works upwards, left to right within each row. This is the opposite of PPM and most other formats, and the commonest cause of upside-down PFM images.

  5. 5EC 51 38 3E

    A 32-bit float

    Each sample is an IEEE 754 single-precision number. Read little-endian, these bytes are 0x3E3851EC: 0.18, the value of a mid-grey card in linear light. Three of them make one grey pixel.

  6. 600 00 80 3F

    1.0, full brightness

    0x3F800000 is exactly 1.0. In an 8-bit image, this would be the brightest value possible.

  7. 700 00 80 40

    Brighter than white

    0x40800000 is 4.0, four times brighter than 1.0. Nothing caps the values, which is what makes PFM a high-dynamic-range format. Negative numbers are possible too.

  8. 860

    No trailer

    The file ends after the last sample: 12 header bytes plus 2 × 2 pixels × 3 samples × 4 bytes = 60. There's no compression, metadata or checksum.

Quirks

Rows from the bottom up

Both main descriptions of PFM say the rows are stored from the bottom of the image to the top, left to right within each row. That's the opposite of PPM, so code adapted from a PPM writer produces upside-down PFM files unless it reverses the rows.

  • Netpbm notes that a PFM variant it attributes to Adobe orders the rows top to bottom instead, and suggests flipping the image if one comes out upside down.
  • There's nothing in the file to say which convention a writer followed. If a PFM looks upside down, it probably is: flip it once and check against a reference image.
terminal
# flip a PFM vertically, keeping the float values
oiiotool upside-down.pfm --flip -o fixed.pfm

Comparison

PFM vs PPM, Radiance HDR and OpenEXR

PFMPPMRadiance HDROpenEXR
Bytes per RGB pixel, uncompressed123 or 646 (half) or 12 (float)
ValuesAny 32-bit float, including negativeWhole numbers from 0 to maxvalZero or positive, about 1% precisionHalf or full floats, or integers
AlphaNoNo (PAM has it)NoYes
CompressionNoneNoneRun-lengthMany, lossless and lossy
MetadataNoneCommentsText headerAny attributes
Best forResearch, tests, disparity and depth mapsSimple 8- or 16-bit imagesHDRI lighting mapsFilm, VFX and rendering

PFM keeps full 32-bit precision and is trivial to read, but the files are large: a 1920 × 1080 colour PFM is about 24.9 MB, twice the size of a half-float EXR before compression and four times an 8-bit PPM. Use it inside a pipeline or for data where exact values matter, and EXR for anything you store or exchange.

Identify

Printer Font Metrics: the other .pfm

On Windows, a PostScript Type 1 font usually comes as a pair: a .pfb file (PostScript Font Binary) with the glyph outlines, and a .pfm file with the font metrics: the character widths and other measurements that Windows and printer drivers use to lay out text. The two must stay together. Older fonts sometimes came as .pfb, .afm and .inf files instead, and installing them produced the .pfm.

Portable FloatMapPrinter Font Metrics
First bytes50 46 or 50 66 (PF or Pf), then a newline00 01: the version field, 0x0100, little-endian
Readable startThree short lines of text, then binary dataBinary from the first byte
Found next toOther images, or render and vision outputA .pfb file of the same name, in a fonts folder
Opens withImage toolsInstalled as a font, with its .pfb

To check, open the file in a text editor or run head -c 16 file.pfm | xxd. If it starts with PF or Pf it's an image; if the first two bytes are 00 01, it's a font. Type 1 fonts are a legacy format: for new work, use an OpenType font.

How to

How to open and convert a PFM file

  • ImageMagick reads and writes colour and greyscale PFM. Builds without HDRI support, such as the ImageMagick 6 packages of many Linux distributions, clip values above 1.0 to white when they read the file.
  • Netpbm: pfmtopam converts PFM to an ordinary Netpbm image and pamtopfm goes the other way, with -endian=little or big to choose the byte order.
  • OpenImageIO (pip install OpenImageIO) reads and writes PFM with full float values, and converts it to EXR or HDR without losing range.
  • GIMP can export images as PFM.
  • Pillow (Python) reads and writes greyscale PFM (Pf) as 32-bit float images (mode F). It doesn't read colour PFM, and in our test with Pillow 12 an RGB image saved with a .pfm name came out as an 8-bit PPM file.
  • Browsers, Windows Photos and macOS Preview don't open PFM.
terminal
# PFM to half-float EXR, keeping the HDR values
oiiotool input.pfm -d half -o output.exr

# EXR or HDR back to PFM
oiiotool input.exr -o output.pfm

# PNG to PFM with Netpbm (values 0 to 1; grey PNGs become Pf)
pngtopam input.png | pamtopfm > output.pfm

# PFM to a Netpbm image with whole numbers
pfmtopam input.pfm > output.pam

Reading one yourself takes a few lines: split the header on whitespace, pick <f4 or >f4 from the sign of the scale, read width × height × channels floats, and reverse the order of the rows. In Python with NumPy that's np.frombuffer(data, dtype).reshape(h, w, c)[::-1].

Troubleshooting

Common PFM problems

  • The image is upside down. The writer or the reader got the row order wrong. Flip it vertically.
  • The image is random noise or a few huge values. The floats were read in the wrong byte order: the reader ignored the sign of the scale line. Swap every group of 4 bytes.
  • It's black, or flat white. The values are linear light and may be far outside 0 to 1. Adjust the exposure in an HDR viewer, or scale the values before converting to an 8-bit format.
  • Bright areas go strange after converting to PNG. Values above 1.0 can't fit in 8 bits: most tools clip them to white, but some converters wrap them around into wrong colours. Scale the image down first.
  • Pillow says "cannot identify image file". It's a colour (PF) file, which Pillow doesn't read. Use OpenImageIO, ImageMagick or a few lines of NumPy.
  • Nothing opens it at all. Look at the first two bytes. 00 01 means it's a font metrics file, not an image.

Security

Is a PFM file safe?

A PFM file is a header and numbers, nothing that runs. As with PPM, the risk is in readers that trust the header: a few bytes can claim an image of 100,000 × 100,000 pixels, which at 12 bytes per pixel is 120 GB. Check the dimensions against a limit, and the file length against width × height × channels × 4, before allocating memory. Values can also be infinities or NaN (not a number), which can break code that sums or divides them.

Sample files

There are no sample PFM files on this page yet. To make one for testing, convert an image with Netpbm (pngtopam input.png | pamtopfm > output.pfm), OpenImageIO (oiiotool input.exr -o output.pfm) or ImageMagick (convert input.png output.pfm).

Put it online

Have a PFM file? Give it a link.

Drop a Portable FloatMap on 99helpers and it gets its own web address. Browsers can't display PFM, so anyone who opens the link downloads the file, ready for an HDR viewer, a vision pipeline or an image library.

Questions

PFM files, frequently asked

What is a .pfm file?

Usually a Portable FloatMap: an uncompressed high-dynamic-range image with a three-line text header and 32-bit floating-point pixels. In a fonts folder, a .pfm is instead the Printer Font Metrics file of a Windows Type 1 font.

How do I open a PFM image?

Use ImageMagick, OpenImageIO, Netpbm or GIMP, or convert it to EXR or PNG first. Pillow reads only greyscale PFM files. Browsers and the built-in photo viewers on Windows and macOS can't open it.

What's the difference between PF and Pf?

PF is a colour image with three floats (red, green, blue) per pixel; Pf is greyscale, with one float per pixel.

Why is my PFM image upside down?

PFM stores rows from the bottom of the image to the top, the opposite of most formats, and some programs get it wrong. Flip the image vertically, for example with oiiotool in.pfm --flip -o out.pfm.

What does -1.0 in a PFM header mean?

The pixels are little-endian. A negative number on the third line means little-endian floats, a positive one big-endian. The absolute value, usually 1, is a scale factor.

Is PFM the same as PPM?

No, but it's modelled on it. PPM stores whole numbers up to a maximum value, top row first; PFM stores 32-bit floats with no maximum, bottom row first. Netpbm converts between them with pfmtopam and pamtopfm.

Is a .pfm file a font?

It can be. If it sits next to a .pfb file and starts with the bytes 00 01, it's the metrics half of a PostScript Type 1 font. If it starts with PF or Pf, it's an image.

Related formats

Other file types explained

Keep going

Related

Sources

Last reviewed 27 October 2026.