rle decoding
This commit is contained in:
@@ -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):
|
||||||
@@ -119,6 +119,7 @@ class RFBClientQt(RFBClientObserver, QAdaptor):
|
|||||||
'''
|
'''
|
||||||
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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -377,6 +388,13 @@ class SimpleType(Type, CallableValue):
|
|||||||
'''
|
'''
|
||||||
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):
|
||||||
'''
|
'''
|
||||||
|
|||||||
Reference in New Issue
Block a user