#image #palette #image-conversion #quantization #quant #dither #width-height

sys imagequant-sys

将 24/32 位图像转换为带 alpha 通道的 8 位调色板。是 pngquant 有损 PNG 压缩器的动力源泉 C API/FFI libimagequant。双授权,类似于 pngquant。有关详细信息,请参阅 https://pngquant.org。

12 个稳定版本

4.0.3 2023 年 10 月 13 日
4.0.1 2022 年 11 月 13 日
4.0.0 2022 年 2 月 1 日
3.1.1+sys2.17.02021 年 11 月 22 日
0.1.1 2017 年 6 月 16 日

#2#quant

Download history 38/week @ 2024-04-15 108/week @ 2024-04-22 90/week @ 2024-04-29 38/week @ 2024-05-06 78/week @ 2024-05-13 50/week @ 2024-05-20 26/week @ 2024-05-27 31/week @ 2024-06-03 64/week @ 2024-06-10 77/week @ 2024-06-17 69/week @ 2024-06-24 42/week @ 2024-07-01 38/week @ 2024-07-08 62/week @ 2024-07-15 58/week @ 2024-07-22 30/week @ 2024-07-29

193 每月下载量
用于 2 个 crate(通过 pngquant

GPL-3.0-or-later

230KB
4K SLoC

libimagequant — 图像量化库

Imagequant 库将 RGBA 图像转换为基于调色板的 8 位索引图像,包括 alpha 通道。非常适合生成小巧的 PNG 图像和看起来很棒的 GIF。

库本身不处理图像编码/解码,请自行提供编码器。如果您正在寻找命令行工具,请参阅 pngquant

许可证

Libimagequant 是双授权

  • 对于免费/开源软件,它可在 GPL v3 或更高版本下使用,并附带额外的 版权声明,这是出于历史原因。
  • 对于用于闭源软件、AppStore 分发和其他非 GPL 用途,您可以 获取商业许可证。如果您需要详细信息或定制许可条款,请随时联系 [email protected]

Rust 文档

添加到 Cargo.toml

[dependencies]
imagequant = "4.0"

在 docs.rs 上查看库 API 文档.

C 语言文档

为 C 构建项目

  1. 通过 rustup 安装 Rust 1.60 或更高版本,并运行 rustup update

  2. cdimagequant-sys

    由名为 imagequant-sys 的单独包暴露 C API。

  3. 运行 cargo build --release

    这将构建 target/release/libimagequant_sys.atarget\release\libimagequant_sys.lib,您可以用它进行静态链接。请不用担心 .a 文件的大小。它包含一些未使用的对象。链接时仅增加500KB。请在您的编译器中使用链接时间优化(LTO)选项,并在需要时将 -Wl,--as-needed 添加到链接器标志中。您可以通过使用 cargo +nightly build --target $TARGET_ARCH --release -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort 编译来使二进制文件更小。

仓库包含一个Xcode项目文件,可用于iOS和macOS。

如果您想构建一个C动态库(DLL、so、dylib),则

  1. cargo安装 cargo-c
  2. cdimagequant-sys
  3. cargo cinstall --destdir=. 这将构建 ./usr/local/lib/libimagequant.0.0.0.{so,dylib,dll}

C API 使用

  1. 创建属性对象并配置库。
  2. 从RGBA像素或数据源创建图像对象。
  3. 进行量化(生成调色板)。
  4. 存储重映射的图像和最终调色板。
  5. 释放内存。

请注意,libimagequant只处理内存中未压缩的像素原始数组,并且与任何文件格式完全独立。

/* 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);

返回 liq_error 的函数在成功时返回 LIQ_OK0)并在错误时返回非零值。

可以安全地将 NULL 传递给接受 liq_attrliq_imageliq_result 的任何函数(在这种情况下将返回错误代码 LIQ_INVALID_POINTER)。这些对象可以被重复使用多次。

有三种方法创建用于量化的图像对象

  • liq_image_create_rgba() 用于简单的、连续的RGBA像素数组(宽度×高度×4字节大小的位图)。
  • liq_image_create_rgba_rows() 用于非连续的RGBA像素数组(这些数组在行之间有填充或顺序相反,例如BMP)。
  • liq_image_create_custom() 用于RGB、ABGR、YUV以及其他可以即时转换为RGBA的格式(您必须提供转换函数)。

请注意,这里的“图像”是指原始未压缩的像素。如果您有一个压缩的图像文件,例如PNG,您必须使用另一个库(例如libpng或lodepng)先解码它。

您可以在库源代码目录中的“example.c”文件中找到完整的示例代码。

C函数


liq_attr* liq_attr_create(void);

返回一个将保存库初始设置(属性)的对象。在不再需要后,应使用 liq_attr_destroy() 释放对象。

在库无法在当前机器上运行的不太可能的情况下(例如,库已针对支持SSE的x86 CPU编译,并在VIA C3 CPU上运行),返回 NULL


liq_error liq_set_max_colors(liq_attr* attr, int colors);

指定要使用的最大颜色数。默认为256。最好使用 liq_set_quality() 而不是设置一个固定的限制。

第一个参数是来自 liq_attr_create() 的属性对象。

如果颜色数超出2-256的范围,则返回 LIQ_VALUE_OUT_OF_RANGE


int liq_get_max_colors(liq_attr* attr);

返回由 liq_set_max_colors() 设置的值。


liq_error liq_set_quality(liq_attr* attr, int minimum, int maximum);

质量范围为 0(最差)到 100(最佳),值与JPEG质量类似(即 80 通常足够好)。

量化将尝试使用最少的颜色数量来实现 maximum 质量。默认的 maximum 值为 100,表示尽可能好的转换。

如果无法以至少 minimum 质量(即256种颜色不足以满足最低质量)转换图像,则 liq_image_quantize() 将失败。默认的最低值为 0(无论质量如何都继续进行)。

质量衡量生成的调色板与 liq_image_quantize() 提供的图像拟合程度。如果使用 liq_write_remapped_image() 将不同图像重新映射,则实际质量可能不同。

无论质量设置如何,颜色数都不会超过最大值(见 liq_set_max_colors())。

第一个参数是来自 liq_attr_create() 的属性对象。

如果目标值低于最小值或任何值超出0-100的范围,则返回 LIQ_VALUE_OUT_OF_RANGE。如果 attr 似乎无效,则返回 LIQ_INVALID_POINTER

liq_attr *attr = liq_attr_create();
liq_set_quality(attr, 50, 80); // use quality 80 if possible. Give up if quality drops below 50.

int liq_get_min_quality(liq_attr* attr);

返回由 liq_set_quality() 设置的下限。


int liq_get_max_quality(liq_attr* attr);

返回由 liq_set_quality() 设置的上限。


liq_image *liq_image_create_rgba(liq_attr *attr, void* pixels, int width, int height, double gamma);

创建一个表示用于量化和解映射的图像像素的对象。像素数组必须是RGBA像素的连续运行(alpha是最后一个组件,0 = 透明,255 = 不透明)。

第一个参数是从 liq_attr_create() 得到的属性对象。在整个过程中,从创建图像到量化,应使用相同的 attr 对象。

在用 liq_image_destroy() 释放此对象之前,不应修改或释放 pixels 数组。另请参阅 liq_image_set_memory_ownership()

widthheight 是以像素为单位的尺寸。一个10x10像素大小的图像需要一个400字节的数组。

如果 gamma 参数是 0,则默认使用 1/2.2 的 gamma 值,这对于大多数 sRGB 图片来说都是好的。否则 gamma 必须大于 0 且小于 1,例如 0.45455(1/2.2)或 0.55555(1/1.8)。生成的调色板将使用相同的 gamma 值,除非使用了 liq_set_output_gamma()。如果没有使用 liq_set_output_gamma,则它只会影响图像的亮部或暗部是否分配更多的调色板颜色。

在失败时返回 NULL,例如如果 pixelsNULLwidth/height 小于等于 0。


liq_image *liq_image_create_rgba_rows(liq_attr *attr, void* rows[], int width, int height, double gamma);

liq_image_create_rgba() 相同,但接受像素行的指针数组。这允许定义具有反转行(如 BMP)、"步长" 与宽度不同或仅使用较大位图的片段等图像。

行数组必须至少有 height 个元素,并且每行必须至少有 width 个 RGBA 像素宽。

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

在用 liq_image_destroy() 释放此对象之前(您可以使用 liq_image_set_memory_ownership() 进行更改),不得修改或释放行指针和像素。

请参阅 liq_image_create_rgba()liq_image_create_custom()


liq_error liq_image_quantize(liq_image *const input_image, liq_attr *const attr, liq_result **out_result);

基于在 attr 中的设置(来自 liq_attr_create())和图像的像素中进行量化(调色板生成)。

如果量化成功,则返回 LIQ_OK 并在 out_result 中的 liq_result 指针中设置。最后一个参数用于接收 result 对象。

liq_result *result;
if (LIQ_OK == liq_image_quantize(img, attr, &result)) { // Note &result
    // result pointer is valid here
}

如果量化失败,并且是由于在 liq_set_quality() 中设置的限制导致的,则返回 LIQ_QUALITY_TOO_LOW

请参阅 liq_write_remapped_image()

如果您想同时为多个图像生成一个调色板,请参阅 liq_histogram_create()


liq_error liq_set_dithering_level(liq_result *res, float dither_level);

liq_write_remapped_image() 中启用/禁用抖动。抖动级别必须在 01(包含)之间。抖动级别 0 启用快速非抖动重映射。否则使用 Floyd-Steinberg 错误扩散的变体。

抖动算法的精度取决于速度设置,请参阅 liq_set_speed()

如果抖动级别超出 0-1 范围,则返回 LIQ_VALUE_OUT_OF_RANGE


liq_error liq_write_remapped_image(liq_result *result, liq_image *input_image, void *buffer, size_t buffer_size);

将图像重映射到调色板并将像素写入给定的缓冲区,每字节 1 像素。

缓冲区必须足够大,以容纳整个图像,即宽度×高度的字节数。为了安全起见,将缓冲区的大小作为buffer_size传递。

为了获得最佳性能,请在此函数之后调用liq_get_palette(),因为调色板在重映射过程中得到改进(除非使用liq_histogram_quantize())。

如果给定的缓冲区大小不足以容纳整个图像,则返回LIQ_BUFFER_TOO_SMALL

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
}

请参阅liq_get_palette()

假设缓冲区是连续的,行从上到下排序,行之间没有间隙。如果您需要写入带有填充或颠倒顺序的行,则使用liq_write_remapped_image_rows()

请注意,它只将原始未压缩的像素写入内存。它不执行任何PNG压缩。如果您想创建一个PNG文件,则需要将原始像素数据传递给另一个库,例如libpng或lodepng。请参阅rwpng.c中的pngquant项目示例,了解如何进行。


const liq_palette *liq_get_palette(liq_result *result);

返回一个针对已量化或重映射的图像优化的调色板(在重映射过程中对调色板进行最终细化)的指针。

在重映射之前调用此方法是有效的,如果您不打算重映射任何图像或想为多个图像使用相同的调色板。

liq_palette->count包含颜色数(最多256),liq_palette->entries[n]包含第n个调色板颜色的RGBA值。

调色板是**临时且只读的**。您必须在调用liq_result_destroy()之前将其复制到其他位置。

发生错误时返回NULL


void liq_attr_destroy(liq_attr *);
void liq_image_destroy(liq_image *);
void liq_result_destroy(liq_result *);
void liq_histogram_destroy(liq_histogram *);

释放给定对象拥有的内存。对象在释放后不得再使用。

释放liq_result也会释放从它获得的任何liq_palette

高级功能


liq_error liq_set_speed(liq_attr* attr, int speed);

较高的速度级别禁用昂贵的算法并减少量化精度。默认速度是4。速度1在显著的CPU成本下提供略微更好的质量。速度10通常质量降低5%,但比默认值快8倍。

liq_set_quality()结合使用的高速度将使用比必要的更多颜色,并且不太可能达到最低所需质量。

依赖于速度的功能
噪声敏感的抖动速度1到5
强制式化简8-10或如果图像有超过百万种颜色
量化误差已知1-7或如果设置了最小质量
额外的量化技术1-6

如果速度超出1-10的范围,则返回LIQ_VALUE_OUT_OF_RANGE


int liq_get_speed(liq_attr* attr);

返回由liq_set_speed()设置的值。


liq_error liq_set_min_opacity(liq_attr* attr, int min);

这是一个针对Internet Explorer 6的解决方案,但由于这个浏览器已经不再使用,这个选项已被弃用并删除。


int liq_get_min_opacity(liq_attr* attr);

此功能已被弃用。


liq_set_min_posterization(liq_attr* attr, int bits);

忽略所有通道中给定数量的最低有效位,将图像转换为 2^bits 级别的伪影。 0 表示全质量。使用 2 对于VGA或16位RGB565显示,如果图像将被输出到RGB444/RGBA4444显示(例如,Android上的低质量纹理),则使用 4

如果值超出0-4的范围,则返回 LIQ_VALUE_OUT_OF_RANGE


int liq_get_min_posterization(liq_attr* attr);

返回由 liq_set_min_posterization() 设置的值。


liq_set_last_index_transparent(liq_attr* attr, int is_last);

0(默认)使alpha颜色在不透明颜色之前排序。非 0 混合颜色,除了完全透明的颜色,它被移动到调色板的末尾。这是针对盲目假设最后一个调色板条目是透明的程序的一个解决方案。


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

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

创建一个使用回调来读取图像数据的图像对象。这允许实时转换不是在RGBA颜色空间中的图像。

user_info 值将被传递给回调。这可能有助于存储指向程序内部图像表示的指针。

回调必须读取/生成 row_index 第行的数据,并将其RGBA像素写入 row_out 数组。为了方便起见,给出了行 width,它始终等于图像宽度。

对于每一行,回调将被多次调用。量化重映射至少需要遍历两次图像数据,因此缓存回调的工作没有意义——在这种情况下,最好转换整个图像并使用 liq_image_create_rgba()

要使用RGB图像

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

该库不支持RGB位图,因为它仅支持单一格式,这允许编译器内联更多代码,4字节像素对齐更快,SSE指令一次操作4个值,因此alpha支持几乎是免费的。


liq_error liq_image_set_memory_ownership(liq_image *image, int ownership_flags);

将图像像素数据及其行数组的所有权传递给 liq_image 对象,因此您不需要自己释放它。对象拥有的内存将在其选择时使用 liq_attr_create_with_allocator() 中指定的 free() 函数释放(默认为stdlib的 free())。

  • LIQ_OWN_PIXELS 使像素数组成为对象的所有权。当不再需要时,像素将自动释放。如果您设置了此标志,则 不得 自己释放像素数组。如果图像是通过 liq_image_create_rgba_rows() 创建的,则假设像素数组的起始地址是任何行的最低地址。

  • LIQ_OWN_ROWS 使行指针数组(但不是这些行指向的像素)成为对象的所有权。当对象被释放时,将释放行。如果您设置了此标志,则 不得 自己释放行数组。此标志仅在该对象是通过 liq_image_create_rgba_rows() 创建的情况下有效。

这些标志可以与二进制结合,例如:LIQ_OWN_PIXELS | LIQ_OWN_ROWS

如果图像是用liq_image_create_custom()创建的,则不得使用此函数。

如果指定了无效的标志或图像对象只从回调中获取像素,则返回LIQ_VALUE_OUT_OF_RANGE


liq_error liq_image_set_background(liq_image *image, liq_image *background_image);

假设此图像始终精确地呈现在此背景之上,分析并重新映射此图像。

当此图像重新映射到具有完全透明颜色的调色板(使用liq_image_add_fixed_color()确保这一点)时,比调色板更好地表示背景的像素将变为透明。此函数可以通过设置前一个动画帧作为背景来提高动画GIF的质量。

此函数完全拥有背景图像,因此您不应该释放背景对象。它将与前景图像一起自动释放。

如果背景图像与前景图像具有不同的尺寸,则返回LIQ_BUFFER_TOO_SMALL


liq_error liq_image_set_importance_map(liq_image *image, unsigned char map[], size_t buffer_size, liq_ownership ownership);

重要性图控制图像的哪些区域获得更多的调色板颜色。映射中对应于0值的像素将被完全忽略。值越高,对给定像素的权重就越大,它影响最终调色板的机会就越高。

该图是每像素一个字节,并且必须与图像大小(宽度×高度字节)相同。buffer_size参数用于进行双重检查。

如果ownershipLIQ_COPY_PIXELS,则立即复制map内容(您必须确保map内存被释放)。

如果ownershipLIQ_OWN_PIXELS,则map内存将由图像拥有,并在图像释放时自动释放。如果已使用liq_attr_create_with_allocator()设置了自定义分配器,则必须使用相同的分配器分配map。此选项已弃用。请改用Rust API或LIQ_COPY_PIXELS

如果任何指针是NULL,则返回LIQ_INVALID_POINTER,如果buffer_size不匹配图像大小,则返回LIQ_BUFFER_TOO_SMALL,如果ownership不是有效的值,则返回LIQ_UNSUPPORTED


liq_error liq_write_remapped_image_rows(liq_result *result, liq_image *input_image, unsigned char **row_pointers);

类似于liq_write_remapped_image()。将重新映射的图像,每像素1字节,写入由row_pointers数组指向的每一行。该数组必须至少有图像高度的元素,每行必须至少有图像宽度的字节。行不得重叠。

为了获得最佳性能,请在调用此函数后调用liq_get_palette(),因为重新映射可能会更改调色板(除非使用liq_histogram_quantize())。

如果resultinput_imageNULL,则返回LIQ_INVALID_POINTER


double liq_get_quantization_error(liq_result *result);

返回量化的均方误差(源图像与其重新映射版本像素值之间的差异的平方)。考虑了alpha通道、伽马校正和像素的大致重要性,因此结果不是所有通道的均方误差。

对于大多数图像,MSE 1-5 是优秀的,7-10 是可接受的,20-30 将会有明显的误差,100 是可怕的。

如果值不可用(当请求高速,图像尚未重新映射且未设置质量限制时),此函数可能返回 -1。当多个图像重新映射时,值不会更新,它仅适用于在 liq_image_quantize() 中使用的图像或第一个已重新映射的图像。请参阅 liq_get_remapping_error()


double liq_get_remapping_error(liq_result *result);

返回上一次完成的重新映射的平均平方误差(重新映射的图像与其重新映射版本像素值之差的平方)。考虑到 alpha 通道和 gamma 校正,因此结果不是所有通道的平均平方误差。

如果值不可用(当请求高速或图像尚未重新映射时),此函数可能返回 -1


double liq_get_quantization_quality(liq_result *result);

类似于 liq_get_quantization_error(),但以 liq_set_quality() 使用的相同 0-100 范围返回量化误差。

如果值不可用(请参阅 liq_get_quantization_error() 中的注释),则可能返回 -1

此函数可用于向用户展示的质量选项添加上限,例如。

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

double liq_get_remapping_quality(liq_result *result);

类似于 liq_get_remapping_error(),但以 liq_set_quality() 使用的相同 0-100 范围返回量化误差。


void liq_set_log_callback(liq_attr*, liq_log_callback_function*, void *user_info);

void log_callback_function(const liq_attr*, const char *message, void *user_info) {}

void liq_set_log_flush_callback(liq_attr*, liq_log_flush_callback_function*, void *user_info);

void log_flush_callback_function(const liq_attr*, void *user_info) {}

设置在库报告状态或错误时调用的回调函数。回调不得调用任何库函数。

user_info 值将传递到回调。它可以 NULL

NULL 回调清除当前回调。

在日志回调中,message 是一个以空字符终止的字符串,包含要输出的信息性消息。它仅在回调返回时有效,因此您必须复制它。

liq_set_log_flush_callback() 设置在最后一个日志回调之后调用的回调函数,可用于刷新缓冲区并释放日志回调使用的资源。


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

int progress_callback_function(const liq_attr*, float progress_percent, void *user_info) {}

设置在库处理图像时调用的回调函数。回调可以通过返回 0 来中止处理。

将回调设置为 NULL 清除当前回调。 liq_set_progress_callback 用于量化进度,而 liq_result_set_progress_callback 用于重新映射进度(目前只有抖动重新映射报告进度)。

user_info 值将传递到回调。它可以 NULL

回调不得调用任何库函数。

progress_percent 是一个介于 0 和 100 之间的值,估计当前任务完成了多少。

回调应返回 1 以继续操作,或返回 0 以中止当前操作。


liq_attr* liq_attr_create_with_allocator(void* (*malloc)(size_t), void (*free)(void*));

此函数已弃用。与 liq_attr_create 相同,但指定使用 freeliq_image_set_memory_ownership。不使用 malloc 参数。

库将使用 Rust 的 全局分配器


liq_attr* liq_attr_copy(liq_attr *orig);

创建 liq_attr 的独立副本。复制也应使用 liq_attr_destroy() 释放。


liq_error liq_set_output_gamma(liq_result* res, double gamma);

为生成的调色板和重映射的图像设置伽玛校正。必须大于 0 且小于 1,例如 PNG 图像中伽玛为 1/2.2 的 0.45455。默认情况下,输出伽玛与输入图像的伽玛相同。


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

获取输入图像的 widthheightgamma

如果输入无效,则所有这些都会返回 -1。


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

在从该图像创建的输出调色板中保留一个颜色。它的行为就像给定的颜色在图像中被使用并且非常重要一样。

liq_color 的 RGB 值假定与图像具有相同的伽玛。对于直方图函数,gamma 可以是 0(参见 liq_image_create_rgba())。

必须在图像量化之前调用。

如果添加了超过 256 种颜色,则返回错误。如果图像量化到的颜色数少于添加的固定颜色数,则多余的固定颜色将被忽略。

有关直方图,请参阅更灵活的 liq_histogram_add_colors()


int liq_version();

以整数形式返回库的版本。与 LIQ_VERSION 相同。可读版本定义为 LIQ_VERSION_STRING

具有相同调色板的多个图像

可以有效地生成单个调色板,该调色板适用于多个图像,例如 APNG 动画。这是通过在 liq_histogram 对象中收集图像统计信息来完成的。

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
}

liq_histogram *liq_histogram_create(liq_attr *attr);

创建用于从多个图像收集颜色统计信息的直方图对象。必须使用 liq_histogram_destroy() 释放。

在创建直方图对象之前,应在 attr 上设置所有选项。稍后更改的选项可能没有效果。


liq_error liq_histogram_add_image(liq_histogram *hist, liq_attr *attr, liq_image* image);

从图像中“学习”颜色,这些颜色将用于以后生成调色板。

在图像添加到直方图后,可以释放它以节省内存(但如果它将被用于重映射,则保留图像对象更有效)。

添加到图像的固定颜色也添加到直方图。如果固定颜色的总数超过 256,则此函数将失败并返回 LIQ_BUFFER_TOO_SMALL


liq_error liq_histogram_add_colors(liq_histogram *hist, liq_attr *attr, liq_histogram_entry entries[], int num_entries, double gamma);

liq_histogram_add_image() 的替代方法。而不是在图像中计数颜色,它直接接受颜色数组的颜色及其计数(参见 liq_histogram_entrylibimagequant.h 中)。此函数仅适用于您已经从另一个来源获得了图像的直方图。

有关伽玛的描述,请参见 liq_image_create_rgba()


liq_error liq_histogram_quantize(liq_histogram *const hist, liq_attr *const attr, liq_result **out_result);

从直方图生成调色板。成功时返回 LIQ_OK 并将 liq_result* 指针写入 out_result。使用方法如下

liq_result *result;
liq_error err = liq_histogram_quantize(attr, hist, &result);
if (LIQ_OK == err) {
    // Use result here to remap and get palette
}

如果调色板比在 liq_set_quality() 中设置的限值还要差,则返回 LIQ_QUALITY_TOO_LOW。一个直方图对象只能量化一次。

使用此函数生成的调色板在重映射期间不会被改进。如果您只为一张图像生成调色板,最好使用 liq_image_quantize()

多线程

  • 不同的线程可以在同一时间执行无关的量化/重映射(例如,每个线程处理不同的图像)。
  • 相同的 liq_attrliq_result 等. 可以从不同的线程中访问,但不能同时访问(例如,您可以在一个线程中创建 liq_attr 并在另一个线程中释放它)。
  • 默认情况下,此库内部使用线程。您可以通过设置 RAYON_NUM_THREADS 环境变量来控制使用的线程数。您可以通过使用 --no-default-features 标志进行编译来完全禁用线程。

处理 GIF

库可以为 GIF 图像生成调色板。为了确保使用正确的透明度,您需要自己预处理图像,并将除 0 或 255 以外的 alpha 值替换为这些之一。

有关动画 GIF,请参阅 liq_image_set_background(),该函数为 GIF 的 "保留" 分配方法重映射图像。请参阅 gif.ski

交叉编译

您可以通过 cargo build --target= 编译库以用于其他平台。有关平台列表,请参阅 rustup target list

当为 WASM 编译时,您需要禁用此库的默认功能(使用 --no-default-features 标志进行编译)。否则,它将使用多线程,这需要在 WASM 中进行特殊处理[特殊处理链接]

如果您正在交叉编译动态库(so/dylib/DLL),您可能需要为 Cargo 配置链接器。有关为 Android 构建的信息,请参阅此教程cargo-ndk

依赖项

~535KB