Merge branch 'master' of github.com:awakecoding/FreeRDP
This commit is contained in:
commit
ea9511fb0d
@ -466,7 +466,6 @@ void wf_gdi_multi_opaque_rect(wfContext* wfc, MULTI_OPAQUE_RECT_ORDER* multi_opa
|
|||||||
rect.bottom = rectangle->top + rectangle->height;
|
rect.bottom = rectangle->top + rectangle->height;
|
||||||
brush = CreateSolidBrush(brush_color);
|
brush = CreateSolidBrush(brush_color);
|
||||||
|
|
||||||
brush = CreateSolidBrush(brush_color);
|
|
||||||
FillRect(wfc->drawing->hdc, &rect, brush);
|
FillRect(wfc->drawing->hdc, &rect, brush);
|
||||||
|
|
||||||
if (wfc->drawing == wfc->primary)
|
if (wfc->drawing == wfc->primary)
|
||||||
|
@ -182,7 +182,7 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
|||||||
{
|
{
|
||||||
status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp);
|
status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp);
|
||||||
|
|
||||||
if (status == FALSE)
|
if (!status)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "xf_Bitmap_Decompress: Bitmap Decompression Failed\n");
|
fprintf(stderr, "xf_Bitmap_Decompress: Bitmap Decompression Failed\n");
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#include <freerdp/api.h>
|
#include <freerdp/api.h>
|
||||||
#include <freerdp/types.h>
|
#include <freerdp/types.h>
|
||||||
|
|
||||||
|
#include <freerdp/codec/color.h>
|
||||||
|
|
||||||
#include <winpr/crt.h>
|
#include <winpr/crt.h>
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
@ -31,4 +33,7 @@ FREERDP_API BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int
|
|||||||
FREERDP_API int freerdp_bitmap_compress(char* in_data, int width, int height,
|
FREERDP_API int freerdp_bitmap_compress(char* in_data, int width, int height,
|
||||||
wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e);
|
wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e);
|
||||||
|
|
||||||
|
FREERDP_API BYTE* freerdp_bitmap_compress_planar(BYTE* data, UINT32 format, int width, int height,
|
||||||
|
int scanline, BYTE* dstData, int* dstSize);
|
||||||
|
|
||||||
#endif /* FREERDP_CODEC_BITMAP_H */
|
#endif /* FREERDP_CODEC_BITMAP_H */
|
||||||
|
@ -23,6 +23,20 @@
|
|||||||
#include <freerdp/api.h>
|
#include <freerdp/api.h>
|
||||||
#include <freerdp/freerdp.h>
|
#include <freerdp/freerdp.h>
|
||||||
|
|
||||||
|
#define FREERDP_PIXEL_FORMAT_TYPE_ARGB 1
|
||||||
|
#define FREERDP_PIXEL_FORMAT_TYPE_ABGR 2
|
||||||
|
|
||||||
|
#define FREERDP_PIXEL_FLIP_NONE 0
|
||||||
|
#define FREERDP_PIXEL_FLIP_VERTICAL 1
|
||||||
|
#define FREERDP_PIXEL_FLIP_HORIZONTAL 2
|
||||||
|
|
||||||
|
#define FREERDP_PIXEL_FORMAT(_bpp, _type, _flip) \
|
||||||
|
((_bpp << 24) | (_type << 16) | (_flip << 8))
|
||||||
|
|
||||||
|
#define FREERDP_PIXEL_FORMAT_BPP(_format) (((_format) >> 24) & 0xFF)
|
||||||
|
#define FREERDP_PIXEL_FORMAT_TYPE(_format) (((_format) >> 16) & 0xFF)
|
||||||
|
#define FREERDP_PIXEL_FORMAT_FLIP(_format) (((_format) >> 8) & 0xFF)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -64,7 +64,7 @@ FREERDP_API int tls_wait_read(rdpTls* tls);
|
|||||||
FREERDP_API int tls_wait_write(rdpTls* tls);
|
FREERDP_API int tls_wait_write(rdpTls* tls);
|
||||||
|
|
||||||
FREERDP_API BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname);
|
FREERDP_API BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname);
|
||||||
FREERDP_API BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname);
|
FREERDP_API BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port);
|
||||||
FREERDP_API void tls_print_certificate_error(char* hostname, char* fingerprint, char* hosts_file);
|
FREERDP_API void tls_print_certificate_error(char* hostname, char* fingerprint, char* hosts_file);
|
||||||
FREERDP_API void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count);
|
FREERDP_API void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count);
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ typedef void (*pPostDisconnect)(freerdp* instance);
|
|||||||
typedef BOOL (*pAuthenticate)(freerdp* instance, char** username, char** password, char** domain);
|
typedef BOOL (*pAuthenticate)(freerdp* instance, char** username, char** password, char** domain);
|
||||||
typedef BOOL (*pVerifyCertificate)(freerdp* instance, char* subject, char* issuer, char* fingerprint);
|
typedef BOOL (*pVerifyCertificate)(freerdp* instance, char* subject, char* issuer, char* fingerprint);
|
||||||
typedef BOOL (*pVerifyChangedCertificate)(freerdp* instance, char* subject, char* issuer, char* new_fingerprint, char* old_fingerprint);
|
typedef BOOL (*pVerifyChangedCertificate)(freerdp* instance, char* subject, char* issuer, char* new_fingerprint, char* old_fingerprint);
|
||||||
typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data, int length, DWORD flags);
|
typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data, int length, const char* hostname, int port, DWORD flags);
|
||||||
|
|
||||||
typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type);
|
typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type);
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@ set(${MODULE_PREFIX}_SRCS
|
|||||||
dsp.c
|
dsp.c
|
||||||
color.c
|
color.c
|
||||||
audio.c
|
audio.c
|
||||||
|
planar.c
|
||||||
|
planar.h
|
||||||
bitmap_decode.c
|
bitmap_decode.c
|
||||||
bitmap_encode.c
|
bitmap_encode.c
|
||||||
rfx_bitstream.h
|
rfx_bitstream.h
|
||||||
@ -106,3 +108,8 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
|
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
|
||||||
|
|
||||||
|
if(BUILD_TESTING)
|
||||||
|
add_subdirectory(test)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
@ -21,7 +21,11 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <winpr/crt.h>
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
|
#include "planar.h"
|
||||||
|
|
||||||
#include <freerdp/codec/color.h>
|
#include <freerdp/codec/color.h>
|
||||||
|
|
||||||
#include <freerdp/codec/bitmap.h>
|
#include <freerdp/codec/bitmap.h>
|
||||||
@ -251,196 +255,12 @@ static UINT32 ExtractRunLength(UINT32 code, BYTE* pbOrderHdr, UINT32* advance)
|
|||||||
#define RLEEXTRA
|
#define RLEEXTRA
|
||||||
#include "include/bitmap.c"
|
#include "include/bitmap.c"
|
||||||
|
|
||||||
#define IN_UINT8_MV(_p) (*((_p)++))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* decompress an RLE color plane
|
|
||||||
* RDP6_BITMAP_STREAM
|
|
||||||
*/
|
|
||||||
static int process_rle_plane(BYTE* in, int width, int height, BYTE* out, int size)
|
|
||||||
{
|
|
||||||
int indexw;
|
|
||||||
int indexh;
|
|
||||||
int code;
|
|
||||||
int collen;
|
|
||||||
int replen;
|
|
||||||
int color;
|
|
||||||
int x;
|
|
||||||
int revcode;
|
|
||||||
BYTE* last_line;
|
|
||||||
BYTE* this_line;
|
|
||||||
BYTE* org_in;
|
|
||||||
BYTE* org_out;
|
|
||||||
|
|
||||||
org_in = in;
|
|
||||||
org_out = out;
|
|
||||||
last_line = 0;
|
|
||||||
indexh = 0;
|
|
||||||
while (indexh < height)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* process a raw color plane
|
|
||||||
*/
|
|
||||||
static int process_raw_plane(BYTE* srcData, int width, int height, BYTE* dstData, int size)
|
|
||||||
{
|
|
||||||
int x, y;
|
|
||||||
|
|
||||||
for (y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
for (x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
dstData[(((height - y - 1) * width) + x) * 4] = srcData[((y * width) + x)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (width * height);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 4 byte bitmap decompress
|
|
||||||
* RDP6_BITMAP_STREAM
|
|
||||||
*/
|
|
||||||
static BOOL bitmap_decompress4(BYTE* srcData, BYTE* dstData, int width, int height, int size)
|
|
||||||
{
|
|
||||||
int RLE;
|
|
||||||
int code;
|
|
||||||
int NoAlpha;
|
|
||||||
int bytes_processed;
|
|
||||||
int total_processed;
|
|
||||||
|
|
||||||
code = IN_UINT8_MV(srcData);
|
|
||||||
RLE = code & 0x10;
|
|
||||||
|
|
||||||
total_processed = 1;
|
|
||||||
NoAlpha = code & 0x20;
|
|
||||||
|
|
||||||
if (NoAlpha == 0)
|
|
||||||
{
|
|
||||||
bytes_processed = process_rle_plane(srcData, width, height, dstData + 3, size - total_processed);
|
|
||||||
total_processed += bytes_processed;
|
|
||||||
srcData += bytes_processed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RLE != 0)
|
|
||||||
{
|
|
||||||
bytes_processed = process_rle_plane(srcData, width, height, dstData + 2, size - total_processed);
|
|
||||||
total_processed += bytes_processed;
|
|
||||||
srcData += bytes_processed;
|
|
||||||
|
|
||||||
bytes_processed = process_rle_plane(srcData, width, height, dstData + 1, size - total_processed);
|
|
||||||
total_processed += bytes_processed;
|
|
||||||
srcData += bytes_processed;
|
|
||||||
|
|
||||||
bytes_processed = process_rle_plane(srcData, width, height, dstData + 0, size - total_processed);
|
|
||||||
total_processed += bytes_processed;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bytes_processed = process_raw_plane(srcData, width, height, dstData + 2, size - total_processed);
|
|
||||||
total_processed += bytes_processed;
|
|
||||||
srcData += bytes_processed;
|
|
||||||
|
|
||||||
bytes_processed = process_raw_plane(srcData, width, height, dstData + 1, size - total_processed);
|
|
||||||
total_processed += bytes_processed;
|
|
||||||
srcData += bytes_processed;
|
|
||||||
|
|
||||||
bytes_processed = process_raw_plane(srcData, width, height, dstData + 0, size - total_processed);
|
|
||||||
total_processed += bytes_processed + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (size == total_processed) ? TRUE : FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bitmap decompression routine
|
* bitmap decompression routine
|
||||||
*/
|
*/
|
||||||
BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size, int srcBpp, int dstBpp)
|
BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size, int srcBpp, int dstBpp)
|
||||||
{
|
{
|
||||||
BYTE * TmpBfr;
|
BYTE* TmpBfr;
|
||||||
|
|
||||||
if (srcBpp == 16 && dstBpp == 16)
|
if (srcBpp == 16 && dstBpp == 16)
|
||||||
{
|
{
|
||||||
@ -451,7 +271,7 @@ BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int
|
|||||||
}
|
}
|
||||||
else if (srcBpp == 32 && dstBpp == 32)
|
else if (srcBpp == 32 && dstBpp == 32)
|
||||||
{
|
{
|
||||||
if (!bitmap_decompress4(srcData, dstData, width, height, size))
|
if (freerdp_bitmap_planar_decompress(srcData, dstData, width, height, size) < 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else if (srcBpp == 15 && dstBpp == 15)
|
else if (srcBpp == 15 && dstBpp == 15)
|
||||||
|
@ -1572,153 +1572,3 @@ int freerdp_bitmap_compress(char* in_data, int width, int height,
|
|||||||
|
|
||||||
return lines_sent;
|
return lines_sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* RDP6 Bitmap Test Case ([MS-RDPEGDI])
|
|
||||||
*/
|
|
||||||
|
|
||||||
const BYTE TEST_RDP6_COMPRESSED_BITMAP[220] =
|
|
||||||
"\x85\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x06\x8B\x99\xD6\x99"
|
|
||||||
"\xD6\x99\xD6\x10\x84\x08\x42\x08\x42\x10\x84\x99\xD6\x99\xD6\x99"
|
|
||||||
"\xD6\x99\xD6\x06\x84\x99\xD6\x99\xD6\x99\xD6\xFF\xFF\x16\x69\x99"
|
|
||||||
"\xD6\x06\x69\x99\xD6\x04\xCC\x89\x52\x03\x6E\xFF\xFF\x02\x6E\x08"
|
|
||||||
"\x42\x01\x70\x08\x42\x71\xFF\xFF\xCE\x18\xC6\x01\x81\x08\x42\xCE"
|
|
||||||
"\x66\x29\x02\xCD\x89\x52\x03\x88\x10\x84\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x00\x00\xD8\x99\xD6\x03\xF8\x01\x00\x00"
|
|
||||||
"\x00\x00\xF0\x66\x99\xD6\x05\x6A\x99\xD6\x00\xC4\xCC\x89\x52\x03"
|
|
||||||
"\x6E\xFF\xFF\x02\x6E\x08\x42\x01\x70\x08\x42\x71\xFF\xFF\xCE\x18"
|
|
||||||
"\xC6\x01\x81\x08\x42\xCE\x66\x29\x02\xCD\x89\x52\x03\x00\x04\xD6"
|
|
||||||
"\x99\xD6\xC3\x80\x61\x00\xA5\x80\x40\xEC\x52\x00\x5A\x00\x2D\x00"
|
|
||||||
"\x24\x00\x12\x00\x24\x00\x12\x00\x5A\x00\x2D\x00\xA5\x80\x52\x00"
|
|
||||||
"\xC3\x80\x61\x00\x00\x00\x00\x00\xCC\x89\x52\x03\x6E\xFF\xFF\x02"
|
|
||||||
"\xCB\x18\xC6\x84\x08\x42\x08\x42\x08\x42\xFF\xFF";
|
|
||||||
|
|
||||||
const BYTE TEST_RDP6_UNCOMPRESSED_BITMAP[2048] =
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
|
|
||||||
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\xFF\xFF"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
|
|
||||||
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
|
|
||||||
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\xFF\xFF"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
|
|
||||||
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
|
|
||||||
"\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
|
|
||||||
"\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00"
|
|
||||||
"\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
|
|
||||||
"\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
|
|
||||||
"\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
|
|
||||||
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\xFF\xFF";
|
|
||||||
|
859
libfreerdp/codec/planar.c
Normal file
859
libfreerdp/codec/planar.c
Normal file
@ -0,0 +1,859 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* RDP6 Planar Codec
|
||||||
|
*
|
||||||
|
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <winpr/crt.h>
|
||||||
|
#include <winpr/print.h>
|
||||||
|
|
||||||
|
#include <freerdp/codec/bitmap.h>
|
||||||
|
|
||||||
|
#include "planar.h"
|
||||||
|
|
||||||
|
static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, int height, BYTE* outPlane, int srcSize)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
int x, y;
|
||||||
|
BYTE* srcp;
|
||||||
|
BYTE* dstp;
|
||||||
|
UINT32 pixel;
|
||||||
|
int scanline;
|
||||||
|
int cRawBytes;
|
||||||
|
int nRunLength;
|
||||||
|
int deltaValue;
|
||||||
|
BYTE controlByte;
|
||||||
|
BYTE* currentScanline;
|
||||||
|
BYTE* previousScanline;
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
|
||||||
|
srcp = inPlane;
|
||||||
|
dstp = outPlane;
|
||||||
|
scanline = width * 4;
|
||||||
|
previousScanline = NULL;
|
||||||
|
|
||||||
|
y = 0;
|
||||||
|
|
||||||
|
while (y < height)
|
||||||
|
{
|
||||||
|
pixel = 0;
|
||||||
|
dstp = (outPlane + height * scanline) - ((y + 1) * scanline);
|
||||||
|
currentScanline = dstp;
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
|
||||||
|
while (x < width)
|
||||||
|
{
|
||||||
|
controlByte = *srcp;
|
||||||
|
srcp++;
|
||||||
|
|
||||||
|
if ((srcp - inPlane) > srcSize)
|
||||||
|
{
|
||||||
|
printf("freerdp_bitmap_planar_decompress_plane_rle: error reading input buffer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nRunLength = PLANAR_CONTROL_BYTE_RUN_LENGTH(controlByte);
|
||||||
|
cRawBytes = PLANAR_CONTROL_BYTE_RAW_BYTES(controlByte);
|
||||||
|
|
||||||
|
//printf("CONTROL(%d, %d)\n", cRawBytes, nRunLength);
|
||||||
|
|
||||||
|
if (nRunLength == 1)
|
||||||
|
{
|
||||||
|
nRunLength = cRawBytes + 16;
|
||||||
|
cRawBytes = 0;
|
||||||
|
}
|
||||||
|
else if (nRunLength == 2)
|
||||||
|
{
|
||||||
|
nRunLength = cRawBytes + 32;
|
||||||
|
cRawBytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
printf("y: %d cRawBytes: %d nRunLength: %d\n", y, cRawBytes, nRunLength);
|
||||||
|
|
||||||
|
printf("RAW[");
|
||||||
|
|
||||||
|
for (k = 0; k < cRawBytes; k++)
|
||||||
|
{
|
||||||
|
printf("0x%02X%s", srcp[k],
|
||||||
|
((k + 1) == cRawBytes) ? "" : ", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("] RUN[%d]\n", nRunLength);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (((dstp + (cRawBytes + nRunLength)) - currentScanline) > width * 4)
|
||||||
|
{
|
||||||
|
printf("freerdp_bitmap_planar_decompress_plane_rle: too many pixels in scanline\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!previousScanline)
|
||||||
|
{
|
||||||
|
/* first scanline, absolute values */
|
||||||
|
|
||||||
|
while (cRawBytes > 0)
|
||||||
|
{
|
||||||
|
pixel = *srcp;
|
||||||
|
srcp++;
|
||||||
|
|
||||||
|
*dstp = pixel;
|
||||||
|
dstp += 4;
|
||||||
|
x++;
|
||||||
|
cRawBytes--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (nRunLength > 0)
|
||||||
|
{
|
||||||
|
*dstp = pixel;
|
||||||
|
dstp += 4;
|
||||||
|
x++;
|
||||||
|
nRunLength--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* delta values relative to previous scanline */
|
||||||
|
|
||||||
|
while (cRawBytes > 0)
|
||||||
|
{
|
||||||
|
deltaValue = *srcp;
|
||||||
|
srcp++;
|
||||||
|
|
||||||
|
if (deltaValue & 1)
|
||||||
|
{
|
||||||
|
deltaValue = deltaValue >> 1;
|
||||||
|
deltaValue = deltaValue + 1;
|
||||||
|
pixel = -deltaValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deltaValue = deltaValue >> 1;
|
||||||
|
pixel = deltaValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
deltaValue = previousScanline[x * 4] + pixel;
|
||||||
|
*dstp = deltaValue;
|
||||||
|
dstp += 4;
|
||||||
|
x++;
|
||||||
|
cRawBytes--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (nRunLength > 0)
|
||||||
|
{
|
||||||
|
deltaValue = previousScanline[x * 4] + pixel;
|
||||||
|
*dstp = deltaValue;
|
||||||
|
dstp += 4;
|
||||||
|
x++;
|
||||||
|
nRunLength--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
previousScanline = currentScanline;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) (srcp - inPlane);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int freerdp_bitmap_planar_decompress_plane_raw(BYTE* srcData, int width, int height, BYTE* dstData, int size)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
for (y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
dstData[(((height - y - 1) * width) + x) * 4] = srcData[((y * width) + x)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (width * height);
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size)
|
||||||
|
{
|
||||||
|
BYTE* srcp;
|
||||||
|
int dstSize;
|
||||||
|
BYTE FormatHeader;
|
||||||
|
|
||||||
|
srcp = srcData;
|
||||||
|
|
||||||
|
FormatHeader = *srcp;
|
||||||
|
srcp++;
|
||||||
|
|
||||||
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA))
|
||||||
|
{
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
{
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 3, size - (srcp - srcData));
|
||||||
|
|
||||||
|
if (dstSize < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
srcp += dstSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 3, size - (srcp - srcData));
|
||||||
|
srcp += dstSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
{
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 2, size - (srcp - srcData));
|
||||||
|
|
||||||
|
if (dstSize < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
srcp += dstSize;
|
||||||
|
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 1, size - (srcp - srcData));
|
||||||
|
|
||||||
|
if (dstSize < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
srcp += dstSize;
|
||||||
|
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 0, size - (srcp - srcData));
|
||||||
|
|
||||||
|
if (dstSize < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
srcp += dstSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 2, size - (srcp - srcData));
|
||||||
|
srcp += dstSize;
|
||||||
|
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 1, size - (srcp - srcData));
|
||||||
|
srcp += dstSize;
|
||||||
|
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 0, size - (srcp - srcData));
|
||||||
|
srcp += dstSize;
|
||||||
|
srcp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (size == (srcp - srcData)) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[5])
|
||||||
|
{
|
||||||
|
int bpp;
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
bpp = FREERDP_PIXEL_FORMAT_BPP(format);
|
||||||
|
|
||||||
|
if (bpp == 32)
|
||||||
|
{
|
||||||
|
UINT32* pixel;
|
||||||
|
|
||||||
|
for (i = height - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
pixel = (UINT32*) &data[scanline * i];
|
||||||
|
|
||||||
|
for (j = 0; j < width; j++)
|
||||||
|
{
|
||||||
|
GetARGB32(planes[0][k], planes[1][k], planes[2][k], planes[3][k], *pixel);
|
||||||
|
pixel++;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bpp == 24)
|
||||||
|
{
|
||||||
|
UINT32* pixel;
|
||||||
|
|
||||||
|
for (i = height - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
pixel = (UINT32*) &data[scanline * i];
|
||||||
|
|
||||||
|
for (j = 0; j < width; j++)
|
||||||
|
{
|
||||||
|
GetRGB32(planes[1][k], planes[2][k], planes[3][k], *pixel);
|
||||||
|
planes[0][k] = 0xFF; /* A */
|
||||||
|
pixel++;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _PLANAR_RLE_CONTEXT
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
BYTE* output;
|
||||||
|
int nRunLength;
|
||||||
|
int cRawBytes;
|
||||||
|
BYTE* rawValues;
|
||||||
|
BYTE* rawScanline;
|
||||||
|
BYTE* outPlane;
|
||||||
|
int outPlaneSize;
|
||||||
|
int outSegmentSize;
|
||||||
|
int nControlBytes;
|
||||||
|
};
|
||||||
|
typedef struct _PLANAR_RLE_CONTEXT PLANAR_RLE_CONTEXT;
|
||||||
|
|
||||||
|
int freerdp_bitmap_planar_compress_plane_rle_segment(PLANAR_RLE_CONTEXT* rle, int position)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
if (position < 0)
|
||||||
|
printf("B");
|
||||||
|
else if (position == 0)
|
||||||
|
printf("M");
|
||||||
|
else
|
||||||
|
printf("E");
|
||||||
|
|
||||||
|
printf(" RAW[");
|
||||||
|
|
||||||
|
for (k = 0; k < rle->cRawBytes; k++)
|
||||||
|
{
|
||||||
|
printf("0x%02X%s", rle->rawValues[k],
|
||||||
|
((k + 1) == rle->cRawBytes) ? "" : ", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("] RUN[%d]\n", rle->nRunLength);
|
||||||
|
|
||||||
|
while ((rle->cRawBytes != 0) || (rle->nRunLength != 0))
|
||||||
|
{
|
||||||
|
printf("cRawBytes: %d nRunLength: %d\n", rle->cRawBytes, rle->nRunLength);
|
||||||
|
|
||||||
|
if (rle->nRunLength < 3)
|
||||||
|
{
|
||||||
|
rle->cRawBytes += rle->nRunLength;
|
||||||
|
rle->nRunLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rle->rawValues - rle->rawScanline) > rle->width)
|
||||||
|
{
|
||||||
|
printf("rawValues overflow! %d\n", rle->rawValues - rle->rawScanline);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rle->cRawBytes > 15)
|
||||||
|
{
|
||||||
|
rle->nControlBytes = 1;
|
||||||
|
rle->outSegmentSize = 15 + rle->nControlBytes;
|
||||||
|
|
||||||
|
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
|
||||||
|
{
|
||||||
|
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rle->output = PLANAR_CONTROL_BYTE(0, 15);
|
||||||
|
rle->output++;
|
||||||
|
|
||||||
|
CopyMemory(rle->output, rle->rawValues, 15);
|
||||||
|
rle->cRawBytes -= 15;
|
||||||
|
rle->rawValues += 15;
|
||||||
|
rle->output += 15;
|
||||||
|
|
||||||
|
/* continue */
|
||||||
|
}
|
||||||
|
else if (rle->cRawBytes == 0)
|
||||||
|
{
|
||||||
|
if (rle->nRunLength > 47)
|
||||||
|
{
|
||||||
|
rle->nControlBytes = 1;
|
||||||
|
rle->outSegmentSize = rle->nControlBytes;
|
||||||
|
|
||||||
|
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
|
||||||
|
{
|
||||||
|
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rle->output = PLANAR_CONTROL_BYTE(2, 15);
|
||||||
|
rle->nRunLength -= 47;
|
||||||
|
rle->output++;
|
||||||
|
|
||||||
|
/* continue */
|
||||||
|
}
|
||||||
|
else if (rle->nRunLength > 31)
|
||||||
|
{
|
||||||
|
rle->nControlBytes = 1;
|
||||||
|
rle->outSegmentSize = rle->nControlBytes;
|
||||||
|
|
||||||
|
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
|
||||||
|
{
|
||||||
|
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rle->output = PLANAR_CONTROL_BYTE(2, (rle->nRunLength - 32));
|
||||||
|
rle->nRunLength -= 32;
|
||||||
|
rle->output++;
|
||||||
|
|
||||||
|
return 0; /* finish */
|
||||||
|
}
|
||||||
|
else if (rle->nRunLength > 15)
|
||||||
|
{
|
||||||
|
rle->nControlBytes = 1;
|
||||||
|
rle->outSegmentSize = rle->nControlBytes;
|
||||||
|
|
||||||
|
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
|
||||||
|
{
|
||||||
|
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rle->output = PLANAR_CONTROL_BYTE(1, (rle->nRunLength - 16));
|
||||||
|
rle->nRunLength -= 16;
|
||||||
|
rle->output++;
|
||||||
|
|
||||||
|
return 0; /* finish */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rle->nControlBytes = 1;
|
||||||
|
rle->outSegmentSize = rle->cRawBytes + rle->nControlBytes;
|
||||||
|
|
||||||
|
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
|
||||||
|
{
|
||||||
|
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rle->output = PLANAR_CONTROL_BYTE(rle->nRunLength, rle->cRawBytes);
|
||||||
|
rle->output++;
|
||||||
|
|
||||||
|
if (rle->cRawBytes)
|
||||||
|
{
|
||||||
|
CopyMemory(rle->output, rle->rawValues, rle->cRawBytes);
|
||||||
|
rle->rawValues += (rle->cRawBytes + rle->nRunLength);
|
||||||
|
rle->output += rle->cRawBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
rle->cRawBytes = 0;
|
||||||
|
rle->nRunLength = 0;
|
||||||
|
|
||||||
|
return 0; /* finish */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (rle->cRawBytes < 16)
|
||||||
|
{
|
||||||
|
if (rle->nRunLength > 15)
|
||||||
|
{
|
||||||
|
rle->nControlBytes = 2;
|
||||||
|
rle->outSegmentSize = rle->cRawBytes + rle->nControlBytes;
|
||||||
|
|
||||||
|
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
|
||||||
|
{
|
||||||
|
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!rle->rawValues[rle->cRawBytes - 1]) && (rle->cRawBytes == 1))
|
||||||
|
{
|
||||||
|
//rle->rawValues += (rle->cRawBytes + rle->nRunLength);
|
||||||
|
//rle->cRawBytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rle->output = PLANAR_CONTROL_BYTE(15, rle->cRawBytes);
|
||||||
|
rle->output++;
|
||||||
|
|
||||||
|
if (rle->cRawBytes)
|
||||||
|
{
|
||||||
|
CopyMemory(rle->output, rle->rawValues, rle->cRawBytes);
|
||||||
|
rle->rawValues += (rle->cRawBytes + rle->nRunLength);
|
||||||
|
rle->output += rle->cRawBytes;
|
||||||
|
rle->cRawBytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rle->nRunLength -= 15;
|
||||||
|
rle->cRawBytes = 0;
|
||||||
|
|
||||||
|
/* continue */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rle->nControlBytes = 1;
|
||||||
|
rle->outSegmentSize = rle->cRawBytes + rle->nControlBytes;
|
||||||
|
|
||||||
|
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
|
||||||
|
{
|
||||||
|
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!rle->rawValues[rle->cRawBytes - 1]) && (rle->cRawBytes == 1))
|
||||||
|
{
|
||||||
|
//rle->rawValues += (rle->cRawBytes + rle->nRunLength);
|
||||||
|
//rle->cRawBytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rle->output = PLANAR_CONTROL_BYTE(rle->nRunLength, rle->cRawBytes);
|
||||||
|
rle->output++;
|
||||||
|
|
||||||
|
if (rle->cRawBytes)
|
||||||
|
{
|
||||||
|
CopyMemory(rle->output, rle->rawValues, rle->cRawBytes);
|
||||||
|
rle->rawValues += (rle->cRawBytes + rle->nRunLength);
|
||||||
|
rle->output += rle->cRawBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
rle->cRawBytes = 0;
|
||||||
|
rle->nRunLength = 0;
|
||||||
|
|
||||||
|
return 0; /* finish */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* inPlane, int width, int height, BYTE* outPlane, int* dstSize)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
int cSegments;
|
||||||
|
PLANAR_RLE_CONTEXT rle_s;
|
||||||
|
PLANAR_RLE_CONTEXT* rle = &rle_s;
|
||||||
|
|
||||||
|
cSegments = 0;
|
||||||
|
|
||||||
|
if (!outPlane)
|
||||||
|
{
|
||||||
|
rle->outPlaneSize = width * height * 2;
|
||||||
|
outPlane = malloc(rle->outPlaneSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rle->outPlaneSize = *dstSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
rle->output = outPlane;
|
||||||
|
rle->outPlane = outPlane;
|
||||||
|
rle->width = width;
|
||||||
|
rle->height = height;
|
||||||
|
|
||||||
|
for (i = 0; i < height; i++)
|
||||||
|
{
|
||||||
|
rle->cRawBytes = 1;
|
||||||
|
rle->nRunLength = 0;
|
||||||
|
rle->rawScanline = &inPlane[i * width];
|
||||||
|
rle->rawValues = rle->rawScanline;
|
||||||
|
|
||||||
|
for (j = 1; j < width; j++)
|
||||||
|
{
|
||||||
|
printf("j: %d cRawBytes: %d nRunLength: %d\n", j, rle->cRawBytes, rle->nRunLength);
|
||||||
|
|
||||||
|
if (rle->rawScanline[j] == rle->rawValues[rle->cRawBytes - 1])
|
||||||
|
{
|
||||||
|
rle->nRunLength++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rle->cRawBytes++;
|
||||||
|
|
||||||
|
if (rle->nRunLength < 3)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (freerdp_bitmap_planar_compress_plane_rle_segment(rle, (j == 1) ? -1 : 0) < 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rle->nRunLength < 3)
|
||||||
|
{
|
||||||
|
rle->cRawBytes += rle->nRunLength;
|
||||||
|
rle->nRunLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (freerdp_bitmap_planar_compress_plane_rle_segment(rle, 1) < 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dstSize = (rle->output - outPlane);
|
||||||
|
|
||||||
|
return outPlane;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_bitmap_planar_compress_planes_rle(BYTE* inPlanes[5], int width, int height, BYTE* outPlanes, int* dstSizes)
|
||||||
|
{
|
||||||
|
int outPlanesSize = width * height * 4;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
dstSizes[0] = outPlanesSize;
|
||||||
|
|
||||||
|
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[0], width, height, outPlanes, &dstSizes[0]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
outPlanes += dstSizes[0];
|
||||||
|
outPlanesSize -= dstSizes[0];
|
||||||
|
#else
|
||||||
|
dstSizes[0] = 0;
|
||||||
|
#endif
|
||||||
|
dstSizes[1] = outPlanesSize;
|
||||||
|
|
||||||
|
printf("PlaneR\n");
|
||||||
|
|
||||||
|
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[1], width, height, outPlanes, &dstSizes[1]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
outPlanes += dstSizes[1];
|
||||||
|
outPlanesSize -= dstSizes[1];
|
||||||
|
dstSizes[2] = outPlanesSize;
|
||||||
|
|
||||||
|
printf("PlaneG\n");
|
||||||
|
|
||||||
|
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[2], width, height, outPlanes, &dstSizes[2]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
outPlanes += dstSizes[2];
|
||||||
|
outPlanesSize -= dstSizes[2];
|
||||||
|
dstSizes[3] = outPlanesSize;
|
||||||
|
|
||||||
|
printf("PlaneB\n");
|
||||||
|
|
||||||
|
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[3], width, height, outPlanes, &dstSizes[3]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
outPlanes += dstSizes[3];
|
||||||
|
outPlanesSize -= dstSizes[3];
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int height, BYTE* outPlane)
|
||||||
|
{
|
||||||
|
char s2c;
|
||||||
|
BYTE u2c;
|
||||||
|
int delta;
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
if (!outPlane)
|
||||||
|
{
|
||||||
|
outPlane = (BYTE*) malloc(width * height);
|
||||||
|
}
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < height; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < width; j++)
|
||||||
|
{
|
||||||
|
if (i < 1)
|
||||||
|
{
|
||||||
|
delta = inPlane[j];
|
||||||
|
|
||||||
|
s2c = (delta >= 0) ? (char) delta : (char) (~((BYTE) (delta * -1)) + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delta = inPlane[(i * width) + j] - inPlane[((i - 1) * width) + j];
|
||||||
|
|
||||||
|
s2c = (delta >= 0) ? (char) delta : (char) (~((BYTE) (delta * -1)) + 1);
|
||||||
|
|
||||||
|
s2c = (s2c >= 0) ? (s2c << 1) : (char) (((~((BYTE) s2c) + 1) << 1) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
u2c = (BYTE) s2c;
|
||||||
|
|
||||||
|
outPlane[(i * width) + j] = u2c;
|
||||||
|
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return outPlane;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[5], int width, int height, BYTE* outPlanes[5])
|
||||||
|
{
|
||||||
|
freerdp_bitmap_planar_delta_encode_plane(inPlanes[0], width, height, outPlanes[0]);
|
||||||
|
freerdp_bitmap_planar_delta_encode_plane(inPlanes[1], width, height, outPlanes[1]);
|
||||||
|
freerdp_bitmap_planar_delta_encode_plane(inPlanes[2], width, height, outPlanes[2]);
|
||||||
|
freerdp_bitmap_planar_delta_encode_plane(inPlanes[3], width, height, outPlanes[3]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE* freerdp_bitmap_compress_planar(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* dstData, int* dstSize)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
BYTE* dstp;
|
||||||
|
int planeSize;
|
||||||
|
int dstSizes[4];
|
||||||
|
BYTE* planes[5];
|
||||||
|
BYTE* planesBuffer;
|
||||||
|
BYTE* deltaPlanes[5];
|
||||||
|
BYTE* deltaPlanesBuffer;
|
||||||
|
BYTE* rlePlanes[4];
|
||||||
|
BYTE* rlePlanesBuffer;
|
||||||
|
BYTE FormatHeader = 0;
|
||||||
|
|
||||||
|
FormatHeader |= PLANAR_FORMAT_HEADER_NA;
|
||||||
|
|
||||||
|
planeSize = width * height;
|
||||||
|
|
||||||
|
planesBuffer = malloc(planeSize * 5);
|
||||||
|
planes[0] = &planesBuffer[planeSize * 0];
|
||||||
|
planes[1] = &planesBuffer[planeSize * 1];
|
||||||
|
planes[2] = &planesBuffer[planeSize * 2];
|
||||||
|
planes[3] = &planesBuffer[planeSize * 3];
|
||||||
|
planes[4] = &planesBuffer[planeSize * 4];
|
||||||
|
|
||||||
|
deltaPlanesBuffer = malloc(planeSize * 5);
|
||||||
|
deltaPlanes[0] = &deltaPlanesBuffer[planeSize * 0];
|
||||||
|
deltaPlanes[1] = &deltaPlanesBuffer[planeSize * 1];
|
||||||
|
deltaPlanes[2] = &deltaPlanesBuffer[planeSize * 2];
|
||||||
|
deltaPlanes[3] = &deltaPlanesBuffer[planeSize * 3];
|
||||||
|
deltaPlanes[4] = &deltaPlanesBuffer[planeSize * 4];
|
||||||
|
|
||||||
|
rlePlanesBuffer = malloc(planeSize * 4);
|
||||||
|
|
||||||
|
freerdp_split_color_planes(data, format, width, height, scanline, planes);
|
||||||
|
|
||||||
|
freerdp_bitmap_planar_delta_encode_planes(planes, width, height, deltaPlanes);
|
||||||
|
|
||||||
|
if (freerdp_bitmap_planar_compress_planes_rle(deltaPlanes, width, height, rlePlanesBuffer, (int*) &dstSizes) > 0)
|
||||||
|
{
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
FormatHeader |= PLANAR_FORMAT_HEADER_RLE;
|
||||||
|
|
||||||
|
rlePlanes[0] = &rlePlanesBuffer[offset];
|
||||||
|
offset += dstSizes[0];
|
||||||
|
|
||||||
|
rlePlanes[1] = &rlePlanesBuffer[offset];
|
||||||
|
offset += dstSizes[1];
|
||||||
|
|
||||||
|
rlePlanes[2] = &rlePlanesBuffer[offset];
|
||||||
|
offset += dstSizes[2];
|
||||||
|
|
||||||
|
rlePlanes[3] = &rlePlanesBuffer[offset];
|
||||||
|
offset += dstSizes[3];
|
||||||
|
|
||||||
|
printf("R: [%d/%d] G: [%d/%d] B: [%d/%d]\n",
|
||||||
|
dstSizes[1], planeSize, dstSizes[2], planeSize, dstSizes[3], planeSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dstData)
|
||||||
|
{
|
||||||
|
size = 1;
|
||||||
|
|
||||||
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA))
|
||||||
|
{
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
size += dstSizes[0];
|
||||||
|
else
|
||||||
|
size += planeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
size += (dstSizes[1] + dstSizes[2] + dstSizes[3]);
|
||||||
|
else
|
||||||
|
size += (planeSize * 3);
|
||||||
|
|
||||||
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_RLE))
|
||||||
|
size++;
|
||||||
|
|
||||||
|
dstData = malloc(size);
|
||||||
|
*dstSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
dstp = dstData;
|
||||||
|
|
||||||
|
*dstp = FormatHeader; /* FormatHeader */
|
||||||
|
dstp++;
|
||||||
|
|
||||||
|
/* AlphaPlane */
|
||||||
|
|
||||||
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA))
|
||||||
|
{
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, rlePlanes[0], dstSizes[0]); /* Alpha */
|
||||||
|
dstp += dstSizes[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, planes[0], planeSize); /* Alpha */
|
||||||
|
dstp += planeSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LumaOrRedPlane */
|
||||||
|
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, rlePlanes[1], dstSizes[1]); /* Red */
|
||||||
|
dstp += dstSizes[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, planes[1], planeSize); /* Red */
|
||||||
|
dstp += planeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OrangeChromaOrGreenPlane */
|
||||||
|
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, rlePlanes[2], dstSizes[2]); /* Green */
|
||||||
|
dstp += dstSizes[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, planes[2], planeSize); /* Green */
|
||||||
|
dstp += planeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GreenChromeOrBluePlane */
|
||||||
|
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, rlePlanes[3], dstSizes[3]); /* Blue */
|
||||||
|
dstp += dstSizes[3];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, planes[3], planeSize); /* Blue */
|
||||||
|
dstp += planeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pad1 (1 byte) */
|
||||||
|
|
||||||
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_RLE))
|
||||||
|
{
|
||||||
|
*dstp = 0;
|
||||||
|
dstp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = (dstp - dstData);
|
||||||
|
*dstSize = size;
|
||||||
|
|
||||||
|
free(rlePlanesBuffer);
|
||||||
|
free(deltaPlanesBuffer);
|
||||||
|
free(planesBuffer);
|
||||||
|
|
||||||
|
return dstData;
|
||||||
|
}
|
78
libfreerdp/codec/planar.h
Normal file
78
libfreerdp/codec/planar.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* RDP6 Planar Codec
|
||||||
|
*
|
||||||
|
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FREERDP_CODEC_PLANAR_PRIVATE_H
|
||||||
|
#define FREERDP_CODEC_PLANAR_PRIVATE_H
|
||||||
|
|
||||||
|
#include <winpr/crt.h>
|
||||||
|
|
||||||
|
#include <freerdp/codec/color.h>
|
||||||
|
|
||||||
|
#define PLANAR_CONTROL_BYTE(_nRunLength, _cRawBytes) \
|
||||||
|
((_nRunLength & 0x0F) | ((_cRawBytes & 0x0F) << 4)) + \
|
||||||
|
(printf("CONTROL_BYTE(%d, %d)\n", _cRawBytes, _nRunLength) * 0)
|
||||||
|
|
||||||
|
#define PLANAR_CONTROL_BYTE_RUN_LENGTH(_controlByte) (_controlByte & 0x0F)
|
||||||
|
#define PLANAR_CONTROL_BYTE_RAW_BYTES(_controlByte) ((_controlByte >> 4) & 0x0F)
|
||||||
|
|
||||||
|
struct _RDP6_RLE_SEGMENT
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* controlByte:
|
||||||
|
* [0-3]: nRunLength
|
||||||
|
* [4-7]: cRawBytes
|
||||||
|
*/
|
||||||
|
BYTE controlByte;
|
||||||
|
BYTE* rawValues;
|
||||||
|
};
|
||||||
|
typedef struct _RDP6_RLE_SEGMENT RDP6_RLE_SEGMENT;
|
||||||
|
|
||||||
|
struct _RDP6_RLE_SEGMENTS
|
||||||
|
{
|
||||||
|
UINT32 cSegments;
|
||||||
|
RDP6_RLE_SEGMENT* segments;
|
||||||
|
};
|
||||||
|
typedef struct _RDP6_RLE_SEGMENTS RDP6_RLE_SEGMENTS;
|
||||||
|
|
||||||
|
#define PLANAR_FORMAT_HEADER_CS (1 << 3)
|
||||||
|
#define PLANAR_FORMAT_HEADER_RLE (1 << 4)
|
||||||
|
#define PLANAR_FORMAT_HEADER_NA (1 << 5)
|
||||||
|
|
||||||
|
struct _RDP6_BITMAP_STREAM
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* formatHeader:
|
||||||
|
* [0-2]: Color Loss Level (CLL)
|
||||||
|
* [3] : Chroma Subsampling (CS)
|
||||||
|
* [4] : Run Length Encoding (RLE)
|
||||||
|
* [5] : No Alpha (NA)
|
||||||
|
* [6-7]: Reserved
|
||||||
|
*/
|
||||||
|
BYTE formatHeader;
|
||||||
|
};
|
||||||
|
typedef struct _RDP6_BITMAP_STREAM RDP6_BITMAP_STREAM;
|
||||||
|
|
||||||
|
int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size);
|
||||||
|
|
||||||
|
int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[5]);
|
||||||
|
BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* plane, int width, int height, BYTE* outPlane, int* dstSize);
|
||||||
|
BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int height, BYTE* outPlane);
|
||||||
|
int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[5], int width, int height, BYTE* outPlanes[5]);
|
||||||
|
|
||||||
|
#endif /* FREERDP_CODEC_PLANAR_PRIVATE_H */
|
3
libfreerdp/codec/test/.gitignore
vendored
Normal file
3
libfreerdp/codec/test/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
TestFreeRDPCodec
|
||||||
|
TestFreeRDPCodec.c
|
||||||
|
|
31
libfreerdp/codec/test/CMakeLists.txt
Normal file
31
libfreerdp/codec/test/CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
set(MODULE_NAME "TestFreeRDPCodec")
|
||||||
|
set(MODULE_PREFIX "TEST_FREERDP_CODEC")
|
||||||
|
|
||||||
|
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||||
|
|
||||||
|
set(${MODULE_PREFIX}_TESTS
|
||||||
|
TestFreeRDPCodecPlanar.c)
|
||||||
|
|
||||||
|
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||||
|
${${MODULE_PREFIX}_DRIVER}
|
||||||
|
${${MODULE_PREFIX}_TESTS})
|
||||||
|
|
||||||
|
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||||
|
|
||||||
|
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||||
|
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||||
|
MODULE freerdp
|
||||||
|
MODULES freerdp-codec)
|
||||||
|
|
||||||
|
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||||
|
|
||||||
|
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||||
|
|
||||||
|
foreach(test ${${MODULE_PREFIX}_TESTS})
|
||||||
|
get_filename_component(TestName ${test} NAME_WE)
|
||||||
|
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/Test")
|
||||||
|
|
1516
libfreerdp/codec/test/TestFreeRDPCodecPlanar.c
Normal file
1516
libfreerdp/codec/test/TestFreeRDPCodecPlanar.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
libfreerdp/codec/test/test01.bmp
Normal file
BIN
libfreerdp/codec/test/test01.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
@ -232,36 +232,46 @@ BOOL gcc_read_conference_create_response(wStream* s, rdpSettings* settings)
|
|||||||
BYTE number;
|
BYTE number;
|
||||||
|
|
||||||
/* ConnectData */
|
/* ConnectData */
|
||||||
per_read_choice(s, &choice);
|
if (!per_read_choice(s, &choice) ||
|
||||||
per_read_object_identifier(s, t124_02_98_oid);
|
!per_read_object_identifier(s, t124_02_98_oid))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* ConnectData::connectPDU (OCTET_STRING) */
|
/* ConnectData::connectPDU (OCTET_STRING) */
|
||||||
per_read_length(s, &length);
|
if (!per_read_length(s, &length))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* ConnectGCCPDU */
|
/* ConnectGCCPDU */
|
||||||
per_read_choice(s, &choice);
|
if (!per_read_choice(s, &choice))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* ConferenceCreateResponse::nodeID (UserID) */
|
/* ConferenceCreateResponse::nodeID (UserID) */
|
||||||
per_read_integer16(s, &nodeID, 1001);
|
if (!per_read_integer16(s, &nodeID, 1001))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* ConferenceCreateResponse::tag (INTEGER) */
|
/* ConferenceCreateResponse::tag (INTEGER) */
|
||||||
per_read_integer(s, &tag);
|
if (!per_read_integer(s, &tag))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* ConferenceCreateResponse::result (ENUMERATED) */
|
/* ConferenceCreateResponse::result (ENUMERATED) */
|
||||||
per_read_enumerated(s, &result, MCS_Result_enum_length);
|
if (!per_read_enumerated(s, &result, MCS_Result_enum_length))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* number of UserData sets */
|
/* number of UserData sets */
|
||||||
per_read_number_of_sets(s, &number);
|
if (!per_read_number_of_sets(s, &number))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* UserData::value present + select h221NonStandard (1) */
|
/* UserData::value present + select h221NonStandard (1) */
|
||||||
per_read_choice(s, &choice);
|
if (!per_read_choice(s, &choice))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* h221NonStandard */
|
/* h221NonStandard */
|
||||||
if (!per_read_octet_string(s, h221_sc_key, 4, 4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */
|
if (!per_read_octet_string(s, h221_sc_key, 4, 4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* userData (OCTET_STRING) */
|
/* userData (OCTET_STRING) */
|
||||||
per_read_length(s, &length);
|
if (!per_read_length(s, &length))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (!gcc_read_server_data_blocks(s, settings, length))
|
if (!gcc_read_server_data_blocks(s, settings, length))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "gcc_read_conference_create_response: gcc_read_server_data_blocks failed\n");
|
fprintf(stderr, "gcc_read_conference_create_response: gcc_read_server_data_blocks failed\n");
|
||||||
@ -1125,7 +1135,7 @@ BOOL gcc_read_server_network_data(wStream* s, rdpSettings* settings)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
UINT16 MCSChannelId;
|
UINT16 MCSChannelId;
|
||||||
UINT16 channelCount;
|
UINT16 channelCount, channelsToTreat;
|
||||||
UINT16 channelId;
|
UINT16 channelId;
|
||||||
|
|
||||||
if(Stream_GetRemainingLength(s) < 4)
|
if(Stream_GetRemainingLength(s) < 4)
|
||||||
@ -1133,16 +1143,21 @@ BOOL gcc_read_server_network_data(wStream* s, rdpSettings* settings)
|
|||||||
Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */
|
Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */
|
||||||
Stream_Read_UINT16(s, channelCount); /* channelCount */
|
Stream_Read_UINT16(s, channelCount); /* channelCount */
|
||||||
|
|
||||||
|
channelsToTreat = channelCount;
|
||||||
if (channelCount != settings->ChannelCount)
|
if (channelCount != settings->ChannelCount)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "requested %d channels, got %d instead\n",
|
fprintf(stderr, "requested %d channels, got %d instead\n",
|
||||||
settings->ChannelCount, channelCount);
|
settings->ChannelCount, channelCount);
|
||||||
|
|
||||||
|
// we ensure that the response is not bigger than the request
|
||||||
|
if (channelCount > settings->ChannelCount)
|
||||||
|
channelsToTreat = settings->ChannelCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Stream_GetRemainingLength(s) < channelCount * 2)
|
if(Stream_GetRemainingLength(s) < channelCount * 2)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
for (i = 0; i < channelCount; i++)
|
for (i = 0; i < channelsToTreat; i++)
|
||||||
{
|
{
|
||||||
Stream_Read_UINT16(s, channelId); /* channelId */
|
Stream_Read_UINT16(s, channelId); /* channelId */
|
||||||
settings->ChannelDefArray[i].ChannelId = channelId;
|
settings->ChannelDefArray[i].ChannelId = channelId;
|
||||||
|
@ -1062,8 +1062,17 @@ void transport_free(rdpTransport* transport)
|
|||||||
{
|
{
|
||||||
if (transport->async)
|
if (transport->async)
|
||||||
{
|
{
|
||||||
assert(!transport->thread);
|
if (transport->stopEvent)
|
||||||
assert(!transport->stopEvent);
|
{
|
||||||
|
SetEvent(transport->stopEvent);
|
||||||
|
WaitForSingleObject(transport->thread, INFINITE);
|
||||||
|
|
||||||
|
CloseHandle(transport->thread);
|
||||||
|
CloseHandle(transport->stopEvent);
|
||||||
|
|
||||||
|
transport->thread = NULL;
|
||||||
|
transport->stopEvent = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transport->ReceiveBuffer)
|
if (transport->ReceiveBuffer)
|
||||||
|
@ -111,6 +111,7 @@ BOOL tls_connect(rdpTls* tls)
|
|||||||
long options = 0;
|
long options = 0;
|
||||||
int connection_status;
|
int connection_status;
|
||||||
char *hostname;
|
char *hostname;
|
||||||
|
int port;
|
||||||
|
|
||||||
tls->ctx = SSL_CTX_new(TLSv1_client_method());
|
tls->ctx = SSL_CTX_new(TLSv1_client_method());
|
||||||
|
|
||||||
@ -214,11 +215,17 @@ BOOL tls_connect(rdpTls* tls)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tls->settings->GatewayEnabled)
|
if (tls->settings->GatewayEnabled)
|
||||||
|
{
|
||||||
hostname = tls->settings->GatewayHostname;
|
hostname = tls->settings->GatewayHostname;
|
||||||
|
port = tls->settings->GatewayPort;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
hostname = tls->settings->ServerHostname;
|
hostname = tls->settings->ServerHostname;
|
||||||
|
port = tls->settings->ServerPort;
|
||||||
|
}
|
||||||
|
|
||||||
if (!tls_verify_certificate(tls, cert, hostname))
|
if (!tls_verify_certificate(tls, cert, hostname, port))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "tls_connect: certificate not trusted, aborting.\n");
|
fprintf(stderr, "tls_connect: certificate not trusted, aborting.\n");
|
||||||
tls_disconnect(tls);
|
tls_disconnect(tls);
|
||||||
@ -568,7 +575,7 @@ BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
|
BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port)
|
||||||
{
|
{
|
||||||
int match;
|
int match;
|
||||||
int index;
|
int index;
|
||||||
@ -651,7 +658,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
|
|||||||
|
|
||||||
if (instance->VerifyX509Certificate)
|
if (instance->VerifyX509Certificate)
|
||||||
{
|
{
|
||||||
status = instance->VerifyX509Certificate(instance, pemCert, length, 0);
|
status = instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "VerifyX509Certificate: (length = %d) status: %d\n%s\n",
|
fprintf(stderr, "VerifyX509Certificate: (length = %d) status: %d\n%s\n",
|
||||||
|
@ -34,6 +34,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
WINPR_API void winpr_HexDump(BYTE* data, int length);
|
WINPR_API void winpr_HexDump(BYTE* data, int length);
|
||||||
|
WINPR_API void winpr_CArrayDump(BYTE* data, int length, int width);
|
||||||
|
|
||||||
WINPR_API int wprintfx(const char *fmt, ...);
|
WINPR_API int wprintfx(const char *fmt, ...);
|
||||||
WINPR_API int wvprintfx(const char *fmt, va_list args);
|
WINPR_API int wvprintfx(const char *fmt, va_list args);
|
||||||
|
@ -60,6 +60,32 @@ void winpr_HexDump(BYTE* data, int length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void winpr_CArrayDump(BYTE* data, int length, int width)
|
||||||
|
{
|
||||||
|
BYTE* p = data;
|
||||||
|
int i, line, offset = 0;
|
||||||
|
|
||||||
|
while (offset < length)
|
||||||
|
{
|
||||||
|
line = length - offset;
|
||||||
|
|
||||||
|
if (line > width)
|
||||||
|
line = width;
|
||||||
|
|
||||||
|
printf("\t\"");
|
||||||
|
|
||||||
|
for (i = 0; i < line; i++)
|
||||||
|
printf("\\x%02X", p[i]);
|
||||||
|
|
||||||
|
printf("\"\n");
|
||||||
|
|
||||||
|
offset += line;
|
||||||
|
p += line;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
int wvprintfx(const char *fmt, va_list args)
|
int wvprintfx(const char *fmt, va_list args)
|
||||||
{
|
{
|
||||||
return trio_vprintf(fmt, args);
|
return trio_vprintf(fmt, args);
|
||||||
|
Loading…
Reference in New Issue
Block a user