add fast library

This commit is contained in:
speyrefitte
2014-06-27 18:01:00 +02:00
parent 1547eeda46
commit f0024db024
12 changed files with 83 additions and 291 deletions

4
.gitignore vendored
View File

@@ -2,3 +2,7 @@
.project
.pydevproject
README.md~
lib/obj/*
*.so
*.os
.sconsign.dblite

View File

@@ -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()

View File

@@ -1,11 +0,0 @@
%Module rle
namespace rle {
%TypeHeaderCode
#include <rle.h>
%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);
};

51
lib/sconstruct Normal file
View File

@@ -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)

9
lib/sip/rle.sip Normal file
View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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 <http://www.gnu.org/licenses/>.
#
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

View File

@@ -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):

View File

@@ -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):

0
rdpy/fast/__init__.py Normal file
View File