diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c index f88a29d18..ce9e028e6 100644 --- a/client/X11/xf_graphics.c +++ b/client/X11/xf_graphics.c @@ -25,6 +25,7 @@ #endif #include +#include #include "xf_graphics.h" @@ -116,7 +117,14 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, else bitmap->data = (uint8*) xrealloc(bitmap->data, size); - if (compressed) + if (compressed == 2) + { + if (!jpeg_decompress(data, bitmap->data, width, height, length, bpp)) + { + printf("jpeg Decompression Failed\n"); + } + } + else if (compressed) { boolean status; diff --git a/include/freerdp/codec/jpeg.h b/include/freerdp/codec/jpeg.h new file mode 100644 index 000000000..36540d922 --- /dev/null +++ b/include/freerdp/codec/jpeg.h @@ -0,0 +1,28 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Compressed Bitmap + * + * Copyright 2012 Jay Sorg + * + * 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 __JPEG_H +#define __JPEG_H + +#include + +boolean +jpeg_decompress(uint8* input, uint8* output, int width, int height, int size, int bpp); + +#endif /* __BITMAP_H */ diff --git a/libfreerdp-cache/bitmap.c b/libfreerdp-cache/bitmap.c index a382bfe0c..6d42d263d 100644 --- a/libfreerdp-cache/bitmap.c +++ b/libfreerdp-cache/bitmap.c @@ -102,9 +102,18 @@ void update_gdi_cache_bitmap_v2(rdpContext* context, CACHE_BITMAP_V2_ORDER* cach cache_bitmap_v2->bitmapBpp = context->instance->settings->color_depth; } - bitmap->Decompress(context, bitmap, - cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapWidth, cache_bitmap_v2->bitmapHeight, - cache_bitmap_v2->bitmapBpp, cache_bitmap_v2->bitmapLength, cache_bitmap_v2->compressed); + if (cache_bitmap_v2->compressed && (cache_bitmap_v2->flags & 0x80)) + { + bitmap->Decompress(context, bitmap, + cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapWidth, cache_bitmap_v2->bitmapHeight, + cache_bitmap_v2->bitmapBpp, cache_bitmap_v2->bitmapLength, 2); + } + else + { + bitmap->Decompress(context, bitmap, + cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapWidth, cache_bitmap_v2->bitmapHeight, + cache_bitmap_v2->bitmapBpp, cache_bitmap_v2->bitmapLength, cache_bitmap_v2->compressed); + } bitmap->New(context, bitmap); diff --git a/libfreerdp-codec/CMakeLists.txt b/libfreerdp-codec/CMakeLists.txt index 78d7610ea..442b5fbba 100644 --- a/libfreerdp-codec/CMakeLists.txt +++ b/libfreerdp-codec/CMakeLists.txt @@ -44,6 +44,7 @@ set(FREERDP_CODEC_SRCS nsc_types.h mppc_dec.c mppc_enc.c + jpeg.c ) if(WITH_SSE2) @@ -67,7 +68,7 @@ endif() add_library(freerdp-codec ${FREERDP_CODEC_SRCS}) set_target_properties(freerdp-codec PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") -target_link_libraries(freerdp-codec freerdp-utils) +target_link_libraries(freerdp-codec freerdp-utils jpeg) install(TARGETS freerdp-codec DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/libfreerdp-codec/jpeg.c b/libfreerdp-codec/jpeg.c new file mode 100644 index 000000000..ac96def9b --- /dev/null +++ b/libfreerdp-codec/jpeg.c @@ -0,0 +1,141 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Compressed jpeg + * + * Copyright 2012 Jay Sorg + * + * 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. + */ + +#include +#include +#include + +#define HAVE_BOOLEAN +#include + +struct mydata_decomp +{ + char* data; + int data_bytes; +}; + +/*****************************************************************************/ +static void my_init_source(j_decompress_ptr cinfo) +{ +} + +/*****************************************************************************/ +static boolean my_fill_input_buffer(j_decompress_ptr cinfo) +{ + struct mydata_decomp* md; + + md = (struct mydata_decomp*)(cinfo->client_data); + cinfo->src->next_input_byte = (unsigned char*)(md->data); + cinfo->src->bytes_in_buffer = md->data_bytes; + return 1; +} + +/*****************************************************************************/ +static void my_skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ +} + +/*****************************************************************************/ +static boolean my_resync_to_restart(j_decompress_ptr cinfo, int desired) +{ + return 1; +} + +/*****************************************************************************/ +static void my_term_source(j_decompress_ptr cinfo) +{ +} + +/*****************************************************************************/ +int +do_decompress(char* comp_data, int comp_data_bytes, + int* width, int* height, int* bpp, + char* decomp_data, int* decomp_data_bytes) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + struct jpeg_source_mgr src_mgr; + struct mydata_decomp md; + JSAMPROW row_pointer[1]; + + memset(&cinfo, 0, sizeof(cinfo)); + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + + memset(&src_mgr, 0, sizeof(src_mgr)); + cinfo.src = &src_mgr; + src_mgr.init_source = my_init_source; + src_mgr.fill_input_buffer = my_fill_input_buffer; + src_mgr.skip_input_data = my_skip_input_data; + src_mgr.resync_to_restart = my_resync_to_restart; + src_mgr.term_source = my_term_source; + + memset(&md, 0, sizeof(md)); + md.data = comp_data; + md.data_bytes = comp_data_bytes; + cinfo.client_data = &md; + + jpeg_read_header(&cinfo, 1); + + cinfo.out_color_space = JCS_RGB; + + *width = cinfo.image_width; + *height = cinfo.image_height; + *bpp = cinfo.num_components * 8; + + jpeg_start_decompress(&cinfo); + + while(cinfo.output_scanline < cinfo.image_height) + { + row_pointer[0] = (JSAMPROW) decomp_data; + jpeg_read_scanlines(&cinfo, row_pointer, 1); + decomp_data += cinfo.image_width * cinfo.num_components; + } + *decomp_data_bytes = cinfo.output_width * + cinfo.output_height * cinfo.num_components; + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + return 0; +} + +/* jpeg decompress */ +boolean +jpeg_decompress(uint8 * input, uint8 * output, int width, int height, int size, int bpp) +{ + int lwidth; + int lheight; + int lbpp; + int ldecomp_data_bytes; + + if (bpp != 24) + { + return 0; + } + if (do_decompress((char*)input, size, + &lwidth, &lheight, &lbpp, + (char*)output, &ldecomp_data_bytes) != 0) + { + return 0; + } + if (lwidth != width || lheight != height || lbpp != bpp) + { + return 0; + } + return 1; +} diff --git a/libfreerdp-core/capabilities.c b/libfreerdp-core/capabilities.c index 001b38f06..43615cdad 100644 --- a/libfreerdp-core/capabilities.c +++ b/libfreerdp-core/capabilities.c @@ -1014,6 +1014,7 @@ void rdp_write_bitmap_cache_v2_capability_set(STREAM* s, rdpSettings* settings) header = rdp_capability_set_start(s); cacheFlags = ALLOW_CACHE_WAITING_LIST_FLAG; + cacheFlags |= 0x80; /* jpeg hack */ if (settings->persistent_bitmap_cache) cacheFlags |= PERSISTENT_KEYS_EXPECTED_FLAG; diff --git a/libfreerdp-gdi/graphics.c b/libfreerdp-gdi/graphics.c index 04816334c..d83ed2031 100644 --- a/libfreerdp-gdi/graphics.c +++ b/libfreerdp-gdi/graphics.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -98,7 +99,14 @@ void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, else bitmap->data = (uint8*) xrealloc(bitmap->data, size); - if (compressed) + if (compressed == 2) + { + if (!jpeg_decompress(data, bitmap->data, width, height, length, bpp)) + { + printf("jpeg Decompression Failed\n"); + } + } + else if (compressed) { boolean status;