python 双端口截图数据传输显示

import io
import time
import socket
import pyautogui


def capture_and_send_image():
    while True:
        try:
            # pil_image = Image.new("RGB", (160, 90), (255, 255, 255))
            # # 截图
            screenshot = pyautogui.screenshot()
            # # 缩小图片
            new_size = (screenshot.width // 20, screenshot.height // 20)
            resized_screenshot = screenshot.resize(new_size)
            # 将图片转换为字节流
            img_byte_arr = io.BytesIO()
            resized_screenshot.save(img_byte_arr, format='PNG')
            img_byte_arr = img_byte_arr.getvalue()
            # 发送数据
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
            s.connect(('localhost', 10000))
            s.sendall(img_byte_arr)
            s.close()
        except Exception as e:
            print(f"发送端发生错误: {e}")
        # 暂停一段时间,避免过于频繁发送
        time.sleep(0.0001)


if __name__ == "__main__":
    while True:
        try:
            capture_and_send_image()
        except Exception as e:
            print(e)
            time.sleep(1)
            print("重新连接")

import io
import time
import socket
import weakref
import threading
import tkinter as tk
from PIL import Image, ImageTk

start_time = None
network_flux = 0
one_second_data = 0
fps_times = 0
fps = 0
all_times = 0
pil_data = None

# 获取网速
def network(KB):
    global start_time, network_flux, one_second_data, fps_times, fps
    network_flux += KB
    if start_time is None:
        start_time = time.time()
        return
    if time.time() - start_time > 2:  # 两秒更新一次
        one_second_data = f"{network_flux / 1024 / (time.time() - start_time):.1f} kb/s"
        fps = f"{fps_times / (time.time() - start_time):.1f} fps/s"
        print(one_second_data)
        network_flux = KB
        start_time = None
        fps_times = 0

# 绘画层
class DraggableImage:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("Image")
        self.bg_color = '#F0F0F0'  # 透明
        self.root.config(bg=self.bg_color)  # 背景色
        self.root.wm_attributes('-transparentcolor', self.bg_color)  # 透明
        self.root.wm_attributes("-topmost", True)  # 置顶
        # self.root.overrideredirect(True)  # 无边框
        self.drag_data = {"x": 0, "y": 0, "is_dragging": False}
        self.tk_image_ref = None  # 使用弱引用
        self.canvas = tk.Canvas(self.root)
        self.canvas.pack()

        self.time_label = tk.Label(self.root, bg=self.bg_color, fg='white', font=('Arial', 12))
        self.time_label.pack(side=tk.TOP)
        self.fps_label = tk.Label(self.root, bg=self.bg_color, fg='white', font=('Arial', 12))
        self.fps_label.pack(side=tk.TOP)

        self.image_id = None
        self.img = None

        # 存储当前显示的图像对象
        self.current_tk_image = None
        # 鼠标事件绑定
        self.canvas.bind("<ButtonPress-1>", self.on_press)
        self.canvas.bind("<B1-Motion>", self.on_drag)
        self.canvas.bind("<ButtonRelease-1>", self.on_release)
        self.canvas.bind("<Button-3>", self.on_right_click)
        # 初始化图像对象
        self.init_image()
        # 图片数据获取
        self.start_receive_image()
        # 数据更新
        self.update_time_and_fps()

    # 初始化图像对象
    def init_image(self):
        # 创建一个初始的空白 PIL 图像
        pil_image = Image.new("RGB", (160, 90), (255, 255, 255))
        # 确保创建一个初始的 ImageTk.PhotoImage 对象
        self.current_tk_image = ImageTk.PhotoImage(pil_image)
        self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW, image=self.current_tk_image)

    # 数据更新
    def start_receive_image(self):
        thread = threading.Thread(target=self.receive_image)
        thread.start()

    # 获取图片数据
    def receive_image(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
        s.bind(('localhost', 10000))
        s.listen(1)
        while True:
            try:
                conn, addr = s.accept()
                img_data = b""
                # 使用 makefile 提高接收性能
                with conn.makefile('rb') as f:
                    while True:
                        data = f.read(1024)
                        if not data:
                            break
                        img_data += data
                conn.close()
                network(len(img_data))
                global all_times,pil_data
                all_times += 1
                if all_times % 100 == 0:
                    print(all_times)
                # 全局数据
                pil_data = img_data
                # 使用 root.after 将更新操作调度到主线程
                self.root.after(0, lambda: self.update_image(img_data))
            except Exception as e:
                print(f"接收端发生错误: {e}")

    # 获取图片数据
    def update_image(self, img_data):
        global fps_times
        fps_times += 1
        if fps_times%100 == 0:
            self.canvas.delete("all")
        pil_image = Image.open(io.BytesIO(img_data))
        original_width, original_height = pil_image.size
        # 创建一个新的 ImageTk.PhotoImage 对象
        new_tk_image = ImageTk.PhotoImage(pil_image)
        # 仅更新图像,而不是销毁并重建 canvas
        self.canvas.config(width=original_width, height=original_height)
        # 使用 after 方法更新图像
        self.root.after(0, lambda: self._update_image_on_canvas(new_tk_image))

    # 更新图片
    def _update_image_on_canvas(self, new_tk_image):
        # 在主线程中更新图像
        if self.image_id:
            old_image = self.canvas.itemcget(self.image_id, 'image')
            if old_image:
                # 删除旧的图像对象
                self.canvas.delete(self.image_id)
                # 显式删除对象引用
                del old_image
            self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW, image=new_tk_image)
        else:
            self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW, image=new_tk_image)
        self.current_tk_image = new_tk_image
        self.img = weakref.ref(self.current_tk_image)  # 弱引用释放
        # self.root.tk.call('image', 'delete', self.current_tk_image)

    # 网速和帧率
    def update_time_and_fps(self):
        global one_second_data, fps
        self.time_label.config(text=one_second_data)
        self.fps_label.config(text=fps)
        self.root.after(2000, self.update_time_and_fps)

    # 右键点击销毁
    def on_right_click(self, event):
        self.canvas.destroy()
        self.root.destroy()
        raise 0

    def on_press(self, event):
        # 记录鼠标按下时的位置
        self.drag_data["x"] = event.x_root
        self.drag_data["y"] = event.y_root
        self.drag_data["is_dragging"] = True

    def on_drag(self, event):
        if self.drag_data["is_dragging"]:
            # 计算鼠标移动的偏移量
            dx = event.x_root - self.drag_data["x"]
            dy = event.y_root - self.drag_data["y"]
            # 移动窗口
            self.root.geometry(f"+{self.root.winfo_x() + dx}+{self.root.winfo_y() + dy}")
            # 更新鼠标位置
            self.drag_data["x"] = event.x_root
            self.drag_data["y"] = event.y_root

    def on_release(self, event):
        # 释放时清除拖动状态
        self.drag_data["is_dragging"] = False


