StupidBeauty
Read times:3841Posted at: - no title specified

WebP开发文档翻译:WebP应用编程接口文档WebP API Documentation

本小节说明的是,WebP 库中包含的编码器和解码器的应用编程接口。本文档对应的是库的0.5.1 版本。

头文件及库

当妳 安装 libwebp 时, 会在妳的平台的典型位置安装一个名为 webp/ 的目录。例如, Unix系列平台 中,会将以下头文件复制到 /usr/local/include/webp/ 目录。

decode.h

encode.h

types.h

库文件呢,会被放置在通常放置库文件的目录。 在Unix 类平台中,静态 及动态库文件会被放置到 /usr/local/lib/ 目录。

简单的解码接口

要想使用解码接口,妳首先需要按照 上面 所说的方法将库文件和头文件安装到系统中。

按照以下示例的方式来在妳的C/C++代码中包含解码接口的头文件:

#include "webp/decode.h"

int WebPGetInfo ( const uint8_t* data, size_t data_size, int * width, int * height);

这个函数,会验证WebP 图片的文件头,并且取出图片的宽度和高度。如果 妳不在意图片的尺寸的话,那么,可以将 *width *height 两个指针传递为空指针 NULL

输入参数

data

指向WebP 图片数据的指针

data_size

data 所指向的图片数据内存块的尺寸。

返回

false

格式有错误,则返回错误码。

true

解析成功 则返回这个。只有 在返回解析成功的情况下, *width *height 中的数据才有效。

width

整数值。其取值范围限制为116383

height

整数值。其取值范围限制为116383

struct WebPBitstreamFeatures {

int width;         // 宽度,单位 是像素。

int height;       // 高度 ,单位是像素。

int has_alpha;     // 如果 这个位流中包含透明通道,则为真( True )。

}

VP8StatusCode WebPGetFeatures ( const uint8_t* data,

size_t data_size,

WebPBitstreamFeatures * features);

这个函数,会从位流中提取出图片的特性。 *features 结构 体的内容,会根据从位流中收集的数据来填充:

输入属性

data

指向WebP 图片数据的指针

data_size

data 所指向的图片数据内存块的尺寸。

返回

VP8_STATUS_OK

成功提取到特性数据则返回此值。

VP8_STATUS_NOT_ENOUGH_DATA

返回此值,则表示,还需要接收更多数据才能够从文件头中提取出特性信息。

其它情况 下,会返回其它的 VP8StatusCode 错误值。

features

指向一个WebPBitstreamFeatures 结构体的指针。

uint8_t* WebPDecodeRGBA ( const uint8_t* data, size_t data_size, int * width, int * height);

uint8_t* WebPDecodeARGB ( const uint8_t* data, size_t data_size, int * width, int * height);

uint8_t* WebPDecodeBGRA ( const uint8_t* data, size_t data_size, int * width, int * height);

uint8_t* WebPDecodeRGB ( const uint8_t* data, size_t data_size, int * width, int * height);

uint8_t* WebPDecodeBGR ( const uint8_t* data, size_t data_size, int * width, int * height);

这些函数,会 data 所指向的WebP 图片数据进行解码。

  • •. WebPDecodeRGBA 返回RGBA图片数据 ,顺序是 [r0, g0, b0, a0, r1, g1, b1, a1, ...]

  • •. WebPDecodeARGB 返回ARGB图片数据 ,顺序是 [a0, r0, g0, b0, a1, r1, g1, b1, ...]

  • •. WebPDecodeBGRA 返回BGRA图片数据 ,顺序是 [b0, g0, r0, a0, b1, g1, r1, a1, ...]

  • •. WebPDecodeRGB 返回RGB图片数据 ,顺序是 [r0, g0, b0, r1, g1, b1, ...]

  • •. WebPDecodeBGR 返回BGR图片数据 ,顺序是 [b0, g0, r0, b1, g1, r1, ...]

对这些函数进行调用的代码,必须使用 WebPFree() 来将这些函数返回的 (uint8_t*) 数据缓冲区释放掉。

输入属性

data

指向WebP 图片数据的指针

