Skip to content

Instantly share code, notes, and snippets.

@qvoid
Created September 6, 2024 08:08
Show Gist options
  • Save qvoid/b144e092149cacd2b4499414a34e18b4 to your computer and use it in GitHub Desktop.
Save qvoid/b144e092149cacd2b4499414a34e18b4 to your computer and use it in GitHub Desktop.
Coeffecients calculation of 8-bits YCbCr translation between BT.601 and BT.709.
import numpy as np
l2l = 0
l2f = 1
f2l = 2
f2f = 3
bt601_y2r_coeff = np.array([
# l2l
[[ 1, 0, 1.37070536],
[ 1, -0.33645467, -0.69819574],
[ 1, 1.73244643, 0. ]],
# l2f
[[ 1.16438356, 0, 1.59602679],
[ 1.16438356, -0.39176229, -0.81296765],
[ 1.16438356, 2.01723214, 0. ]],
# f2l
[[ 0.85882353, 0, 1.20407059],
[ 0.85882353, -0.29555234, -0.61331705],
[ 0.85882353, 1.52183529, 0. ]],
#f2f
[[ 1, 0, 1.402 ],
[ 1, -0.34413629, -0.71413629],
[ 1, 1.772, 0. ]]
])
bt601_r2y_coeff = np.array([
# l2l
[[ 0.299, 0.587, 0.114 ],
[-0.17258831, -0.33882722, 0.51141553],
[ 0.51141553, -0.42824667, -0.08316886]],
# l2f
[[ 0.34815068, 0.68349315, 0.13273973],
[-0.1964733, -0.38571848, 0.58219178],
[ 0.58219178, -0.48751295, -0.09467883]],
# f2l
[[ 0.25678824, 0.50412941, 0.09790588],
[-0.1482229, -0.29099279, 0.43921569],
[ 0.43921569, -0.36778831, -0.07142737]],
# f2f
[[ 0.299, 0.587, 0.114 ],
[-0.16873589, -0.33126411, 0.5 ],
[ 0.5, -0.41868759, -0.08131241]]
])
bt709_r2y_coeff = np.array([
# l2l
[[ 0.2126, 0.7152, 0.0722 ],
[-0.11718791, -0.39422762, 0.51141553],
[ 0.51141553, -0.4645217, -0.04689383]],
# l2f
[[ 0.24754795, 0.83276712, 0.08406849],
[-0.13340588, -0.4487859, 0.58219178],
[ 0.58219178, -0.52880818, -0.0533836 ]],
# f2l
[[ 0.18258588, 0.61423059, 0.06200706],
[-0.10064373, -0.33857195, 0.43921569],
[ 0.43921569, -0.39894216, -0.04027352]],
# f2f
[[ 0.2126, 0.7152, 0.0722 ],
[-0.11457211, -0.38542789, 0.5 ],
[ 0.5, -0.45415291, -0.04584709]]
])
bt709_y2r_coeff = np.array([
# l2l
[[ 1, 0, 1.53964821],
[ 1, -0.18314293, -0.45767507],
[ 1, 1.81418036, 0. ]],
# l2f
[[ 1.16438356, 0, 1.79274107],
[ 1.16438356, -0.21324861, -0.53290933],
[ 1.16438356, 2.11240179, 0. ]],
# f2l
[[ 0.85882353, 0, 1.35247529],
[ 0.85882353, -0.16087849, -0.40203614],
[ 0.85882353, 1.59363294, 0. ]],
# f2f
[[ 1, 0, 1.5748 ],
[ 1, -0.18732427, -0.46812427],
[ 1, 1.8556, 0. ]]
])
y2r_comp_offset = np.array([
# l2l
[[0], [-128], [-128]],
# l2f
[[-16], [-128], [-128]],
# f2l
[[0], [-128], [-128]],
# f2f
[[0], [-128], [-128]]
])
y2r_offset = np.array([
# l2l
[[0], [0], [0]],
# l2f
[[0], [0], [0]],
# f2l
[[16], [16], [16]],
# f2f
[[0], [0], [0]]
])
r2y_offset = np.array([
# l2l
[[0], [128], [128]],
# l2f
[[-255 * 16 / 219], [128], [128]],
# f2f
[[16], [128], [128]],
# f2l
[[0], [128], [128]]
])
# BT.601 limit to BT.709 limit
print("BT.601 limit to BT.709 limit:")
i = l2l
j = l2l
coeff = np.dot(bt709_r2y_coeff[j], bt601_y2r_coeff[i])
offset = np.dot(coeff, y2r_comp_offset[i]) + np.dot(bt709_r2y_coeff[j], y2r_offset[i]) + r2y_offset[j]
print("coeff \n", np.round(coeff, 4))
print("offset \n", np.round(offset, 4))
# BT.601 limit to BT.709 full
print("BT.601 limit to BT.709 full:")
i = l2f
j = f2f
coeff = np.dot(bt709_r2y_coeff[j], bt601_y2r_coeff[i])
offset = np.dot(coeff, y2r_comp_offset[i]) + np.dot(bt709_r2y_coeff[j], y2r_offset[i]) + r2y_offset[j]
print("coeff \n", np.round(coeff, 4))
print("offset \n", np.round(offset, 4))
# BT.601 full to BT.709 full
print("BT.601 full to BT.709 full:")
i = f2f
j = f2f
coeff = np.dot(bt709_r2y_coeff[j], bt601_y2r_coeff[i])
offset = np.dot(coeff, y2r_comp_offset[i]) + np.dot(bt709_r2y_coeff[j], y2r_offset[i]) + r2y_offset[j]
print("coeff \n", np.round(coeff, 4))
print("offset \n", np.round(offset, 4))
# BT.601 full to BT.709 limit
print("BT.601 full to BT.709 limit:")
i = f2l
j = l2l
coeff = np.dot(bt709_r2y_coeff[j], bt601_y2r_coeff[i])
offset = np.dot(coeff, y2r_comp_offset[i]) + np.dot(bt709_r2y_coeff[j], y2r_offset[i]) + r2y_offset[j]
print("coeff \n", np.round(coeff, 4))
print("offset \n", np.round(offset, 4))
# BT.709 limit to BT.601 limit
print("BT.709 limit to BT.601 limit:")
i = l2l
j = l2l
coeff = np.dot(bt601_r2y_coeff[j], bt709_y2r_coeff[i])
offset = np.dot(coeff, y2r_comp_offset[i]) + np.dot(bt601_r2y_coeff[j], y2r_offset[i]) + r2y_offset[j]
print("coeff \n", np.round(coeff, 4))
print("offset \n", np.round(offset, 4))
# BT.709 full to BT.601 full
print("BT.709 full to BT.601 full:")
i = f2f
j = f2f
coeff = np.dot(bt601_r2y_coeff[j], bt709_y2r_coeff[i])
offset = np.dot(coeff, y2r_comp_offset[i]) + np.dot(bt601_r2y_coeff[j], y2r_offset[i]) + r2y_offset[j]
print("coeff \n", np.round(coeff, 4))
print("offset \n", np.round(offset, 4))
# BT.709 full to BT.601 limit
print("BT.709 full to BT.601 limit:")
i = f2l
j = l2l
coeff = np.dot(bt601_r2y_coeff[j], bt709_y2r_coeff[i])
offset = np.dot(coeff, y2r_comp_offset[i]) + np.dot(bt601_r2y_coeff[j], y2r_offset[i]) + r2y_offset[j]
print("coeff \n", np.round(coeff, 4))
print("offset \n", np.round(offset, 4))
# BT.709 limit to BT.601 full
print("BT.709 limit to BT.601 full:")
i = l2f
j = f2f
coeff = np.dot(bt601_r2y_coeff[j], bt709_y2r_coeff[i])
offset = np.dot(coeff, y2r_comp_offset[i]) + np.dot(bt601_r2y_coeff[j], y2r_offset[i]) + r2y_offset[j]
print("coeff \n", np.round(coeff, 4))
print("offset \n", np.round(offset, 4))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment