### Build and Install ImageQuant with cargo-c Source: https://github.com/imageoptim/libimagequant/blob/main/README.md Use cargo-c to build and install the ImageQuant dynamic library system-wide. This ensures a correct pkg-config file is generated. ```bash rustup update cd imagequant-sys cargo install cargo-c cargo cinstall --prefix=/usr/local --destdir=. ``` -------------------------------- ### Quantization Quality Workflow Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Example demonstrating how to use liq_get_quantization_quality to limit quality options presented to a user. ```c liq_attr *attr = liq_attr_create(); liq_image *img = liq_image_create_rgba(…); liq_result *res; liq_image_quantize(img, attr, &res); int max_attainable_quality = liq_get_quantization_quality(res); printf("Please select quality between 0 and %d: ", max_attainable_quality); int user_selected_quality = prompt(); if (user_selected_quality < max_attainable_quality) { liq_set_quality(user_selected_quality, 0); liq_result_destroy(res); liq_image_quantize(img, attr, &res); } liq_write_remapped_image(…); ``` -------------------------------- ### Build libimagequant-sys in C Source: https://github.com/imageoptim/libimagequant/blob/main/README.md Build the libimagequant-sys Rust package to obtain a static C library. Ensure Rust is installed and updated. ```bash rustup update git clone https://github.com/ImageOptim/libimagequant cd libimagequant/imagequant-sys cargo build --release --target-dir=target # makes target/release/libimagequant_sys.a ``` -------------------------------- ### Build dynamic C library with cargo-c Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Install cargo-c and use it to build a dynamic C library (DLL, so, dylib) for libimagequant. This command generates the dynamic library files in a specified destination directory. ```bash cargo install cargo-c cd imagequant-sys cargo cinstall --destdir=. ``` -------------------------------- ### Build libimagequant-sys static library Source: https://github.com/imageoptim/libimagequant/blob/main/README.md Build the static C library for libimagequant-sys using Cargo. This command assumes Rust is installed and updated. The output is a .a file in the target/release directory. ```bash rustup update cd imagequant-sys cargo build --release ``` -------------------------------- ### Get Minimum Posterization Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Retrieves the minimum posterization setting previously set by liq_set_min_posterization(). ```c int liq_get_min_posterization(liq_attr* attr); ``` -------------------------------- ### Get Library Version Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Returns the library version as an integer. ```c int liq_version(); ``` -------------------------------- ### C API Usage for ImageQuant Source: https://context7.com/imageoptim/libimagequant/llms.txt Example C code demonstrating the usage of the libimagequant C API for image quantization. This includes creating attributes, setting quality and speed, creating an image, quantizing, and retrieving palette information. ```c // Example C code using libimagequant #include "libimagequant.h" #include #include int main() { // Create attribute handle liq_attr *attr = liq_attr_create(); liq_set_quality(attr, 70, 99); liq_set_speed(attr, 4); // Create image (your_rgba_pixels is width*height*4 bytes) int width = 100, height = 100; unsigned char *rgba_pixels = malloc(width * height * 4); // ... fill rgba_pixels with your image data ... liq_image *image = liq_image_create_rgba(attr, rgba_pixels, width, height, 0.0); // Quantize liq_result *result; liq_error err = liq_image_quantize(image, attr, &result); if (err == LIQ_OK) { // Set dithering liq_set_dithering_level(result, 1.0); // Get palette const liq_palette *palette = liq_get_palette(result); printf("Palette has %d colors\n", palette->count); // Remap image to palette indices unsigned char *indexed_pixels = malloc(width * height); liq_write_remapped_image(result, image, indexed_pixels, width * height); // Get quality metrics printf("Quality: %d%%\n", liq_get_quantization_quality(result)); free(indexed_pixels); liq_result_destroy(result); } liq_image_destroy(image); liq_attr_destroy(attr); free(rgba_pixels); return 0; } ``` -------------------------------- ### Get Minimum Posterization Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Retrieves the current minimum posterization setting. ```APIDOC ## liq_get_min_posterization ### Description Returns the value set by `liq_set_min_posterization()`. ### Method `int liq_get_min_posterization(liq_attr* attr);` ### Parameters #### Path Parameters - **attr** (liq_attr*) - Required - Pointer to the quantization attribute structure. ### Returns An integer representing the current minimum posterization setting. ``` -------------------------------- ### Build libimagequant-sys for Android Source: https://github.com/imageoptim/libimagequant/blob/main/README.md Cross-compile the libimagequant-sys static library for Android's aarch64 architecture. Ensure you have the necessary Rust target installed. ```bash rustup target add aarch64-linux-android cargo build --release --target aarch64-linux-android ``` -------------------------------- ### Add imagequant to Cargo.toml Source: https://github.com/imageoptim/libimagequant/blob/main/README.md Add the imagequant Rust package as a dependency to your project's Cargo.toml file. This command assumes Rust is installed and updated. ```bash rustup update cargo add imagequant ``` -------------------------------- ### Get Image Metadata Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Retrieves width, height, and gamma information from the image or result. ```c int liq_image_get_width(const liq_image *img); int liq_image_get_height(const liq_image *img); double liq_get_output_gamma(const liq_result *result); ``` -------------------------------- ### Get Remapping Quality Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Returns quantization error as a quality value in the 0-100 range. ```c double liq_get_remapping_quality(liq_result *result); ``` -------------------------------- ### Get Quantization Speed Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Retrieves the currently set quantization speed. ```APIDOC ## liq_get_speed ### Description Returns the value set by `liq_set_speed()`. ### Method `int liq_get_speed(liq_attr* attr);` ### Parameters #### Path Parameters - **attr** (liq_attr*) - Required - Pointer to the quantization attribute structure. ### Returns An integer representing the current speed setting. ``` -------------------------------- ### Get Quantization Speed Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Retrieves the current quantization speed setting previously set by liq_set_speed(). ```c int liq_get_speed(liq_attr* attr); ``` -------------------------------- ### Get Palette Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Retrieves the optimized palette from a `liq_result` object. This palette can be improved during the remapping process. ```APIDOC ## GET /imageoptim/libimagequant/palette ### Description Returns a pointer to the palette that has been optimized for the image. This palette can be further refined during the remapping process. ### Method GET ### Endpoint /imageoptim/libimagequant/palette ### Parameters #### Path Parameters None #### Query Parameters - **result** (liq_result *) - Required - Pointer to the quantization result. ### Request Example ```c const liq_palette *pal = liq_get_palette(result); ``` ### Response #### Success Response (200) - **palette** (liq_palette *) - A pointer to the optimized palette. `palette->count` indicates the number of colors (up to 256), and `palette->entries[n]` contains the RGBA value for the nth color. The palette is temporary and read-only. #### Response Example ```json { "palette": { "count": 256, "entries": [ {"r": 255, "g": 0, "b": 0, "a": 255}, ... ] } } ``` #### Error Response (400) - **error** (string) - Indicates `NULL` if an error occurred. ``` -------------------------------- ### Perform Image Quantization in C Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Demonstrates the standard workflow for quantizing an RGBA image, including attribute creation, quantization, remapping, and memory cleanup. ```c /* See imagequant-sys/example.c for the full code! */ #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); ``` -------------------------------- ### Create library attributes Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Initializes the object holding library settings. Must be freed with liq_attr_destroy(). ```c liq_attr* liq_attr_create(void); ``` -------------------------------- ### Build dynamic library with cdylib Source: https://github.com/imageoptim/libimagequant/blob/main/README.md Build a dynamic library (SO, DYLIB, DLL) by adding 'cdylib' to the crate-type in imagequant-sys/Cargo.toml. This is a less recommended approach for application developers. ```bash cargo build --release ``` -------------------------------- ### liq_attr_create Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Creates an object that holds initial settings for the library. ```APIDOC ## liq_attr* liq_attr_create(void) ### Description Returns an object that will hold initial settings (attributes) for the library. The object should be freed using liq_attr_destroy() after it's no longer needed. ### Returns - **liq_attr*** - Pointer to the attributes object, or NULL if the library cannot run on the current machine. ``` -------------------------------- ### Log Callback Configuration Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Functions for setting up log and flush callbacks to report library status or errors. ```c void liq_set_log_callback(liq_attr*, liq_log_callback_function*, void *user_info); ``` ```c void log_callback_function(const liq_attr*, const char *message, void *user_info) {} ``` ```c void liq_set_log_flush_callback(liq_attr*, liq_log_flush_callback_function*, void *user_info); ``` ```c void log_flush_callback_function(const liq_attr*, void *user_info) {} ``` -------------------------------- ### Progress Callback Configuration Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Functions for tracking quantization and remapping progress, with the ability to abort operations. ```c void liq_set_progress_callback(liq_attr*, liq_progress_callback_function*, void *user_info); void liq_result_set_progress_callback(liq_result*, liq_progress_callback_function*, void *user_info); ``` ```c int progress_callback_function(const liq_attr*, float progress_percent, void *user_info) {} ``` -------------------------------- ### Build static C library with Rust Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Build the static C library for libimagequant by navigating to the imagequant-sys directory and running cargo build. This produces a .a or .lib file for static linking. ```bash cd imagequant-sys cargo build --release ``` -------------------------------- ### Image Creation Source: https://context7.com/imageoptim/libimagequant/llms.txt Describes how to initialize image data for quantization using various ownership models. ```APIDOC ## Image Creation ### Description The `Image` struct describes image dimensions and pixel data for quantization. Several methods are available for different ownership models. ### Methods - **new_image(pixels, width, height, gamma)** - Creates an image by moving ownership of pixels. - **new_image_borrowed(pixels, width, height, gamma)** - Creates an image by borrowing pixels (zero-copy). - **new_image_stride(pixels, width, height, stride, gamma)** - Creates an image with stride for padding or subregions. ``` -------------------------------- ### Quantize an image with libimagequant Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Use liq_image_quantize to perform quantization. The result pointer must be passed by reference to receive the output object. ```c liq_result *result; if (LIQ_OK == liq_image_quantize(img, attr, &result)) { // Note &result // result pointer is valid here } ``` -------------------------------- ### Create Images for Quantization in Rust Source: https://context7.com/imageoptim/libimagequant/llms.txt Initialize Image objects using various ownership models, including moving pixel data, borrowing, or specifying strides for padded images. ```rust use imagequant::{Attributes, Image, RGBA}; fn main() -> Result<(), imagequant::Error> { let attr = Attributes::new(); // Create image by moving ownership of pixels (no copy) let pixels: Vec = vec![RGBA { r: 100, g: 150, b: 200, a: 255 }; 100 * 100]; let mut img = attr.new_image(pixels, 100, 100, 0.0)?; // Create image by borrowing pixels (zero-copy, but image lifetime is tied to pixels) let borrowed_pixels: Vec = vec![RGBA::new(50, 100, 150, 255); 50 * 50]; let img_borrowed = attr.new_image_borrowed(&borrowed_pixels, 50, 50, 0.0)?; // Create image with stride (for images with padding or subregions) let padded_pixels: Vec = vec![RGBA::new(0, 0, 0, 255); 120 * 100]; let img_stride = attr.new_image_stride(padded_pixels, 100, 100, 120, 0.0)?; // Image dimensions println!("Image: {}x{}", img.width(), img.height()); Ok(()) } ``` -------------------------------- ### Perform Basic Quantization in Rust Source: https://context7.com/imageoptim/libimagequant/llms.txt Execute the quantization process on an image, apply dithering, and retrieve the resulting palette and indexed pixel data. ```rust use imagequant::{Attributes, RGBA}; fn main() -> Result<(), imagequant::Error> { let width = 100; let height = 100; // Create sample image with gradient let mut pixels = Vec::with_capacity(width * height); for y in 0..height { for x in 0..width { pixels.push(RGBA { r: (x * 255 / width) as u8, g: (y * 255 / height) as u8, b: 128, a: 255, }); } } // Configure and quantize let mut attr = Attributes::new(); attr.set_speed(5)?; attr.set_quality(70, 99)?; let mut img = attr.new_image(pixels, width, height, 0.0)?; let mut result = attr.quantize(&mut img)?; // Set dithering level (0.0 = none, 1.0 = full) result.set_dithering_level(1.0)?; // Get remapped image and palette let (palette, indexed_pixels) = result.remapped(&mut img)?; println!("Palette has {} colors", palette.len()); println!("Quality: {}%", result.quantization_quality().unwrap_or(0)); println!("Indexed image has {} pixels", indexed_pixels.len()); Ok(()) } ``` -------------------------------- ### Callback Management Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Functions to set up logging and progress callbacks for library operations. ```APIDOC ## void liq_set_log_callback(liq_attr*, liq_log_callback_function*, void *user_info) ## void liq_set_progress_callback(liq_attr*, liq_progress_callback_function*, void *user_info) ### Description Sets up callback functions for logging status/errors and tracking image processing progress. The progress callback can abort operations by returning 0. ### Parameters - **user_info** (void*) - Optional user-defined data passed to the callback. ``` -------------------------------- ### Configure Remapping Options Source: https://context7.com/imageoptim/libimagequant/llms.txt Adjust dithering levels and output gamma to influence the final visual quality of the remapped image. ```rust use imagequant::{Attributes, RGBA}; fn main() -> Result<(), imagequant::Error> { let attr = Attributes::new(); let pixels = vec![RGBA::new(100, 150, 200, 255); 200 * 200]; let mut img = attr.new_image(pixels, 200, 200, 0.0)?; let mut result = attr.quantize(&mut img)?; // Set dithering level: 0.0 = no dithering, 1.0 = full dithering result.set_dithering_level(0.8)?; // Set output gamma (default is sRGB ~0.45455) result.set_output_gamma(0.45455)?; // Get quality metrics println!("Output gamma: {}", result.output_gamma()); println!("Quantization quality: {:?}", result.quantization_quality()); println!("Quantization error (MSE): {:?}", result.quantization_error()); // Remap to palette let (palette, pixels) = result.remapped(&mut img)?; // After remapping, can get remapping-specific quality println!("Remapping quality: {:?}", result.remapping_quality()); println!("Remapping error (MSE): {:?}", result.remapping_error()); Ok(()) } ``` -------------------------------- ### Working with GIF Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Guidelines for using the library with GIF images, including transparency handling and animated GIFs. ```APIDOC ## Working with GIF The library can generate palettes for GIF images. To ensure correct transparency is used you need to preprocess the image yourself and replace alpha values other than 0 or 255 with one of these. For animated GIFs see `liq_image_set_background()` which remaps images for GIF's "keep" frame disposal method. See [gif.ski](https://gif.ski). ``` -------------------------------- ### Perform quantization Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Generates a palette based on the provided image and attribute settings. ```c liq_error liq_image_quantize(liq_image *const input_image, liq_attr *const attr, liq_result **out_result); ``` -------------------------------- ### Build smaller static library with trimmed std Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Build a smaller static library by using a trimmed version of the Rust standard library. This requires nightly Rust and specific cargo build flags. ```bash rustup default nightly rustup update cargo clean cargo +nightly build --release -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort ``` -------------------------------- ### Create image objects Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Creates image objects for quantization from raw RGBA pixels or row pointers. Pixels must remain valid until the image object is destroyed. ```c liq_image *liq_image_create_rgba(liq_attr *attr, void* pixels, int width, int height, double gamma); ``` ```c liq_image *liq_image_create_rgba_rows(liq_attr *attr, void* rows[], int width, int height, double gamma); ``` ```c unsigned char *bitmap = …; void *rows = malloc(height * sizeof(void*)); int bytes_per_row = width * 4 + padding; // stride for(int i=0; i < height; i++) { rows[i] = bitmap + i * bytes_per_row; } liq_image *img = liq_image_create_rgba_rows(attr, rows, width, height, 0); // … liq_image_destroy(img); free(rows); ``` -------------------------------- ### Cross-compilation Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Instructions for cross-compiling the library for different platforms, including WASM and Android. ```APIDOC ## Cross-compilation You can compile the library for other platforms via `cargo build --target=…`. See `rustup target list` for the list of platforms. When compiling for WASM, you need to disable default features of this library (compile with `--no-default-features` flag). Otherwise it will use mult-threading, which requires [special handling in WASM](https://github.com/RReverser/wasm-bindgen-rayon). If you're cross-compiling a dynamic library (so/dylib/DLL), you may need to [configure a linker](https://doc.rust-lang.org/cargo/reference/config.html#target) for Cargo. For building for Android see [this tutorial](https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-21-rust-on-android.html) and [cargo-ndk](https://lib.rs/crates/cargo-ndk). ``` -------------------------------- ### Monitor Quantization Progress Source: https://context7.com/imageoptim/libimagequant/llms.txt Use progress and log callbacks to track status or abort the quantization process via an atomic flag. ```rust use imagequant::{Attributes, ControlFlow, RGBA}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; fn main() -> Result<(), imagequant::Error> { let mut attr = Attributes::new(); // Track if we should cancel let should_cancel = Arc::new(AtomicBool::new(false)); let cancel_flag = should_cancel.clone(); // Set progress callback attr.set_progress_callback(move |progress_percent| { println!("Progress: {:.1}%", progress_percent); if cancel_flag.load(Ordering::Relaxed) { ControlFlow::Break // Abort processing } else { ControlFlow::Continue } }); // Set logging callback attr.set_log_callback(|_attr, message| { println!("Log: {}", message); }); let pixels = vec![RGBA::new(100, 150, 200, 255); 500 * 500]; let mut img = attr.new_image(pixels, 500, 500, 0.0)?; match attr.quantize(&mut img) { Ok(result) => println!("Completed with quality {}%", result.quantization_quality().unwrap_or(0)), Err(imagequant::Error::Aborted) => println!("Cancelled by user"), Err(e) => return Err(e), } Ok(()) } ``` -------------------------------- ### Attributes Configuration Source: https://context7.com/imageoptim/libimagequant/llms.txt Configures the quantization settings such as quality, speed, and palette constraints. ```APIDOC ## Attributes Configuration ### Description The `Attributes` struct is the starting point for all quantization operations, holding configuration settings for speed, quality, and other parameters. ### Methods - **set_quality(min, target)** - Sets the quality range (0-100). - **set_speed(speed)** - Sets the speed (1-10, lower is better quality). - **set_max_colors(count)** - Limits the maximum number of colors in the palette. - **set_min_posterization(level)** - Sets posterization level for retro platforms. - **set_last_index_transparent(bool)** - Configures transparency index placement. ``` -------------------------------- ### Create Image with Custom Callback Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Creates an image object that uses a callback function to read image data, enabling on-the-fly conversion from non-RGBA formats. The callback receives a row buffer and must fill it with RGBA pixels. Caching within the callback is discouraged. ```c liq_image *liq_image_create_custom(liq_attr *attr, liq_image_get_rgba_row_callback *row_callback, void *user_info, int width, int height, double gamma); ``` ```c void image_get_rgba_row_callback(liq_color row_out[], int row_index, int width, void *user_info) { for(int column_index=0; column_index < width; column_index++) { row_out[column_index] = /* generate pixel at (row_index, column_index) */; } } ``` ```c void rgb_to_rgba_callback(liq_color row_out[], int row_index, int width, void *user_info) { unsigned char *rgb_row = ((unsigned char *)user_info) + 3*width*row_index; for(int i=0; i < width; i++) { row_out[i].r = rgb_row[i*3]; row_out[i].g = rgb_row[i*3+1]; row_out[i].b = rgb_row[i*3+2]; row_out[i].a = 255; } } liq_image *img = liq_image_create_custom(attr, rgb_to_rgba_callback, rgb_bitmap, width, height, 0); ``` -------------------------------- ### Handle ImageQuant Errors in Rust Source: https://context7.com/imageoptim/libimagequant/llms.txt Demonstrates how to handle various error types returned by the imagequant crate, including quality issues, invalid parameters, and memory errors. Ensure proper error checking for robust image processing. ```rust use imagequant::{Attributes, Error, RGBA}; fn main() { let mut attr = Attributes::new(); // QualityTooLow: minimum quality couldn't be achieved attr.set_quality(99, 100).unwrap(); // Very strict quality let pixels = vec![RGBA::new(0, 0, 0, 255); 10 * 10]; let mut img = attr.new_image(pixels, 10, 10, 0.0).unwrap(); // This might fail if quality can't be met match attr.quantize(&mut img) { Ok(result) => println!("Success!"), Err(Error::QualityTooLow) => println!("Image too complex for requested quality"), Err(Error::ValueOutOfRange) => println!("Invalid parameter value"), Err(Error::OutOfMemory) => println!("Not enough memory"), Err(Error::Aborted) => println!("Cancelled by progress callback"), Err(Error::BufferTooSmall) => println!("Output buffer too small"), Err(Error::InvalidPointer) => println!("NULL pointer (C API)"), Err(Error::Unsupported) => println!("Unsupported operation"), Err(Error::InternalError) => println!("Internal error"), #[cfg(feature = "_internal_c_ffi")] Err(Error::LIQ_OK) => unreachable!(), } // Parameter validation assert!(attr.set_speed(0).is_err()); // Must be 1-10 assert!(attr.set_speed(11).is_err()); // Must be 1-10 assert!(attr.set_quality(80, 70).is_err()); // min > max } ``` -------------------------------- ### Multiple Images with Same Palette Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md This section demonstrates how to generate a single palette that is optimal for multiple images by collecting statistics into a `liq_histogram` object. ```APIDOC ## Multiple images with the same palette It's possible to efficiently generate a single palette that is optimal for multiple images, e.g. for an APNG animation. This is done by collecting statistics of images in a `liq_histogram` object. ```c 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 } ``` ``` -------------------------------- ### Configure Quantization Attributes in Rust Source: https://context7.com/imageoptim/libimagequant/llms.txt Initialize and configure quantization parameters such as quality range, speed, and color limits using the Attributes struct. ```rust use imagequant::{Attributes, RGBA}; fn main() -> Result<(), imagequant::Error> { // Create new attributes with default settings let mut attr = imagequant::new(); // Or equivalently let mut attr = Attributes::new(); // Configure quality range (0-100, like JPEG) // Minimum quality: abort if can't achieve this // Target quality: aim for this quality level attr.set_quality(70, 99)?; // Set speed 1-10 (lower = better quality, slower) attr.set_speed(4)?; // Limit maximum colors in palette attr.set_max_colors(256)?; // Set posterization for retro platforms (VGA, 15-bit textures) attr.set_min_posterization(0)?; // Put transparent color at end of palette (for some broken software) attr.set_last_index_transparent(false); println!("Speed: {}, Max colors: {}", attr.speed(), attr.max_colors()); Ok(()) } ``` -------------------------------- ### Configure quantization quality Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Sets the quality range from 0 to 100. The library attempts to meet the maximum quality while staying within the minimum. ```c liq_error liq_set_quality(liq_attr* attr, int minimum, int maximum); ``` ```c liq_attr *attr = liq_attr_create(); liq_set_quality(attr, 50, 80); // use quality 80 if possible. Give up if quality drops below 50. ``` ```c int liq_get_min_quality(liq_attr* attr); ``` ```c int liq_get_max_quality(liq_attr* attr); ``` -------------------------------- ### liq_image_quantize Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Performs the quantization process. ```APIDOC ## liq_error liq_image_quantize(liq_image *const input_image, liq_attr *const attr, liq_result **out_result) ### Description Performs quantization (palette generation) based on settings in attr and pixels of the image. ### Parameters - **input_image** (liq_image*) - Required - The input image object. - **attr** (liq_attr*) - Required - The attributes object. - **out_result** (liq_result**) - Required - Pointer to store the resulting quantization result. ``` -------------------------------- ### Add imagequant to Cargo.toml Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Add this to your Cargo.toml file to include the imagequant library as a dependency for your Rust project. ```toml [dependencies] imagequant = "4.4" ``` -------------------------------- ### Quantize Histogram to Generate Palette Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Generates a palette from the collected histogram data. On success, it returns `LIQ_OK` and a `liq_result` pointer. Returns `LIQ_QUALITY_TOO_LOW` if the palette quality is below the set limit. A histogram can only be quantized once. ```c liq_error liq_histogram_quantize(liq_histogram *const hist, liq_attr *const attr, liq_result **out_result); if (LIQ_OK == err) { // Use result here to remap and get palette } ``` -------------------------------- ### Create Histogram Object Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Initializes a histogram object for collecting color statistics from multiple images. This object must be freed using `liq_histogram_destroy()`. All `liq_attr` options should be set prior to creation. ```c liq_histogram *liq_histogram_create(liq_attr *attr); ``` -------------------------------- ### Optimize GIF Animation with Background Images Source: https://context7.com/imageoptim/libimagequant/llms.txt Optimize transparency in GIF animations by setting a background image. Pixels in the current frame that match the background will be rendered as transparent, reducing file size. ```rust use imagequant::{Attributes, RGBA}; fn main() -> Result<(), imagequant::Error> { let attr = Attributes::new(); let width = 100; let height = 100; // Previous frame (background) let bg_pixels = vec![RGBA::new(200, 200, 200, 255); width * height]; let background = attr.new_image(bg_pixels, width, height, 0.0)?; // Current frame let frame_pixels = vec![RGBA::new(100, 150, 200, 255); width * height]; let mut frame = attr.new_image(frame_pixels, width, height, 0.0)?; // Pixels matching background will be made transparent frame.set_background(background)?; let mut result = attr.quantize(&mut frame)?; result.set_dithering_level(0.8)?; let (palette, pixels) = result.remapped(&mut frame)?; println!("Frame optimized with {} colors", palette.len()); Ok(()) } ``` -------------------------------- ### Set Minimum Posterization Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Ignores the least significant bits in all color channels, posterizing the image to 2^bits levels. Use 0 for full quality, 2 for VGA displays, or 4 for RGB444/RGBA4444 displays. Values outside 0-4 return LIQ_VALUE_OUT_OF_RANGE. ```c liq_set_min_posterization(liq_attr* attr, int bits); ``` -------------------------------- ### Utility Functions Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md General utility functions for versioning and image metadata. ```APIDOC ## int liq_version() ### Description Returns the library version as an integer. ## int liq_image_get_width(const liq_image *img) ## int liq_image_get_height(const liq_image *img) ### Description Getters for image dimensions. Returns -1 if the input is invalid. ``` -------------------------------- ### Implement Custom Row Callback Source: https://context7.com/imageoptim/libimagequant/llms.txt Use a callback to generate pixel rows on-the-fly, which is useful for memory-efficient processing or direct format conversion. ```rust use imagequant::{Attributes, Image, RGBA}; use std::mem::MaybeUninit; fn main() -> Result<(), imagequant::Error> { let attr = Attributes::new(); let width = 100; let height = 100; // Create image with row callback (useful for format conversion) // SAFETY: callback must initialize all pixels in the output row let mut img = unsafe { Image::new_fn(&attr, |output_row, row_index| { // Generate row on-demand for (col, pixel) in output_row.iter_mut().enumerate() { pixel.write(RGBA { r: (col * 255 / 100) as u8, g: (row_index * 255 / 100) as u8, b: 128, a: 255, }); } }, width, height, 0.0)? }; let mut result = attr.quantize(&mut img)?; let (palette, pixels) = result.remapped(&mut img)?; println!("Processed with callback: {} colors", palette.len()); Ok(()) } ``` -------------------------------- ### liq_image_set_background Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Sets a background image to improve transparency quality during remapping. ```APIDOC ## liq_image_set_background ### Description Analyze and remap this image with the assumption that it will be presented on top of the specified background image. This is useful for improving quality in animated GIFs. ### Method C Function ### Parameters - **image** (liq_image*) - Required - The foreground image object. - **background_image** (liq_image*) - Required - The background image object. ### Response - **liq_error** - Returns LIQ_BUFFER_TOO_SMALL if the background image has a different size than the foreground. ``` -------------------------------- ### Quantization Process Source: https://context7.com/imageoptim/libimagequant/llms.txt Performs color quantization and retrieves the resulting palette and indexed pixels. ```APIDOC ## Quantization Process ### Description The `quantize()` method performs color quantization on an image, returning a `QuantizationResult` containing the optimized palette. ### Methods - **quantize(image)** - Performs the quantization process. - **set_dithering_level(level)** - Sets the dithering level (0.0 to 1.0). - **remapped(image)** - Returns the palette and indexed pixels for the quantized image. ``` -------------------------------- ### liq_image_create_rgba Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Creates an image object from a contiguous RGBA pixel array. ```APIDOC ## liq_image *liq_image_create_rgba(liq_attr *attr, void* pixels, int width, int height, double gamma) ### Description Creates an object that represents the image pixels to be used for quantization and remapping. ### Parameters - **attr** (liq_attr*) - Required - Attributes object. - **pixels** (void*) - Required - Contiguous run of RGBA pixels. - **width** (int) - Required - Image width. - **height** (int) - Required - Image height. - **gamma** (double) - Required - Gamma correction value (0 for default 1/2.2). ### Returns - **liq_image*** - Pointer to the image object, or NULL on failure. ``` -------------------------------- ### Attribute and Image Management Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Functions for creating, copying, and configuring image attributes and fixed colors. ```APIDOC ## liq_attr* liq_attr_copy(liq_attr *orig) ### Description Creates an independent copy of liq_attr. The copy must be freed using liq_attr_destroy(). ## liq_error liq_image_add_fixed_color(liq_image* img, liq_color color) ### Description Reserves a color in the output palette. Must be called before quantization. Returns an error if more than 256 colors are added. ``` -------------------------------- ### Quality and Remapping Functions Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Functions to retrieve quantization quality and remapping quality metrics. ```APIDOC ## double liq_get_remapping_quality(liq_result *result) ### Description Returns the quantization error as a quality value in the 0-100 range, analogous to liq_get_remapping_error(). ### Response - **quality** (double) - Quality value between 0 and 100. ``` -------------------------------- ### Multithreading Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Information on how the library handles multithreading for parallel processing. ```APIDOC ## Multithreading * Different threads can perform unrelated quantizations/remappings at the same time (e.g. each thread working on a different image). * The same `liq_attr`, `liq_result`, etc. can be accessed from different threads, but not at the same time (e.g. you can create `liq_attr` in one thread and free it in another). * By default, this library uses threads internally. You can set `RAYON_NUM_THREADS` environmental variable to control the number of threads used. You can disable threads completely by compiling with `--no-default-features`. ``` -------------------------------- ### Create Image with Custom Callback Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Creates an image object that uses a callback function to read or generate image data. This is useful for on-the-fly conversion of images not in RGBA format. ```APIDOC ## liq_image_create_custom ### Description Creates image object that will use callback to read image data. This allows on-the-fly conversion of images that are not in the RGBA color space. The callback must read/generate `row_index`-th row and write its RGBA pixels to the `row_out` array. Row `width` is given for convenience and will always equal to image width. The callback will be called multiple times for each row. Quantization and remapping require at least two full passes over image data, so caching of callback's work makes no sense — in such case it's better to convert entire image and use `liq_image_create_rgba()` instead. Example callback for RGB to RGBA conversion: ```c void rgb_to_rgba_callback(liq_color row_out[], int row_index, int width, void *user_info) { unsigned char *rgb_row = ((unsigned char *)user_info) + 3*width*row_index; for(int i=0; i < width; i++) { row_out[i].r = rgb_row[i*3]; row_out[i].g = rgb_row[i*3+1]; row_out[i].b = rgb_row[i*3+2]; row_out[i].a = 255; } } ``` ### Method `liq_image *liq_image_create_custom(liq_attr *attr, liq_image_get_rgba_row_callback *row_callback, void *user_info, int width, int height, double gamma);` ### Parameters #### Path Parameters - **attr** (liq_attr*) - Required - Pointer to the quantization attribute structure. - **row_callback** (liq_image_get_rgba_row_callback*) - Required - Pointer to the callback function that provides image rows. - **user_info** (void*) - Optional - User-provided data to be passed to the callback. - **width** (int) - Required - The width of the image in pixels. - **height** (int) - Required - The height of the image in pixels. - **gamma** (double) - Optional - The gamma correction value for the image. Use 0 for default. ### Returns A pointer to the created `liq_image` object, or NULL on failure. ``` -------------------------------- ### Image Quantization Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Quantizes an image and returns the result. It can return LIQ_OK on success or LIQ_QUALITY_TOO_LOW if the quality limit is not met. ```APIDOC ## POST /imageoptim/libimagequant/quantize ### Description Quantizes an image using the provided attributes and stores the result in the `out_result` pointer. Success is indicated by `LIQ_OK`. ### Method POST ### Endpoint /imageoptim/libimagequant/quantize ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **img** (liq_image *) - The input image to quantize. - **attr** (liq_attr *) - Attributes for quantization. - **out_result** (liq_result **) - Pointer to receive the quantization result. ### Request Example ```c liq_result *result; if (LIQ_OK == liq_image_quantize(img, attr, &result)) { // result pointer is valid here } ``` ### Response #### Success Response (200) - **result** (liq_result *) - A pointer to the quantization result if successful. #### Response Example ```json { "status": "LIQ_OK" } ``` #### Error Response (400) - **error** (string) - Indicates `LIQ_QUALITY_TOO_LOW` if quantization fails due to quality limits. ``` -------------------------------- ### Add Fixed Colors Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Reserves specific colors in the output palette; must be called before quantization. ```c liq_error liq_image_add_fixed_color(liq_image* img, liq_color color); liq_error liq_histogram_add_fixed_color(liq_histogram* hist, liq_color color, double gamma); ``` -------------------------------- ### Configure maximum colors Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Sets the maximum number of colors allowed. Returns LIQ_VALUE_OUT_OF_RANGE if the value is outside 2-256. ```c liq_error liq_set_max_colors(liq_attr* attr, int colors); ``` ```c int liq_get_max_colors(liq_attr* attr); ``` -------------------------------- ### Create Shared Palette for Multiple Images Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Collect color statistics from multiple images into a histogram to generate a single, optimal palette for all of them. Ensure `liq_attr` options are set before creating the histogram. ```c 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 } ``` -------------------------------- ### Create Importance Map for Pixel Prioritization Source: https://context7.com/imageoptim/libimagequant/llms.txt Utilize importance maps to specify which pixels should be better represented in the generated palette. Higher values in the map indicate greater importance for those pixels. ```rust use imagequant::{Attributes, RGBA}; fn main() -> Result<(), imagequant::Error> { let attr = Attributes::new(); let width = 100; let height = 100; let pixels = vec![RGBA::new(100, 150, 200, 255); width * height]; let mut img = attr.new_image(pixels, width, height, 0.0)?; // Create importance map (same size as image) // Higher values = more important pixels let mut importance_map = vec![128u8; width * height]; // Make center region more important for y in 25..75 { for x in 25..75 { importance_map[y * width + x] = 255; } } // Apply importance map img.set_importance_map(importance_map)?; let mut result = attr.quantize(&mut img)?; println!("Quality: {}%", result.quantization_quality().unwrap_or(0)); Ok(()) } ``` -------------------------------- ### Quantization Metrics Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Functions to retrieve quantization and remapping error metrics. ```APIDOC ## Quantization Metrics ### Description Functions to retrieve mean square error (MSE) or quality scores for quantization and remapping processes. ### Methods - **liq_get_quantization_error(liq_result *result)**: Returns mean square error of quantization. - **liq_get_remapping_error(liq_result *result)**: Returns mean square error of the last remapping. - **liq_get_quantization_quality(liq_result *result)**: Returns quantization error as a 0-100 quality value. ### Response - **double**: Returns the error or quality value, or -1 if the value is not available. ``` -------------------------------- ### Add Colors Directly to Histogram Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md An alternative to `liq_histogram_add_image`, this function directly accepts an array of colors and their counts. It's useful when you already have histogram data from another source. Gamma parameter description is available in `liq_image_create_rgba()`. ```c liq_error liq_histogram_add_colors(liq_histogram *hist, liq_attr *attr, liq_histogram_entry entries[], int num_entries, double gamma); ``` -------------------------------- ### Retrieve optimized palette Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Returns a read-only pointer to the optimized palette. The palette must be copied before the result object is destroyed. ```c const liq_palette *liq_get_palette(liq_result *result); ``` -------------------------------- ### Configure dithering level Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Sets the dithering intensity between 0 and 1. A value of 0 disables dithering for faster processing. ```c liq_error liq_set_dithering_level(liq_result *res, float dither_level); ``` -------------------------------- ### Copy Attributes Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Creates an independent copy of liq_attr that must be freed with liq_attr_destroy. ```c liq_attr* liq_attr_copy(liq_attr *orig); ``` -------------------------------- ### Write remapped image to buffer Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Remaps an image to a palette and writes raw pixel data to a buffer. The buffer must be large enough to hold width * height bytes. ```c liq_error liq_write_remapped_image(liq_result *result, liq_image *input_image, void *buffer, size_t buffer_size); ``` ```c int buffer_size = width*height; char *buffer = malloc(buffer_size); if (LIQ_OK == liq_write_remapped_image(result, input_image, buffer, buffer_size)) { liq_palette *pal = liq_get_palette(result); // save image } ``` -------------------------------- ### Create Attributes with Allocator Source: https://github.com/imageoptim/libimagequant/blob/main/imagequant-sys/README.md Deprecated function for creating attributes with a custom allocator. ```c liq_attr* liq_attr_create_with_allocator(void* (*malloc)(size_t), void (*free)(void*)); ```