data_size

data 所指向的图片数据内存块的尺寸。

width

整数值。其取值范围限制为116383

height

整数值。其取值范围限制为116383

返回

uint8_t*

指向解码后的WebP 图片数据的指针,其具体数据顺序分别为RGBA/ARGB/BGRA/RGB/BGR。

uint8_t* WebPDecodeRGBAInto ( const uint8_t* data, size_t data_size,

uint8_t* output_buffer, int output_buffer_size, int output_stride);

uint8_t* WebPDecodeARGBInto ( const uint8_t* data, size_t data_size,

uint8_t* output_buffer, int output_buffer_size, int output_stride);

uint8_t* WebPDecodeBGRAInto ( const uint8_t* data, size_t data_size,

uint8_t* output_buffer, int output_buffer_size, int output_stride);

uint8_t* WebPDecodeRGBInto ( const uint8_t* data, size_t data_size,

uint8_t* output_buffer, int output_buffer_size, int output_stride);

uint8_t* WebPDecodeBGRInto ( const uint8_t* data, size_t data_size,

uint8_t* output_buffer, int output_buffer_size, int output_stride);

这些函数是之前所说函数的变种,它们 会将图片直接解码到某个预先分配的缓冲区 output_buffer 中去。 此缓冲区中可用的最大存储空间数量,由 output_buffer_size 参数指定。如果 这块存储空间不够大(或者发生了错误),那么,会返回空值( NULL )。否则 ,会返回 output_buffer ,以便妳日后使用。

参数 output_stride ,指定的是,相邻扫描线之间的距离(单位 是字节 )。因此 ,预期的 output_buffer_size 最小值应当是 output_stride * ( picture.height )

输入属性

data

指向WebP 图片数据的指针

data_size

data 所指向的图片数据内存块的尺寸

output_buffer_size

整数值。所分配的缓冲区的尺寸

output_stride

整数值。指定相邻扫描线之间的距离。

返回

output_buffer

指向解码后的WebP图片

uint8_t*

解码成功则返回 output_buffer ;否则返回空值( NULL )。

高级解码接口

WebP的解码模块,还支持一个高级接口,可用来在解码的同时进行裁剪和重采样,这种功能对于内存数量受限的环境狠有用,例如移动设备。简单来说,如果妳只是需要解码出一个预览图片或者局部区域放大的图片,而并不完整地解码出原本狠大的原始图片的话,这个过程中所使用的内存,会随着输出图片的尺寸改变,而不是随着输入图片的尺寸改变。并且,在某些情况下,还会节省CPU运算量。

WebP的解码过程,有两种使用方式:一种是,对完整图片进行解码;另一个种,利用较小的输入缓冲区,对图片进行渐进式解码。用户还可以提供一个外部内存缓冲区,以用于图片的解码。以下代码示例,会展示,如何使用高级解码接口。

首先,要初始化一个配置对象:

#include "webp/decode.h"

WebPDecoderConfig config;

CHECK( WebPInitDecoderConfig (&config));

// 此处可调整某些附加解码选项:

config.options.no_fancy_upsampling = 1 ;

config.options.use_scaling = 1 ;

config.options.scaled_width = scaledWidth();

config.options.scaled_height = scaledHeight();

// 狠多选项。

解码选项, 都汇集到了 WebPDecoderConfig 结构体中:

struct WebPDecoderOptions {

int bypass_filtering;             // 如果设置 为真(true),则跳过循环体内的过滤流程。

int no_fancy_upsampling;           // 如果设置 为真(true),则使用较快的基于点的超采样器(pointwise upsampler)

int use_cropping;                 // 如果设置 为真(true),则,会 首先 进行裁剪

int crop_left, crop_top;           // 裁剪操作 中的左上角位置。

// 会对齐 到偶数值。

int crop_width, crop_height;       // 裁剪区域 的尺寸

int use_scaling;                   // 如果设置 为真(true),会在 最后 进行缩放

int scaled_width, scaled_height;   // 缩放 后的最终分辨率

int use_threads;                   // 如果设置 为真(true),则使用多线程解码

};

