diff --git a/.gitignore b/.gitignore index 54c012d..9268917 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ .project .pydevproject README.md~ +lib/obj/* +*.so +*.os +.sconsign.dblite diff --git a/lib/build/configure.py b/lib/build/configure.py deleted file mode 100644 index d99ef90..0000000 --- a/lib/build/configure.py +++ /dev/null @@ -1,27 +0,0 @@ -''' -@author: sylvain -''' - -import os -import sipconfig - -# The name of the SIP build file generated by SIP and used by the build -# system. -build_file = "rle.sbf" - -# Get the SIP configuration information. -config = sipconfig.Configuration() - -# Run SIP to generate the code. -os.system(" ".join([config.sip_bin, "-c", ".", "-b", build_file, "../src/rle.sip"])) - -# Create the Makefile. -makefile = sipconfig.SIPModuleMakefile(config, build_file) - -# Add the library we are wrapping. The name doesn't include any platform -# specific prefixes or extensions (e.g. the "lib" prefix on UNIX, or the -# ".dll" extension on Windows). -makefile.extra_libs = ["rle"] - -# Generate the Makefile itself. -makefile.generate() diff --git a/lib/build/rle.sip b/lib/build/rle.sip deleted file mode 100644 index 482e3f3..0000000 --- a/lib/build/rle.sip +++ /dev/null @@ -1,11 +0,0 @@ -%Module rle - -namespace rle { -%TypeHeaderCode -#include -%End - - int decode_uint8(char* output, int width, int height, char* input, int size); - int decode_uint16(char* output, int width, int height, char* input, int size); - int decode_uint24(char* output, int width, int height, char* input, int size); -}; \ No newline at end of file diff --git a/lib/sconstruct b/lib/sconstruct new file mode 100644 index 0000000..d51ebcd --- /dev/null +++ b/lib/sconstruct @@ -0,0 +1,51 @@ +import os +import sipconfig + +script_dir = os.path.dirname(os.path.realpath(Dir("#/Sconstruct").abspath)) +build_dir = os.path.join(script_dir, "build") +src_dir = os.path.join(script_dir, "src") +sip_dir = os.path.join(script_dir, "sip") +#generate install dir +install_dir = os.path.join(script_dir, "..", "rdpy", "fast") + +def build_sip(target, source, env): + # Get the SIP configuration information. + config = sipconfig.Configuration() + + # Run SIP to generate the code. + os.system(" ".join([config.sip_bin, "-c", "src", str(source[0])])) + + # Create the Makefile. + #makefile = sipconfig.SIPModuleMakefile(config, str(target[0])) + + # Add the library we are wrapping. The name doesn't include any platform + # specific prefixes or extensions (e.g. the "lib" prefix on UNIX, or the + # ".dll" extension on Windows). + #makefile.extra_libs = ["rle"] + + #add build directory as extra lib + #makefile.extra_lib_dirs = [os.path.dirname(str(target[0]))] + + # Generate the Makefile itself. + #makefile.generate() + + +#building library +env = Environment() +env.Append(BUILDERS = {'Sip' : Builder(action = build_sip)}) +env.VariantDir('build', 'src', duplicate=0) + +cppdefines = {} +targetName = os.path.join(build_dir, "libfastrdpy.so") + +sources = [Glob(os.path.join(src_dir, '*.c'))] + +env.Append(CPPDEFINES = cppdefines); + +libSip = env.Sip([os.path.join(build_dir, "rle.sbf")], [os.path.join(sip_dir, "rle.sip")]) + +libC = env.SharedLibrary(target = targetName, + source = sources + ) + +env.Depends(libSip, libC) diff --git a/lib/sip/rle.sip b/lib/sip/rle.sip new file mode 100644 index 0000000..0e52d13 --- /dev/null +++ b/lib/sip/rle.sip @@ -0,0 +1,9 @@ +%Module(name=rle, language="C") + +%UnitCode +#include <../src/rle.h> +%End + +int rle_decode_uint8(void* output, int width, int height, char* input, int size); +int rle_decode_uint16(void* output, int width, int height, char* input, int size); +int rle_decode_uint24(void* output, int width, int height, char* input, int size); diff --git a/lib/src/rle.cpp b/lib/src/rle.c similarity index 98% rename from lib/src/rle.cpp rename to lib/src/rle.c index fa921de..90bf3bc 100644 --- a/lib/src/rle.cpp +++ b/lib/src/rle.c @@ -1,8 +1,6 @@ #include "rle_m.h" -namespace test { - -int decode_uint8(char* output, int width, int height, char* input, int size) +int rle_decode_uint8(char* output, int width, int height, char* input, int size) { char* prevline; char* line; @@ -241,7 +239,7 @@ int decode_uint8(char* output, int width, int height, char* input, int size) return 1; } -int decode_uint16(char* output, int width, int height, char* input, int size) +int rle_decode_uint16(char* output, int width, int height, char* input, int size) { char* prevline; char* line; @@ -526,7 +524,7 @@ int decode_uint16(char* output, int width, int height, char* input, int size) return 1; } -int decode_uint24(char* output, int width, int height, char* input, int size) +int rle_decode_uint24(char* output, int width, int height, char* input, int size) { char* prevline; char* line; @@ -832,5 +830,3 @@ int decode_uint24(char* output, int width, int height, char* input, int size) } return 1; } - -} diff --git a/lib/src/rle.h b/lib/src/rle.h index a5154bc..0b206bb 100644 --- a/lib/src/rle.h +++ b/lib/src/rle.h @@ -1,10 +1,9 @@ #ifndef _RLE_H_ #define _RLE_H_ -namespace rle { - int decode_uint8(char* output, int width, int height, char* input, int size); - int decode_uint16(char* output, int width, int height, char* input, int size); - int decode_uint24(char* output, int width, int height, char* input, int size); -} + +int rle_decode_uint8(char* output, int width, int height, char* input, int size); +int rle_decode_uint16(char* output, int width, int height, char* input, int size); +int rle_decode_uint24(char* output, int width, int height, char* input, int size); #endif diff --git a/rdpy/display/qt.py b/rdpy/display/qt4.py similarity index 92% rename from rdpy/display/qt.py rename to rdpy/display/qt4.py index af5288f..b5b29f9 100644 --- a/rdpy/display/qt.py +++ b/rdpy/display/qt4.py @@ -26,9 +26,8 @@ QRemoteDesktop is a widget use for render in rdpy from PyQt4 import QtGui, QtCore from rdpy.protocol.rfb.rfb import RFBClientObserver from rdpy.protocol.rdp.rdp import RDPClientObserver +import rdpy.fast.rle as rle -from rdpy.network.type import UInt16Le, UInt24Le, Stream -import rle class QAdaptor(object): ''' @@ -150,22 +149,24 @@ class RDPClientQt(RDPClientObserver, QAdaptor): @param isCompress: use RLE compression @param data: bitmap data ''' - - imageFormat = None + image = None if bitsPerPixel == 16: - imageFormat = QtGui.QImage.Format_RGB16 if isCompress: - data = rle.decode(Stream(data), width, height, UInt16Le).getvalue() + image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB16) + data = rle.rle_decode_uint16(image.bits(), width, height, data, len(data)) + else: + image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB16) elif bitsPerPixel == 24: - imageFormat = QtGui.QImage.Format_RGB888 if isCompress: - data = rle.decode(Stream(data), width, height, UInt24Le).getvalue() + image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB888) + data = rle.rle_decode_uint24(image.bits(), width, height, data, len(data)) + else: + image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB24) else: print "Receive image in bad format" return - image = QtGui.QImage(data, width, height, imageFormat) self._widget.notifyImage(destLeft, destTop, image) diff --git a/rdpy/display/rle.py b/rdpy/display/rle.py deleted file mode 100644 index 370dd0b..0000000 --- a/rdpy/display/rle.py +++ /dev/null @@ -1,230 +0,0 @@ -# -# Copyright (c) 2014 Sylvain Peyrefitte -# -# This file is part of rdpy. -# -# rdpy is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -from rdpy.network.error import InvalidExpectedDataException - -""" -Run length Encoding Algorithm implementation - -It's the microsoft view of RLE algorithm - -Most of bitmap in RDP protocol use this encoding - -@see: http://msdn.microsoft.com/en-us/library/dd240593.aspx -""" -from rdpy.network.type import UInt8, UInt16Le, Stream - -def decode(src, width, height, colorType): - """ - It's a python transcription of rdesktop algorithm - """ - prevLine = None - line = None - lastopcode = None - x = width - insertMix = False - biColor = False - color1 = colorType() - color2 = colorType() - mix = ~colorType() - mask = UInt8() - fom_mask = UInt8() - code = UInt8() - opcode = UInt8() - isFillOrMix = False - count = UInt16Le() - dst = [colorType()] * width * height - - while src.dataLen() > 0: - #compute orders - fom_mask = UInt8() - src.readType(code) - opcode = code >> 4 - - if opcode == 0xc or opcode == 0xd or opcode == 0xe: - opcode -= 6 - count.value = (code & 0xf).value - offset = 16 - elif opcode == 0xf: - opcode = code & 0xf - if opcode < 9: - src.readType(count) - else: - count.value = 8 if opcode < 0xb else 1 - offset = 0 - else: - opcode >>= 1 - count.value = (code & 0x1f).value - offset = 32 - - if offset != 0: - isFillOrMix = ((opcode == 2) or (opcode == 7)) - if count == 0: - tmp = UInt8() - src.readType(tmp) - if isFillOrMix: - count.value = (tmp + 1).value - else: - count.value = (tmp + offset).value - elif isFillOrMix: - count <<= 3 - - - if opcode == 0: - if not lastopcode is None and lastopcode == opcode and not ((x == width) and (prevLine is None)): - insertMix = True - elif opcode == 3 or opcode == 8: - src.readType(color2) - if opcode == 8: - src.readType(color1) - elif opcode == 6 or opcode == 7: - src.readType(mix) - opcode -= 5 - elif opcode == 9: - mask.value = 0x03 - opcode.value = 0x02 - fom_mask.value = 3 - elif opcode == 0x0a: - mask.value = 0x05; - opcode.value = 0x02; - fom_mask.value = 5; - - lastopcode = opcode - mixmask = 0 - - while count > 0: - if x >= width: - if height <= 0: - raise InvalidExpectedDataException("In RLE decompression height must be greater than 0") - x = 0 - height -= 1 - prevLine = line - line = width * height - - #fill - if opcode == 0: - if insertMix: - if prevLine is None: - dst[line + x] = mix - else: - dst[line + x] = dst[prevLine + x] ^ mix - insertMix = False - count -= 1 - x += 1 - - if prevLine is None: - while count > 0 and x < width: - dst[line + x] = colorType() - count -= 1 - x += 1 - else: - while count > 0 and x < width: - dst[line + x] = dst[prevLine + x] - count -= 1 - x += 1 - #mix - elif opcode == 1: - if prevLine is None: - while count > 0 and x < width: - dst[line + x] = mix - count -= 1 - x += 1 - else: - while count > 0 and x < width: - dst[line + x] = dst[prevLine + x] ^ mix - count -= 1 - x += 1 - #fill or mix - elif opcode == 2: - if prevLine is None: - while count > 0 and x < width: - - mixmask <<= 1 - if mixmask & 0xff == 0: - if fom_mask: - mask = fom_mask - else: - src.readType(mask) - mixmask = 1 - - if mask & mixmask: - dst[line + x] = mix - else: - dst[line + x] = colorType() - count -= 1 - x += 1 - else: - while count > 0 and x < width: - - mixmask <<= 1 - if mixmask & 0xff == 0: - if fom_mask: - mask = fom_mask - else: - src.readType(mask) - mixmask = 1 - - if mask & mixmask: - dst[line + x] = dst[prevLine + x] ^ mix - else: - dst[line + x] = dst[prevLine + x] - - count -= 1 - x += 1 - - #color - elif opcode == 3: - while count > 0 and x < width: - dst[line + x] = color2 - count -= 1 - x += 1 - #copy - elif opcode == 4: - while count > 0 and x < width: - src.readType(dst[line + x]) - count -= 1 - x += 1 - #bicolor - elif opcode == 8: - while count > 0 and x < width: - if biColor: - dst[line + x] = color2 - biColor = False - else: - dst[line + x] = color1 - biColor = True - count += 1 - count -= 1 - x += 1 - #write - elif opcode == 0xd: - while count > 0 and x < width: - dst[line + x] = ~colorType() - count -= 1 - x += 1 - elif opcode == 0xe: - while count > 0 and x < width: - dst[line + x] = colorType() - count -= 1 - x += 1 - else: - raise InvalidExpectedDataException("In RLE decompression invalid opcode") - output = Stream() - output.writeType(dst) - return output - \ No newline at end of file diff --git a/rdpy/examples/rdpclient.py b/rdpy/examples/rdpclient.py index af98e75..7ae897a 100644 --- a/rdpy/examples/rdpclient.py +++ b/rdpy/examples/rdpclient.py @@ -28,7 +28,7 @@ import os sys.path.insert(1, os.path.join(sys.path[0], '../..')) from PyQt4 import QtGui -from rdpy.display.qt import RDPClientQt +from rdpy.display.qt4 import RDPClientQt from rdpy.protocol.rdp import rdp class RDPClientQtFactory(rdp.ClientFactory): diff --git a/rdpy/examples/vncclient.py b/rdpy/examples/vncclient.py index ca44504..e3eedd1 100644 --- a/rdpy/examples/vncclient.py +++ b/rdpy/examples/vncclient.py @@ -28,7 +28,7 @@ import os sys.path.insert(1, os.path.join(sys.path[0], '../..')) from PyQt4 import QtGui -from rdpy.display.qt import RFBClientQt +from rdpy.display.qt4 import RFBClientQt from rdpy.protocol.rfb import rfb class RFBClientQtFactory(rfb.ClientFactory): diff --git a/rdpy/fast/__init__.py b/rdpy/fast/__init__.py new file mode 100644 index 0000000..e69de29