in src/libguac/encode-webp.c [165:257]
int guac_webp_write(guac_socket* socket, guac_stream* stream,
cairo_surface_t* surface, int quality, int lossless) {
guac_webp_stream_writer writer;
WebPPicture picture;
uint32_t* argb_output;
int x, y;
int width = cairo_image_surface_get_width(surface);
int height = cairo_image_surface_get_height(surface);
int stride = cairo_image_surface_get_stride(surface);
cairo_format_t format = cairo_image_surface_get_format(surface);
unsigned char* data = cairo_image_surface_get_data(surface);
if (format != CAIRO_FORMAT_RGB24 && format != CAIRO_FORMAT_ARGB32) {
guac_error = GUAC_STATUS_INTERNAL_ERROR;
guac_error_message = "Invalid Cairo image format. Unable to create WebP.";
return -1;
}
/* Flush pending operations to surface */
cairo_surface_flush(surface);
/* Configure WebP compression bits */
WebPConfig config;
if (!WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, quality))
return -1;
/* Add additional tuning */
config.lossless = lossless;
config.quality = quality;
config.thread_level = 1; /* Multi threaded */
config.method = 2; /* Compression method (0=fast/larger, 6=slow/smaller) */
/* Validate configuration */
WebPValidateConfig(&config);
/* Set up WebP picture */
WebPPictureInit(&picture);
picture.use_argb = 1;
picture.width = width;
picture.height = height;
/* Allocate and init writer */
WebPPictureAlloc(&picture);
picture.writer = guac_webp_stream_write;
picture.custom_ptr = &writer;
guac_webp_stream_writer_init(&writer, socket, stream);
/* Copy image data into WebP picture */
argb_output = picture.argb;
for (y = 0; y < height; y++) {
/* Get pixels at start of each row */
uint32_t* src = (uint32_t*) data;
uint32_t* dst = argb_output;
/* For each pixel in row */
for (x = 0; x < width; x++) {
/* Pull pixel data, removing alpha channel if necessary */
uint32_t src_pixel = *src;
if (format != CAIRO_FORMAT_ARGB32)
src_pixel |= 0xFF000000;
/* Store converted pixel data */
*dst = src_pixel;
/* Next pixel */
src++;
dst++;
}
/* Next row */
data += stride;
argb_output += picture.argb_stride;
}
/* Encode image */
WebPEncode(&config, &picture);
/* Free picture */
WebPPictureFree(&picture);
/* Ensure all data is written */
guac_webp_flush_data(&writer);
return 0;
}