Coverage for pyguymer3/media/yuv2rgb.py: 5%

22 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-07-08 18:47 +0000

1#!/usr/bin/env python3 

2 

3# Define function ... 

4def yuv2rgb( 

5 im, 

6 /, 

7 *, 

8 version = "SDTV", 

9): 

10 """ 

11 Convert array-like YUV image to RGB colourspace 

12 

13 Parameters 

14 ---------- 

15 version : str, optional 

16 "SDTV" is ITU-R BT.601 version (default); "HDTV" is ITU-R BT.709 version 

17 

18 Notes 

19 ----- 

20 This function was obtained from a question on StackOverflow [1]_. The 

21 licence of this function is unknown but as of February 2017 the author, 

22 "wim" [2]_, says "Code included below, for future readers to use:". I have 

23 copied the code and use it for personal use only. 

24 

25 References 

26 ---------- 

27 .. [1] StackOverflow question, https://stackoverflow.com/q/7041172 

28 .. [2] StackOverflow user, https://stackoverflow.com/users/674039/wim 

29 """ 

30 

31 # Import special modules ... 

32 try: 

33 import numpy 

34 except: 

35 raise Exception("\"numpy\" is not installed; run \"pip install --user numpy\"") from None 

36 

37 # check input 

38 if not im.dtype == "uint8": 

39 raise TypeError("yuv2rgb only implemented for uint8 arrays") from None 

40 

41 # clip input to the valid range 

42 yuv = numpy.zeros(im.shape, dtype = numpy.float64) 

43 yuv[:, :, 0] = im[:, :, 0].clip(16, 235).astype(yuv.dtype) - 16 

44 yuv[:, :, 1:] = im[:, :, 1:].clip(16, 240).astype(yuv.dtype) - 128 

45 

46 # decide what to do 

47 match version.upper(): 

48 case "SDTV": 

49 A = numpy.array( 

50 [ 

51 [1.0, 0.0, 0.701 ], 

52 [1.0, -0.886 * 0.114 / 0.587, -0.701 * 0.299 / 0.587], 

53 [1.0, 0.886 , 0.0] 

54 ], 

55 dtype = numpy.float64 

56 ) 

57 A[:, 0] *= 255.0 / 219.0 

58 A[:, 1:] *= 255.0 / 112.0 

59 case "HDTV": 

60 A = numpy.array( 

61 [ 

62 [1.164, 0.0, 1.793], 

63 [1.164, -0.213, -0.533], 

64 [1.164, 2.112, 0.0] 

65 ], 

66 dtype = numpy.float64 

67 ) 

68 case _: 

69 # crash ... 

70 raise ValueError(f"\"version.upper()\" is an unexpected value ({repr(version.upper())})") from None 

71 

72 rgb = numpy.dot(yuv, A.T) 

73 result = rgb.clip(0, 255).astype("uint8") 

74 

75 return result