rle decoding

This commit is contained in:
speyrefitte
2014-06-26 18:00:29 +02:00
parent 4331a215c6
commit 149d212d93
4 changed files with 109 additions and 41 deletions

View File

@@ -27,7 +27,7 @@ from PyQt4 import QtGui, QtCore
from rdpy.protocol.rfb.rfb import RFBClientObserver
from rdpy.protocol.rdp.rdp import RDPClientObserver
from rdpy.network.type import UInt16Le, Stream
from rdpy.network.type import UInt16Le, UInt24Le, Stream
import rle
class QAdaptor(object):
@@ -118,7 +118,8 @@ class RFBClientQt(RFBClientObserver, QAdaptor):
@param e: qKeyEvent
'''
self.keyEvent(True, e.nativeVirtualKey())
class RDPClientQt(RDPClientObserver, QAdaptor):
'''
Adaptor for RDP client
@@ -149,18 +150,17 @@ class RDPClientQt(RDPClientObserver, QAdaptor):
@param isCompress: use RLE compression
@param data: bitmap data
'''
#TODO
if isCompress:
#rle.decode("", Stream(data), width, height, UInt16Le)
return
imageFormat = None
if bitsPerPixel == 16:
imageFormat = QtGui.QImage.Format_RGB16
if isCompress:
data = rle.decode(Stream(data), width, height, UInt16Le).getvalue()
elif bitsPerPixel == 24:
imageFormat = QtGui.QImage.Format_RGB888
elif bitsPerPixel == 32:
imageFormat = QtGui.QImage.Format_RGB32
if isCompress:
data = rle.decode(Stream(data), width, height, UInt24Le).getvalue()
else:
print "Receive image in bad format"
return

View File

@@ -27,66 +27,66 @@ 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, sizeof
from rdpy.network.type import UInt8, UInt16Le, Stream
def decode(src, width, height, colorType):
"""
It's a python transcription of rdesktop algorithm
"""
lastopcode = -1
prevLine = None
line = None
lastopcode = None
x = width
prevLine = 0
code = UInt8()
opcode = UInt8()
insertMix = False
biColor = False
color1 = colorType()
color2 = colorType()
mix = colorType()
mix = ~colorType()
mask = UInt8()
fom_mask = UInt8()
code = UInt8()
opcode = UInt8()
isFillOrMix = False
insertMix = False
fom_mask = 0
mask = 0
line = 0
count = UInt16Le()
dst = [colorType()] * width * height
while src.dataLen() > 0:
#compute orders
fom_mask = UInt8()
src.readType(code)
opcode = code >> 4
count = UInt16Le()
if opcode == 0xc or opcode == 0xd or opcode == 0xe:
opcode -= 6
count = code & 0xf
count.value = (code & 0xf).value
offset = 16
elif opcode == 0xf:
opcode = code & 0xf
if opcode < 9:
src.readType(count)
else:
count = UInt16Le(8 if opcode < 0xb else 1)
count.value = 8 if opcode < 0xb else 1
offset = 0
else:
opcode >>= 1
count = UInt16Le((code & 0xf).value)
count.value = (code & 0x1f).value
offset = 32
if offset != 0:
isFillOrMix = opcode == 2 or opcode == 7
isFillOrMix = ((opcode == 2) or (opcode == 7))
if count == 0:
tmp = UInt8()
src.readType(tmp)
if isFillOrMix:
count = UInt16Le((tmp + 1).value)
count.value = (tmp + 1).value
else:
count = UInt16Le((tmp + offset).value)
count.value = (tmp + offset).value
elif isFillOrMix:
count <<= 3
if opcode == 0:
if lastopcode == opcode and not (x == width and prevLine == 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)
@@ -94,16 +94,21 @@ def decode(src, width, height, colorType):
src.readType(color1)
elif opcode == 6 or opcode == 7:
src.readType(mix)
opcode -= 5
elif opcode == 9:
mask = 0x03
opcode = UInt8(0x02)
fom_mask = 5
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 x >= width:
if height <= 0:
raise InvalidExpectedDataException("In RLE decompression height must be greater than 0")
x = 0
@@ -114,7 +119,7 @@ def decode(src, width, height, colorType):
#fill
if opcode == 0:
if insertMix:
if prevLine == 0:
if prevLine is None:
dst[line + x] = mix
else:
dst[line + x] = dst[prevLine + x] ^ mix
@@ -122,7 +127,7 @@ def decode(src, width, height, colorType):
count -= 1
x += 1
if prevLine == 0:
if prevLine is None:
while count > 0 and x < width:
dst[line + x] = colorType()
count -= 1
@@ -134,7 +139,7 @@ def decode(src, width, height, colorType):
x += 1
#mix
elif opcode == 1:
if prevLine == 0:
if prevLine is None:
while count > 0 and x < width:
dst[line + x] = mix
count -= 1
@@ -146,7 +151,42 @@ def decode(src, width, height, colorType):
x += 1
#fill or mix
elif opcode == 2:
pass
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:
@@ -161,7 +201,16 @@ def decode(src, width, height, colorType):
x += 1
#bicolor
elif opcode == 8:
pass
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:
@@ -173,8 +222,9 @@ def decode(src, width, height, colorType):
dst[line + x] = colorType()
count -= 1
x += 1
else:
raise InvalidExpectedDataException("In RLE decompression invalid opcode")
output = Stream()
output.writeType(dst)
return output
return output

View File

@@ -45,7 +45,7 @@ class RDPClientQtFactory(rdp.ClientFactory):
#create qt widget
self._w = client.getWidget()
self._w.resize(1024, 800)
self._w.setWindowTitle('rdpyclient-vnc')
self._w.setWindowTitle('rdpyclient-rdp')
self._w.show()
return client

View File

@@ -341,7 +341,7 @@ class SimpleType(Type, CallableValue):
def __or__(self, other):
'''
implement bitwise and operator
implement bitwise or operator
@param other: SimpleType value or try to construct same type as self
around other value
@return: self.__class__ object with or result
@@ -350,6 +350,17 @@ class SimpleType(Type, CallableValue):
other = self.__class__(other)
return self.__class__(self.value.__or__(other.value))
def __xor__(self, other):
'''
implement bitwise xor operator
@param other: SimpleType value or try to construct same type as self
around other value
@return: self.__class__ object with or result
'''
if not isinstance(other, SimpleType):
other = self.__class__(other)
return self.__class__(self.value.__xor__(other.value))
def __lshift__(self, other):
'''
left shift operator
@@ -376,6 +387,13 @@ class SimpleType(Type, CallableValue):
@return: hash of inner value
'''
return hash(self.value)
def __nonzero__(self):
'''
boolean conversion
@return: bool of inner value
'''
return bool(self.value)
class CompositeType(Type):