python截图、压缩、转base64,可以用2m压缩到100k,肉眼不失真

zwnsyw / 2023-08-23 / 原文

 1 import win32gui
 2 import win32ui
 3 import win32con
 4 import numpy as np
 5 import cv2
 6 import base64
 7 
 8 # 通过句柄截取窗口内容
 9 def capture_window_by_handle(handle):
10     left, top, right, bottom = win32gui.GetWindowRect(handle)
11     width = right - left
12     height = bottom - top
13 
14     hwnd_dc = win32gui.GetWindowDC(handle)
15     mfc_dc = win32ui.CreateDCFromHandle(hwnd_dc)
16 
17     save_dc = mfc_dc.CreateCompatibleDC()
18     save_bitmap = win32ui.CreateBitmap()
19     save_bitmap.CreateCompatibleBitmap(mfc_dc, width, height)
20     save_dc.SelectObject(save_bitmap)
21 
22     result = save_dc.BitBlt((0, 0), (width, height), mfc_dc, (0, 0), win32con.SRCCOPY)
23 
24     bmp_info = save_bitmap.GetInfo()
25     bmp_str = save_bitmap.GetBitmapBits(True)
26 
27     # 从缓冲区创建NumPy数组
28     image = np.frombuffer(bmp_str, dtype=np.uint8)
29     image = image.reshape((height, width, 4))  # RGBA格式
30 
31     save_dc.DeleteDC()
32     mfc_dc.DeleteDC()
33     win32gui.ReleaseDC(handle, hwnd_dc)
34     win32gui.DeleteObject(save_bitmap.GetHandle())
35 
36     return image
37 
38 # 压缩图像函数
39 def pic_compress(img_cv, target_size=199, quality=100, step=5):
40     img_byte = cv2.imencode('.jpg', img_cv, [int(cv2.IMWRITE_JPEG_QUALITY), quality])[1]
41     current_size = len(img_byte) / 1024
42     while current_size > target_size:
43         img_byte = cv2.imencode('.jpg', img_cv, [int(cv2.IMWRITE_JPEG_QUALITY), quality])[1]
44         if quality - step < 0:
45             break
46         quality -= step
47         current_size = len(img_byte) / 1024
48     return img_byte
49 
50 def main():
51     # 通过句柄获取窗口
52     target_handle = win32gui.FindWindow(None, "地下城与勇士:创新世纪")  # 替换为目标窗口的标题
53 
54     if target_handle == 0:
55         print("未找到目标窗口")
56         return
57 
58     # 截取窗口内容
59     captured_image = capture_window_by_handle(target_handle)
60 
61     # 保存截图到本地
62     # original_save_path = "01original_captured_image.png"
63     # cv2.imwrite(original_save_path, captured_image)
64     # print("原始截图已保存到:", original_save_path)
65 
66     # 将图像转换为OpenCV格式(BGR)
67     cv2_captured_image = cv2.cvtColor(captured_image, cv2.COLOR_RGBA2BGR)
68 
69     # 压缩图像
70     compressed_image_byte = pic_compress(captured_image, target_size=100)
71 
72     # 保存压缩后的图像到本地
73     compressed_save_path = "01compressed_captured_image.jpg"
74     with open(compressed_save_path, 'wb') as f:
75         f.write(compressed_image_byte)
76     print("压缩后的图像已保存到:", compressed_save_path)
77 
78     # 将压缩后的图像转为base64
79     compressed_image_base64 = base64.b64encode(compressed_image_byte).decode('utf-8')
80     print("压缩后的图像base64编码:", compressed_image_base64)
81 
82 if __name__ == '__main__':
83     while True:
84         import time
85         t1 = time.time()
86         main()
87         t2 = time.time()
88         print(t2-t1)