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.6.0.
Đầu trang 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 tại 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 đây 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 các thư mục thư viện thông thường. Các thư viện tĩnh và động nằm trong /usr/local/lib/
trên các nền tảng Unix.
Simple Decoding API
Để 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.
Đưa tiêu đề API giải mã vào mã C/C++ của bạn 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 cũng như chiều cao của hình ảnh. Bạn có thể truyền con trỏ *width
và *height
NULL
nếu cho rằng không liên quan.
Thuộc tính đầu vào
- khác
- Con trỏ đến dữ liệu hình ảnh WebP
- data_size
- Đây là kích thước của khối bộ nhớ được
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.
- true
- 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 giới hạn từ 1 đến 16383.
- độ cao
- Giá trị số nguyên. Phạm vi 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 đối tượng từ luồng bit. Cấu trúc *features
chứa thông tin được thu thập từ luồng bit:
Thuộc tính đầu vào
- khác
- Con trỏ đến dữ liệu hình ảnh WebP
- data_size
- Đây là kích thước của khối bộ nhớ được
data
trỏ đến, chứa dữ liệu hình ảnh.
Giá trị trả về
VP8_STATUS_OK
- Khi truy xuất thành công các đối tượ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
khác trong những trường hợp khác.
- tính năng
- Con 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ã một hình ảnh WebP được 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
- khác
- 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 tại bị giới hạn từ 1 đến 16383.
- độ cao
- Giá trị số nguyên. Phạm vi hiện tại 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 được phân bổ trước output_buffer
. 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), thì NULL
sẽ được trả về. Nếu không, output_buffer
sẽ được trả về để thuận tiện.
Tham số output_stride
chỉ định khoảng cách (tính bằng byte) giữa các đường quét. Do đó, output_buffer_size
dự kiến sẽ có ít nhất output_stride * picture - height
.
Thuộc tính đầu vào
- khác
- 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 vùng đệm được phân bổ
- output_stride
- Giá trị số nguyên. Chỉ định khoảng cách giữa các đườ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
Hoạt độ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 tỷ lệ tức thì, 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ỷ lệ thuận với 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 nhanh hoặc phóng to một phần của bức ảnh có kích thước quá lớn. Tình cờ là bạn cũng có thể tiết kiệm được một số CPU.
Quá trình giải mã WebP có 2 biến thể, cụ thể là giải mã hình ảnh đầy đủ và giải mã gia tăng trên các vùng đệm đầu vào nhỏ. Người dùng có thể cung cấp một vùng đệm bộ nhớ bên ngoài để giải mã hình ảnh (không bắt buộc). 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 lựa 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 bitstream vào config.input
(nếu cần biết trước). Ví dụ: bạn có thể biết liệu 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 và do đó, đây là một cách hay để biết liệu luồng bit có giống với một luồng bit 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 trực tiếp thay vì dựa vào bộ giải mã để phân bổ. 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 dòng (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 để được giải mã. Có 2 biến thể có thể có để 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 pháp gia tăng để giải mã dần hình ảnh khi có 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.
Giờ đây, hình ảnh đã giải mã 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ì hệ 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 config. Bạn có thể 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 dùng API này, hình ảnh cũng có thể được giải mã thành định dạng YUV và YUVA bằng cách dùng lần lượt 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á mảng mẫu RGBA trong bố cục phổ biến nhất. Chúng được khai báo trong tiêu đề webp/encode.h
dưới dạng:
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 mức độ mất dữ liệu 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, 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ỗi mảng cho một kênh, như tên của hàm dự kiến). stride
tương ứng với số byte cần thiết để chuyển từ hàng này 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 mất dữ liệu, 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 (như các phiên bản có tổn hao) sử dụng chế độ cài đặt mặc định của thư viện. Đối với chế độ nén 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 dùng WebPEncode()
và đặt WebPConfig::exact
thành 1
.
Advanced Encoding API
Về cơ bản, bộ mã hoá đi kèm với nhiều thông số mã hoá nâng cao.
Các kỹ thuật này có thể hữu ích để cân bằng tốt hơn sự đánh đổi giữa hiệu quả nén và thời gian xử lý.
Các tham số này được thu thập trong cấu trúc WebPConfig
.
Các trường được 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 ra 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 một 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 một số 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 đó, các mẫu đầu vào cần được tham chiếu vào một WebPPicture
bằng cách tham chiếu hoặc sao chép. Sau đâ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 một "khung 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 ra các byte đã nén, một lệnh gọi hook sẽ được thực hiện mỗi khi có byte mới. Sau đây là một 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 khởi chạy này cho 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 chúng 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 cho việc khám phá các thông số ít được sử dụng.