if __name__ == "__main__":
    app = DraggableImage()
    app.root.mainloop()
import io
import time
import socket
import pyautogui


def capture_and_send_image():
    while True:
        try:
            # pil_image = Image.new("RGB", (160, 90), (255, 255, 255))
            # # 截图
            screenshot = pyautogui.screenshot()
            # # 缩小图片
            new_size = (screenshot.width // 20, screenshot.height // 20)
            resized_screenshot = screenshot.resize(new_size)
            # 将图片转换为字节流
            img_byte_arr = io.BytesIO()
            resized_screenshot.save(img_byte_arr, format='PNG')
            img_byte_arr = img_byte_arr.getvalue()
            # 发送数据
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
            s.connect(('localhost', 10000))
            s.sendall(img_byte_arr)
            s.close()
        except Exception as e:
            print(f"发送端发生错误: {e}")
        # 暂停一段时间,避免过于频繁发送
        time.sleep(0.0001)


if __name__ == "__main__":
    while True:
        try:
            capture_and_send_image()
        except Exception as e:
            print(e)
            time.sleep(1)
            print("重新连接")

import io
import time
import socket
import weakref
import threading
import tkinter as tk
from PIL import Image, ImageTk

start_time = None
network_flux = 0
one_second_data = 0
fps_times = 0
fps = 0
all_times = 0
pil_data = None

# 获取网速
def network(KB):
    global start_time, network_flux, one_second_data, fps_times, fps
    network_flux += KB
    if start_time is None:
        start_time = time.time()
        return
    if time.time() - start_time > 2:  # 两秒更新一次
        one_second_data = f"{network_flux / 1024 / (time.time() - start_time):.1f} kb/s"
        fps = f"{fps_times / (time.time() - start_time):.1f} fps/s"
        print(one_second_data)
        network_flux = KB
        start_time = None
        fps_times = 0

# 绘画层
class DraggableImage:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("Image")
        self.bg_color = '#F0F0F0'  # 透明
        self.root.config(bg=self.bg_color)  # 背景色
        self.root.wm_attributes('-transparentcolor', self.bg_color)  # 透明
        self.root.wm_attributes("-topmost", True)  # 置顶
        # self.root.overrideredirect(True)  # 无边框
        self.drag_data = {"x": 0, "y": 0, "is_dragging": False}
        self.tk_image_ref = None  # 使用弱引用
        self.canvas = tk.Canvas(self.root)
        self.canvas.pack()

        self.time_label = tk.Label(self.root, bg=self.bg_color, fg='white', font=('Arial', 12))
        self.time_label.pack(side=tk.TOP)
        self.fps_label = tk.Label(self.root, bg=self.bg_color, fg='white', font=('Arial', 12))
        self.fps_label.pack(side=tk.TOP)

        self.image_id = None
        self.img = None

        # 存储当前显示的图像对象
        self.current_tk_image = None
        # 鼠标事件绑定
        self.canvas.bind("<ButtonPress-1>", self.on_press)
        self.canvas.bind("<B1-Motion>", self.on_drag)
        self.canvas.bind("<ButtonRelease-1>", self.on_release)
        self.canvas.bind("<Button-3>", self.on_right_click)
        # 初始化图像对象
        self.init_image()
        # 图片数据获取
        self.start_receive_image()
        # 数据更新
        self.update_time_and_fps()

    # 初始化图像对象
    def init_image(self):
        # 创建一个初始的空白 PIL 图像
        pil_image = Image.new("RGB", (160, 90), (255, 255, 255))
        # 确保创建一个初始的 ImageTk.PhotoImage 对象
        self.current_tk_image = ImageTk.PhotoImage(pil_image)
        self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW, image=self.current_tk_image)

    # 数据更新
    def start_receive_image(self):
        thread = threading.Thread(target=self.receive_image)
        thread.start()

    # 获取图片数据
    def receive_image(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
        s.bind(('localhost', 10000))
        s.listen(1)
        while True:
            try:
                conn, addr = s.accept()
                img_data = b""
                # 使用 makefile 提高接收性能
                with conn.makefile('rb') as f:
                    while True:
                        data = f.read(1024)
                        if not data:
                            break
                        img_data += data
                conn.close()
                network(len(img_data))
                global all_times,pil_data
                all_times += 1
                if all_times % 100 == 0:
                    print(all_times)
                # 全局数据
                pil_data = img_data
                # 使用 root.after 将更新操作调度到主线程
                self.root.after(0, lambda: self.update_image(img_data))
            except Exception as e:
                print(f"接收端发生错误: {e}")

    # 获取图片数据
    def update_image(self, img_data):
        global fps_times
        fps_times += 1
        if fps_times%100 == 0:
            self.canvas.delete("all")
        pil_image = Image.open(io.BytesIO(img_data))
        original_width, original_height = pil_image.size
        # 创建一个新的 ImageTk.PhotoImage 对象
        new_tk_image = ImageTk.PhotoImage(pil_image)
        # 仅更新图像,而不是销毁并重建 canvas
        self.canvas.config(width=original_width, height=original_height)
        # 使用 after 方法更新图像
        self.root.after(0, lambda: self._update_image_on_canvas(new_tk_image))

    # 更新图片
    def _update_image_on_canvas(self, new_tk_image):
        # 在主线程中更新图像
        if self.image_id:
            old_image = self.canvas.itemcget(self.image_id, 'image')
            if old_image:
                # 删除旧的图像对象
                self.canvas.delete(self.image_id)
                # 显式删除对象引用
                del old_image
            self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW, image=new_tk_image)
        else:
            self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW, image=new_tk_image)
        self.current_tk_image = new_tk_image
        self.img = weakref.ref(self.current_tk_image)  # 弱引用释放
        # self.root.tk.call('image', 'delete', self.current_tk_image)

    # 网速和帧率
    def update_time_and_fps(self):
        global one_second_data, fps
        self.time_label.config(text=one_second_data)
        self.fps_label.config(text=fps)
        self.root.after(2000, self.update_time_and_fps)

    # 右键点击销毁
    def on_right_click(self, event):
        self.canvas.destroy()
        self.root.destroy()
        raise 0

    def on_press(self, event):
        # 记录鼠标按下时的位置
        self.drag_data["x"] = event.x_root
        self.drag_data["y"] = event.y_root
        self.drag_data["is_dragging"] = True

    def on_drag(self, event):
        if self.drag_data["is_dragging"]:
            # 计算鼠标移动的偏移量
            dx = event.x_root - self.drag_data["x"]
            dy = event.y_root - self.drag_data["y"]
            # 移动窗口
            self.root.geometry(f"+{self.root.winfo_x() + dx}+{self.root.winfo_y() + dy}")
            # 更新鼠标位置
            self.drag_data["x"] = event.x_root
            self.drag_data["y"] = event.y_root

    def on_release(self, event):
        # 释放时清除拖动状态
        self.drag_data["is_dragging"] = False


if __name__ == "__main__":
    app = DraggableImage()
    app.root.mainloop()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值