或者 ,也可将位流中的各个特性信息读取到 config.input 中去,这样,我们就可以预先得知对应的信息了。例如 ,我们预先知道图片中是否有透明通道的话,也能为后续运行过程提供便利。注意 ,这个 过程中也会对位流的文件头进行解析,因此,也能顺便得知,这个位流是不是一个有效的WebP 图片。

CHECK( WebPGetFeatures (data, data_size, &config.input) == VP8_STATUS_OK);

然后,我们就需要分配好解码过程中所使用的内存缓冲区,以直接提供给解码器,而不是让解码器来分配内存。我们只需要提供三个参数:指向该内存块的指针;缓冲区的总大小;以及,扫描线间距(line stride(相邻扫描线之间的距离,以字节为单位)

// 指定预期 的输出颜色空间:

config.output.colorspace = MODE_BGRA;

// config.output指向 一块外部缓冲区:

config.output.u.RGBA.rgba = (uint8_t*)memory_buffer;

config.output.u.RGBA.stride = scanline_stride;

config.output.u.RGBA.size = total_size_of_the_memory_buffer;

config.output.is_external_memory = 1 ;

现在,可以对图片进行解码了。可选用两种方式来对图片进行解码。我们可以一次性对图片进行解码:

CHECK( WebPDecode (data, data_size, &config) == VP8_STATUS_OK);

也可以使用渐进式方法进行解码,随着后续字节的到来而逐渐解析出图片:

WebPIDecoder * idec = WebPINewDecoder (NULL, NULL, &config);

CHECK(idec != NULL);

while (bytes_remaining > 0 ) {

VP8StatusCode status = WebPIAppend (idec, input, bytes_read);

if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) {

bytes_remaining -= bytes_read;

} else {

break ;

}

// 上述代码会对当前可用的缓冲区内容进行解码。

// 此刻 ,可通过调用WebPIDecGetRGB()/WebPIDecGetYUVA()等方法来获取到图片中的部分内容。

}

WebPIDelete (idec);   // 该对象并不占据图片内存的所有权,因此,可以删除了。

现在,解码后的图片位于config.output(或者,具体对于本示例来说,位于config.output.u.RGBA)。可对它进行保存、显示或其它处理。之后,我们只需要回收针对 config 对象所分配的内存。即使该内存是外部分配的,根本就不是由WebPDecode()分配的,也可以安全地调用此函数:

WebPFreeDecBuffer (&config.output);

利用 这个接口,还可以将图片解码成 YUV YUVA格式 ,具体 就是,分别使用 MODE_YUV MODE_YUVA 这种格式,也被称作 亮色浓

简单编码接口

库中提供了某些狠简单的函数,用于将 一些按照常见布局方式排列的RGBA 样本数组编码成图片。 这些函数,都是在 webp/encode.h 头文件中声明的:

size_t WebPEncodeRGB ( const uint8_t* rgb, int width, int height, int stride, float quality_factor, uint8_t** output);

size_t WebPEncodeBGR ( const uint8_t* bgr, int width, int height, int stride, float quality_factor, uint8_t** output);

size_t WebPEncodeRGBA ( const uint8_t* rgba, int width, int height, int stride, float quality_factor, uint8_t** output);

size_t WebPEncodeBGRA ( const uint8_t* bgra, int width, int height, int stride, float quality_factor, uint8_t** output);

质量因子 quality_factor ,取值范围 是从 0 100 。它控制的是,压缩过程中 的信息损耗和图片质量。 值为 0 ,则表示低质量,输出文件尺寸也小。 值为 100 ,则表示,最高质量,输出文件尺寸也最大。如果 码成功 ,那么,压缩后的字节数据会被放置到 *output 指针 处, 而其总尺寸会以字节为单位被返回 (失败 则返回 0) 。调用 者必须在日后对 *output 指针调用 WebPFree() 来回收内存。

输入数组 ,应当是 一个紧缩存储的字节数组 (每个颜色通道 一个字节,具体顺序 与函数名字所对应 的顺序一致 ) stride ,表示的是, 从一行跳到下一行的过程中,要跳过的字节个数。例如, BGRA格式应当如下布局:

