This page is for developers who want to read or write FIF2
files in their own programs. It explains the concepts of the
libfif interface, gives a complete example, and lists the
functions.
The library has one header, include/fif/fif.h, and one library
file: libfif.a on Linux and macOS, libfif.lib on
Windows. The interface is plain C and can be called from C, C++ and other
languages with a C interface.
clang -O2 -Iinclude -c myprogram.c
clang++ myprogram.o libfif.a -lpng -ljpeg -lpthread -o myprogram
The library is written in C++20, so the final program must be linked with
a C++ compiler or with the C++ standard library. Add -lpng and
-ljpeg only if the library was built with PNG and JPEG
support.
FIF_OK (0) means
success; every error is negative. fif_status_string() gives a
readable description.fif_encode_options_defaults() or
fif_decode_options_defaults() before you set individual fields.
New fields may be added in later versions; the defaults function gives them
correct values.fif_image holds grey or RGB pixels row by row, with an explicit
row stride.fif_free(), pictures with fif_image_free().fif_get_info, fif_get_chunk,
fif_get_thumbnail, fif_get_raw) return pointers
into the data you passed. They stay valid as long as that data exists.#include <fif/fif.h>
#include <stdio.h>
int main(void)
{
fif_image img = {0};
fif_status st = fif_image_load("photo.png", &img);
if (st != FIF_OK) {
fprintf(stderr, "load: %s\n", fif_status_string(st));
return 1;
}
/* Encode with quality 70 and a 200-pixel preview. */
fif_encode_options eo;
fif_encode_options_defaults(&eo);
eo.quality = 70;
eo.thumbnail_size = 200;
eo.source_name = "photo.png";
uint8_t *data = NULL;
size_t size = 0;
st = fif_encode(&img, &eo, &data, &size, NULL);
fif_image_free(&img);
if (st != FIF_OK) {
fprintf(stderr, "encode: %s\n", fif_status_string(st));
return 1;
}
/* Decode at 1920 pixels wide. */
fif_decode_options dopt;
fif_decode_options_defaults(&dopt);
dopt.out_width = 1920;
fif_image out = {0};
st = fif_decode(data, size, &dopt, &out, NULL);
if (st == FIF_OK)
st = fif_image_save("photo-1920.png", &out);
fif_image_free(&out);
fif_free(data);
return st == FIF_OK ? 0 : 1;
}
fif_info in;
if (fif_get_info(data, size, &in) == FIF_OK) {
printf("%d x %d, from %.*s (%d x %d)\n", in.width, in.height,
(int)in.source_name_len, in.source_name,
in.source_width, in.source_height);
if (in.fic_crc_ok == 0)
printf("warning: picture data is damaged\n");
}
/* List all metadata entries. */
fif_chunk c;
for (int i = 0; fif_get_chunk(data, size, i, &c) == FIF_OK; ++i)
if (c.value_type == FIF_VALUE_TEXT)
printf("%s %.*s = %.*s\n", c.type, (int)c.name_len, c.name,
(int)c.size, (const char *)c.data);
/* Show a preview of at least 256 pixels while the full picture decodes. */
fif_image preview = {0};
int k = fif_find_thumbnail(data, size, 256, "JPEG");
if (k >= 0 && fif_decode_thumbnail(data, size, k, &preview) == FIF_OK) {
/* ... display preview ... */
fif_image_free(&preview);
}
fif_status fif_encode(const fif_image *img, const fif_encode_options *opts, uint8_t **out_data, size_t *out_size, fif_stats *stats)*out_data points to a new
buffer of *out_size bytes; release it with
fif_free(). opts and stats may be
NULL.fif_status fif_decode(const uint8_t *data, size_t size, const fif_decode_options *opts, fif_image *out, fif_stats *stats)out receives a new picture; release
it with fif_image_free(). A truncated file is not an error: the
function returns the best picture the data allows.fif_get_info(data, size, &info)base_prefix_bytes). Cheap and safe
on untrusted data.fif_get_chunk(data, size, index, &chunk)FIF_OK.fif_get_thumbnail(data, size, index, &thumb)"JPEG"), width, height, and a pointer to the
complete image file. A file can hold any number of previews. Count up from 0
until the function returns FIF_ERR_ARG.fif_find_thumbnail(data, size, min_edge, format)min_edge, or of the largest if none is that big. A non-NULL
format limits the choice to that format code. Returns −1 if
there is no preview.fif_decode_thumbnail(data, size, index, &image)fif_get_raw(data, size, index, &entry)fif_image_load(path, &img), fif_image_save(path, &img)FIF_ERR_UNSUPPORTED.fif_image_alloc(&img, width, height, channels), fif_image_free(&img)fif_image_downscale(&src, w, h, &dst)fif_psnr, fif_ssim, fif_ms_ssim| Field | Default | Meaning |
|---|---|---|
quality | 75 | 0 to 100. |
effort | 5 | 0 to 9. |
subsampling | 4:2:0 | FIF_SUBSAMPLING_444, _420 or _400. |
target_bpp, target_psnr | 0 (off) | Search the quality that reaches this value. |
threads | 0 | 0 = half of the processor cores. |
thumbnail_size | 0 | Longer edge of the JPEG preview; 0 = none. The encoder writes at most one preview; the format allows more. |
thumbnail_quality | 0 (= 85) | JPEG quality of the preview. |
source_name, source_width, source_height, source_scale | unknown | Origin of the picture, stored in the header. The library cannot know these; set them if you reduced the picture before encoding. |
chunks, chunk_count | none | Additional metadata entries. |
progress, progress_user | none | Callback that receives the progress from 0 to 1. |
| Field | Default | Meaning |
|---|---|---|
scale_num, scale_den | 1, 1 | Render at scale_num / scale_den of the coded size. scale_num 1 to 16. |
out_width, out_height | 0 | Output size in pixels. One of them keeps the shape; both fill the box and trim the excess. |
deblock | −1 | Edge filter strength; −1 = recommendation in the file. |
max_iterations, convergence | 0 | Maximum reconstruction rounds and stop threshold. 0 = use the file's recommendation, else the defaults 16 and 0.5. |
max_pixels | 0 (= 228) | Safety limit for the decoded size. |
threads | 0 | 0 = half of the processor cores. |
| Status | Meaning |
|---|---|
FIF_OK | Success. |
FIF_ERR_ARG | Invalid argument, or the requested item does not exist. |
FIF_ERR_IO | A file could not be read or written. |
FIF_ERR_FORMAT | The data is not a valid FIF2 file, or is from an unsupported container version. |
FIF_ERR_NOMEM | Out of memory. |
FIF_ERR_UNSUPPORTED | Valid request that this build cannot serve, e.g. JPEG without libjpeg, or an enlargement beyond 16×. |
FIF_ERR_TOO_LARGE | The decoded picture would exceed max_pixels. |
Encoding and decoding use several threads internally. The functions can also
be called from several threads at the same time, each on its own data. The one
exception is the context training interface
(fif_context_training_*), which is meant for building the codec
itself and is not thread-safe.
©2026 By Oskar Behzadpour & Rezar Behzad | FIF v2 Format created by Rezar Behzad