Hide keyboard shortcuts

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. 

6 

7 

8from PIL import Image 

9 

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 

17 

18log = Logger("encoding") 

19 

20 

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 } 

37 

38 

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