这些函数,还有对应的无损压缩版本,其格式如下:

size_t WebPEncodeLosslessRGB ( const uint8_t* rgb, int width, int height, int stride, uint8_t** output);

size_t WebPEncodeLosslessBGR ( const uint8_t* bgr, int width, int height, int stride, uint8_t** output);

size_t WebPEncodeLosslessRGBA ( const uint8_t* rgba, int width, int height, int stride, uint8_t** output);

size_t WebPEncodeLosslessBGRA ( const uint8_t* bgra, int width, int height, int stride, uint8_t** output);

高级编码接口

编码 器,还提供了若干个高级的编码参数。利用 这些参数,可以更好地 在压缩效率和处理时间之间取得平衡。 这些参数,汇聚在 WebPConfig 结构体中。 这个结构体的最常 字段列举如下:

struct WebPConfig {

int lossless;           // 无损编码(0= 有损 (默认 ) 1=无损)

float quality;           // 取值范围 0(最小文件尺寸) 100(最大文件尺寸)

int method;             // 质量/速度之间 的取舍 (0=快速 6= 较慢然而质量较好 )

WebPImageHint image_hint;   // 图片类型建议(目前 只对无损压缩有效 )

// 以下参数只与有损压缩有关:

int target_size;         // 如果 这个字段不为零,则表示,预期的目标文件尺寸,单位是字节。

// 优先 级高于'compression'参数。

float target_PSNR;       // 如果 这个字段不为零,则表示,预期达到 的最小失真值。

// 优先 级高于 target_size

int segments;           // 使用 的最大片断个数,取值范围 [1..4]

int sns_strength;       // 立体噪声整形 Spatial Noise Shaping )。 0=关闭 100=最大

int filter_strength;     // 范围 [0 = 关闭 .. 100 = 最强]

int filter_sharpness;   // 范围 [0 = 关闭 .. 7 = 最小锐利 ]

int filter_type;         // 过滤类型 0 = 简单 1 = ( 仅当filter_strength > 0 或 autofilter > 0 时才有用 )

int autofilter;         // 自动调整过滤 器的强度 [0 = 关闭 1 = 开启]

int alpha_compression;   // 透明通道平面 的编码算法 (0 = 不使用算法,

// 1 = 按照WebP 无损压缩方式压缩) 。默认值是 1

int alpha_filtering;     // 对于透明通道平面 的预测式过滤方法。

//  0: 不使用, 1: 快速 2: 最佳 。默认值是 1

int alpha_quality;       // 取值位于0 (最小尺寸) 100 (无损)之间

// 默认 值是 100

int pass ;               // 进行 熵分析的遍数 (取值范围[1..10])

int show_compressed;     // 如果设置 为真( true ),那么 ,将压缩后的图片导出。

// 不会应用循环体内的过滤。

int preprocessing;       // 预处理过滤器 (0= 不使用, 1=片断 式流畅( segment-smooth )

int partitions;         // log2(标记分区 的个数 ) ,取值范围 [0..3]

// 默认 值是 0 ,以降低渐进式解码的难度。

int partition_limit;     // 允许 为了适应预测模式编码中的512k 限制而进行质量降级的程度

// (0: 不进行降级,

// 100: 最大可能 的降级程度 )

};

注意 ,这里的大部分参数, 都可以通过 cwebp 命令行工具来进行试验。

输入 的采样数据,应当被包装在一个 WebPPicture 结构体中。 这个结构体,可以以RGBA 或YUVA 格式来储存输入的采样数据,具体取决于 use_argb 标志位。

结构体,是按照以下方式来组织的:

