diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 044499b0d..98b4bb437 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -294,7 +294,6 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { int status; - UINT32 DstSize = 0; BYTE* DstData = NULL; xfGfxSurface* surface; RECTANGLE_16 invalidRect; @@ -304,13 +303,8 @@ int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGF if (!surface) return -1; - DstSize = cmd->width * cmd->height * 4; - DstData = (BYTE*) malloc(DstSize); - - if (!DstData) - return -1; - - status = freerdp_bitmap_planar_decompress(cmd->data, DstData, cmd->width, cmd->height, cmd->length); + status = planar_decompress(NULL, cmd->data, cmd->length, &DstData, + PIXEL_FORMAT_XRGB32, cmd->width * 4, 0, 0, cmd->width, cmd->height); freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, DstData, PIXEL_FORMAT_XRGB32_VF, cmd->width * 4, 0, 0); diff --git a/include/freerdp/codec/bitmap.h b/include/freerdp/codec/bitmap.h index babfe6246..0f0a6c6da 100644 --- a/include/freerdp/codec/bitmap.h +++ b/include/freerdp/codec/bitmap.h @@ -48,4 +48,7 @@ FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, FREERDP_API BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, int maxWidth, int maxHeight); FREERDP_API void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context); +FREERDP_API int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize, + BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight); + #endif /* FREERDP_CODEC_BITMAP_H */ diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index a320da5a3..4021651e7 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -273,6 +273,118 @@ int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, in return (size == (srcp - srcData)) ? 0 : -1; } +int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize, + BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) +{ + int status; + BYTE* srcp; + BYTE FormatHeader; + BYTE* pDstData = NULL; + UINT32 UncompressedSize; + + if ((nWidth * nHeight) <= 0) + return -1; + + srcp = pSrcData; + UncompressedSize = nWidth * nHeight * 4; + + pDstData = *ppDstData; + + if (!pDstData) + { + pDstData = (BYTE*) malloc(UncompressedSize); + + if (!pDstData) + return -1; + + *ppDstData = pDstData; + } + + FormatHeader = *srcp; + srcp++; + + /* AlphaPlane */ + + if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA)) + { + if (FormatHeader & PLANAR_FORMAT_HEADER_RLE) + { + status = freerdp_bitmap_planar_decompress_plane_rle(srcp, nWidth, nHeight, + pDstData + 3, UncompressedSize - (srcp - pSrcData)); + + if (status < 0) + return -1; + + srcp += status; + } + else + { + status = freerdp_bitmap_planar_decompress_plane_raw(srcp, nWidth, nHeight, + pDstData + 3, UncompressedSize - (srcp - pSrcData)); + + srcp += status; + } + } + + if (FormatHeader & PLANAR_FORMAT_HEADER_RLE) + { + /* LumaOrRedPlane */ + + status = freerdp_bitmap_planar_decompress_plane_rle(srcp, nWidth, nHeight, + pDstData + 2, UncompressedSize - (srcp - pSrcData)); + + if (status < 0) + return -1; + + srcp += status; + + /* OrangeChromaOrGreenPlane */ + + status = freerdp_bitmap_planar_decompress_plane_rle(srcp, nWidth, nHeight, + pDstData + 1, UncompressedSize - (srcp - pSrcData)); + + if (status < 0) + return -1; + + srcp += status; + + /* GreenChromeOrBluePlane */ + + status = freerdp_bitmap_planar_decompress_plane_rle(srcp, nWidth, nHeight, + pDstData + 0, UncompressedSize - (srcp - pSrcData)); + + if (status < 0) + return -1; + + srcp += status; + } + else + { + /* LumaOrRedPlane */ + + status = freerdp_bitmap_planar_decompress_plane_raw(srcp, nWidth, nHeight, + pDstData + 2, UncompressedSize - (srcp - pSrcData)); + srcp += status; + + /* OrangeChromaOrGreenPlane */ + + status = freerdp_bitmap_planar_decompress_plane_raw(srcp, nWidth, nHeight, + pDstData + 1, UncompressedSize - (srcp - pSrcData)); + srcp += status; + + /* GreenChromeOrBluePlane */ + + status = freerdp_bitmap_planar_decompress_plane_raw(srcp, nWidth, nHeight, + pDstData + 0, UncompressedSize - (srcp - pSrcData)); + srcp += status; + srcp++; + } + + status = (UncompressedSize == (srcp - pSrcData)) ? 1 : -1; + + return status; +} + int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[4]) { int bpp;