Cette section décrit l'API de l'encodeur et du décodeur inclus dans la bibliothèque WebP. Cette description de l'API concerne la version 1.6.0.
En-têtes et bibliothèques
Lorsque vous installez libwebp
, un répertoire nommé webp/
est installé à l'emplacement habituel de votre plate-forme. Par exemple, sur les plates-formes Unix, les fichiers d'en-tête suivants seraient copiés dans /usr/local/include/webp/
.
decode.h
encode.h
types.h
Les bibliothèques se trouvent dans les répertoires de bibliothèques habituels. Les bibliothèques statiques et dynamiques se trouvent dans /usr/local/lib/
sur les plates-formes Unix.
API Simple Decoding
Pour commencer à utiliser l'API de décodage, vous devez vous assurer que la bibliothèque et les fichiers d'en-tête sont installés, comme décrit ci-dessus.
Incluez l'en-tête de l'API de décodage dans votre code C/C++ comme suit :
#include "webp/decode.h"
int WebPGetInfo(const uint8_t* data, size_t data_size, int* width, int* height);
Cette fonction validera l'en-tête de l'image WebP et récupérera la largeur et la hauteur de l'image. Les pointeurs *width
et *height
peuvent être transmis NULL
s'ils sont jugés non pertinents.
Attributs d'entrée
- données
- Pointeur vers les données d'image WebP
- data_size
- Il s'agit de la taille du bloc de mémoire pointé par
data
contenant les données d'image.
Renvoie
- faux
- Code d'erreur renvoyé en cas d'erreur(s) de mise en forme.
- true
- En cas de réussite.
*width
et*height
ne sont valables qu'en cas de retour réussi. - largeur
- : valeur entière. La plage de valeurs est limitée de 1 à 16 383.
- hauteur
- : valeur entière. La plage est limitée de 1 à 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);
Cette fonction récupère les caractéristiques du flux de bits. La structure *features
est remplie avec les informations recueillies à partir du flux de bits :
Attributs d'entrée
- données
- Pointeur vers les données d'image WebP
- data_size
- Il s'agit de la taille du bloc de mémoire pointé par
data
contenant les données d'image.
Renvoie
VP8_STATUS_OK
- Lorsque les fonctionnalités sont récupérées.
VP8_STATUS_NOT_ENOUGH_DATA
- Lorsque davantage de données sont nécessaires pour récupérer les caractéristiques des en-têtes.
Valeurs d'erreur VP8StatusCode
supplémentaires dans d'autres cas.
- fonctionnalités
- Pointeur vers la structure 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);
Ces fonctions décodent une image WebP pointée par data
.
WebPDecodeRGBA
renvoie des exemples d'images RGBA dans l'ordre[r0, g0, b0, a0, r1, g1, b1, a1, ...]
.WebPDecodeARGB
renvoie des exemples d'images ARVB dans l'ordre[a0, r0, g0, b0, a1, r1, g1, b1, ...]
.WebPDecodeBGRA
renvoie des exemples d'images BGRA dans l'ordre[b0, g0, r0, a0, b1, g1, r1, a1, ...]
.WebPDecodeRGB
renvoie des exemples d'images RVB dans l'ordre[r0, g0, b0, r1, g1, b1, ...]
.WebPDecodeBGR
renvoie des exemples d'images BGR dans l'ordre[b0, g0, r0, b1, g1, r1, ...]
.
Le code qui appelle l'une de ces fonctions doit supprimer le tampon de données (uint8_t*)
renvoyé par ces fonctions avec WebPFree()
.
Attributs d'entrée
- données
- Pointeur vers les données d'image WebP
- data_size
- Il s'agit de la taille du bloc de mémoire pointé par
data
contenant les données d'image. - largeur
- : valeur entière. La plage est actuellement limitée de 1 à 16 383.
- hauteur
- : valeur entière. La plage est actuellement limitée de 1 à 16 383.
Renvoie
- uint8_t*
- Pointeur vers les exemples d'images WebP décodées dans l'ordre RGBA/ARGB/BGRA/RGB/BGR linéaire, respectivement.
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);
Ces fonctions sont des variantes de celles ci-dessus et décodent l'image directement dans un tampon préalloué output_buffer
. L'espace de stockage maximal disponible dans cette mémoire tampon est indiqué par output_buffer_size
. Si cet espace de stockage n'est pas suffisant (ou si une erreur s'est produite), NULL
est renvoyé. Sinon, output_buffer
est renvoyé, pour plus de commodité.
Le paramètre output_stride
spécifie la distance (en octets) entre les lignes de balayage. Par conséquent, output_buffer_size
doit être au moins égal à output_stride * picture - height
.
Attributs d'entrée
- données
- Pointeur vers les données d'image WebP
- data_size
- Il s'agit de la taille du bloc de mémoire pointé par
data
contenant les données d'image. - output_buffer_size
- : valeur entière. Taille de la mémoire tampon allouée
- output_stride
- : valeur entière. Spécifie la distance entre les lignes de balayage.
Renvoie
- output_buffer
- Pointeur vers l'image WebP décodée.
- uint8_t*
output_buffer
si la fonction réussit,NULL
dans le cas contraire.
Advanced Decoding API
Le décodage WebP est compatible avec une API avancée qui permet de recadrer et de redimensionner les images à la volée, ce qui est très utile dans les environnements à mémoire limitée comme les téléphones mobiles. En gros, l'utilisation de la mémoire sera proportionnelle à la taille de la sortie, et non à celle de l'entrée, lorsqu'il ne faut qu'un aperçu rapide ou une partie agrandie d'une image trop grande. Par ailleurs, vous pouvez également économiser du processeur.
Le décodage WebP se présente sous deux variantes : le décodage d'image complète et le décodage incrémentiel sur de petits tampons d'entrée. Les utilisateurs peuvent éventuellement fournir un tampon de mémoire externe pour décoder l'image. L'exemple de code suivant décrit les étapes d'utilisation de l'API de décodage avancé.
Nous devons d'abord initialiser un objet de configuration :
#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.
Les options de décodage sont regroupées dans la structure 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]
};
Les caractéristiques du flux de bits peuvent être lues dans config.input
, au cas où nous aurions besoin de les connaître à l'avance. Par exemple, il peut être utile de savoir si l'image est transparente. Notez que cela analysera également l'en-tête du flux binaire. C'est donc un bon moyen de savoir si le flux binaire ressemble à un flux WebP valide.
CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
Nous devons ensuite configurer le tampon de mémoire de décodage au cas où nous souhaiterions le fournir directement au lieu de nous appuyer sur le décodeur pour son allocation. Il nous suffit de fournir le pointeur vers la mémoire, ainsi que la taille totale du tampon et le pas de ligne (distance en octets entre les lignes de balayage).
// 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;
L'image est prête à être décodée. Il existe deux variantes possibles pour décoder l'image. Nous pouvons décoder l'image en une seule fois à l'aide de la commande suivante :
CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK);
Vous pouvez également utiliser la méthode incrémentielle pour décoder progressivement l'image à mesure que de nouveaux octets sont disponibles :
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.
L'image décodée se trouve maintenant dans config.output (ou plutôt dans config.output.u.RGBA dans ce cas, puisque l'espace colorimétrique de sortie demandé était MODE_BGRA). L'image peut être enregistrée, affichée ou traitée d'une autre manière. Ensuite, il ne nous reste plus qu'à récupérer la mémoire allouée dans l'objet de configuration. Il est possible d'appeler cette fonction même si la mémoire est externe et n'a pas été allouée par WebPDecode() :
WebPFreeDecBuffer(&config.output);
Cette API permet également de décoder l'image aux formats YUV et YUVA, en utilisant respectivement MODE_YUV
et MODE_YUVA
. Ce format est également appelé Y'CbCr.
API Simple Encoding
Certaines fonctions très simples sont fournies pour encoder des tableaux d'échantillons RGBA dans les mises en page les plus courantes. Elles sont déclarées dans l'en-tête webp/encode.h
comme suit :
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);
Le facteur de qualité quality_factor
est compris entre 0 et 100, et contrôle la perte et la qualité lors de la compression. La valeur 0 correspond à une qualité faible et à une petite taille de sortie, tandis que 100 correspond à la qualité la plus élevée et à la taille de sortie la plus grande.
En cas de réussite, les octets compressés sont placés dans le pointeur *output
et la taille en octets est renvoyée (sinon, 0 est renvoyé en cas d'échec). L'appelant doit appeler WebPFree()
sur le pointeur *output
pour récupérer la mémoire.
Le tableau d'entrée doit être un tableau compressé d'octets (un pour chaque canal, comme prévu par le nom de la fonction). stride
correspond au nombre d'octets nécessaires pour passer d'une ligne à la suivante. Par exemple, la mise en page BGRA est la suivante :
Il existe des fonctions équivalentes pour l'encodage sans perte, avec les signatures suivantes :
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);
Notez que ces fonctions, comme les versions avec perte, utilisent les paramètres par défaut de la bibliothèque. Pour le format sans perte, cela signifie que la qualité "exacte" est désactivée. Les valeurs RVB dans les zones transparentes seront modifiées pour améliorer la compression. Pour éviter cela, utilisez WebPEncode()
et définissez WebPConfig::exact
sur 1
.
API Advanced Encoding
En arrière-plan, l'encodeur est fourni avec de nombreux paramètres d'encodage avancés.
Ils peuvent être utiles pour mieux équilibrer le compromis entre l'efficacité de la compression et le temps de traitement.
Ces paramètres sont rassemblés dans la structure WebPConfig
.
Voici les champs les plus utilisés de cette structure :
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
};
Notez que la plupart de ces paramètres sont accessibles pour les tests à l'aide de l'outil de ligne de commande cwebp
.
Les exemples d'entrée doivent être encapsulés dans une structure WebPPicture
.
Cette structure peut stocker des exemples d'entrée au format RGBA ou YUVA, selon la valeur de l'indicateur use_argb
.
La structure est organisée comme suit :
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;
};
Cette structure dispose également d'une fonction permettant d'émettre les octets compressés au fur et à mesure de leur disponibilité. Vous trouverez ci-dessous un exemple avec un enregistreur en mémoire.
D'autres rédacteurs peuvent stocker directement des données dans un fichier (voir examples/cwebp.c
pour un exemple).
Le flux général d'encodage à l'aide de l'API avancée se présente comme suit :
Nous devons d'abord configurer un encodage contenant les paramètres de compression. Notez que la même configuration peut être utilisée pour compresser plusieurs images différentes par la suite.
#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)
Les exemples d'entrée doivent ensuite être référencés dans un WebPPicture
, soit par référence, soit par copie. Voici un exemple d'allocation du tampon pour contenir les échantillons. Cependant, il est facile de configurer une "vue" sur un tableau d'échantillons déjà alloué. Consultez la fonction 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.
Pour émettre les octets compressés, un crochet est appelé chaque fois que de nouveaux octets sont disponibles. Voici un exemple simple avec le memory-writer déclaré dans webp/encode.h
. Cette initialisation est probablement nécessaire pour compresser chaque image :
// Set up a byte-writing method (write-to-memory, in this case):
WebPMemoryWriter writer;
WebPMemoryWriterInit(&writer);
pic.writer = WebPMemoryWrite;
pic.custom_ptr = &writer;
Nous sommes maintenant prêts à compresser les exemples d'entrée (et à libérer leur mémoire par la suite) :
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);
}
Pour une utilisation plus avancée de l'API et de la structure, il est recommandé de consulter la documentation disponible dans l'en-tête webp/encode.h
.
La lecture de l'exemple de code examples/cwebp.c
peut s'avérer utile pour découvrir les paramètres les moins utilisés.