Using the library

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.

Setting up

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.

Five rules

  1. Every function returns a status. FIF_OK (0) means success; every error is negative. fif_status_string() gives a readable description.
  2. Always start from the defaults. Call 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.
  3. Pictures are 8-bit, interleaved, 1 or 3 channels. A fif_image holds grey or RGB pixels row by row, with an explicit row stride.
  4. Free what the library allocates. Encoded data is released with fif_free(), pictures with fif_image_free().
  5. Views point into your buffer. Functions that inspect a file (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.

Example: encode and decode

#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;
}

Example: inspect a file

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);
}

Functions

Encoding and decoding

fif_status fif_encode(const fif_image *img, const fif_encode_options *opts, uint8_t **out_data, size_t *out_size, fif_stats *stats)
Compresses a picture. On success, *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)
Reconstructs a picture. 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.

Inspecting a file

fif_get_info(data, size, &info)
Reads the header without decoding the picture: size, coding parameters, source name and size, section sizes, checksum status, and the number of bytes needed for a coarse picture (base_prefix_bytes). Cheap and safe on untrusted data.
fif_get_chunk(data, size, index, &chunk)
Returns the metadata entry with the given index. Count up from 0 until the function no longer returns FIF_OK.
fif_get_thumbnail(data, size, index, &thumb)
Returns the stored preview with the given index without decoding it: its format code ("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)
Returns the index of the smallest preview whose longer edge is at least 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)
Returns a preview as pixels. Needs JPEG support in the build.
fif_get_raw(data, size, index, &entry)
Returns an attached file (see the specification, section 7).

Pictures and helpers

fif_image_load(path, &img), fif_image_save(path, &img)
Read and write PNG, JPEG and PNM files. The format follows the file extension. When saving, an extension the build cannot write returns FIF_ERR_UNSUPPORTED.
fif_image_alloc(&img, width, height, channels), fif_image_free(&img)
Allocate and release a picture.
fif_image_downscale(&src, w, h, &dst)
Reduce a picture with an exact area filter.
fif_psnr, fif_ssim, fif_ms_ssim
Quality measures between two pictures of the same size.

Important options

fif_encode_options

FieldDefaultMeaning
quality750 to 100.
effort50 to 9.
subsampling4:2:0FIF_SUBSAMPLING_444, _420 or _400.
target_bpp, target_psnr0 (off)Search the quality that reaches this value.
threads00 = half of the processor cores.
thumbnail_size0Longer edge of the JPEG preview; 0 = none. The encoder writes at most one preview; the format allows more.
thumbnail_quality0 (= 85)JPEG quality of the preview.
source_name, source_width, source_height, source_scaleunknownOrigin of the picture, stored in the header. The library cannot know these; set them if you reduced the picture before encoding.
chunks, chunk_countnoneAdditional metadata entries.
progress, progress_usernoneCallback that receives the progress from 0 to 1.

fif_decode_options

FieldDefaultMeaning
scale_num, scale_den1, 1Render at scale_num / scale_den of the coded size. scale_num 1 to 16.
out_width, out_height0Output size in pixels. One of them keeps the shape; both fill the box and trim the excess.
deblock−1Edge filter strength; −1 = recommendation in the file.
max_iterations, convergence0Maximum reconstruction rounds and stop threshold. 0 = use the file's recommendation, else the defaults 16 and 0.5.
max_pixels0 (= 228)Safety limit for the decoded size.
threads00 = half of the processor cores.

Errors

StatusMeaning
FIF_OKSuccess.
FIF_ERR_ARGInvalid argument, or the requested item does not exist.
FIF_ERR_IOA file could not be read or written.
FIF_ERR_FORMATThe data is not a valid FIF2 file, or is from an unsupported container version.
FIF_ERR_NOMEMOut of memory.
FIF_ERR_UNSUPPORTEDValid request that this build cannot serve, e.g. JPEG without libjpeg, or an enlargement beyond 16×.
FIF_ERR_TOO_LARGEThe decoded picture would exceed max_pixels.

Threads

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