Skip to content

Instantly share code, notes, and snippets.

@InJeCTrL
Created October 23, 2022 19:11
Show Gist options
  • Select an option

  • Save InJeCTrL/884be49800bc61445ef8ad05cb413ffc to your computer and use it in GitHub Desktop.

Select an option

Save InJeCTrL/884be49800bc61445ef8ad05cb413ffc to your computer and use it in GitHub Desktop.
Python Remote Screen Sharing
from PIL import Image, ImageDraw
from io import BytesIO
import socket
import struct
import threading
import matplotlib.pyplot as plt
######################
IP = "xxx"
PORT = 5555
SHOW_SPLIT_LINE = False
######################
skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
skt.connect((IP, PORT))
plt.ion()
plt.show()
img = None
def recv_data(skt, data_sz):
data = b''
while (len(data) < data_sz):
data = data + skt.recv(data_sz - len(data))
return data
def recv_screen():
global img
data_byte_cnt = 0
width = struct.unpack('i', recv_data(skt, 4))[0]
height = struct.unpack('i', recv_data(skt, 4))[0]
img = Image.new('RGB', (width, height), (255, 255, 255))
if SHOW_SPLIT_LINE:
draw = ImageDraw.Draw(img)
while True:
x_start = struct.unpack('i', recv_data(skt, 4))[0]
y_start = struct.unpack('i', recv_data(skt, 4))[0]
x_end = struct.unpack('i', recv_data(skt, 4))[0]
y_end = struct.unpack('i', recv_data(skt, 4))[0]
recv_size = struct.unpack('i', recv_data(skt, 4))[0]
data = recv_data(skt, recv_size)
data_byte_cnt += recv_size
if data_byte_cnt < 1024:
print("Received: {} Bytes\r".format(data_byte_cnt), end='', flush=True)
elif data_byte_cnt < 1024 * 1024:
print("Received: {:.2f} KB \r".format(data_byte_cnt / 1024), end='', flush=True)
else:
print("Received: {:.2f} MB \r".format(data_byte_cnt / 1024 / 1024), end='', flush=True)
try:
buf = BytesIO(data)
sub_img = Image.open(buf)
img.paste(sub_img, (x_start, y_start))
buf.close()
if SHOW_SPLIT_LINE:
draw.rectangle(xy=(x_start, y_start, x_end, y_end), fill=None, outline="red", width=1)
except Exception as e:
print(e)
finally:
pass
m = threading.Thread(target=recv_screen, daemon = True)
m.start()
while True:
if img is not None:
if img.size[1] > 1080:
out = img.resize((int(img.size[0] * (1080 / img.size[1])), 1080), Image.ANTIALIAS)
else:
out = img
plt.clf()
plt.axis('off')
plt.gca().xaxis.set_major_locator(plt.NullLocator())
plt.gca().yaxis.set_major_locator(plt.NullLocator())
plt.subplots_adjust(top=1,bottom=0,left=0,right=1,hspace=0,wspace=0)
plt.imshow(out)
plt.pause(0.5)
from PIL import ImageGrab, ImageChops
from io import BytesIO
import socketserver
import time
import struct
######################
PORT = 5555
######################
X_PART_CNT = 25
Y_PART_CNT = 15
QUALITY = 35
######################
class Handler(socketserver.BaseRequestHandler):
def split_image(self, image, x_part_cnt = X_PART_CNT, y_part_cnt = Y_PART_CNT):
sz = image.size
width = sz[0]
height = sz[1]
width_part = width // x_part_cnt
height_part = height // y_part_cnt
x_start = list(range(0, width, width_part))
y_start = list(range(0, height, height_part))
x_end = [(start + width_part if start + width_part < width else width) for start in x_start]
y_end = [(start + height_part if start + height_part < height else height) for start in y_start]
blocks = []
for idx_y in range(y_part_cnt):
blocks.append([])
for idx_x in range(x_part_cnt):
blocks[idx_y].append([
x_start[idx_x],
y_start[idx_y],
x_end[idx_x],
y_end[idx_y],
])
for idx_y in range(y_part_cnt):
for idx_x in range(x_part_cnt):
sub_img = image.crop((
blocks[idx_y][idx_x][0],
blocks[idx_y][idx_x][1],
blocks[idx_y][idx_x][2],
blocks[idx_y][idx_x][3]
))
blocks[idx_y][idx_x].append(sub_img)
return blocks
def map_diff_blocks(self, blocks, prev_blocks):
if not prev_blocks:
diff_map = [[True] * len(blocks[0])] * len(blocks)
else:
diff_map = [[False] * len(blocks[0])] * len(blocks)
for idx_line in range(len(blocks)):
for idx_col in range(len(blocks[idx_line])):
img_origin = prev_blocks[idx_line][idx_col][4]
img = blocks[idx_line][idx_col][4]
diff = ImageChops.difference(img_origin, img)
if diff.getbbox():
diff_map[idx_line][idx_col] = True
return blocks, diff_map
def handle(self):
print("Online: ", self.client_address)
prev_blocks = None
img = ImageGrab.grab()
self.request.sendall(struct.pack('i', img.size[0]))
self.request.sendall(struct.pack('i', img.size[1]))
while True:
img = ImageGrab.grab()
img = img.convert('RGB')
blocks = self.split_image(img)
prev_blocks, diff_map = self.map_diff_blocks(blocks, prev_blocks)
for idx_line in range(len(diff_map)):
for idx_col in range(len(diff_map[idx_line])):
if diff_map[idx_line][idx_col]:
img_bytes = BytesIO()
block = blocks[idx_line][idx_col]
block[4].save(img_bytes, format = "JPEG", quality=QUALITY, optimize=True)
img_data = img_bytes.getvalue()
data_sz = len(img_data)
img_bytes.close()
try:
self.request.sendall(struct.pack('i', block[0]))
self.request.sendall(struct.pack('i', block[1]))
self.request.sendall(struct.pack('i', block[2]))
self.request.sendall(struct.pack('i', block[3]))
self.request.sendall(struct.pack('i', data_sz))
self.request.sendall(img_data)
except ConnectionResetError:
print("Offline: ", self.client_address)
return
except Exception as e:
# print(e)
pass
time.sleep(1)
server = socketserver.ThreadingTCPServer(('', PORT), Handler)
server.serve_forever()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment