W tej sekcji opisano interfejsy API dla kodera i dekodera zawartych w bibliotece WebP. Ten opis interfejsu API dotyczy wersji 1.3.2.
Nagłówki i biblioteki
Podczas instalacji libwebp
katalog o nazwie webp/
zostanie zainstalowany w typowej lokalizacji na Twojej platformie. Na przykład na platformach Unix te pliki nagłówka byłyby kopiowane do /usr/local/include/webp/
.
decode.h
encode.h
types.h
Biblioteki te znajdują się w zwykłych katalogach bibliotek. Biblioteki statyczne i dynamiczne są dostępne w języku /usr/local/lib/
na platformach Unix.
Simple Decoding API
Aby zacząć korzystać z interfejsu API dekodowania, musisz zainstalować bibliotekę i pliki nagłówkowe w sposób opisany powyżej.
Umieść nagłówek interfejsu dekodowania interfejsu API w kodzie C/C++ w ten sposób:
#include "webp/decode.h"
int WebPGetInfo(const uint8_t* data, size_t data_size, int* width, int* height);
Ta funkcja sprawdza nagłówek obrazu WebP oraz pobiera szerokość i wysokość obrazu. Wskaźniki *width
i *height
można przekazywać NULL
, jeśli zostaną uznane za nieistotne.
Atrybuty wejściowe
- dane
- Wskaż dane obrazu WebP
- data_size
- Jest to rozmiar bloku pamięci, na który wskazuje
data
, zawierający dane obrazu.
Akcje powrotne
- false
- Kod błędu zwrócony w przypadku (a) błędów formatowania.
- prawda
- Na sukces. Wartości
*width
i*height
są ważne tylko w przypadku pomyślnego zwrotu. - szerokość
- Liczba całkowita. Może on wynosić od 1 do 16 383.
- wysokość
- Liczba całkowita. Zakres jest ograniczony od 1 do 16 383.
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);
Ta funkcja pobierze cechy ze strumienia bitowego. Struktura *features
jest wypełniana informacjami zebranymi ze strumienia bitowego:
Atrybuty wejściowe
- dane
- Wskaż dane obrazu WebP
- data_size
- Jest to rozmiar bloku pamięci, na który wskazuje
data
, zawierający dane obrazu.
Akcje powrotne
VP8_STATUS_OK
- Po pobraniu funkcji.
VP8_STATUS_NOT_ENOUGH_DATA
- Gdy do pobrania cech z nagłówków potrzeba więcej danych.
Dodatkowe wartości błędu (VP8StatusCode
) w innych przypadkach.
- Funkcje
- Wskazuje strukturę 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);
Te funkcje dekodują obraz WebP wskazywany przez: data
.
WebPDecodeRGBA
zwraca próbki obrazów RGBA w kolejności[r0, g0, b0, a0, r1, g1, b1, a1, ...]
.WebPDecodeARGB
zwraca próbki obrazów ARGB w kolejności[a0, r0, g0, b0, a1, r1, g1, b1, ...]
.WebPDecodeBGRA
zwraca próbki obrazów BGRA w kolejności[b0, g0, r0, a0, b1, g1, r1, a1, ...]
.WebPDecodeRGB
zwraca próbki obrazów RGB w kolejności[r0, g0, b0, r1, g1, b1, ...]
.WebPDecodeBGR
zwraca próbki obrazów BGR w kolejności[b0, g0, r0, b1, g1, r1, ...]
.
Kod wywołujący dowolną z tych funkcji musi usunąć bufor danych (uint8_t*)
zwrócony przez te funkcje z atrybutem WebPFree()
.
Atrybuty wejściowe
- dane
- Wskaż dane obrazu WebP
- data_size
- Jest to rozmiar bloku pamięci, na który wskazuje
data
, zawierający dane obrazu - szerokość
- Liczba całkowita. Zakres jest obecnie ograniczony od 1 do 16 383.
- wysokość
- Liczba całkowita. Zakres jest obecnie ograniczony od 1 do 16 383.
Akcje powrotne
- uint8_t*
- Wskazuje zdekodowane próbki obrazów WebP w liniowej kolejności 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);
Te funkcje są wariantami powyższych funkcji i dekodują obraz bezpośrednio do wstępnie przydzielonego bufora output_buffer
. Maksymalna ilość dostępnego miejsca w tym buforze jest określona wartością output_buffer_size
. Jeśli ilość miejsca na dane będzie niewystarczająca (lub wystąpił błąd), zwracana jest wartość NULL
. W przeciwnym razie dla wygody zwracana jest wartość output_buffer
.
Parametr output_stride
określa odległość (w bajtach) między liniami skanowania. Dlatego wartość output_buffer_size
powinna wynosić co najmniej output_stride * picture - height
.
Atrybuty wejściowe
- dane
- Wskaż dane obrazu WebP
- data_size
- Jest to rozmiar bloku pamięci, na który wskazuje
data
, zawierający dane obrazu - output_buffer_size
- Liczba całkowita. Rozmiar przydzielonego bufora
- output_stride
- Liczba całkowita. Określa odległość między liniami skanowania.
Akcje powrotne
- output_buffer
- Wskaźnik zdekodowanego obrazu WebP.
- uint8_t*
output_buffer
, jeśli funkcja jest skuteczna; w przeciwnym razieNULL
.
Interfejs API zaawansowanego dekodowania
Dekodowanie WebP obsługuje zaawansowany interfejs API, który umożliwia przycinanie i skalowanie na bieżąco. Jest to niezwykle przydatne w środowiskach z ograniczoną pamięcią, takich jak telefony komórkowe. Zasadniczo wykorzystanie pamięci będzie skalowane zgodnie z rozmiarem danych wyjściowych, a nie danych wejściowych, gdy potrzebny jest tylko szybki podgląd lub powiększony fragment zbyt dużego obrazu. Niektóre procesory też można przypadkiem zaoszczędzić.
Dekodowanie WebP występuje w 2 wariantach – pełnego dekodowania obrazu i dekodowania przyrostowego z wykorzystaniem małych buforów wejściowych. Użytkownicy mogą opcjonalnie udostępnić zewnętrzny bufor pamięci do dekodowania obrazu. Z podanego niżej przykładowego kodu dowiesz się, jak korzystać z interfejsu API zaawansowanego dekodowania.
Najpierw musimy zainicjować obiekt konfiguracji:
#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.
Opcje dekodowania są zbierane w ramach struktury 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]
};
Opcjonalnie funkcje strumienia bitów mogą zostać odczytywane w interfejsie config.input
na wypadek, gdyby trzeba je było poznać z wyprzedzeniem. Dobrze jest na przykład wiedzieć,
czy obraz jest w ogóle przezroczysty. Pamiętaj, że spowoduje to również przeanalizowanie nagłówka strumienia bitów, więc jest to dobry sposób na sprawdzenie, czy strumień transmisji bitów wygląda jak prawidłowy w systemie WebP.
CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
Następnie musimy skonfigurować bufor pamięci dekodowania, na wypadek gdyby miał być on dostarczany bezpośrednio, a nie na podstawie przydziału dekodera. Musimy tylko podać wskaźnik do pamięci, a także całkowity rozmiar bufora oraz krok linii (odległość między wierszami skanowania w bajtach).
// 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;
Obraz jest gotowy do dekodowania. Istnieją 2 warianty dekodowania obrazu. Obraz możemy zdekodować za jednym razem, używając:
CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK);
Możemy też używać metody przyrostowej, aby stopniowo dekodować obraz w miarę udostępniania nowych bajtów:
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.
Zdekodowany obraz jest teraz dostępny w parametrze config.output (a w tym przypadku config.output.u.RGBA, ponieważ żądana wyjściowa przestrzeń kolorów to WYST.NAJCZĘŚCIEJ). Obraz można zapisać, wyświetlić lub w inny sposób przetworzyć. Potem musimy odzyskać tylko pamięć przydzieloną w obiekcie konfiguracji. Tę funkcję można bezpiecznie wywołać, nawet jeśli pamięć jest zewnętrzna i nie została przydzielona przez WebPDecode():
WebPFreeDecBuffer(&config.output);
Za pomocą tego interfejsu API obraz można też dekodować do formatów YUV i YUVA za pomocą odpowiednio MODE_YUV
i MODE_YUVA
. Format ten ma też nazwę Y'CbCr.
Simple Encoding API
Do kodowania tablic próbek RGBA w większości układów dostępnych jest kilka bardzo prostych funkcji. W nagłówku webp/encode.h
są one zadeklarowane jako:
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);
Współczynnik jakości quality_factor
mieści się w zakresie od 0 do 100 i pozwala kontrolować utratę oraz jakość podczas kompresji. Wartość 0 odpowiada niskiej jakości i niewielkim rozmiarom wyjściowym, a 100 oznacza najwyższą jakość i największy rozmiar danych wyjściowych.
Po pomyślnym zakończeniu skompresowane bajty są umieszczane w wskaźniku *output
, a rozmiar w bajtach jest zwracany (w przeciwnym razie w przypadku niepowodzenia zwracany jest rozmiar 0). Aby odzyskać pamięć, rozmówca musi wywołać metodę WebPFree()
po wskaźniku *output
.
Tablica wejściowa powinna być spakowaną tablicą bajtów (po jednym na każdy kanał, zgodnie z nazwą funkcji). stride
odpowiada liczbie bajtów potrzebnej do przeskoczenia z jednego wiersza do następnego. Na przykład układ BGRA:
Istnieją równoważne funkcje do bezstratnego kodowania z podpisami:
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);
Pamiętaj, że te funkcje, takie jak wersje stratne, korzystają z domyślnych ustawień biblioteki. W przypadku bezstratnego tryb „ścisłe” jest wyłączony. Wartości RGB w przezroczystych obszarach zostaną zmienione w celu poprawy kompresji. Aby tego uniknąć, użyj właściwości WebPEncode()
i ustaw WebPConfig::exact
na 1
.
Interfejs API zaawansowanego kodowania
Ten koder jest wyposażony w wiele zaawansowanych parametrów kodowania.
Mogą one pomóc w zachowaniu równowagi między wydajnością kompresji a czasem przetwarzania.
Te parametry są zbierane w obrębie struktury WebPConfig
.
Najczęściej używane pola tej struktury to:
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
};
Pamiętaj, że większość z tych parametrów jest dostępna do eksperymentów za pomocą narzędzia wiersza poleceń cwebp
.
Próbki wejściowe powinny być zawarte w strukturze WebPPicture
.
Ta struktura może przechowywać próbki wejściowe w formacie RGBA lub YUVA, w zależności od wartości flagi use_argb
.
Struktura jest uporządkowana w ten sposób:
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;
};
Struktura ta ma też funkcję wysyłania skompresowanych bajtów w miarę ich udostępniania. Poniżej znajdziesz przykład użycia zapisującego w pamięci.
Inni autorzy mogą zapisywać dane bezpośrednio w pliku (przykład znajdziesz tutaj: examples/cwebp.c
).
Ogólna procedura kodowania przy użyciu zaawansowanego interfejsu API wygląda tak:
Najpierw musimy skonfigurować konfigurację kodowania zawierającą parametry kompresji. Pamiętaj, że tej samej konfiguracji możesz później skompresować kilka różnych obrazów.
#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)
Następnie do próbek wejściowych należy się odwoływać w elemencie WebPPicture
za pomocą odwołania lub kopii. Oto przykład przydzielania bufora do przechowywania próbek. Można jednak łatwo skonfigurować widok dla już przydzielonej tablicy przykładowej. Zobacz funkcję 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.
Aby wysyłać skompresowane bajty, za każdym razem, gdy dostępne są nowe bajty, jest wywoływany haczyk. Oto prosty przykład z użyciem zapisującego w pamięci zadeklarowanego w zasadzie webp/encode.h
. Takie inicjowanie prawdopodobnie będzie potrzebne w przypadku każdego zdjęcia do skompresowania:
// Set up a byte-writing method (write-to-memory, in this case):
WebPMemoryWriter writer;
WebPMemoryWriterInit(&writer);
pic.writer = WebPMemoryWrite;
pic.custom_ptr = &writer;
Jesteśmy teraz gotowi do skompresowania próbek wejściowych (i zwolnienia ich pamięci później):
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);
}
Jeśli chcesz dowiedzieć się więcej o korzystaniu z interfejsu API i struktury, zapoznaj się z dokumentacją dostępną w nagłówku webp/encode.h
.
Odczytanie przykładowego kodu examples/cwebp.c
może pomóc w odkrywaniu rzadziej używanych parametrów.