From 19223a2503ace70afc6c223520b8e56af76c73da Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Sat, 9 Jul 2011 19:55:11 -0700 Subject: [PATCH] added 32 bpp color decompression --- libfreerdp-core/CMakeLists.txt | 2 +- libfreerdp-core/bitmap.c | 235 +++++++++++++++++++++++++++++---- libfreerdp-core/bitmap_inc.c | 46 +++---- 3 files changed, 232 insertions(+), 51 deletions(-) diff --git a/libfreerdp-core/CMakeLists.txt b/libfreerdp-core/CMakeLists.txt index 6026882d6..b404227be 100644 --- a/libfreerdp-core/CMakeLists.txt +++ b/libfreerdp-core/CMakeLists.txt @@ -47,7 +47,7 @@ set(LIBFREERDP_CORE_SRCS tpkt.h transport.c transport.h - rle_bitmap_stream.c + bitmap.c ) include_directories(../libfreerdp-asn1) diff --git a/libfreerdp-core/bitmap.c b/libfreerdp-core/bitmap.c index 148d32a37..2f77386fd 100644 --- a/libfreerdp-core/bitmap.c +++ b/libfreerdp-core/bitmap.c @@ -1,6 +1,6 @@ /** * FreeRDP: A Remote Desktop Protocol Client - * RLE Compressed Bitmap Stream + * Compressed Bitmap * * Copyright 2011 Jay Sorg * @@ -71,10 +71,10 @@ typedef uint32 PIXEL; #define BLACK_PIXEL 0 #define WHITE_PIXEL 0xffffff -/* - Reads the supplied order header and extracts the compression - order code ID. -*/ +/** + * Reads the supplied order header and extracts the compression + * order code ID. + */ static uint32 ExtractCodeId(uint8 bOrderHdr) { int code; @@ -108,10 +108,10 @@ static uint32 ExtractCodeId(uint8 bOrderHdr) return bOrderHdr >> 4; } -/* - Extract the run length of a compression order. -*/ -static uint32 ExtractRunLength(uint32 code, uint8 * pbOrderHdr, uint32 * advance) +/** + * Extract the run length of a compression order. + */ +static uint32 ExtractRunLength(uint32 code, uint8* pbOrderHdr, uint32* advance) { uint32 runLength; uint32 ladvance; @@ -248,26 +248,207 @@ static uint32 ExtractRunLength(uint32 code, uint8 * pbOrderHdr, uint32 * advance #define RLEEXTRA #include "bitmap_inc.c" -int bitmap_decompress(void * inst, uint8 * output, int width, int height, - uint8 * input, int size, int Bpp) +#define IN_UINT8_MV(_p) (*((_p)++)) + +/** + * decompress a color plane + */ +static int process_plane(uint8* in, int width, int height, uint8* out, int size) { - switch (Bpp) + int indexw; + int indexh; + int code; + int collen; + int replen; + int color; + int x; + int revcode; + uint8* last_line; + uint8* this_line; + uint8* org_in; + uint8* org_out; + + org_in = in; + org_out = out; + last_line = 0; + indexh = 0; + while (indexh < height) { - case 1: - RleDecompress8to8(input, size, output, width, width, height); - break; - case 2: - RleDecompress16to16(input, size, output, width * 2, width, height); - break; - case 3: - RleDecompress24to24(input, size, output, width * 3, width, height); - break; - case 4: - /* TODO */ - break; - default: - /* TODO */ - break; + out = (org_out + width * height * 4) - ((indexh + 1) * width * 4); + color = 0; + this_line = out; + indexw = 0; + if (last_line == 0) + { + while (indexw < width) + { + code = IN_UINT8_MV(in); + replen = code & 0xf; + collen = (code >> 4) & 0xf; + revcode = (replen << 4) | collen; + if ((revcode <= 47) && (revcode >= 16)) + { + replen = revcode; + collen = 0; + } + while (collen > 0) + { + color = IN_UINT8_MV(in); + *out = color; + out += 4; + indexw++; + collen--; + } + while (replen > 0) + { + *out = color; + out += 4; + indexw++; + replen--; + } + } + } + else + { + while (indexw < width) + { + code = IN_UINT8_MV(in); + replen = code & 0xf; + collen = (code >> 4) & 0xf; + revcode = (replen << 4) | collen; + if ((revcode <= 47) && (revcode >= 16)) + { + replen = revcode; + collen = 0; + } + while (collen > 0) + { + x = IN_UINT8_MV(in); + if (x & 1) + { + x = x >> 1; + x = x + 1; + color = -x; + } + else + { + x = x >> 1; + color = x; + } + x = last_line[indexw * 4] + color; + *out = x; + out += 4; + indexw++; + collen--; + } + while (replen > 0) + { + x = last_line[indexw * 4] + color; + *out = x; + out += 4; + indexw++; + replen--; + } + } + } + indexh++; + last_line = this_line; + } + return (int) (in - org_in); +} + +/** + * 4 byte bitmap decompress + */ +static int bitmap_decompress4(uint8* output, int width, int height, uint8* input, int size) +{ + int code; + int bytes_pro; + int total_pro; + + code = IN_UINT8_MV(input); + if (code != 0x10) + { + return False; + } + total_pro = 1; + bytes_pro = process_plane(input, width, height, output + 3, size - total_pro); + total_pro += bytes_pro; + input += bytes_pro; + bytes_pro = process_plane(input, width, height, output + 2, size - total_pro); + total_pro += bytes_pro; + input += bytes_pro; + bytes_pro = process_plane(input, width, height, output + 1, size - total_pro); + total_pro += bytes_pro; + input += bytes_pro; + bytes_pro = process_plane(input, width, height, output + 0, size - total_pro); + total_pro += bytes_pro; + return size == total_pro; +} + +/** + * bitmap flip + */ +static int bitmap_flip(uint8* src, uint8* dst, int delta, int height) +{ + int index; + + dst = (dst + delta * height) - delta; + for (index = 0; index < height; index++) + { + memcpy(dst, src, delta); + src += delta; + dst -= delta; + } + return 0; +} + +/** + * bitmap decompression routine + */ +int bitmap_decompress(void* inst, uint8* output, int width, int height, + uint8* input, int size, int in_bpp, int out_bpp) +{ + uint8* data; + + if (in_bpp == 16 && out_bpp == 16) + { + data = (uint8*)xmalloc(width * height * 2); + RleDecompress16to16(input, size, data, width * 2, width, height); + bitmap_flip(data, output, width * 2, height); + xfree(data); + } + else if (in_bpp == 32 && out_bpp == 32) + { + if (!bitmap_decompress4(output, width, height, input, size)) + { + return 1; + } + } + else if (in_bpp == 15 && out_bpp == 15) + { + data = (uint8*)xmalloc(width * height * 2); + RleDecompress16to16(input, size, output, width * 2, width, height); + bitmap_flip(data, output, width * 2, height); + xfree(data); + } + else if (in_bpp == 8 && out_bpp == 8) + { + data = (uint8*)xmalloc(width * height); + RleDecompress8to8(input, size, output, width, width, height); + bitmap_flip(data, output, width, height); + xfree(data); + } + else if (in_bpp == 24 && out_bpp == 24) + { + data = (uint8*)xmalloc(width * height * 3); + RleDecompress24to24(input, size, output, width * 3, width, height); + bitmap_flip(data, output, width * 3, height); + xfree(data); + } + else + { + return 1; } return 0; } diff --git a/libfreerdp-core/bitmap_inc.c b/libfreerdp-core/bitmap_inc.c index deafcff8e..f1d84bf45 100644 --- a/libfreerdp-core/bitmap_inc.c +++ b/libfreerdp-core/bitmap_inc.c @@ -19,10 +19,10 @@ /* do not compile the file directly */ -/* - Write a foreground/background image to a destination buffer. -*/ -static uint8 * WRITEFGBGIMAGE(uint8 * pbDest, uint32 rowDelta, +/** + * Write a foreground/background image to a destination buffer. + */ +static uint8* WRITEFGBGIMAGE(uint8* pbDest, uint32 rowDelta, uint8 bitmask, PIXEL fgPel, uint32 cBits) { PIXEL xorPixel; @@ -138,11 +138,11 @@ static uint8 * WRITEFGBGIMAGE(uint8 * pbDest, uint32 rowDelta, return pbDest; } -/* - Write a foreground/background image to a destination buffer - for the first line of compressed data. -*/ -static uint8 * WRITEFIRSTLINEFGBGIMAGE(uint8 * pbDest, uint8 bitmask, +/** + * Write a foreground/background image to a destination buffer + * for the first line of compressed data. + */ +static uint8* WRITEFIRSTLINEFGBGIMAGE(uint8* pbDest, uint8 bitmask, PIXEL fgPel, uint32 cBits) { if (bitmask & g_MaskBit0) @@ -248,15 +248,15 @@ static uint8 * WRITEFIRSTLINEFGBGIMAGE(uint8 * pbDest, uint8 bitmask, return pbDest; } -/* - Decompress an RLE compressed bitmap. -*/ -void RLEDECOMPRESS(uint8 * pbSrcBuffer, uint32 cbSrcBuffer, uint8 * pbDestBuffer, +/** + * Decompress an RLE compressed bitmap. + */ +void RLEDECOMPRESS(uint8* pbSrcBuffer, uint32 cbSrcBuffer, uint8* pbDestBuffer, uint32 rowDelta, uint32 width, uint32 height) { - uint8 * pbSrc = pbSrcBuffer; - uint8 * pbEnd = pbSrcBuffer + cbSrcBuffer; - uint8 * pbDest = pbDestBuffer; + uint8* pbSrc = pbSrcBuffer; + uint8* pbEnd = pbSrcBuffer + cbSrcBuffer; + uint8* pbDest = pbDestBuffer; PIXEL temp; PIXEL fgPel = WHITE_PIXEL; @@ -304,7 +304,7 @@ void RLEDECOMPRESS(uint8 * pbSrcBuffer, uint32 cbSrcBuffer, uint8 * pbDestBuffer DESTNEXTPIXEL(pbDest); runLength = runLength - 1; } - while (runLength > UNROLL_COUNT) + while (runLength >= UNROLL_COUNT) { UNROLL( DESTWRITEPIXEL(pbDest, BLACK_PIXEL); @@ -327,7 +327,7 @@ void RLEDECOMPRESS(uint8 * pbSrcBuffer, uint32 cbSrcBuffer, uint8 * pbDestBuffer DESTNEXTPIXEL(pbDest); runLength = runLength - 1; } - while (runLength > UNROLL_COUNT) + while (runLength >= UNROLL_COUNT) { UNROLL( DESTREADPIXEL(temp, pbDest - rowDelta); @@ -368,7 +368,7 @@ void RLEDECOMPRESS(uint8 * pbSrcBuffer, uint32 cbSrcBuffer, uint8 * pbDestBuffer } if (fFirstLine) { - while (runLength > UNROLL_COUNT) + while (runLength >= UNROLL_COUNT) { UNROLL( DESTWRITEPIXEL(pbDest, fgPel); @@ -384,7 +384,7 @@ void RLEDECOMPRESS(uint8 * pbSrcBuffer, uint32 cbSrcBuffer, uint8 * pbDestBuffer } else { - while (runLength > UNROLL_COUNT) + while (runLength >= UNROLL_COUNT) { UNROLL( DESTREADPIXEL(temp, pbDest - rowDelta); @@ -411,7 +411,7 @@ void RLEDECOMPRESS(uint8 * pbSrcBuffer, uint32 cbSrcBuffer, uint8 * pbDestBuffer SRCNEXTPIXEL(pbSrc); SRCREADPIXEL(pixelB, pbSrc); SRCNEXTPIXEL(pbSrc); - while (runLength > UNROLL_COUNT) + while (runLength >= UNROLL_COUNT) { UNROLL( DESTWRITEPIXEL(pbDest, pixelA); @@ -437,7 +437,7 @@ void RLEDECOMPRESS(uint8 * pbSrcBuffer, uint32 cbSrcBuffer, uint8 * pbDestBuffer pbSrc = pbSrc + advance; SRCREADPIXEL(pixelA, pbSrc); SRCNEXTPIXEL(pbSrc); - while (runLength > UNROLL_COUNT) + while (runLength >= UNROLL_COUNT) { UNROLL( DESTWRITEPIXEL(pbDest, pixelA); @@ -504,7 +504,7 @@ void RLEDECOMPRESS(uint8 * pbSrcBuffer, uint32 cbSrcBuffer, uint8 * pbDestBuffer case MEGA_MEGA_COLOR_IMAGE: runLength = ExtractRunLength(code, pbSrc, &advance); pbSrc = pbSrc + advance; - while (runLength > UNROLL_COUNT) + while (runLength >= UNROLL_COUNT) { UNROLL( SRCREADPIXEL(temp, pbSrc);