From 49cd7806d9d15f2c2155da733cc5d707f89acec8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 26 Jun 2014 17:08:51 -0400 Subject: [PATCH] libfreerdp-codec: improve ClearCodec decompressor --- client/X11/xf_gfx.c | 2 + include/freerdp/codec/clear.h | 2 + libfreerdp/codec/clear.c | 166 ++++++++++++++++++++++---- libfreerdp/codec/test/TestFreeRDPCodecClear.c | 16 +-- 4 files changed, 155 insertions(+), 31 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 4ebbe54..01ec060 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -270,10 +270,12 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R status = clear_decompress(NULL, cmd->data, cmd->length, &DstData, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height); +#if 0 /* fill with pink for now to distinguish from the rest */ freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, 0xFF69B4); +#endif invalidRect.left = cmd->left; invalidRect.top = cmd->top; diff --git a/include/freerdp/codec/clear.h b/include/freerdp/codec/clear.h index fdb59e9..03aed70 100644 --- a/include/freerdp/codec/clear.h +++ b/include/freerdp/codec/clear.h @@ -23,6 +23,8 @@ #include #include +#include + #define CLEARCODEC_FLAG_GLYPH_INDEX 0x01 #define CLEARCODEC_FLAG_GLYPH_HIT 0x02 #define CLEARCODEC_FLAG_CACHE_RESET 0x03 diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c index c67cfa2..40dcfc2 100644 --- a/libfreerdp/codec/clear.c +++ b/libfreerdp/codec/clear.c @@ -28,17 +28,58 @@ #include #include +static UINT32 CLEAR_LOG2_FLOOR[256] = +{ + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +}; + +static BYTE CLEAR_8BIT_MASKS[9] = +{ + 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF +}; + int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) { - int index; + UINT32 i; + UINT32 count; + BYTE r, g, b; + UINT32 color; BYTE glyphFlags; BYTE seqNumber; UINT16 glyphIndex; UINT32 offset = 0; + BYTE* pDstData = NULL; UINT32 residualByteCount; UINT32 bandsByteCount; UINT32 subcodecByteCount; + BYTE runLengthFactor1; + UINT16 runLengthFactor2; + UINT32 runLengthFactor3; + UINT32 runLengthFactor; + + if (!ppDstData) + return -1; + + pDstData = *ppDstData; + + if (!pDstData) + return -1; if (SrcSize < 2) return -1001; @@ -83,17 +124,12 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, if (residualByteCount > 0) { - UINT32 color; - BYTE blueValue; - BYTE greenValue; - BYTE redValue; UINT32 suboffset; BYTE* residualData; + UINT32* pDstPixel; + UINT32 pixelX, pixelY; UINT32 pixelIndex = 0; - BYTE runLengthFactor1 = 0; - UINT16 runLengthFactor2 = 0; - UINT32 runLengthFactor3 = 0; - UINT32 runLengthFactor = 0; + UINT32 pixelCount = 0; if ((SrcSize - offset) < residualByteCount) return -1004; @@ -106,10 +142,10 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, if ((residualByteCount - suboffset) < 4) return -1005; - blueValue = residualData[suboffset]; - greenValue = residualData[suboffset + 1]; - redValue = residualData[suboffset + 2]; - color = RGB32(redValue, greenValue, blueValue); + b = residualData[suboffset]; /* blueValue */ + g = residualData[suboffset + 1]; /* greenValue */ + r = residualData[suboffset + 2]; /* redValue */ + color = RGB32(r, g, b); suboffset += 3; runLengthFactor1 = residualData[suboffset]; @@ -136,8 +172,28 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, } } - //freerdp_image_fill(*ppDstData, DstFormat, nDstStep, - // nXDst + (pixelIndex % nWidth), nYDst + (pixelIndex / nWidth), nWidth, nHeight, color); + pixelX = (pixelIndex % nWidth); + pixelY = (pixelIndex - pixelX) / nWidth; + pixelCount = runLengthFactor; + + while (pixelCount > 0) + { + count = nWidth - pixelX; + + if (count > pixelCount) + count = pixelCount; + + pDstPixel = (UINT32*) &pDstData[((nYDst + pixelY) * nDstStep) + ((nXDst + pixelX) * 4)]; + pixelCount -= count; + + while (count--) + { + *pDstPixel++ = color; + } + + pixelX = 0; + pixelY++; + } pixelIndex += runLengthFactor; } @@ -169,9 +225,6 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, UINT16 xEnd; UINT16 yStart; UINT16 yEnd; - BYTE blueBkg; - BYTE greenBkg; - BYTE redBkg; BYTE* vBars; UINT16 vBarHeader; UINT16 vBarIndex; @@ -187,17 +240,18 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, xEnd = *((UINT16*) &bandsData[suboffset + 2]); yStart = *((UINT16*) &bandsData[suboffset + 4]); yEnd = *((UINT16*) &bandsData[suboffset + 6]); - blueBkg = bandsData[suboffset + 8]; - greenBkg = bandsData[suboffset + 9]; - redBkg = bandsData[suboffset + 10]; + b = bandsData[suboffset + 8]; /* blueBkg */ + g = bandsData[suboffset + 9]; /* greenBkg */ + r = bandsData[suboffset + 10]; /* redBkg */ + color = RGB32(r, g, b); suboffset += 11; vBarCount = (xEnd - xStart) + 1; printf("CLEARCODEC_BAND: xStart: %d xEnd: %d yStart: %d yEnd: %d vBarCount: %d blueBkg: 0x%02X greenBkg: 0x%02X redBkg: 0x%02X\n", - xStart, xEnd, yStart, yEnd, vBarCount, blueBkg, greenBkg, redBkg); + xStart, xEnd, yStart, yEnd, vBarCount, b, g, r); - for (index = 0; index < vBarCount; index++) + for (i = 0; i < vBarCount; i++) { vBars = &bandsData[suboffset]; @@ -265,10 +319,16 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, UINT16 width; UINT16 height; BYTE* bitmapData; + UINT32 bitmapDataOffset; UINT32 bitmapDataByteCount; BYTE subcodecId; BYTE* subcodecs; UINT32 suboffset; + BYTE paletteCount; + BYTE* paletteEntries; + BYTE stopIndex; + BYTE suiteDepth; + UINT32 numBits; if ((SrcSize - offset) < subcodecByteCount) return -1015; @@ -297,6 +357,66 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, bitmapData = &subcodecs[suboffset]; + if (subcodecId == 0) /* Uncompressed */ + { + + } + else if (subcodecId == 1) /* NSCodec */ + { + + } + else if (subcodecId == 2) /* CLEARCODEC_SUBCODEC_RLEX */ + { + paletteCount = bitmapData[0]; + paletteEntries = &bitmapData[1]; + bitmapDataOffset = 1 + (paletteCount * 3); + + for (i = 0; i < paletteCount; i++) + { + b = paletteEntries[(i * 3) + 0]; /* blue */ + g = paletteEntries[(i * 3) + 1]; /* green */ + r = paletteEntries[(i * 3) + 2]; /* red */ + } + + numBits = CLEAR_LOG2_FLOOR[paletteCount - 1] + 1; + + while (bitmapDataOffset < bitmapDataByteCount) + { + stopIndex = bitmapData[bitmapDataOffset] & CLEAR_8BIT_MASKS[numBits]; + suiteDepth = (bitmapData[bitmapDataOffset] >> numBits) & CLEAR_8BIT_MASKS[numBits]; + bitmapDataOffset++; + + runLengthFactor1 = bitmapData[bitmapDataOffset]; + runLengthFactor = runLengthFactor1; + bitmapDataOffset += 1; + + if (runLengthFactor1 >= 0xFF) + { + if ((bitmapDataByteCount - bitmapDataOffset) < 2) + return -1; + + runLengthFactor2 = *((UINT16*) &bitmapData[bitmapDataOffset]); + runLengthFactor = runLengthFactor2; + bitmapDataOffset += 2; + + if (runLengthFactor2 >= 0xFFFF) + { + if ((bitmapDataByteCount - bitmapDataOffset) < 4) + return -1; + + runLengthFactor3 = *((UINT32*) &bitmapData[bitmapDataOffset]); + runLengthFactor = runLengthFactor3; + bitmapDataOffset += 4; + } + } + } + } + else + { + fprintf(stderr, "clear_decompress: unknown subcodecId: %d\n", subcodecId); + return -1; + } + suboffset += bitmapDataByteCount; } diff --git a/libfreerdp/codec/test/TestFreeRDPCodecClear.c b/libfreerdp/codec/test/TestFreeRDPCodecClear.c index fcec61a..4b65ac8 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecClear.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecClear.c @@ -42,7 +42,6 @@ int test_ClearDecompressExample1() int status; BYTE* pSrcData; UINT32 SrcSize; - UINT32 DstSize; BYTE* pDstData = NULL; CLEAR_CONTEXT* clear; @@ -51,7 +50,8 @@ int test_ClearDecompressExample1() SrcSize = sizeof(TEST_CLEAR_EXAMPLE_1) - 1; pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_1; - status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize); + status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, + PIXEL_FORMAT_XRGB32, 0, 0, 0, 0, 0); printf("clear_decompress example 1 status: %d\n", status); @@ -65,7 +65,6 @@ int test_ClearDecompressExample2() int status; BYTE* pSrcData; UINT32 SrcSize; - UINT32 DstSize; BYTE* pDstData = NULL; CLEAR_CONTEXT* clear; @@ -74,7 +73,8 @@ int test_ClearDecompressExample2() SrcSize = sizeof(TEST_CLEAR_EXAMPLE_2) - 1; pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_2; - status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize); + status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, + PIXEL_FORMAT_XRGB32, 0, 0, 0, 0, 0); printf("clear_decompress example 2 status: %d\n", status); @@ -88,7 +88,6 @@ int test_ClearDecompressExample3() int status; BYTE* pSrcData; UINT32 SrcSize; - UINT32 DstSize; BYTE* pDstData = NULL; CLEAR_CONTEXT* clear; @@ -97,7 +96,8 @@ int test_ClearDecompressExample3() SrcSize = sizeof(TEST_CLEAR_EXAMPLE_3) - 1; pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_3; - status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize); + status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, + PIXEL_FORMAT_XRGB32, 0, 0, 0, 0, 0); printf("clear_decompress example 3 status: %d\n", status); @@ -111,7 +111,6 @@ int test_ClearDecompressExample4() int status; BYTE* pSrcData; UINT32 SrcSize; - UINT32 DstSize; BYTE* pDstData = NULL; CLEAR_CONTEXT* clear; @@ -120,7 +119,8 @@ int test_ClearDecompressExample4() SrcSize = sizeof(TEST_CLEAR_EXAMPLE_4) - 1; pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_4; - status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize); + status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, + PIXEL_FORMAT_XRGB32, 0, 0, 0, 0, 0); printf("clear_decompress example 4 status: %d\n", status); -- 2.7.4