- Added cursor pseudo encoding support. - Added Windows support for cursor image capturing in `get_cursor_image` method. Implemented Windows-specific logic using the `win32gui`, `win32ui`, and related libraries to capture the current cursor image, enhancing the cross-platform capability of the application. - Fixed issues in `get_bitmap` method for handling different bpp formats. Specifically addressed the processing logic for 16 bpp (BGR565) format, ensuring that the image conversion and rendering are handled correctly for VNC clients expecting this format. - Added initial Tight encoding support. - Updated the `send_image` method in the Tight encoding class to correctly handle JPEG and ZLIB compression. This includes proper signaling to the client about the type of compression used (JPEG or ZLIB) and ensuring that the data is formatted and sent according to the Tight encoding specifications. - Added checks and conversions in `send_image` to handle different image modes (like RGBX and RGBA) and convert them to the appropriate format (RGB) before compression and transmission. - Implemented a more robust and accurate method for determining when to use JPEG compression in Tight encoding based on the unique color count and image characteristics. These updates significantly improve the functionality, stability, and compatibility of the VNC server, particularly in handling different pixel formats and encoding methods.
74 lines
2.9 KiB
Python
74 lines
2.9 KiB
Python
import ctypes
|
|
from ctypes import POINTER, c_int, c_short, c_ushort, c_ulong, c_void_p, Structure, cast
|
|
from PIL import Image
|
|
import numpy as np
|
|
|
|
# Definición de Atom para su uso en la estructura XFixesCursorImage
|
|
Atom = c_ulong
|
|
|
|
# Definición de la estructura XFixesCursorImage
|
|
class XFixesCursorImage(Structure):
|
|
_fields_ = [
|
|
("x", c_short),
|
|
("y", c_short),
|
|
("width", c_ushort),
|
|
("height", c_ushort),
|
|
("xhot", c_ushort),
|
|
("yhot", c_ushort),
|
|
("cursor_serial", Atom),
|
|
("pixels", POINTER(c_ulong)), # Suponiendo que 'pixels' es un puntero a c_ulong
|
|
("atom", Atom), # Presente en la versión 2 y superiores de XFixes
|
|
("name", ctypes.c_char_p)
|
|
]
|
|
|
|
|
|
class XCursor:
|
|
def __init__(self):
|
|
# Cargar las bibliotecas X11 y Xfixes
|
|
self.xlib = ctypes.cdll.LoadLibrary("libX11.so")
|
|
self.xfixes = ctypes.cdll.LoadLibrary("libXfixes.so.3")
|
|
|
|
# Configurar los tipos de retorno
|
|
self.xlib.XOpenDisplay.restype = POINTER(c_void_p)
|
|
self.xlib.XOpenDisplay.argtypes = [ctypes.c_char_p]
|
|
|
|
self.xfixes.XFixesGetCursorImage.restype = POINTER(XFixesCursorImage)
|
|
self.xfixes.XFixesGetCursorImage.argtypes = [c_void_p]
|
|
|
|
# Abrir la conexión con X
|
|
self.display = self.xlib.XOpenDisplay(None)
|
|
if not self.display:
|
|
raise Exception("No se pudo abrir el display")
|
|
|
|
def __del__(self):
|
|
self.xlib.XCloseDisplay(self.display)
|
|
|
|
def get_cursor_image(self):
|
|
# Llamar a XFixesGetCursorImage
|
|
cursor_image_ref = self.xfixes.XFixesGetCursorImage(self.display)
|
|
if not cursor_image_ref:
|
|
# return a 2x2 red image
|
|
return Image.fromarray(np.array([[[255, 0, 0, 255], [255, 0, 0, 255]], [[255, 0, 0, 255], [255, 0, 0, 255]]], dtype=np.uint8), 'RGBA')
|
|
|
|
cursor_image = cursor_image_ref.contents
|
|
width, height = cursor_image.width, cursor_image.height
|
|
|
|
# Leer los datos de píxeles
|
|
pixels_array_type = c_ulong * (cursor_image.width * cursor_image.height)
|
|
pixels_pointer = cast(cursor_image.pixels, POINTER(pixels_array_type))
|
|
pixels_64bit = np.frombuffer(pixels_pointer.contents, dtype=np.uint64)
|
|
|
|
# Convertir cada valor de 64 bits en un píxel RGBA
|
|
pixels_rgba = np.zeros((cursor_image.height, cursor_image.width, 4), dtype=np.uint8)
|
|
|
|
for i in range(cursor_image.height):
|
|
for j in range(cursor_image.width):
|
|
pixel = int(pixels_64bit[i * cursor_image.width + j]) # Convertir a int para bit shifting
|
|
pixels_rgba[i, j, 0] = (pixel >> 16) & 0xFF # Rojo
|
|
pixels_rgba[i, j, 1] = (pixel >> 8) & 0xFF # Verde
|
|
pixels_rgba[i, j, 2] = pixel & 0xFF # Azul
|
|
pixels_rgba[i, j, 3] = (pixel >> 24) & 0xFF
|
|
|
|
return Image.fromarray(pixels_rgba, 'RGBA')
|
|
|