Coverage for /home/antoine/projects/xpra-git/dist/python3/lib64/python/xpra/codecs/rgb_transform.py : 100%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: utf-8 -*-
2# This file is part of Xpra.
3# Copyright (C) 2010-2020 Antoine Martin <antoine@xpra.org>
4# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
5# later version. See the file COPYING for details.
8from PIL import Image
10from xpra.os_util import bytestostr, monotonic_time
11from xpra.util import first_time
12from xpra.log import Logger
13try:
14 from xpra.codecs.argb.argb import argb_swap #@UnresolvedImport
15except ImportError: # pragma: no cover
16 argb_swap = None
18log = Logger("encoding")
21#source format : [(PIL input format, output format), ..]
22PIL_conv = {
23 "XRGB" : [("XRGB", "RGB")],
24 #try to drop alpha channel since it isn't used:
25 "BGRX" : [("BGRX", "RGB"), ("BGRX", "RGBX")],
26 #try with alpha first:
27 "BGRA" : [("BGRA", "RGBA"), ("BGRX", "RGB"), ("BGRX", "RGBX")],
28 }
29#as above but for clients which cannot handle alpha:
30PIL_conv_noalpha = {
31 "XRGB" : [("XRGB", "RGB")],
32 #try to drop alpha channel since it isn't used:
33 "BGRX" : [("BGRX", "RGB"), ("BGRX", "RGBX")],
34 #try with alpha first:
35 "BGRA" : [("BGRX", "RGB"), ("BGRA", "RGBA"), ("BGRX", "RGBX")],
36 }
39def rgb_reformat(image, rgb_formats, supports_transparency) -> bool:
40 """ convert the RGB pixel data into a format supported by the client """
41 #need to convert to a supported format!
42 pixel_format = bytestostr(image.get_pixel_format())
43 pixels = image.get_pixels()
44 assert pixels, "failed to get pixels from %s" % image
45 if pixel_format in ("r210", "BGR565"):
46 #try to fallback to argb module
47 #(required for r210 which is not handled by PIL directly)
48 assert argb_swap, "no argb codec"
49 log("rgb_reformat: using argb_swap for %s", image)
50 return argb_swap(image, rgb_formats, supports_transparency)
51 if supports_transparency:
52 modes = PIL_conv.get(pixel_format, ())
53 else:
54 modes = PIL_conv_noalpha.get(pixel_format, ())
55 target_rgb = [(im,om) for (im,om) in modes if om in rgb_formats]
56 if not target_rgb:
57 log("rgb_reformat: no matching target modes for converting %s to %s", image, rgb_formats)
58 #try argb module:
59 assert argb_swap, "no argb codec"
60 if argb_swap(image, rgb_formats, supports_transparency):
61 return True
62 warning_key = "rgb_reformat(%s, %s, %s)" % (pixel_format, rgb_formats, supports_transparency)
63 if first_time(warning_key):
64 log.warn("Warning: cannot convert '%s' to one of: %s" % (pixel_format, rgb_formats))
65 return False
66 input_format, target_format = target_rgb[0]
67 start = monotonic_time()
68 w = image.get_width()
69 h = image.get_height()
70 #PIL cannot use the memoryview directly:
71 if isinstance(pixels, memoryview):
72 pixels = pixels.tobytes()
73 img = Image.frombuffer(target_format, (w, h), pixels, "raw", input_format, image.get_rowstride())
74 rowstride = w*len(target_format) #number of characters is number of bytes per pixel!
75 data = img.tobytes("raw", target_format)
76 assert len(data)==rowstride*h, "expected %s bytes in %s format but got %s" % (rowstride*h, target_format, len(data))
77 image.set_pixels(data)
78 image.set_rowstride(rowstride)
79 image.set_pixel_format(target_format)
80 end = monotonic_time()
81 log("rgb_reformat(%s, %s, %s) converted from %s (%s bytes) to %s (%s bytes) in %.1fms, rowstride=%s",
82 image, rgb_formats, supports_transparency, pixel_format, len(pixels),
83 target_format, len(data), (end-start)*1000.0, rowstride)
84 return True