struct WebPPicture {

int use_argb;               // 在ARGB 和YUVA 格式的输入模式之间选择。

// YUV输入模式 ,是针对有损压缩方式的建议输入模式。

// use_argb = 0 则表示使用这个格式。

WebPEncCSP colorspace;     // 颜色空间:目前 ,应当使用 YUVA420 YUV420(=Y'CbCr)

int width, height;         // 维度数据(小于 或等于 WEBP_MAX_DIMENSION)

uint8_t *y, *u, *v;         // 指向亮度 luma /色度 chroma )平 的指针。

int y_stride, uv_stride;   // 亮度/色度平 面的扫描线间距( strides )。

uint8_t* a;                 // 指向透明通道平面 的指针

int a_stride;               // 透明通道平面 的扫描线间距( stride

// 或者使用ARGB格式 的输入,这种格式,是进行无损压缩时建议使用的格式。

// use_argb = 1 则表示使用这个格式。

uint32_t* argb;             // 指向argb (32 ) 平面 的指针。

int argb_stride;           // 扫描 线间距,以像素为单位, 而不是以字节为单位。

// 字节 发射钩子( Byte-emission hook ),用于 在压缩后的字节可用的时刻对它们进行存储。

WebPWriterFunction writer;   // 可以为空值( NULL

void * custom_ptr;           // 可由写入器(writer)使用。

// 编码过程 中最后一次发生的错误的错误码

WebPEncodingError error_code;

};

这个结构体中,还包含有一个函数,可用于在产生了压缩后的字节的时刻将它们传输出来。查看下面 的示例, 它是一个内存中的写入器。其它 的写入器,可将数据直接写入文件中 ( examples/cwebp.c 就是一个例子 )

使用高级接口来进行编码的常规流程是:

首先,我们需要创建一个编码配置对象,其它包含着压缩参数。注意,同一个配置对象,可用于压缩日后的多个不同图片。

#include "webp/encode.h"

WebPConfig config;

if (! WebPConfigPreset (&config, WEBP_PRESET_PHOTO, quality_factor)) return 0 ;   // 版本 号错误

// 做出额外 的调整:

config.sns_strength = 90 ;

config.filter_sharpness = 6 ;

config.alpha_quality = 90 ;

config_error = WebPValidateConfig (&config);   // 验证各个参数 的取值范围 ( 这是个好习惯 )

然而 ,输入的采样数据,需要通过引用 或复制方式传入 到某个 WebPPicture 中。 以下示例,就会分配缓冲区,用于存储采样数据。 不过,妳也可以轻易地创建一个“视图”("view"),指向某个 已分配的采样数据数组。参考 WebPPictureView() 函数以了解细节。

// 设置输入数据 ,分配一个图片对象,其尺寸为 width x height

WebPPicture pic;

if (! WebPPictureInit (&pic)) return 0 ;   // 版本 号错误

pic.width = width;

pic.height = height;

if (! WebPPictureAllocate (&pic)) return 0 ;   // 内存错误

// 此刻 'pic' 已被初始化为一个容器, 可接收 YUVA RGBA采样数据 了。

// 或者 ,也可以使用现成的导入函数,例如 WebPPictureImportRGBA() 它会处理好

// 内存分配 的事。无论如何 ,在最后,需要调用 WebPPictureFree(&pic)

// 来回收之前分配的内存。

为了将压缩后的字节流传输出来,会在每次有新的字节可用时调用某个钩子函数。 以下是一个简单的示例,使用的是 webp/encode.h 中声明的内存写入器。对于 每张要压缩的图片, 都要进行这种初始化:

// 创建 一个字节写入方法 ( 在这个示例中,写入到内存中 )

WebPMemoryWriter writer;

WebPMemoryWriterInit (&writer);

pic.writer = WebPMemoryWrite ;

pic.custom_ptr = &writer;

现在,可以对输入采样数据进行压缩了(日后,要释放它们的内存)

int ok = WebPEncode (&config, &pic);

WebPPictureFree (&pic);   // 一定要 将与输入数据相关联的内存释放掉。

if (!ok) {

printf( "Encoding error: %d\n" , pic.error_code);

} else {

printf( "Output size: %d\n" , writer.size);

}

对于 该接口及结构体的更高级用法,建议妳阅读 webp/encode.h 头文件中的文档。阅读示例代码 examples/cwebp.c ,也有助于发现那些不那么常用的参数。

未知美人

Your opinions
Your name:Email:Website url:Opinion content: