Phần này mô tả API cho bộ mã hoá và bộ giải mã có trong thư viện WebP. Nội dung mô tả API này liên quan đến phiên bản 1.5.0.
Tiêu đề và thư viện
Khi bạn cài đặt libwebp
, một thư mục có tên webp/
sẽ được cài đặt ở vị trí thông thường cho nền tảng của bạn. Ví dụ: trên các nền tảng Unix, các tệp tiêu đề sau sẽ được sao chép vào /usr/local/include/webp/
.
decode.h
encode.h
types.h
Các thư viện này nằm trong thư mục thư viện thông thường. Thư viện tĩnh và động nằm trong /usr/local/lib/
trên các nền tảng Unix.
API giải mã đơn giản
Để bắt đầu sử dụng API giải mã, bạn phải đảm bảo rằng bạn đã cài đặt thư viện và tệp tiêu đề như mô tả ở trên.
Thêm tiêu đề API giải mã vào mã C/C++ như sau:
#include "webp/decode.h"
int WebPGetInfo(const uint8_t* data, size_t data_size, int* width, int* height);
Hàm này sẽ xác thực tiêu đề hình ảnh WebP và truy xuất chiều rộng và chiều cao hình ảnh. Bạn có thể truyền con trỏ *width
và *height
NULL
nếu cho là không liên quan.
Thuộc tính đầu vào
- dữ liệu
- Con trỏ đến dữ liệu hình ảnh WebP
- data_size
- Đây là kích thước của khối bộ nhớ mà
data
trỏ đến, chứa dữ liệu hình ảnh.
Giá trị trả về
- false
- Mã lỗi được trả về trong trường hợp (các) lỗi định dạng.
- đúng
- Khi thành công.
*width
và*height
chỉ hợp lệ khi trả về thành công. - chiều rộng
- Giá trị số nguyên. Phạm vi này bị giới hạn từ 1 đến 16383.
- độ cao
- Giá trị số nguyên. Phạm vi này bị giới hạn từ 1 đến 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);
Hàm này sẽ truy xuất các tính năng từ luồng bit. Cấu trúc *features
được điền sẵn thông tin thu thập được từ luồng bit:
Thuộc tính đầu vào
- dữ liệu
- Con trỏ đến dữ liệu hình ảnh WebP
- data_size
- Đây là kích thước của khối bộ nhớ mà
data
trỏ đến, chứa dữ liệu hình ảnh.
Giá trị trả về
VP8_STATUS_OK
- Khi các tính năng được truy xuất thành công.
VP8_STATUS_NOT_ENOUGH_DATA
- Khi cần thêm dữ liệu để truy xuất các tính năng từ tiêu đề.
Các giá trị lỗi VP8StatusCode
bổ sung trong các trường hợp khác.
- tính năng
- Con trỏ trỏ đến cấu trúc 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);
Các hàm này giải mã hình ảnh WebP do data
trỏ đến.
WebPDecodeRGBA
trả về các mẫu hình ảnh RGBA theo thứ tự[r0, g0, b0, a0, r1, g1, b1, a1, ...]
.WebPDecodeARGB
trả về các mẫu hình ảnh ARGB theo thứ tự[a0, r0, g0, b0, a1, r1, g1, b1, ...]
.WebPDecodeBGRA
trả về các mẫu hình ảnh BGRA theo thứ tự[b0, g0, r0, a0, b1, g1, r1, a1, ...]
.WebPDecodeRGB
trả về các mẫu hình ảnh RGB theo thứ tự[r0, g0, b0, r1, g1, b1, ...]
.WebPDecodeBGR
trả về các mẫu hình ảnh BGR theo thứ tự[b0, g0, r0, b1, g1, r1, ...]
.
Mã gọi bất kỳ hàm nào trong số này phải xoá vùng đệm dữ liệu (uint8_t*)
do các hàm này trả về bằng WebPFree()
.
Thuộc tính đầu vào
- dữ liệu
- Con trỏ đến dữ liệu hình ảnh WebP
- data_size
- Đây là kích thước của khối bộ nhớ mà
data
trỏ đến, chứa dữ liệu hình ảnh - chiều rộng
- Giá trị số nguyên. Phạm vi hiện bị giới hạn từ 1 đến 16383.
- độ cao
- Giá trị số nguyên. Phạm vi hiện bị giới hạn từ 1 đến 16383.
Giá trị trả về
- uint8_t*
- Con trỏ đến các mẫu hình ảnh WebP đã giải mã theo thứ tự RGBA/ARGB/BGRA/RGB/BGR tuyến tính tương ứng.
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);
Các hàm này là biến thể của các hàm ở trên và giải mã hình ảnh trực tiếp vào vùng đệm output_buffer
được phân bổ trước. Dung lượng lưu trữ tối đa có trong vùng đệm này được biểu thị bằng output_buffer_size
. Nếu bộ nhớ này không đủ (hoặc xảy ra lỗi), NULL
sẽ được trả về. Nếu không, hệ thống sẽ trả về output_buffer
để thuận tiện.
Tham số output_stride
chỉ định khoảng cách (tính bằng byte) giữa các dòng quét. Do đó, output_buffer_size
dự kiến sẽ có giá trị tối thiểu là output_stride * picture - height
.
Thuộc tính đầu vào
- dữ liệu
- Con trỏ đến dữ liệu hình ảnh WebP
- data_size
- Đây là kích thước của khối bộ nhớ mà
data
trỏ đến, chứa dữ liệu hình ảnh - output_buffer_size
- Giá trị số nguyên. Kích thước của bộ nhớ đệm được phân bổ
- output_stride
- Giá trị số nguyên. Chỉ định khoảng cách giữa các dòng quét.
Giá trị trả về
- output_buffer
- Con trỏ đến hình ảnh WebP đã giải mã.
- uint8_t*
output_buffer
nếu hàm thành công;NULL
nếu không.
Advanced Decoding API (API giải mã nâng cao)
Tính năng giải mã WebP hỗ trợ một API nâng cao để cung cấp khả năng cắt và điều chỉnh theo tỷ lệ nhanh chóng, một tính năng rất hữu ích trong các môi trường bị hạn chế về bộ nhớ như điện thoại di động. Về cơ bản, mức sử dụng bộ nhớ sẽ tăng theo kích thước đầu ra, chứ không phải kích thước đầu vào khi người dùng chỉ cần xem trước nhanh hoặc phóng to một phần của hình ảnh quá lớn. Một số CPU cũng có thể được lưu.
Quá trình giải mã WebP có hai biến thể, đó là giải mã hình ảnh đầy đủ và giải mã tăng dần qua vùng đệm đầu vào nhỏ. Người dùng có thể tuỳ ý cung cấp vùng đệm bộ nhớ ngoài để giải mã hình ảnh. Mã mẫu sau đây sẽ hướng dẫn các bước sử dụng API giải mã nâng cao.
Trước tiên, chúng ta cần khởi tạo một đối tượng cấu hình:
#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.
Các tuỳ chọn giải mã được thu thập trong cấu trúc 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]
};
Bạn có thể đọc các tính năng luồng bit vào config.input
(không bắt buộc) trong trường hợp cần biết trước các tính năng đó. Ví dụ: bạn có thể biết được hình ảnh có độ trong suốt hay không. Xin lưu ý rằng thao tác này cũng sẽ phân tích cú pháp tiêu đề của luồng bit, do đó, đây là một cách hay để biết liệu luồng bit có giống với luồng WebP hợp lệ hay không.
CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
Sau đó, chúng ta cần thiết lập bộ đệm bộ nhớ giải mã trong trường hợp muốn cung cấp bộ đệm đó trực tiếp thay vì dựa vào bộ giải mã để phân bổ bộ đệm. Chúng ta chỉ cần cung cấp con trỏ cho bộ nhớ cũng như tổng kích thước của vùng đệm và bước đường quét (khoảng cách tính bằng byte giữa các đường quét).
// 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;
Hình ảnh đã sẵn sàng để giải mã. Có hai biến thể có thể dùng để giải mã hình ảnh. Chúng ta có thể giải mã hình ảnh cùng một lúc bằng cách sử dụng:
CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK);
Ngoài ra, chúng ta có thể sử dụng phương thức gia tăng để giải mã hình ảnh dần dần khi có sẵn các byte mới:
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.
Hình ảnh đã giải mã hiện nằm trong config.output (hoặc chính xác hơn là trong config.output.u.RGBA trong trường hợp này, vì không gian màu đầu ra được yêu cầu là MODE_BGRA). Hình ảnh có thể được lưu, hiển thị hoặc xử lý theo cách khác. Sau đó, chúng ta chỉ cần thu hồi bộ nhớ được phân bổ trong đối tượng của cấu hình. Bạn có thể an toàn khi gọi hàm này ngay cả khi bộ nhớ là bộ nhớ ngoài và không được WebPDecode() phân bổ:
WebPFreeDecBuffer(&config.output);
Khi sử dụng API này, hình ảnh cũng có thể được giải mã thành định dạng YUV và YUVA, tương ứng là MODE_YUV
và MODE_YUVA
. Định dạng này còn được gọi là Y'CbCr.
Simple Encoding API
Một số hàm rất đơn giản được cung cấp để mã hoá các mảng mẫu RGBA trong hầu hết các bố cục phổ biến. Các thuộc tính này được khai báo trong tiêu đề webp/encode.h
như sau:
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);
Hệ số chất lượng quality_factor
nằm trong khoảng từ 0 đến 100 và kiểm soát độ hao tổn cũng như chất lượng trong quá trình nén. Giá trị 0 tương ứng với chất lượng thấp và kích thước đầu ra nhỏ, trong khi 100 là chất lượng cao nhất và kích thước đầu ra lớn nhất.
Khi thành công, các byte đã nén sẽ được đặt trong con trỏ *output
và kích thước tính bằng byte sẽ được trả về (nếu không, giá trị 0 sẽ được trả về trong trường hợp không thành công). Phương thức gọi phải gọi WebPFree()
trên con trỏ *output
để thu hồi bộ nhớ.
Mảng đầu vào phải là một mảng byte được đóng gói (một mảng cho mỗi kênh, như tên hàm dự kiến). stride
tương ứng với số byte cần thiết để chuyển từ một hàng sang hàng tiếp theo. Ví dụ: bố cục BGRA là:
Có các hàm tương đương để mã hoá không suy hao, với chữ ký:
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);
Xin lưu ý rằng các hàm này, giống như các phiên bản bị mất dữ liệu, sử dụng chế độ cài đặt mặc định của thư viện. Đối với chế độ không mất dữ liệu, điều này có nghĩa là chế độ "chính xác" bị tắt. Các giá trị RGB trong các vùng trong suốt sẽ được sửa đổi để cải thiện khả năng nén. Để tránh điều này, hãy sử dụng WebPEncode()
và đặt WebPConfig::exact
thành 1
.
Advanced Encoding API
Bên trong, bộ mã hoá đi kèm với nhiều tham số mã hoá nâng cao.
Các tham số này có thể hữu ích để cân bằng tốt hơn giữa hiệu quả nén và thời gian xử lý.
Các thông số này được thu thập trong cấu trúc WebPConfig
.
Các trường được sử dụng nhiều nhất của cấu trúc này là:
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
};
Xin lưu ý rằng bạn có thể truy cập vào hầu hết các tham số này để thử nghiệm bằng công cụ dòng lệnh cwebp
.
Các mẫu đầu vào phải được gói vào cấu trúc WebPPicture
.
Cấu trúc này có thể lưu trữ các mẫu đầu vào ở định dạng RGBA hoặc YUVA, tuỳ thuộc vào giá trị của cờ use_argb
.
Cấu trúc được sắp xếp như sau:
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;
};
Cấu trúc này cũng có một hàm để phát các byte nén khi chúng được cung cấp. Hãy xem ví dụ bên dưới về trình ghi trong bộ nhớ.
Các trình ghi khác có thể trực tiếp lưu trữ dữ liệu vào một tệp (xem examples/cwebp.c
để biết ví dụ như vậy).
Quy trình chung để mã hoá bằng API nâng cao như sau:
Trước tiên, chúng ta cần thiết lập cấu hình mã hoá chứa các tham số nén. Xin lưu ý rằng bạn có thể sử dụng cùng một cấu hình để nén nhiều hình ảnh khác nhau sau đó.
#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)
Sau đó, bạn cần tham chiếu các mẫu đầu vào vào WebPPicture
bằng cách tham chiếu hoặc sao chép. Dưới đây là ví dụ về cách phân bổ vùng đệm để lưu trữ các mẫu. Tuy nhiên, bạn có thể dễ dàng thiết lập "thành phần hiển thị" cho một mảng mẫu đã được phân bổ. Xem hàm 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.
Để phát các byte đã nén, một trình nối sẽ được gọi mỗi khi có các byte mới. Dưới đây là ví dụ đơn giản với trình ghi bộ nhớ được khai báo trong webp/encode.h
. Bạn có thể cần đến quá trình khởi chạy này để mỗi bức ảnh nén:
// Set up a byte-writing method (write-to-memory, in this case):
WebPMemoryWriter writer;
WebPMemoryWriterInit(&writer);
pic.writer = WebPMemoryWrite;
pic.custom_ptr = &writer;
Bây giờ, chúng ta đã sẵn sàng nén các mẫu đầu vào (và giải phóng bộ nhớ của các mẫu đó sau đó):
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);
}
Để sử dụng API và cấu trúc nâng cao hơn, bạn nên xem tài liệu có trong tiêu đề webp/encode.h
.
Việc đọc mã ví dụ examples/cwebp.c
có thể hữu ích để khám phá các thông số ít được sử dụng hơn.