WebP API 說明文件

本節說明 WebP 程式庫中包含的編碼器和解碼器專用 API。此 API 說明適用於 1.3.2 版。

標頭與程式庫

安裝 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 圖片標頭,並擷取圖片寬度和高度。如果系統判定指標不相關,可以傳遞 NULL*height 指標 *width

輸入屬性

資料或曾存取這類資料的人員
WebP 圖片資料指標
資料大小
這是包含圖片資料的 data 所指向的記憶體區塊大小。

傳回

false
在發生 (a) 格式錯誤時傳回的錯誤代碼。
true
成效卓越。*width*height 只有在傳回成功時才會生效。
width
整數值。範圍限制為 1 至 16383。
height
整數值。範圍限制從 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 所指向的記憶體區塊大小。

傳回

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 所指向的記憶體區塊大小
width
整數值。目前範圍限制在 1 至 16383 之間。
height
整數值。目前範圍限制在 1 至 16383 之間。

傳回

uint8_t*
分別以線性 RGBA/ARGB/BGRA/RGB/BGR 順序解碼的 WebP 圖片樣本指標。
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 所指向的記憶體區塊大小
輸出_緩衝區大小
整數值。分配的緩衝區大小
輸出內容_stride
整數值。指定掃描線之間的距離。

傳回

輸出緩衝區
用於解碼 WebP 圖片的指標。
uint8_t*
output_buffer 表示函式成功;否則為 NULL

進階解碼 API

WebP 解碼支援進階 API,讓您可即時裁剪和調整大小,這對手機等記憶體有限的環境而言非常有用。基本上,記憶體用量會隨著輸出大小改變,而不是因為一個需要快速預覽,或放大過度放大相片的一部分而放大輸入。有些 CPU 有時可能會一併儲存。

WebP 解碼有兩種變體 viz 完整圖片解碼,以及對小型輸入緩衝區進行漸進式解碼。使用者可以選擇提供外部記憶體緩衝區,用來解碼圖片。下列程式碼範例會逐步介紹使用進階解碼 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_YUVMODE_YUVA,將圖片解碼為 YUV 和 YUVA 格式。此格式又稱為 Y'CbCr

簡易編碼 API

系統會提供部分非常簡單的函式,用於在最常見的版面配置中 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;如果失敗,系統會傳回 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 有助於找出較少使用的參數。