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.rfb.rfb import RFBClientObserver
from rdpy.protocol.rdp.rdp import RDPClientObserver from rdpy.protocol.rdp.rdp import RDPClientObserver
from rdpy.network.type import UInt16Le, Stream from rdpy.network.type import UInt16Le, UInt24Le, Stream
import rle import rle
class QAdaptor(object): class QAdaptor(object):
@@ -118,7 +118,8 @@ class RFBClientQt(RFBClientObserver, QAdaptor):
@param e: qKeyEvent @param e: qKeyEvent
''' '''
self.keyEvent(True, e.nativeVirtualKey()) self.keyEvent(True, e.nativeVirtualKey())
class RDPClientQt(RDPClientObserver, QAdaptor): class RDPClientQt(RDPClientObserver, QAdaptor):
''' '''
Adaptor for RDP client Adaptor for RDP client
@@ -149,18 +150,17 @@ class RDPClientQt(RDPClientObserver, QAdaptor):
@param isCompress: use RLE compression @param isCompress: use RLE compression
@param data: bitmap data @param data: bitmap data
''' '''
#TODO
if isCompress:
#rle.decode("", Stream(data), width, height, UInt16Le)
return
imageFormat = None imageFormat = None
if bitsPerPixel == 16: if bitsPerPixel == 16:
imageFormat = QtGui.QImage.Format_RGB16 imageFormat = QtGui.QImage.Format_RGB16
if isCompress:
data = rle.decode(Stream(data), width, height, UInt16Le).getvalue()
elif bitsPerPixel == 24: elif bitsPerPixel == 24:
imageFormat = QtGui.QImage.Format_RGB888 imageFormat = QtGui.QImage.Format_RGB888
elif bitsPerPixel == 32: if isCompress:
imageFormat = QtGui.QImage.Format_RGB32 data = rle.decode(Stream(data), width, height, UInt24Le).getvalue()
else: else:
print "Receive image in bad format" print "Receive image in bad format"
return 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 @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): def decode(src, width, height, colorType):
""" """
It's a python transcription of rdesktop algorithm It's a python transcription of rdesktop algorithm
""" """
lastopcode = -1 prevLine = None
line = None
lastopcode = None
x = width x = width
prevLine = 0 insertMix = False
code = UInt8() biColor = False
opcode = UInt8()
color1 = colorType() color1 = colorType()
color2 = colorType() color2 = colorType()
mix = colorType() mix = ~colorType()
mask = UInt8()
fom_mask = UInt8()
code = UInt8()
opcode = UInt8()
isFillOrMix = False isFillOrMix = False
insertMix = False count = UInt16Le()
fom_mask = 0
mask = 0
line = 0
dst = [colorType()] * width * height dst = [colorType()] * width * height
while src.dataLen() > 0: while src.dataLen() > 0:
#compute orders #compute orders
fom_mask = UInt8()
src.readType(code) src.readType(code)
opcode = code >> 4 opcode = code >> 4
count = UInt16Le()
if opcode == 0xc or opcode == 0xd or opcode == 0xe: if opcode == 0xc or opcode == 0xd or opcode == 0xe:
opcode -= 6 opcode -= 6
count = code & 0xf count.value = (code & 0xf).value
offset = 16 offset = 16
elif opcode == 0xf: elif opcode == 0xf:
opcode = code & 0xf opcode = code & 0xf
if opcode < 9: if opcode < 9:
src.readType(count) src.readType(count)
else: else:
count = UInt16Le(8 if opcode < 0xb else 1) count.value = 8 if opcode < 0xb else 1
offset = 0 offset = 0
else: else:
opcode >>= 1 opcode >>= 1
count = UInt16Le((code & 0xf).value) count.value = (code & 0x1f).value
offset = 32 offset = 32
if offset != 0: if offset != 0:
isFillOrMix = opcode == 2 or opcode == 7 isFillOrMix = ((opcode == 2) or (opcode == 7))
if count == 0: if count == 0:
tmp = UInt8() tmp = UInt8()
src.readType(tmp) src.readType(tmp)
if isFillOrMix: if isFillOrMix:
count = UInt16Le((tmp + 1).value) count.value = (tmp + 1).value
else: else:
count = UInt16Le((tmp + offset).value) count.value = (tmp + offset).value
elif isFillOrMix: elif isFillOrMix:
count <<= 3 count <<= 3
if opcode == 0: 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 insertMix = True
elif opcode == 3 or opcode == 8: elif opcode == 3 or opcode == 8:
src.readType(color2) src.readType(color2)
@@ -94,16 +94,21 @@ def decode(src, width, height, colorType):
src.readType(color1) src.readType(color1)
elif opcode == 6 or opcode == 7: elif opcode == 6 or opcode == 7:
src.readType(mix) src.readType(mix)
opcode -= 5
elif opcode == 9: elif opcode == 9:
mask = 0x03 mask.value = 0x03
opcode = UInt8(0x02) opcode.value = 0x02
fom_mask = 5 fom_mask.value = 3
elif opcode == 0x0a:
mask.value = 0x05;
opcode.value = 0x02;
fom_mask.value = 5;
lastopcode = opcode lastopcode = opcode
mixmask = 0 mixmask = 0
while count > 0: while count > 0:
if x > width: if x >= width:
if height <= 0: if height <= 0:
raise InvalidExpectedDataException("In RLE decompression height must be greater than 0") raise InvalidExpectedDataException("In RLE decompression height must be greater than 0")
x = 0 x = 0
@@ -114,7 +119,7 @@ def decode(src, width, height, colorType):
#fill #fill
if opcode == 0: if opcode == 0:
if insertMix: if insertMix:
if prevLine == 0: if prevLine is None:
dst[line + x] = mix dst[line + x] = mix
else: else:
dst[line + x] = dst[prevLine + x] ^ mix dst[line + x] = dst[prevLine + x] ^ mix
@@ -122,7 +127,7 @@ def decode(src, width, height, colorType):
count -= 1 count -= 1
x += 1 x += 1
if prevLine == 0: if prevLine is None:
while count > 0 and x < width: while count > 0 and x < width:
dst[line + x] = colorType() dst[line + x] = colorType()
count -= 1 count -= 1
@@ -134,7 +139,7 @@ def decode(src, width, height, colorType):
x += 1 x += 1
#mix #mix
elif opcode == 1: elif opcode == 1:
if prevLine == 0: if prevLine is None:
while count > 0 and x < width: while count > 0 and x < width:
dst[line + x] = mix dst[line + x] = mix
count -= 1 count -= 1
@@ -146,7 +151,42 @@ def decode(src, width, height, colorType):
x += 1 x += 1
#fill or mix #fill or mix
elif opcode == 2: 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 #color
elif opcode == 3: elif opcode == 3:
while count > 0 and x < width: while count > 0 and x < width:
@@ -161,7 +201,16 @@ def decode(src, width, height, colorType):
x += 1 x += 1
#bicolor #bicolor
elif opcode == 8: 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 #write
elif opcode == 0xd: elif opcode == 0xd:
while count > 0 and x < width: while count > 0 and x < width:
@@ -173,8 +222,9 @@ def decode(src, width, height, colorType):
dst[line + x] = colorType() dst[line + x] = colorType()
count -= 1 count -= 1
x += 1 x += 1
else:
raise InvalidExpectedDataException("In RLE decompression invalid opcode")
output = Stream() output = Stream()
output.writeType(dst) output.writeType(dst)
return output return output

View File

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

View File

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