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
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
1#!/usr/bin/env python3
3# Define function ...
4def yuv2rgb(
5 im,
6 /,
7 *,
8 version = "SDTV",
9):
10 """
11 Convert array-like YUV image to RGB colourspace
13 Parameters
14 ----------
15 version : str, optional
16 "SDTV" is ITU-R BT.601 version (default); "HDTV" is ITU-R BT.709 version
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.
25 References
26 ----------
27 .. [1] StackOverflow question, https://stackoverflow.com/q/7041172
28 .. [2] StackOverflow user, https://stackoverflow.com/users/674039/wim
29 """
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
37 # check input
38 if not im.dtype == "uint8":
39 raise TypeError("yuv2rgb only implemented for uint8 arrays") from None
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
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
72 rgb = numpy.dot(yuv, A.T)
73 result = rgb.clip(0, 255).astype("uint8")
75 return result