Documentation sur l'API WebP

Cette section décrit l'API pour l'encodeur et le décodeur inclus dans la bibliothèque WebP. Cette description d'API concerne la version 1.4.0.

En-têtes et bibliothèques

Lorsque vous installez libwebp, un répertoire nommé webp/ est installé à l'emplacement standard de votre plate-forme. Par exemple, sur les plates-formes Unix, les fichiers d'en-tête suivants seront copiés dans /usr/local/include/webp/.

decode.h
encode.h
types.h

Les bibliothèques se trouvent dans les répertoires habituels des bibliothèques. 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 valide l'en-tête de l'image WebP, et récupère la largeur et la hauteur de l'image. Les pointeurs *width et *height peuvent être transmis avec NULL s'ils sont jugés non pertinents.

Attributs d'entrée

données
Pointer vers des données d'image WebP
data_size
Il s'agit de la taille du bloc de mémoire vers lequel pointe data, qui contient les données de l'image.

Renvoie

false
Code d'erreur renvoyé en cas (a) erreur(s) de mise en forme.
true
En cas de réussite. *width et *height ne sont valides qu'en cas de retour réussi.
largeur
Valeur entière. La plage est limitée de 1 à 16 383.
taille
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 des caractéristiques à partir du flux de bits. La structure *features est remplie d'informations collectées à partir du flux de bits:

Attributs d'entrée

données
Pointer vers des données d'image WebP
data_size
Il s'agit de la taille du bloc de mémoire vers lequel pointe data, qui contient les données de l'image.

Renvoie

VP8_STATUS_OK
Lorsque les caractéristiques ont bien été récupérées.
VP8_STATUS_NOT_ENOUGH_DATA
Lorsque davantage de données sont nécessaires pour récupérer les caractéristiques à partir des en-têtes.

Valeurs d'erreur VP8StatusCode supplémentaires dans les 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 vers laquelle data renvoie.

  • WebPDecodeRGBA renvoie des échantillons d'images RVBA dans l'ordre [r0, g0, b0, a0, r1, g1, b1, a1, ...].
  • WebPDecodeARGB renvoie des échantillons 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 échantillons 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
Pointer vers des données d'image WebP
data_size
Il s'agit de la taille du bloc de mémoire vers lequel pointe data, qui contient les données de l'image.
largeur
Valeur entière. La plage est actuellement limitée entre 1 et 16 383.
taille
Valeur entière. La plage est actuellement limitée entre 1 et 16 383.

Renvoie

uint8_t*
Pointeur vers des échantillons d'images WebP décodées dans l'ordre RVBA/ARVB/BGRA/RVB/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 des fonctions ci-dessus et décodent l'image directement dans une output_buffer de tampon pré-allouée. L'espace de stockage maximal disponible dans ce 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 recherche. Par conséquent, output_buffer_size doit être au moins égal à output_stride * picture - height.

Attributs d'entrée

données
Pointer vers des données d'image WebP
data_size
Il s'agit de la taille du bloc de mémoire vers lequel pointe data, qui contient les données de l'image.
output_buffer_size
Valeur entière. Taille du tampon alloué
output_stride
Valeur entière. Spécifie la distance entre les lignes de numérisation.

Renvoie

output_buffer
Pointeur vers une image WebP décodée.
uint8_t*
output_buffer si la fonction aboutit, NULL dans le cas contraire.

API Advanced Decoding

Le décodage WebP est compatible avec une API avancée qui permet d'effectuer un recadrage et un redimensionnement à la volée, ce qui est très utile dans les environnements à mémoire limitée tels que les téléphones mobiles. En gros, l'utilisation de la mémoire est ajustée en fonction de la taille de la sortie, et non de celle de l'entrée lorsqu'il suffit d'un aperçu rapide ou d'un zoom avant sur une partie d'une image autrement trop grande. Certains processeurs peuvent également être enregistrés.

Le décodage WebP se décline en deux variantes : le décodage complet d'images 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 fonctionnalités de bitstream peuvent éventuellement ê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 présente une certaine transparence. Notez que cela permet également d'analyser l'en-tête du flux de bits. Il s'agit donc d'un bon moyen de savoir si le flux de bits 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 voulions le fournir directement au lieu de dépendre du décodeur pour son allocation. Il 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 scan).

// 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 de décodage de l'image. Nous pouvons décoder l'image en une seule fois en utilisant:

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.RVBA, car 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. Il ne nous reste plus qu'à récupérer la mémoire allouée dans l'objet de la configuration. Vous pouvez 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, à l'aide respectivement de 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 RVBA 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 à des sorties de faible qualité et de petite taille, tandis que 100 correspond à la qualité et à la taille de sortie les plus élevées. 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 de la mémoire.

Le tableau d'entrée doit être un tableau empaqueté 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 de la BGRA est:

Il existe des fonctions équivalentes pour l'encodage sans perte, avec des signatures:

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 pertes, utilisent les paramètres par défaut de la bibliothèque. Pour les données sans perte, l'option "exact" 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 comporte de nombreux paramètres d'encodage avancés. Ils peuvent être utiles pour mieux équilibrer le compromis entre efficacité de la compression et temps de traitement. Ces paramètres sont rassemblés dans la structure WebPConfig. Les champs les plus utilisés de cette structure sont les suivants:

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 peuvent être testés à l'aide de l'outil de ligne de commande cwebp.

Les échantillons d'entrée doivent être encapsulés dans une structure WebPPicture. Cette structure peut stocker des échantillons d'entrée au format RVBA ou YUVA, en fonction de 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 possède également une fonction permettant d'émettre les octets compressés dès qu'ils sont mis à disposition. Vous trouverez ci-dessous un exemple d'utilisation d'un rédacteur en mémoire. D'autres rédacteurs peuvent stocker des données directement 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:

Tout d'abord, nous devons définir une configuration d'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)

Ensuite, les exemples d'entrée doivent être référencés dans un WebPPicture par référence ou par copie. Voici un exemple d'allocation du tampon pour la conservation des échantillons. Toutefois, vous pouvez facilement configurer une "vue" pour un exemple de tableau 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 hook est appelé chaque fois que de nouveaux octets sont disponibles. Voici un exemple simple avec l'écriture de mémoire déclarée dans webp/encode.h. Cette initialisation est probablement nécessaire à la compression de 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 échantillons 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, nous vous recommandons 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 des paramètres moins utilisés.