GUACAMOLE-249: Convert absolutely all rdpBitmaps before attempting to draw.

This commit is contained in:
Michael Jumper 2019-12-31 16:17:36 -08:00
parent f33416949f
commit 7ef1dcafba
3 changed files with 55 additions and 20 deletions

View File

@ -37,6 +37,31 @@
#include <stdio.h>
#include <stdlib.h>
BOOL guac_rdp_bitmap_convert(rdpContext* context, rdpBitmap* bitmap) {
/* No need to convert if there is no image data or the image data is
* already in the format used by libguac (the format used by Cairo) */
if (bitmap->data == NULL || bitmap->format == PIXEL_FORMAT_BGRX32)
return TRUE;
/* Allocate sufficient space for converted image */
unsigned char* image_buffer = _aligned_malloc(bitmap->width * bitmap->height * 4, 16);
/* Attempt image conversion, replacing existing image data if successful */
if (freerdp_image_copy(image_buffer, PIXEL_FORMAT_BGRX32, 0, 0, 0,
bitmap->width, bitmap->height, bitmap->data, bitmap->format,
0, 0, 0, &context->gdi->palette, FREERDP_FLIP_NONE)) {
_aligned_free(bitmap->data);
bitmap->data = image_buffer;
bitmap->format = PIXEL_FORMAT_BGRX32;
return TRUE;
}
_aligned_free(image_buffer);
return FALSE;
}
BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) {
guac_client* client = ((rdp_freerdp_context*) context)->client;
@ -49,6 +74,9 @@ BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) {
/* Cache image data if present */
if (bitmap->data != NULL) {
/* Convert image data to format used by libguac */
guac_rdp_bitmap_convert(context, bitmap);
/* Create surface from image data */
cairo_surface_t* image = cairo_image_surface_create_for_data(
bitmap->data, CAIRO_FORMAT_RGB24,
@ -71,26 +99,8 @@ BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) {
BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) {
/* Convert image data if present */
if (bitmap->data != NULL && bitmap->format != PIXEL_FORMAT_BGRX32) {
/* Allocate sufficient space for converted image */
unsigned char* image_buffer = _aligned_malloc(bitmap->width * bitmap->height * 4, 16);
/* Attempt image conversion */
if (!freerdp_image_copy(image_buffer, PIXEL_FORMAT_BGRX32, 0, 0, 0,
bitmap->width, bitmap->height, bitmap->data, bitmap->format,
0, 0, 0, &context->gdi->palette, FREERDP_FLIP_NONE)) {
_aligned_free(image_buffer);
}
/* If successful, replace original image with converted image */
else {
_aligned_free(bitmap->data);
bitmap->data = image_buffer;
}
}
/* Convert image data to format used by libguac */
guac_rdp_bitmap_convert(context, bitmap);
/* No corresponding surface yet - caching is deferred. */
((guac_rdp_bitmap*) bitmap)->layer = NULL;
@ -125,6 +135,9 @@ BOOL guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) {
/* Otherwise, draw with stored image data */
else if (bitmap->data != NULL) {
/* Convert image data to format used by libguac */
guac_rdp_bitmap_convert(context, bitmap);
/* Create surface from image data */
cairo_surface_t* image = cairo_image_surface_create_for_data(
bitmap->data, CAIRO_FORMAT_RGB24,

View File

@ -49,6 +49,25 @@ typedef struct guac_rdp_bitmap {
} guac_rdp_bitmap;
/**
* Converts the image data within the given rdpBitmap to the pixel format used
* by libguac (Cairo) for 24-bit RGB images lacking an alpha channel. Any
* existing image data within the bitmap is freed and replaced with
* newly-allocated image data in the needed format, and the format field of the
* rdpBitmap is updated to match.
*
* @param context
* The rdpContext associated with the current RDP session.
*
* @param bitmap
* The rdpBitmap to convert.
*
* @return
* TRUE if image conversion was successful or there was no image data to
* convert, FALSE otherwise.
*/
BOOL guac_rdp_bitmap_convert(rdpContext* context, rdpBitmap* bitmap);
/**
* Caches the given bitmap immediately, storing its data in a remote Guacamole
* buffer. As RDP bitmaps are frequently created, used once, and immediately

View File

@ -274,6 +274,9 @@ BOOL guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) {
if (bitmap->layer == NULL) {
if (memblt->bitmap->data != NULL) {
/* Convert image data to format used by libguac */
guac_rdp_bitmap_convert(context, memblt->bitmap);
/* Create surface from image data */
cairo_surface_t* surface = cairo_image_surface_create_for_data(
memblt->bitmap->data + 4*(x_src + y_src*memblt->bitmap->width),