本節將說明 WebP 程式庫中的編碼器和解碼器適用的 API。此 API 說明與 1.4.0 版有關。
標頭與程式庫
安裝 libwebp
時,系統會在平台的一般位置安裝一個名為 webp/
的目錄。舉例來說,在 Unix 平台上,下列標頭檔案會複製到 /usr/local/include/webp/
。
decode.h
encode.h
types.h
程式庫位於一般的程式庫目錄中。靜態和動態程式庫位於 Unix 平台的 /usr/local/lib/
中。
簡易解碼 API
如要開始使用解碼 API,您必須按照上述說明安裝程式庫和標頭檔案。
在 C/C++ 程式碼中加入解碼 API 標頭,如下所示:
#include "webp/decode.h"
int WebPGetInfo(const uint8_t* data, size_t data_size, int* width, int* height);
這個函式會驗證 WebP 圖片標頭,並擷取圖片的寬度和高度。如果系統判定指標 *width
和 *height
無關,可以傳遞 NULL
指標。
輸入屬性
- 資料或曾存取這類資料的人員
- 指向 WebP 圖片資料
- data_size
- 這是包含圖片資料的
data
所指向的記憶體區塊大小。
傳回
- false
- 出現 (a) 格式錯誤時傳回的錯誤代碼。
- true
- 成功時。
*width
和*height
只有在成功傳回時才有效。 - 寬度
- 整數值。範圍從 1 到 16383。
- 高度
- 整數值。範圍從 1 到 16383。
struct WebPBitstreamFeatures {
int width; // Width in pixels.
int height; // Height in pixels.
int has_alpha; // True if the bitstream contains an alpha channel.
int has_animation; // True if the bitstream is an animation.
int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless
}
VP8StatusCode WebPGetFeatures(const uint8_t* data,
size_t data_size,
WebPBitstreamFeatures* features);
這個函式會從位元串流中擷取功能。*features
結構會填入從位元串流收集的資訊:
輸入屬性
- 資料或曾存取這類資料的人員
- 指向 WebP 圖片資料
- data_size
- 這是包含圖片資料的
data
所指向的記憶體區塊大小。
傳回
VP8_STATUS_OK
- 成功擷取特徵時。
VP8_STATUS_NOT_ENOUGH_DATA
- 需要更多資料才能從標頭擷取特徵。
其他情況下則為額外的 VP8StatusCode
錯誤值。
- 功能
- 指向 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
會以[r0, g0, b0, a0, r1, g1, b1, a1, ...]
順序傳回 RGBA 圖片範例。WebPDecodeARGB
會以[a0, r0, g0, b0, a1, r1, g1, b1, ...]
順序傳回 ARGB 圖片範例。WebPDecodeBGRA
會以[b0, g0, r0, a0, b1, g1, r1, a1, ...]
順序傳回 BGRA 圖片樣本。WebPDecodeRGB
會以[r0, g0, b0, r1, g1, b1, ...]
順序傳回 RGB 圖片範例。WebPDecodeBGR
會以[b0, g0, r0, b1, g1, r1, ...]
順序傳回 BGR 圖片範例。
呼叫任何這些函式的程式碼必須刪除這些函式使用 WebPFree()
傳回的資料緩衝區 (uint8_t*)
。
輸入屬性
- 資料或曾存取這類資料的人員
- 指向 WebP 圖片資料
- data_size
- 這是包含圖片資料的
data
所指向的記憶體區塊大小 - 寬度
- 整數值。目前限制的範圍是 1 到 16383。
- 高度
- 整數值。目前限制的範圍是 1 到 16383。
傳回
- 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
。
輸入屬性
- 資料或曾存取這類資料的人員
- 指向 WebP 圖片資料
- data_size
- 這是包含圖片資料的
data
所指向的記憶體區塊大小 - output_buffer_size
- 整數值。已分配的緩衝區大小
- output_stride
- 整數值。指定掃描線之間的距離。
傳回
- output_buffer
- 指向已解碼 WebP 圖片的指標。
- uint8_t*
- 如果函式成功,則為
output_buffer
;否則傳回NULL
。
進階解碼 API
WebP 解碼支援進階 API,能夠即時裁剪及調整大小,在手機等記憶體受限的環境中可以帶來許多實用功能。基本上,如果只需要快速預覽或放大畫面的部分內容,記憶體用量會隨輸出的大小而調整,而非輸入內容。有些 CPU 甚至可以 單獨儲存
WebP 解碼提供兩種版本,支援完整圖片解碼,而小型輸入緩衝區則採用漸進式解碼。使用者可選擇提供外部記憶體緩衝區,以解碼圖片。以下程式碼範例將逐步說明如何使用進階解碼 API。
首先,需要初始化設定物件:
#include "webp/decode.h"
WebPDecoderConfig config;
CHECK(WebPInitDecoderConfig(&config));
// One can adjust some additional decoding options:
config.options.no_fancy_upsampling = 1;
config.options.use_scaling = 1;
config.options.scaled_width = scaledWidth();
config.options.scaled_height = scaledHeight();
// etc.
解碼選項會收集 WebPDecoderConfig
結構內:
struct WebPDecoderOptions {
int bypass_filtering; // if true, skip the in-loop filtering
int no_fancy_upsampling; // if true, use faster pointwise upsampler
int use_cropping; // if true, cropping is applied first
int crop_left, crop_top; // top-left position for cropping.
// Will be snapped to even values.
int crop_width, crop_height; // dimension of the cropping area
int use_scaling; // if true, scaling is applied afterward
int scaled_width, scaled_height; // final resolution
int use_threads; // if true, use multi-threaded decoding
int dithering_strength; // dithering strength (0=Off, 100=full)
int flip; // if true, flip output vertically
int alpha_dithering_strength; // alpha dithering strength in [0..100]
};
您可以視需要在 config.input
中讀取位元串流功能,以便事先瞭解這些功能。舉例來說,如果想知道相片是否有透明度
就會很方便。請注意,這樣做也會剖析位元串流的標頭,因此是瞭解位元串流看起來是否像有效的 WebP 方法的好方法。
CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
接著,我們需要設定解碼記憶體緩衝區,以便直接提供,而非仰賴解碼器進行配置。我們只需要提供指向記憶體的指標,以及緩衝區的總大小和行距 (掃描線之間的距離,以位元組為單位)。
// Specify the desired output colorspace:
config.output.colorspace = MODE_BGRA;
// Have config.output point to an external buffer:
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(&config.output);
CHECK(idec != NULL);
while (additional_data_is_available) {
// ... (get additional data in some new_data[] buffer)
VP8StatusCode status = WebPIAppend(idec, new_data, new_data_size);
if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) {
break;
}
// The above call decodes the current available buffer.
// Part of the image can now be refreshed by calling
// WebPIDecGetRGB()/WebPIDecGetYUVA() etc.
}
WebPIDelete(idec); // the object doesn't own the image memory, so it can
// now be deleted. config.output memory is preserved.
解碼後的圖片現在位於 config.output 中 (在這個例子中則是 config.output.u.RGBA,因為要求的輸出色域為 MODE_BGRA)。您可以儲存、顯示或處理圖片。之後,我們只需收回在設定物件中分配的記憶體即可。即使記憶體是外部且並未由 WebPDecode() 分配,呼叫這個函式也很安全:
WebPFreeDecBuffer(&config.output);
使用這個 API 也可以分別使用 MODE_YUV
和 MODE_YUVA
將圖片解碼為 YUV 和 YUVA 格式。這種格式又稱為 Y'CbCr。
簡單編碼 API
有些非常簡單的函式,用於在最常見的版面配置中為 RGBA 範例的編碼陣列提供。這些 API 會在 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);
請注意,這些功能 (例如有損版本) 使用程式庫的預設設定。若是無損資料,表示「完全比對」已停用。透明區域中的 RGB 值會經過修改,以利壓縮。如要避免這種情況發生,請使用 WebPEncode()
,並將 WebPConfig::exact
設為 1
。
進階編碼 API
基本上,編碼器隨附許多進階編碼參數。在壓縮效率與處理時間之間的平衡點上,這些做法會很有用。這些參數會收集到 WebPConfig
結構中。這個結構中最常用的欄位如下:
struct WebPConfig {
int lossless; // Lossless encoding (0=lossy(default), 1=lossless).
float quality; // between 0 and 100. For lossy, 0 gives the smallest
// size and 100 the largest. For lossless, this
// parameter is the amount of effort put into the
// compression: 0 is the fastest but gives larger
// files compared to the slowest, but best, 100.
int method; // quality/speed trade-off (0=fast, 6=slower-better)
WebPImageHint image_hint; // Hint for image type (lossless only for now).
// Parameters related to lossy compression only:
int target_size; // if non-zero, set the desired target size in bytes.
// Takes precedence over the 'compression' parameter.
float target_PSNR; // if non-zero, specifies the minimal distortion to
// try to achieve. Takes precedence over target_size.
int segments; // maximum number of segments to use, in [1..4]
int sns_strength; // Spatial Noise Shaping. 0=off, 100=maximum.
int filter_strength; // range: [0 = off .. 100 = strongest]
int filter_sharpness; // range: [0 = off .. 7 = least sharp]
int filter_type; // filtering type: 0 = simple, 1 = strong (only used
// if filter_strength > 0 or autofilter > 0)
int autofilter; // Auto adjust filter's strength [0 = off, 1 = on]
int alpha_compression; // Algorithm for encoding the alpha plane (0 = none,
// 1 = compressed with WebP lossless). Default is 1.
int alpha_filtering; // Predictive filtering method for alpha plane.
// 0: none, 1: fast, 2: best. Default if 1.
int alpha_quality; // Between 0 (smallest size) and 100 (lossless).
// Default is 100.
int pass; // number of entropy-analysis passes (in [1..10]).
int show_compressed; // if true, export the compressed picture back.
// In-loop filtering is not applied.
int preprocessing; // preprocessing filter (0=none, 1=segment-smooth)
int partitions; // log2(number of token partitions) in [0..3]
// Default is set to 0 for easier progressive decoding.
int partition_limit; // quality degradation allowed to fit the 512k limit on
// prediction modes coding (0: no degradation,
// 100: maximum possible degradation).
int use_sharp_yuv; // if needed, use sharp (and slow) RGB->YUV conversion
};
請注意,您可以透過 cwebp
指令列工具測試大部分的參數。
輸入範例應納入 WebPPicture
結構中。根據 use_argb
旗標的值,這個結構可以儲存 RGBA 或 YUVA 格式的輸入範例。
架構的組織方式如下:
struct WebPPicture {
int use_argb; // To select between ARGB and YUVA input.
// YUV input, recommended for lossy compression.
// Used if use_argb = 0.
WebPEncCSP colorspace; // colorspace: should be YUVA420 or YUV420 for now (=Y'CbCr).
int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION)
uint8_t *y, *u, *v; // pointers to luma/chroma planes.
int y_stride, uv_stride; // luma/chroma strides.
uint8_t* a; // pointer to the alpha plane
int a_stride; // stride of the alpha plane
// Alternate ARGB input, recommended for lossless compression.
// Used if use_argb = 1.
uint32_t* argb; // Pointer to argb (32 bit) plane.
int argb_stride; // This is stride in pixels units, not bytes.
// Byte-emission hook, to store compressed bytes as they are ready.
WebPWriterFunction writer; // can be NULL
void* custom_ptr; // can be used by the writer.
// Error code for the latest error encountered during encoding
WebPEncodingError error_code;
};
這個結構也具備函式,可以在系統提供壓縮的位元組時發出輸出。請參閱以下記憶體內寫入器的範例。其他寫入者可以將資料直接儲存至檔案 (如需範例,請參閱 examples/cwebp.c
)。
使用進階 API 進行編碼的一般流程如下:
首先,我們必須設定包含壓縮參數的編碼設定。請注意,之後如要壓縮多個不同的映像檔,可以使用相同的設定。
#include "webp/encode.h"
WebPConfig config;
if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) return 0; // version error
// Add additional tuning:
config.sns_strength = 90;
config.filter_sharpness = 6;
config.alpha_quality = 90;
config_error = WebPValidateConfig(&config); // will verify parameter ranges (always a good habit)
接著,您必須透過參照或複製的方式,在 WebPPicture
中參照輸入範例。以下範例說明如何分配緩衝區來保留樣本。不過,您可以輕鬆將「檢視畫面」設定為已配置的範例陣列。請參閱 WebPPictureView()
函式。
// Setup the input data, allocating a picture of width x height dimension
WebPPicture pic;
if (!WebPPictureInit(&pic)) return 0; // version error
pic.width = width;
pic.height = height;
if (!WebPPictureAlloc(&pic)) return 0; // memory error
// At this point, 'pic' has been initialized as a container, and can receive the YUVA or RGBA samples.
// Alternatively, one could use ready-made import functions like WebPPictureImportRGBA(), which will take
// care of memory allocation. In any case, past this point, one will have to call WebPPictureFree(&pic)
// to reclaim allocated memory.
為了發出已壓縮的位元組,每當有新位元組時就會呼叫掛鉤。以下是在 webp/encode.h
中宣告記憶體寫入器的簡單範例。每張圖片可能需要經過此初始化才能壓縮:
// Set up a byte-writing method (write-to-memory, in this case):
WebPMemoryWriter writer;
WebPMemoryWriterInit(&writer);
pic.writer = WebPMemoryWrite;
pic.custom_ptr = &writer;
現在可以壓縮輸入樣本了 (之後釋出記憶體):
int ok = WebPEncode(&config, &pic);
WebPPictureFree(&pic); // Always free the memory associated with the input.
if (!ok) {
printf("Encoding error: %d\n", pic.error_code);
} else {
printf("Output size: %d\n", writer.size);
}
如要進一步瞭解 API 和結構的使用方式,建議您查看 webp/encode.h
標頭中的可用說明文件。閱讀程式碼範例 examples/cwebp.c
很實用,可證明您能找出較少使用的參數。