libimagequant Documentation

repository·main·Indexed 21 days ago

https://github.com/imageoptim/libimagequant

A high-performance image quantization library that converts 24/32-bit RGBA images into 8-bit indexed palettes with alpha channels. Designed for optimizing PNG and GIF images, it operates on raw uncompressed pixel arrays in memory and does not handle file encoding or decoding. Available as a C library and a Rust crate (imagequant v4.4/4.5.0), it provides tools for configuring quantization quality, speed, dithering, and posterization.

Tokens
14.4K
Snippets
58
Records
69
Agent score
76%

What's inside libimagequant

  1. What is libimagequant?

    main

    libimagequant is an image quantization library that converts RGBA images to palette-based 8-bit indexed images, including the alpha component. It is designed for generating small PNG images and high-quality GIFs.

    Key constraints:

    • No Encoding/Decoding: The library does not handle file formats (like PNG or GIF). It operates exclusively on raw, uncompressed pixel arrays in memory. You must use a separate library (e.g., libpng, lodepng) to decode files into pixels and encode the resulting palette-based pixels back into a file.
    • Input Formats: It primarily works with RGBA data, though custom conversion functions can be provided for other formats.
  2. Configure threads and WASM support

    main

    Multi-threading

    By default, the threads Cargo feature is enabled. You can control the number of threads used by setting the RAYON_NUM_THREADS environment variable.

    WASM (WebAssembly)

    Threads in WASM are experimental and require special handling (e.g., wasm-bindgen-rayon). If you are targeting WASM, it is recommended to disable threads to avoid complexity.

    To disable threads in your Cargo.toml:

    [dependencies]
    imagequant = { version = "4.0", default-features = false }

    If building the library directly via CLI, use:

    --no-default-features
  3. Generate a shared palette for multiple images

    main

    To efficiently generate a single palette that is optimal for multiple images (such as for an APNG animation), use the liq_histogram API. This involves collecting color statistics from all target images into a histogram object before performing quantization.

    1. Create a liq_attr object and a liq_histogram object.
    2. For each image, create a liq_image and add it to the histogram using liq_histogram_add_image.
    3. Call liq_histogram_quantize to generate the shared palette.

    Note: One histogram object can only be quantized once. If you are only processing a single image, use liq_image_quantize() instead for better results.

        liq_attr *attr = liq_attr_create();
        liq_histogram *hist = liq_histogram_create(attr);
    
        liq_image *image1 = liq_image_create_rgba(attr, example_bitmap_rgba1, width, height, 0);
        liq_histogram_add_image(hist, attr, image1);
    
        liq_image *image2 = liq_image_create_rgba(attr, example_bitmap_rgba2, width, height, 0);
        liq_histogram_add_image(hist, attr, image2);
    
        liq_result *result;
        liq_error err = liq_histogram_quantize(attr, hist, &result);
        if (LIQ_OK == err) {
            // result will contain shared palette best for both image1 and image2
        }
  4. Multithreading and WASM configuration

    main

    Multithreading

    • Concurrency: Different threads can perform unrelated quantizations or remappings simultaneously (e.g., processing different images).
    • Thread Safety: Objects like liq_attr and liq_result can be accessed from different threads, but not concurrently (e.g., one thread can create an object and another can free it, but they cannot access it at the exact same time).
    • Control: The library uses threads internally by default. You can control the thread count using the RAYON_NUM_THREADS environment variable.

    WASM and Cross-compilation

    • WASM: When compiling for WebAssembly, you must disable default features using the --no-default-features flag. This prevents the library from attempting to use multithreading, which requires special handling in WASM environments.
    • Cross-compiling: Use cargo build --target=... for other platforms. If building a dynamic library (.so, .dylib, .dll), you may need to configure a linker for Cargo.
  5. C API usage workflow

    main

    The typical lifecycle for using the C API is:

    1. Initialize: Create an attributes object (liq_attr_create) and configure it.
    2. Load Image: Create an image object (liq_image_create_rgba, etc.) from raw RGBA pixels.
    3. Quantize: Perform quantization to generate a palette (liq_image_quantize).
    4. Process Output: Write the remapped image and extract the final palette (liq_write_remapped_image, liq_get_palette).
    5. Cleanup: Free all allocated memory (liq_result_destroy, liq_image_destroy, liq_attr_destroy).

    Error Handling: Functions returning liq_error return LIQ_OK (0) on success and a non-zero value on error. Passing NULL to functions accepting liq_attr, liq_image, or liq_result will return LIQ_INVALID_POINTER.

    #include "libimagequant.h"
    
    liq_attr *attr = liq_attr_create();
    liq_image *image = liq_image_create_rgba(attr, example_bitmap_rgba, width, height, 0);
    liq_result *res;
    liq_image_quantize(image, attr, &res);
    
    liq_write_remapped_image(res, image, example_bitmap_8bpp, example_bitmap_size);
    const liq_palette *pal = liq_get_palette(res);
    
    // Save the image and the palette now.
    for(int i=0; i < pal->count; i++) {
        example_copy_palette_entry(pal->entries[i]);
    }
    // You'll need a PNG library to write to a file.
    example_write_image(example_bitmap_8bpp);
    
    liq_result_destroy(res);
    liq_image_destroy(image);
    liq_attr_destroy(attr);
  6. Build libimagequant as a C dynamic library

    main

    To build a dynamic library (DLL, .so, or .dylib), use the cargo-c helper tool:

    1. Install cargo-c: cargo install cargo-c.
    2. Navigate to imagequant-sys.
    3. Run cargo cinstall --destdir=..

    This will generate the library files in ./usr/local/lib/ (e.g., libimagequant.0.4.so).

    cargo install cargo-c
    cd imagequant-sys
    cargo cinstall --destdir=.
  7. Build libimagequant as a C static library

    main

    To build a static library (.a on Unix, .lib on Windows) for use in C/C++ projects, follow these steps:

    1. Ensure you have Rust 1.80 or later installed via rustup.
    2. Navigate to the imagequant-sys directory.
    3. Run cargo build --release.

    The resulting library will be located in target/release/libimagequant_sys.a or target\release\libimagequant_sys.lib.

    rustup update
    cd imagequant-sys
    cargo build --release
  8. Working with GIF images

    main

    To use libimagequant for GIF generation, follow these requirements:

    1. Transparency: You must preprocess the image to ensure alpha values are strictly either 0 or 255. Any other alpha values must be replaced manually.
    2. Animation: For animated GIFs, use liq_image_set_background() to remap images specifically for the GIF "keep" frame disposal method.
  9. Migrate from imagequant-sys to imagequant (Rust)

    main

    If you are upgrading from v2/v3 (using imagequant-sys) to v4, switch to the high-level imagequant crate.

    Key Changes:

    • Feature Renaming: The openmp Cargo feature is now named threads.
    • Ownership in .new_image(): This method can now take ownership of its argument to avoid copying.
      • If you encounter an error that From<&Vec<RGBA>> is not implemented, you should either move the vector (avoiding the reference) or call .as_slice() to copy the pixels. Alternatively, use the .new_image_borrowed() method.
  10. Use libimagequant in C via imagequant-sys

    main

    To use libimagequant in a C program, you must build the imagequant-sys Rust package, which provides the C interface.

    1. Install Rust via rustup.
    2. Clone the repository.
    3. Build the static library using cargo.

    The resulting static library can be linked into your C/C++ project. The API, ABI, and header files remain compatible with previous C versions.

    rustup update
    git clone https://github.com/ImageOptim/libimagequant
    cd libimagequant/imagequant-sys
    cargo build --release --target-dir=target
    # This produces target/release/libimagequant_sys.a