Documentation sur l'API WebP

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.5.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 sont copiés dans /usr/local/include/webp/.

decode.h
encode.h
types.h

Les bibliothèques se trouvent dans les répertoires de bibliothèque 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 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 NULL s'ils sont jugés non pertinents.

Saisir les attributs

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 valides que si la réponse est renvoyée.
largeur
Valeur entière. La plage 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 éléments du flux de bits. La structure *features est remplie d'informations collectées à partir du flux de bits:

Saisir les attributs

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 éléments sont correctement récupérés.
VP8_STATUS_NOT_ENOUGH_DATA
Lorsque davantage de données sont nécessaires pour récupérer les fonctionnalités à partir 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 échantillons 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 échantillons 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().

Saisir les attributs

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 des échantillons d'images WebP décodés 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 des fonctions ci-dessus et décodent l'image directement dans un tampon output_buffer préallooué. 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 d'au moins output_stride * picture - height.

Saisir les attributs

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 du tampon alloué
output_stride
Valeur entière. Indique 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.

API Advanced Decoding

Le décodage WebP est compatible avec une API avancée qui permet de recadrer et de redimensionner des images instantanément, 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 évoluera en fonction de la taille de la sortie, et non de l'entrée, lorsque vous n'avez besoin que d'un aperçu rapide ou d'une partie agrandie d'une image trop grande. Par ailleurs, vous pouvez économiser du processeur.

Le décodage WebP se présente sous deux variantes : le décodage d'image complet 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 explique comment utiliser 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 rassemblé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 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 comporte une transparence. Notez que cela analysera également l'en-tête du flux de bits et constitue donc 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 voudrions le fournir directement au lieu de s'appuyer sur le décodeur pour son allocation. Il suffit de fournir le pointeur vers la mémoire, ainsi que la taille totale du tampon et la longueur 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:

CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK);

Nous pouvons également utiliser la méthode incrémentielle pour décoder progressivement l'image à mesure que de nouveaux octets deviennent 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 désormais dans config.output (ou plutôt dans config.output.u.RGBA dans ce cas, car l'espace de couleurs de sortie demandé était MODE_BGRA). L'image peut être enregistrée, affichée ou traitée de toute autre manière. Ensuite, il ne nous reste plus qu'à récupérer la mémoire allouée dans l'objet de configuration. Vous pouvez appeler cette fonction en toute sécurité, même si la mémoire est externe et n'a pas été allouée par WebPDecode():

WebPFreeDecBuffer(&config.output);

À l'aide de cette API, l'image peut également être décodée au format YUV et YUVA, à l'aide de MODE_YUV et MODE_YUVA, respectivement. 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 varie de 0 à 100 et contrôle la perte et la qualité lors de la compression. La valeur 0 correspond à une qualité faible et à de petites tailles de sortie, tandis que la valeur 100 correspond à la qualité la plus élevée et à la plus grande taille de sortie. 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 d'octets compact (un pour chaque canal, comme indiqué 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 les formats sans perte, cela signifie que "exact" est désactivé. 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 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 échantillons d'entrée doivent être encapsulés dans une structure WebPPicture. Cette structure peut stocker des échantillons d'entrée au format RGBA 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 dispose également d'une fonction permettant d'émettre les octets compressés lorsqu'ils sont mis à disposition. Vous trouverez ci-dessous un exemple avec un éditeur en mémoire. D'autres écrivains peuvent stocker directement des données dans un fichier (voir examples/cwebp.c pour un tel 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 configurer 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, soit par référence, soit par copie. Voici un exemple d'allocation du tampon pour contenir les échantillons. Toutefois, vous pouvez facilement 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 hook est appelé chaque fois que de nouveaux octets sont disponibles. Voici un exemple simple avec l'écrivain de mémoire déclaré dans webp/encode.h. Cette initialisation est probablement nécessaire pour que chaque image soit compressée:

// 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, 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 moins utilisés.