The command-line tool fif converts pictures to
FIF2 and back and inspects FIF2 files. This page first shows common tasks and
how to find the best quality for the size, then lists every command and option
and explains the error messages.
Every command follows the same pattern: first the command, then the input and output files, then the options.
fif <command> <input> [<output>] [options]
fif help lists the commands with examples;
fif help decode (or fif decode --help) lists all options
of one command, grouped by what they are for.
Options must come after the file names. fif encode in.png
out.fif -q 80 works; fif encode -q 80 in.png out.fif
does not.
fif encode holiday.jpg holiday.fif -q 70
The tool prints the size of the result and the bits per pixel. Quality 70 gives a good picture for most photographs; lower values give smaller files.
fif encode holiday.jpg web.fif --max-dim 1600 -q 50 --thumbnail 200
--max-dim 1600 reduces the picture so that its longer edge is at
most 1600 pixels before it is encoded. --thumbnail 200 adds a JPEG
preview of 200 pixels, which a viewer can show before it has decoded the
picture. The original file name, the original size and the reduction factor
are recorded in the file.
fif encode holiday.jpg holiday.fif --meta author="Ada Lovelace" --text copyright="(c) 2026 Ada Lovelace"
The camera's own data comes along by itself: from the EXIF block of a JPEG or
PNG the tool takes the camera, lens, date taken, exposure, author, copyright and
description, and it turns the picture upright if the camera stored it sideways.
The GPS position is never taken over. A --meta or
--text value with the same name replaces the camera's;
--no-exif ignores the EXIF data altogether.
Each --meta and --text option stores one named
value. You can use them as often as you like. The values may contain any
characters, including accents and non-Latin scripts.
fif decode holiday.fif poster.png --scale 3
The decoder carries out the fractal reconstruction at three times the coded resolution. This gives sharper edges than enlarging the normal decode in an image editor. Factors of 2 to 3 give the best results; up to 16 is possible.
fif decode holiday.fif wallpaper.png --size 2560x1440
The picture fills the box completely. If its shape differs from the box, the excess is cut off equally on both sides; the picture is never stretched. To keep the whole picture, give only one dimension:
fif decode holiday.fif wide.png --width 2560
fif info holiday.fif --tiles # the tile map
fif decode holiday.fif detail.png --region 400x300+600+200
fif decode holiday.fif detail.png --region 400x300+600+200 --scale 4
fif decode holiday.fif some.png --tiles 0,5-6
A FIF2 picture is made of tiles that decode independently, so a part of
it costs only the tiles it touches. --region takes the rectangle in
the usual geometry notation: widthxheight+left+top,
in the pixels of the picture as fif info reports them. The result
is exactly the same as cutting the rectangle out of a full decode, only much
faster: on a 3840 × 2160 picture, a 512 × 512
region decoded four times larger took 0.09 s instead of 0.62 s for
the whole picture. --region combines with --scale,
--width, --height and --size, which then
refer to the region.
--tiles picks tiles by number, with ranges as in a print
dialog. The picture keeps its full size; tiles that are not listed stay grey.
fif info … --tiles shows where each tile is and which bytes of the
file it needs.
fif thumbnail holiday.fif preview.jpg # the largest stored preview, if there is one
fif thumbnail holiday.fif small.jpg 0 # preview number 0
fif decode holiday.fif preview.png --scale 1/4 # fast reduced decode
A reduced decode with 1/2, 1/4 or 1/8
is much faster than a full decode, because the reconstruction itself runs at
the smaller size. The result is an approximation: 1/2 is almost
indistinguishable from a properly reduced picture, 1/8 is good
enough for a preview only.
fif info holiday.fif
Example output:
file holiday.fif
format FIF2 v3.0
dimensions 1000 x 560, 3 channel(s)
size 102.3 KiB (1.4965 bpp)
source holiday.jpg, 1749 x 980, reduced by 1.749 before encoding
blocks 4..32, tile 256
chroma 4:2:0, shared
base layer first 52.9 KiB of 102.3 KiB (51.7%) decodes at DC resolution
tiles 12 (4 x 3), independently decodable
sections chunks 488 B, thumbnail 16.6 KiB, fic 85.2 KiB, raw 0 B
checksums fic ok, chunks ok, thumbnail ok
thumbnails 1
[0] 333 x 186 JPEG, 16.6 KiB
chunks 10
ENCO encoder "libfif v3.2"
ENCO source_name "holiday.jpg"
ENCO credits "libfif v3.2 - (c) 2026 Oskar Behzadpour
FIF2 format v3.0 by Rezar Behzad
More info: www.FractalImageCompression.com"
COLR transfer "sRGB"
COLR primaries "sRGB"
META author "Ada Lovelace"
TEXT copyright "(c) 2026 Ada Lovelace"
ENCO quality 70
ENCO effort 5
DECO deblock 60
The line base layer states how much of the file is needed for a complete, coarse picture. The line checksums shows whether the file is intact.
fif compare original.png decoded.png
Prints three common quality measures: PSNR in decibels, SSIM and MS-SSIM. For all three, higher means closer to the original.
No single setting is best for every picture, but five steps find the best one for yours in a few minutes. The numbers below come from a landscape photograph reduced to 1920×1080. Other pictures give other numbers, but the curve has the same shape.
fif encode photo.jpg photo.fif --max-dim 1920
The number of pixels matters more than any quality setting. Half the width
and height means a quarter of the pixels and roughly a third of the file size.
Use the same --max-dim in all the following steps, so that what you
measure is what you will encode.
fif bench encodes and decodes in one step, writes no file and
reports the size and the quality. Run it for several quality values:
for q in 20 35 50 65 75 85 95; do
echo "q=$q"; fif bench photo.jpg --max-dim 1920 -q $q -e 2 --no-progress | grep -E 'size|psnr|ms-ssim'
done
-q | Size | Bits per pixel | PSNR | MS-SSIM |
|---|---|---|---|---|
| 20 | 37.8 KiB | 0.15 | 26.81 dB | 0.871 |
| 35 | 102.3 KiB | 0.40 | 29.28 dB | 0.940 |
| 50 | 177.8 KiB | 0.70 | 30.76 dB | 0.967 |
| 65 | 304.6 KiB | 1.20 | 31.57 dB | 0.981 |
| 75 | 379.3 KiB | 1.50 | 31.76 dB | 0.984 |
| 85 | 469.9 KiB | 1.86 | 31.86 dB | 0.986 |
| 95 | 551.7 KiB | 2.18 | 31.91 dB | 0.987 |
Look for the knee: the point after which more bytes buy hardly any quality. From 35 to 50, 75 KiB more bring 1.5 dB. From 75 to 95, 172 KiB more bring only 0.15 dB. A useful rule: go higher only while 10% more size still brings at least 0.1 dB. Here the knee lies between 50 and 65.
The quality of a fractal code levels off at the top, so above about 75 you mainly buy bytes. The numbers are a guide; look at the two candidates at the knee before you decide. MS-SSIM follows the eye better than PSNR, and values above 0.98 are hard to tell from the original at normal viewing size.
fif encode photo.jpg a.fif --max-dim 1920 -q 50 && fif decode a.fif a.png
fif encode photo.jpg b.fif --max-dim 1920 -q 65 && fif decode b.fif b.png
The effort changes the time much more than the size. At quality 65:
-e | Encode time | Size | PSNR |
|---|---|---|---|
| 0 | 0.04 s | 304.7 KiB | 30.88 dB |
| 2 | 0.12 s | 304.6 KiB | 31.57 dB |
| 5 (default) | 0.56 s | 304.6 KiB | 31.57 dB |
| 7 | 0.95 s | 311.9 KiB | 31.72 dB |
| 9 | 4.35 s | 319.4 KiB | 31.81 dB |
For photographs -e 2 is almost always right: the same result as
the default, five times faster. Higher effort pays off for textures, patterns
and aerial pictures; compare -e 2 and -e 7 with
fif bench to find out.
--subsampling | Size at quality 65 | Use for |
|---|---|---|
420 (default) | 304.6 KiB | Photographs. The eye sees colour less sharply than brightness. |
444 | 368.4 KiB (+21%) | Screenshots, diagrams, coloured text, sharp colour edges. |
400 | 186.2 KiB (−39%) | Greyscale pictures, or when colour does not matter. |
-q 55): the same look for every
picture; the size depends on the content. Right for most batches.--target-bpp 1.0): the file is as large as
asked; the quality varies. Right when storage or bandwidth is fixed.--target-psnr 31): the smallest
file that reaches it.A target tries seven qualities, so use -e 2 to keep it fast. The
tool tells you which quality it chose, and warns you if the target cannot be
reached:
$ fif encode photo.jpg photo.fif --max-dim 1920 --target-psnr 31 -e 2
photo.fif: 1920x1080 -> 198.6 KiB (0.7847 bpp) in 0.933 s
target 31 dB -> quality 54, 31.00 dB
$ fif encode photo.jpg photo.fif --max-dim 1920 --target-psnr 34 -e 2
photo.fif: 1920x1080 -> 583.6 KiB (2.3055 bpp) in 1.121 s
target 34 dB -> quality 100, 31.92 dB
fif: warning: 34 dB is not reachable for this image; the best result has 31.92 dB
The warning is useful in itself: this picture levels off just below 32 dB, and anything above about 31 dB costs a lot of bytes for little gain.
In short: reduce to the display size with --max-dim;
measure with fif bench and pick the knee, usually between 50 and 70;
use -e 2 for photographs; use --subsampling 444 for
graphics and 400 for greyscale; fix -q for batches, or
use --target-bpp for a fixed budget.
| Command | Purpose |
|---|---|
fif encode <in> [<out.fif>] | Compress a PNG, JPEG or PNM picture. Without an output name it writes <in> with the extension .fif. |
fif decode <in.fif> <out> | Reconstruct a picture. The extension of out selects the format: .png, .jpg, .jpeg, .ppm, .pgm, .pnm. |
fif info <in.fif> [--tiles] | Show header, metadata, preview and attached files; with --tiles also the tile map. |
fif thumbnail <in.fif> <out> [N] | Write stored preview N, or the largest one without N. To .jpg a JPEG preview is copied unchanged; other formats are converted. |
fif compare <a> <b> | Measure the difference between two pictures of the same size. |
fif bench <in> | Encode, decode and report quality and speed in one step. Takes the encode options. |
fif version | Show the version. |
| Option | Default | Effect |
|---|---|---|
-q, --quality N | 75 | Quality, 0 to 100. |
-e, --effort N | 5 | Search effort, 0 to 9. 0–1: fastest. 2: good balance. 3–7: wider search. 8–9: exhaustive. |
--target-bpp X | – | Choose the quality that gives X bits per pixel. |
--target-psnr X | – | Choose the quality that gives X dB. |
--subsampling S | 420 | Colour resolution. 444: full. 420: half in each direction, as in JPEG. 400: greyscale only. |
--chroma M | shared | How colour is coded. shared: follows the brightness structure. from-luma: predicted from brightness, faster decode. |
--downscale F | – | Reduce the input by factor F before encoding. |
--width N, --height N | – | Reduce the input to this width or height, keeping its shape. |
--max-dim N | – | Reduce the input so its longer edge is at most N. Smaller pictures are not changed. |
--thumbnail N | 0 (none) | Add a JPEG preview with a longer edge of N pixels, at most a third of the picture's longer edge. |
--thumbnail-quality Q | 85 | JPEG quality of the preview, 1 to 100. |
--meta KEY=VALUE | – | Store a metadata entry. Repeatable. |
--text KEY=VALUE | – | Store a text entry, e.g. a copyright notice. Repeatable. |
--misc KEY=VALUE | – | Store an entry of type MISC, for anything that is neither metadata nor text. Repeatable. |
--chunk TYPE:KEY=VALUE | – | Store an entry of a type of your own, 1 to 4 characters, e.g. --chunk ACME:render=soft. Other programs skip types they do not know. |
--compress-chunks | off | Store all entries zlib-compressed. Worth it for long texts. |
--remarks ABCD | – | Set the four-character REMARKS field in the header, free for any use, e.g. to mark processed files. |
--no-credits | off | Leave out the credits entry naming the authors and the website (about 140 bytes). Worth it only for very small files. |
--no-exif | off | Ignore the EXIF data of the input: no camera metadata, and no rotation by its orientation tag. |
-t, --threads N | 0 | Number of threads. 0 uses half of the processor cores. |
--stats | off | Print statistics about the encoded blocks. |
--progress, --no-progress | auto | Show or hide the progress bar. |
Further options for experts adjust the block sizes (--min-block,
--max-block, powers of two from 2 to 256, --tile), the search
(--local-radius, --kd-candidates,
--domain-shift) and the planar mode (--planar). fif help encode lists them.
The defaults are chosen from measurements; changing them rarely helps.
| Option | Default | Effect |
|---|---|---|
--scale S | 1 | N (2 to 16): decode N times larger. 1/2, 1/4, 1/8: fast reduced decode. Other 1/N: full decode, then reduced. |
--width W, --height H | – | Output width or height; the other side follows the shape of the picture. |
--size WxH | – | Output box. The picture fills it and is trimmed at the centre if necessary, never stretched. |
--deblock N | from file | Strength of the filter that smooths block edges, 0 to 100. 0 turns it off, -1 uses the file's recommendation. |
--no-smooth-dc | on | Paint flat blocks as single values instead of soft surfaces. |
--chroma-upsampling M | edge | 4:2:0 colour: edge follows the brightness edges, bilinear is the reference interpolation. |
--dither | off | Break up banding in smooth gradients when rounding to 8 bits. |
--iterations N | from file, else 16 | Maximum number of reconstruction rounds. Overrides a recommendation in the file. |
--eps X | from file, else 0.5 | Stop when no pixel changes by more than X between rounds. |
--region WxH+X+Y | – | Decode only this rectangle, e.g. 400x300+600+200. Only the tiles it touches are decoded; the pixels equal those of a full decode. |
--tiles LIST | – | Decode only these tiles, e.g. 0,5-6; the others stay grey. |
--max-pixels N | 268435456 | Refuse pictures larger than this. A safety limit against damaged or hostile files. |
-t, --threads N | 0 | Number of threads. 0 uses half of the processor cores. |
Every message has the same form: one line that says what went wrong, and indented hints that say what to do about it.
fif: error: cannot open 'holiday.png': no such file
hint: the file is looked for in the current directory; give the full path if it is elsewhere
fif: warning: means the command ran, but perhaps not as you
expected. fif: error: means it stopped. All messages go to the
error output, so the normal output stays clean for scripts.
| Message (shortened) | What to do |
|---|---|
unknown command 'ecnode' | The tool suggests the command you probably meant. |
unknown command 'photo.png' | The command is missing: fif encode photo.png out.fif. |
options must come after the file names | Write the files first, then the options. |
unknown option '--qualty' | The tool suggests the closest option, or names the command the option belongs to. |
-q 150 is out of range; allowed is 0..100 | Every value is checked before anything is read; the hint explains the option. |
the output … is the input file | Choose another output name. The tool never overwrites the picture it reads. |
.bmp is not an image format fif writes | Use one of the listed extensions. This is checked before decoding. |
the directory 'x' does not exist | Create it first. This is checked before encoding, so no work is lost. |
'a.png' is named .png but contains a JPEG image | Rename the file; the tool picks the reader by the extension. |
'a.webp' is a WebP image, which fif cannot read | Convert it to PNG first. |
this fif cannot read PNG | The tool was built without libpng (or libjpeg). Install it and build again. |
is a PNG image, not a FIF2 file | Use fif encode for pictures, fif decode for FIF2 files. |
is not a FIF2 file | The tool shows the first bytes. An interrupted download or a renamed file looks like this. |
uses container version 2.0 | An old development file. Encode the picture again from the original. |
is cut off / the header checksum does not match | The file is incomplete or damaged. Copy or download it again. |
the image data does not decode | Check with fif info; the embedded preview may still be usable. |
would have N pixels; the limit is M | The hint gives the exact --max-pixels value, or decode smaller. |
--region … reaches past the picture | The hint gives the largest region that fits. |
there is no tile 40 | The message says how many tiles the file has; fif info … --tiles lists them. |
warning: … is not reachable for this image | A --target-bpp or --target-psnr cannot be met. The file is the closest result. |
| Code | Meaning |
|---|---|
| 0 | Success. There may be warnings. |
| 1 | The command failed: a file is missing, cannot be read or written, is not a valid FIF2 file or is damaged. |
| 2 | The command line is wrong: unknown command or option, missing or invalid value, options before the file names, an unusable output name. Nothing was read or written. |
fif info and
fif debug stays clean for scripts.fif info shows truncated in that case.