LoginSignup
1
1

FFmpegで指定できる輝度の伝達特性の一覧

Last updated at Posted at 2023-04-07

FFmpegの入出力オプションcolor_trcで指定可能な輝度の伝達特性を表す関数の一覧。
参考にzscaleフィルタの該当ソースコードを引用する。1ここで、$L$は輝度に線形な電気信号値2、$V$は伝達後の電気信号値である。

指定可能な値 伝達特性
bt709 Rec. ITU-R BT.709-6
gamma22 Rec. ITU-R BT.470-6 System M
gamma28 Rec. ITU-R BT.470-6 System B, G
smpte170m SMPTE ST 170 (2004)
smpte240m SMPTE ST 240 (1999)
linear Linear transfer characteristics
log
log100
Rec. ITU-T H.273 Log
log_sqrt
log316
Rec. ITU-T H.273 Log Sqrt
iec61966_2_4
iec61966-2-4
IEC 61966-2-4 xvYCC
bt1361
bt1361e
Rec. ITU-R BT.1361-0 extended colour gamut system
iec61966_2_1
iec61966-2-1
IEC 61966-2-1 sRGB
bt2020_10
bt2020_10bit
Rec. ITU-R BT.2020-2 (10-bit system)
bt2020_12
bt2020_12bit
Rec. ITU-R BT.2020-2 (12-bit system)
smpte2084 SMPTE ST 2084 PQ
smpte428
smpte428_1
SMPTE ST 428-1 (2019)
arib-std-b67 ARIB STD-B67 HLG

特別な伝達特性

指定可能な値 Rec. ITU-T H.273による説明
unknown
unspecified
Image characteristics are unknown or
are determined by the application.
reserved For future use by ITU-T | ISO/IEC

Rec. ITU-T H.273 CICP Code Value3

指定可能な値 CV     
bt709 1
unknown
unspecified
2
reserved 3
gamma22 4
gamma28 5
smpte170m 6
smpte240m 7
linear 8
log
log100
9
log_sqrt
log316
10
iec61966_2_4
iec61966-2-4
11
bt1361
bt1361e
12
iec61966_2_1
iec61966-2-1
13
bt2020_10
bt2020_10bit
14
bt2020_12
bt2020_12bit
15
smpte2084 16
smpte428
smpte428_1
17
arib-std-b67 18

ビデオフィルタの対応状況
変換に対応していない伝達関数には、"×"を付けている。

colorspace zscale libplacebo
bt709
unknown
unspecified
× × ×
reserved × × ×
gamma22
gamma28
smpte170m
smpte240m
linear
log
log100
× ×
log_sqrt
log316
× ×
iec61966_2_4
iec61966-2-4
bt1361
bt1361e
× ×
4
iec61966_2_1
iec61966-2-1
bt2020_10
bt2020_10bit
bt2020_12
bt2020_12bit
smpte2084 ×
smpte428
smpte428_1
× × ×
arib-std-b67 ×

各フィルターの特徴は以下の通り。

  • colorspaceは、Scene-referred5の変換にのみ対応している。
  • zscaleは、colorspaceよりもRec. ITU-T H.273に沿った動作をする。そのため、より多くの計算資源を必要とする。
  • libplaceboは、トーンマッピングとHDRアップスケーリングアルゴリズムが最も充実している。動作にはVulkan互換のGPUが必要。

フィルタオプションエイリアス
同じ行にある名前は、同じ伝達関数を指す。フィルタ側で指定できない場合は、"×"を付けている。"×"のついた伝達関数は color_trc setparams によって強制的に指定することができるが、フィルター内部ではunknown、unspecifiedとして扱われる。

指定可能な値 colorspace zscale libplacebo
bt709 bt709 709
bt709
bt709
unknown
unspecified
× unknown
unspecified
unknown
reserved × × ×
gamma22 bt470m
gamma22
bt470m bt470m
gamma28 bt470bg
gamma28
bt470bg bt470bg
smpte170m smpte170m 601
smpte170m
smpte170m
smpte240m smpte240m smpte240m smpte240m
linear linear linear linear
log
log100
× log100 ×
log_sqrt
log316
× log316 ×
iec61966_2_4
iec61966-2-4
xvycc
iec61966-2-4
iec61966-2-4 iec61966-2-4
bt1361
bt1361e
× × bt1361e
iec61966_2_1
iec61966-2-1
srgb
iec61966-2-1
iec61966-2-1 iec61966-2-1
bt2020_10
bt2020_10bit
bt2020-10 2020_10
bt2020-10
bt2020-10
bt2020_12
bt2020_12bit
bt2020-12 2020_12
bt2020-12
bt2020-12
smpte2084 × smpte2084 smpte2084
smpte428
smpte428_1
× × ×
arib-std-b67 × arib-std-b67 arib-std-b67

OETFとEOTFの関係。
OFTF-EOTF Workflow!
伝達関数に応じて輝度の分布が変化するイメージ、横軸が入力、縦軸が出力。画像はGIMPのトーンカーブ。
ここでは入力画像の暗い部分が伸張され、明るい部分が圧縮されている。また、入力画像のゼロ付近が強く伸張されている。
Imitation of BT.709 OETF

Rec. ITU-R BT.709-6 6

一般的なSDRの転送特性。

非線形な値へ変換する場合
もしScene-referred5ならば、Rec. 709 OETFを適用する、もしDisplay-referred7ならばRec. 1886 inverse EOTFを適用する。

線形な値へ変換する場合
もしScene-referredならば、Rec. 709 inverse OETFを適用する、もしDisplay-referredならばRec. 1886 EOTFを適用する。

OOTF8は(Rec. 1886 EOTF ∘ Rec. 709 OETF)(L)となる。

// src/zimg/colorspace/gamma.cppより

switch (transfer) {

case TransferCharacteristics::REC_709:
	func.to_linear = scene_referred ? rec_709_inverse_oetf : rec_1886_eotf;
	func.to_gamma = scene_referred ? rec_709_oetf : rec_1886_inverse_eotf;
	break;

Scene-referredな伝達関数

Rec. 709 OETF

\mbox{V=}\begin{cases}
1.09929682680944 L^{0.45} - (1.09929682680944 - 1.0) & 1.0 \ge L \ge 0.018053968510807\\
4.5L & 0.018053968510807 > L \ge 0.0
\end{cases}

Rec. 709 inverse OETF

\mbox{L=}\begin{cases}
\left ( \dfrac{ V+(1.09929682680944 - 1.0) }{1.09929682680944} \right ) ^{\frac{1.0}{0.45} } & 1.0 \ge V \ge 4.5\cdot0.018053968510807\\
\dfrac{V}{4.5} & 4.5\cdot0.018053968510807 > V \ge 0.0
\end{cases}
// src/zimg/colorspace/gamma.cppより

constexpr float REC709_ALPHA = 1.09929682680944f;
constexpr float REC709_BETA = 0.018053968510807f;

float rec_709_oetf(float x) noexcept
{
	x = std::max(x, 0.0f);

	if (x < REC709_BETA)
		x = x * 4.5f;
	else
		x = REC709_ALPHA * zimg_x_powf(x, 0.45f) - (REC709_ALPHA - 1.0f);

	return x;
}

float rec_709_inverse_oetf(float x) noexcept
{
	x = std::max(x, 0.0f);

	if (x < 4.5f * REC709_BETA)
		x = x / 4.5f;
	else
		x = zimg_x_powf((x + (REC709_ALPHA - 1.0f)) / REC709_ALPHA, 1.0f / 0.45f);

	return x;
}

Display-referredな伝達関数

黒レベルを0.0cd/m^2とすると
Rec. 1886 inverse EOTF

$\mbox{V=}{L}^{\frac{1.0}{2.4}}\qquad{L}\ge 0.0$

Rec. 1886 EOTF

$\mbox{L=}{V}^{2.4}\qquad{V}\ge 0.0$

// src/zimg/colorspace/gamma.cppより

// Ignore the BT.1886 provisions for limited contrast and assume an ideal CRT.
float rec_1886_inverse_eotf(float x) noexcept
{
	return x < 0.0f ? 0.0f : zimg_x_powf(x, 1.0f / 2.4f);
}

float rec_1886_eotf(float x) noexcept
{
	return x < 0.0f ? 0.0f : zimg_x_powf(x, 2.4f);
}

OOTF(L)=(Rec. 1886 EOTF ∘ Rec. 709 OETF)(L)
ディスプレイの輝度9がシーンの輝度10より全体的に暗くなる(輝度1.0以上を除く)。
ガンマ補正$\mbox{V=}L^{1.22}$で近似できるが、比較すると暗い部分がより圧縮されていることがわかる。

\mbox{V=}\begin{cases}
(1.09929682680944 L^{0.45}−(1.09929682680944−1.0) )^{2.4} & L \ge 0.018053968510807\\
(4.5L)^{2.4} & 0.018053968510807 > L \ge 0.0
\end{cases}

Rec. ITU-R BT.470-6 System M11

非線形な値へ変換する場合
Rec. 470M OETFを適用する

線形な値へ変換する場合
Rec. 470M inverse OETFを適用する

OOTF8は線形となる。

// src/zimg/colorspace/gamma.cppより
// OETFとinverse OETF、func.to_linearとfunc.to_gammaが逆になっている

switch (transfer) {

case TransferCharacteristics::REC_470_M:
	func.to_linear = rec_470m_oetf;
	func.to_gamma = rec_470m_inverse_oetf;
	break;

Rec. 470M OETF

V={L}^{\frac{1.0}{2.2}}\qquad{L}\ge 0.0

Rec. 470M inverse OETF

L={V}^{2.2}\qquad{V}\ge 0.0
// src/zimg/colorspace/gamma.cppより

float rec_470m_oetf(float x) noexcept
{
	return x < 0.0f ? 0.0f : zimg_x_powf(x, 2.2f);
}

float rec_470m_inverse_oetf(float x) noexcept
{
	return x < 0.0f ? 0.0f : zimg_x_powf(x, 1.0f / 2.2f);
}

Rec. ITU-R BT.470-6 System B, G11

非線形な値へ変換する場合
Rec. 470BG OETFを適用する

線形な値へ変換する場合
Rec. 470BG inverse OETFを適用する

OOTF8は線形となる。

// src/zimg/colorspace/gamma.cppより
// OETFとinverse OETF、func.to_linearとfunc.to_gammaが逆になっている
switch (transfer) {

case TransferCharacteristics::REC_470_BG:
	func.to_linear = rec_470bg_oetf;
	func.to_gamma = rec_470bg_inverse_oetf;
	break;

Rec. 470BG OETF

V=^{\frac{1.0}{2.8}}\qquad{L}\ge 0.0

Rec. 470BG inverse OETF

L={V}^{2.8}\qquad{V}\ge 0.0
// src/zimg/colorspace/gamma.cppより

float rec_470bg_oetf(float x) noexcept
{
	return x < 0.0f ? 0.0f : zimg_x_powf(x, 2.8f);
}

float rec_470bg_inverse_oetf(float x) noexcept
{
	return x < 0.0f ? 0.0f : zimg_x_powf(x, 1.0f / 2.8f);
}

SMPTE ST 170 (2004)

機能的にRec. ITU-R BT.709-6と同じ。

// src/zimg/api/zimg.cppより

zimg::colorspace::TransferCharacteristics translate_transfer(zimg_transfer_characteristics_e transfer)
{
	using zimg::colorspace::TransferCharacteristics;

	static SM_CONSTEXPR_14 const zimg::static_map<zimg_transfer_characteristics_e, TransferCharacteristics, 15> map{
		{ ZIMG_TRANSFER_BT709,         TransferCharacteristics::REC_709 },
		{ ZIMG_TRANSFER_UNSPECIFIED,   TransferCharacteristics::UNSPECIFIED },
		{ ZIMG_TRANSFER_ST240_M,       TransferCharacteristics::SMPTE_240M },
		{ ZIMG_TRANSFER_BT601,         TransferCharacteristics::REC_709 },
		{ ZIMG_TRANSFER_BT470_M,       TransferCharacteristics::REC_470_M },
		{ ZIMG_TRANSFER_BT470_BG,      TransferCharacteristics::REC_470_BG },
		{ ZIMG_TRANSFER_IEC_61966_2_4, TransferCharacteristics::XVYCC },
		{ ZIMG_TRANSFER_IEC_61966_2_1, TransferCharacteristics::SRGB },
		{ ZIMG_TRANSFER_BT2020_10,     TransferCharacteristics::REC_709 },
		{ ZIMG_TRANSFER_BT2020_12,     TransferCharacteristics::REC_709 },
		{ ZIMG_TRANSFER_LINEAR,        TransferCharacteristics::LINEAR },
		{ ZIMG_TRANSFER_LOG_100,       TransferCharacteristics::LOG_100 },
		{ ZIMG_TRANSFER_LOG_316,       TransferCharacteristics::LOG_316 },
		{ ZIMG_TRANSFER_ST2084,        TransferCharacteristics::ST_2084 },
		{ ZIMG_TRANSFER_ARIB_B67,      TransferCharacteristics::ARIB_B67 },
	};
	return search_itu_enum_map(map, transfer, "unrecognized transfer characteristics");
}

SMPTE ST 240 (1999)12

非線形な値へ変換する場合
もしScene-referred5ならば、SMPTE 240M OETFを適用する、もしDisplay-referred7ならばRec. 1886 inverse EOTFを適用する。

線形な値へ変換する場合
もしScene-referredならば、SMPTE 240M inverse OETFを適用する、もしDisplay-referredならばRec. 1886 EOTFを適用する。

OOTF8は(Rec. 1886 EOTF ∘ SMPTE 240M OETF)(L)となる。

// src/zimg/colorspace/gamma.cppより

switch (transfer) {

case TransferCharacteristics::SMPTE_240M:
	func.to_linear = scene_referred ? smpte_240m_inverse_oetf : rec_1886_eotf;
	func.to_gamma = scene_referred ? smpte_240m_oetf : rec_1886_inverse_eotf;
	break;

Scene-referredな伝達関数

SMPTE 240M OETF

V=\begin{cases}
1.111572195921731 L^{0.45} - (1.111572195921731 - 1.0) & 1.0 \ge L \ge 0.022821585529445\\
4.0L & 0.022821585529445 > L \ge 0.0
\end{cases}

SMPTE 240M inverse OETF

L=\begin{cases}
\left ( \dfrac{ V+(1.111572195921731 - 1.0) }{1.111572195921731} \right ) ^{\frac{1.0}{0.45} } & 1.0 \ge V \ge 4.0\cdot0.022821585529445\\
\dfrac{V}{4.0} & 4.0\cdot0.022821585529445 > V \ge 0.0
\end{cases}
// src/zimg/colorspace/gamma.cppより
// OETFとinverse OETFが逆になっている

constexpr float SMPTE_240M_ALPHA = 1.111572195921731f;
constexpr float SMPTE_240M_BETA  = 0.022821585529445f;

float smpte_240m_oetf(float x) noexcept
{
	x = std::max(x, 0.0f);

	if (x < 4.0f * SMPTE_240M_BETA)
		x = x / 4.0f;
	else
		x = zimg_x_powf((x + (SMPTE_240M_ALPHA - 1.0f)) / SMPTE_240M_ALPHA, 1.0f / 0.45f);

	return x;
}

float smpte_240m_inverse_oetf(float x) noexcept
{
	x = std::max(x, 0.0f);

	if (x < SMPTE_240M_BETA)
		x = x * 4.0f;
	else
		x = SMPTE_240M_ALPHA * zimg_x_powf(x, 0.45f) - (SMPTE_240M_ALPHA - 1.0f);

	return x;
}

Display-referredな伝達関数

黒レベルを0.0cd/m^2とすると
Rec. 1886 inverse EOTF

\mbox{V=}{L}^{\frac{1.0}{2.4}}\qquad{L}\ge 0.0

Rec. 1886 EOTF

\mbox{L=}{V}^{2.4}\qquad{V}\ge 0.0
// src/zimg/colorspace/gamma.cppより

// Ignore the BT.1886 provisions for limited contrast and assume an ideal CRT.
float rec_1886_inverse_eotf(float x) noexcept
{
	return x < 0.0f ? 0.0f : zimg_x_powf(x, 1.0f / 2.4f);
}

float rec_1886_eotf(float x) noexcept
{
	return x < 0.0f ? 0.0f : zimg_x_powf(x, 2.4f);
}

OOTF(L)=(Rec. 1886 EOTF ∘ SMPTE 240M OETF)(L)
ディスプレイの輝度9がシーンの輝度10より全体的に暗くなる(輝度1.0以上を除く)。
ガンマ補正$\mbox{V=}L^{1.20}$で近似できるが、比較すると暗い部分がより圧縮されていることがわかる。

\mbox{V=}\begin{cases}
(1.111572195921731 L^{0.45}−(1.111572195921731−1.0) )^{2.4} & L \ge 0.022821585529445\\
(4.0L)^{2.4} & 0.022821585529445 > L \ge 0.0
\end{cases}

Linear transfer characteristics

伝達特性は線形
値が変化しない、いうまでもなく$V$は輝度に線形。

Linear EOTF

\mbox{V=}L

Linear inverse EOTF

\mbox{L=}V

OOTF8は線形となる。

Rec. ITU-T H.273 Log13

伝達関数が$L \ge 0.01$ と $V \ge 0.0$にclampされているのが特徴。
Rec. ITU-T H.273ではLogarithmic transfer characteristic (100:1 range)と呼ばれている。

非線形な値へ変換する場合
Log 100 OETFを適用する。

線形な値へ変換する場合
Log 100 inverse OETFを適用する。

OOTF8は線形となる。

// src/zimg/colorspace/gamma.cppより

switch (transfer) {
case TransferCharacteristics::LOG_100:
	func.to_linear = log100_inverse_oetf;
	func.to_gamma = log100_oetf;
	break;

$1.0 + \frac{\log_{10}(\color{blue}{0.01})}{2.0}=\color{blue}0$ であり、$\mbox{L=}0.01$の場合は$\mbox{V=}0$となる、よってzimgでは式の区間を調整している。
つまり、
H.273 Log 100 OETF

\mbox{V=}\begin{cases}
1.0 + \dfrac{\log_{10}(L)}{2.0} & 1.0 \ge L \color{blue}\ge\color{black} 0.01\\
0.0 & 0.01 \color{blue}>\color{black} L \ge 0.0
\end{cases}

以上青文字部分を

zimg Log 100 OETF

\mbox{V=}\begin{cases}
1.0 + \dfrac{\log_{10}(L)}{2.0} & 1.0 \ge L \color{red}>\color{black} 0.01\\
0.0 & 0.01 \color{red}\ge\color{black} L \ge 0.0
\end{cases}

以上赤文字部分としている。

zimg Log 100 inverse OETF

\mbox{L=}\begin{cases}
10^{2\cdot(V-1.0)} & 1.0 \ge V > 0.0\\
0.01 & 0.0 \ge V \ge -\infty
\end{cases}

別式

H.273 Log 100 OETF

\mbox{V=}\begin{cases}
1.0 + \dfrac{\log_{10}(L)}{2.0} & 1.0 \ge L \ge 0.01\\
0.0 & 0.01 > L \ge 0.0
\end{cases}

H.273 Log 100 inverse OETF

\mbox{L=}\begin{cases}
10^{2\cdot(V-1.0)} & 1.0 \ge V \ge 1.0 + \dfrac{\log_{10}(0.01)}{2.0} = 0.0\\
0.0 & 0.0 = 1.0 + \dfrac{\log_{10}(0.01)}{2.0} > V \ge -\infty
\end{cases}

// src/zimg/colorspace/gamma.cppより

float log100_oetf(float x) noexcept
{
	return x <= 0.01f ? 0.0f : 1.0f + zimg_x_log10f(x) / 2.0f;
}

float log100_inverse_oetf(float x) noexcept
{
	return x <= 0.0f ? 0.01f : zimg_x_powf(10.0f, 2 * (x - 1.0f));
}

Rec. ITU-T H.273 Log Sqrt13

伝達関数が$L \ge \frac{\sqrt{10}} {1000}$ と $V \ge 0.0$にclampされているのが特徴。
Rec. ITU-T H.273ではLogarithmic transfer characteristic (100 * Sqrt ( 10 ) : 1 range)と呼ばれている。

非線形な値へ変換する場合
Log 316 OETFを適用する。

線形な値へ変換する場合
Log 316 inverse OETFを適用する。

OOTF8は線形となる。

// src/zimg/colorspace/gamma.cppより

switch (transfer) {

case TransferCharacteristics::LOG_316:
	func.to_linear = log316_inverse_oetf;
	func.to_gamma = log316_oetf;
	break;

$1.0 + \frac{\log_{10}(\color{blue}{\frac{\sqrt{10}}{1000}})}{2.5}=\color{blue}0$ であり、$\mbox{L=}\frac{\sqrt{10}}{1000}$の場合は$\mbox{V=}0$となる、よってzimgでは式の区間を調整している。
つまり、
H.273 Log 316 OETF

\mbox{V=}\begin{cases}
1.0 + \dfrac{\log_{10}(L)}{2.5} & 1.0 \ge L \color{blue}\ge \dfrac{\sqrt{10}}{1000}\\
0.0 & \dfrac{\sqrt{10}}{1000} \color{blue}> L \ge 0.0
\end{cases}

以上青文字部分を

zimg Log 316 OETF

\mbox{V=}\begin{cases}
1.0 + \dfrac{\log_{10}(L)}{2.5} & 1.0 \ge L \color{red}> \dfrac{\sqrt{10}}{1000}\\
0.0 & \dfrac{\sqrt{10}}{1000} \color{red}\ge L \ge 0.0
\end{cases}

以上赤文字部分としている。

zimg Log 316 inverse OETF

\mbox{L=}\begin{cases}
10^{2.5\cdot(V-1.0)} & 1.0 \ge V > 0.0\\
\dfrac{\sqrt{10}}{1000} & 0.0 \ge V -\infty
\end{cases}

別式

H.273 Log 316 OETF

\mbox{V=}\begin{cases}
1.0 + \dfrac{\log_{10}(L)}{2.5} & 1.0 \ge L \ge \dfrac{\sqrt{10}}{1000}\\
0.0 & \dfrac{\sqrt{10}}{1000} > L \ge 0.0
\end{cases}

H.273 Log 316 inverse OETF

\mbox{L=}\begin{cases}
10^{2.5\cdot(V-1.0)} & 1.0 \ge V \ge 1.0 + \dfrac{\log_{10}(\frac{\sqrt{10}}{1000})}{2.5} = 0.0\\
0.0 & 0.0 = 1.0 + \dfrac{\log_{10}(\frac{\sqrt{10}}{1000})}{2.5} > V \ge -\infty
\end{cases}

// src/zimg/colorspace/gamma.cppより

float log316_oetf(float x) noexcept
{
	return x <= 0.00316227766f ? 0.0f : 1.0f + zimg_x_log10f(x) / 2.5f;
}

float log316_inverse_oetf(float x) noexcept
{
	return x <= 0.0f ? 0.00316227766f : zimg_x_powf(10.0f, 2.5f * (x - 1.0f));
}

IEC 61966-2-4 xvYCC

Rec. ITU-R BT.709-5(04/02)をスーパーホワイト、サブブラックまで拡張した伝達特性。
定義域と値域は$\infty \ge L \ge -\infty$、$\infty \ge V \ge -\infty$で、原点に関して対称である。

非線形な値へ変換する場合
もしScene-referred5ならば、xvYCC OETFを適用する、もしDisplay-referred7ならばxvYCC inverse EOTFを適用する。

線形な値へ変換する場合
もしScene-referredならば、xvYCC inverse OETFを適用する、もしDisplay-referredならばxvYCC EOTFを適用する。

OOTF12は(xvYCC EOTF ∘ xvYCC OETF)(L)となる。

// src/zimg/colorspace/gamma.cppより

switch (transfer) {

case TransferCharacteristics::XVYCC:
	func.to_linear = scene_referred ? xvycc_inverse_oetf : xvycc_eotf;
	func.to_gamma = scene_referred ? xvycc_oetf : xvycc_inverse_eotf;
	break;

Scene-referredな伝達関数

xvYCC OETF

\mbox{V=}\begin{cases}
1.09929682680944 L^{0.45} - (1.09929682680944 - 1.0) & \infty \ge L \ge 0.018053968510807\\
4.5L & 0.018053968510807 > L > -0.018053968510807\\
1.09929682680944 L^{0.45} - (1.09929682680944 - 1.0) & -0.018053968510807 \ge L \ge -\infty
\end{cases}

xvYCC inverse OETF

\mbox{L=}\begin{cases}
\left ( \dfrac{ V+(1.09929682680944 - 1.0) }{1.09929682680944} \right ) ^{\frac{1.0}{0.45} } & \infty \ge V \ge 4.5\cdot0.018053968510807\\
\dfrac{V}{4.5} & 4.5 \cdot 0.018053968510807 > V > 4.5 \cdot -0.018053968510807\\
\left ( \dfrac{ V+(1.09929682680944 - 1.0) }{1.09929682680944} \right ) ^{\frac{1.0}{0.45} } & 4.5 \cdot -0.018053968510807 \ge V \ge -\infty
\end{cases}

Display-referredな伝達関数

zimg xvYCC inverse EOTF (Rec. 1886: 1.0>=L>=0.0)

\mbox{V=}\begin{cases}
1.09929682680944 L^{0.45} - (1.09929682680944 - 1.0) & \infty \ge L > 1.0\\
L^{\frac{1.0}{2.4}} & 1.0 \ge L \ge 0.0\\
4.5L & 0.0 > L > -0.018053968510807\\
1.09929682680944 L^{0.45} - (1.09929682680944 - 1.0) & -0.018053968510807 \ge L \ge -\infty
\end{cases}

zimg xvYCC EOTF (Rec. 1886: 1.0>=V>=0.0)

\mbox{L=}\begin{cases}
\left ( \dfrac{ V+(1.09929682680944 - 1.0) }{1.09929682680944} \right ) ^{\frac{1.0}{0.45} } & \infty \ge V >1.0\\
{V}^{2.4} & 1.0 \ge V \ge 0.0\\
\dfrac{V}{4.5} & 0.0 > V > 4.5 \cdot -0.018053968510807\\
\left ( \dfrac{ V+(1.09929682680944 - 1.0) }{1.09929682680944} \right ) ^{\frac{1.0}{0.45} } & 4.5 \cdot -0.018053968510807 \ge V \ge -\infty
\end{cases}
// src/zimg/colorspace/gamma.cppより

float xvycc_oetf(float x) noexcept
{
	return std::copysign(rec_709_oetf(std::fabs(x)), x);
}

float xvycc_inverse_oetf(float x) noexcept
{
	return std::copysign(rec_709_inverse_oetf(std::fabs(x)), x);
}



// Handle values in the range [0.0-1.0] such that they match a legacy CRT.
float xvycc_eotf(float x) noexcept
{
	if (x < 0.0f || x > 1.0f)
		return std::copysign(rec_709_inverse_oetf(std::fabs(x)), x);
	else
		return std::copysign(rec_1886_eotf(std::fabs(x)), x);
}

float xvycc_inverse_eotf(float x) noexcept
{
	if (x < 0.0f || x > 1.0f)
		return std::copysign(rec_709_oetf(std::fabs(x)), x);
	else
		return std::copysign(rec_1886_inverse_eotf(std::fabs(x)), x);
}

黒レベルを0.0cd/m^2とすると
Rec. 1886 inverse EOTF

\mbox{V=}{L}^{\frac{1.0}{2.4}}\qquad{L}\ge 0.0

Rec. 1886 EOTF

\mbox{L=}{V}^{2.4}\qquad{V}\ge 0.0
// src/zimg/colorspace/gamma.cppより

// Ignore the BT.1886 provisions for limited contrast and assume an ideal CRT.
float rec_1886_inverse_eotf(float x) noexcept
{
	return x < 0.0f ? 0.0f : zimg_x_powf(x, 1.0f / 2.4f);
}

float rec_1886_eotf(float x) noexcept
{
	return x < 0.0f ? 0.0f : zimg_x_powf(x, 2.4f);
}

OOTF(L)=(xvYCC EOTF ∘ xvYCC OETF)(L)
ディスプレイの輝度9がシーンの輝度10より全体的に暗くなる(輝度1.0以上を除く)。
ガンマ補正$\mbox{V=}L^{1.22}$で近似できるが、比較すると暗い部分がより圧縮されていることがわかる(輝度0.0未満、また1.0を超える輝度を除く)。

\mbox{V=}\begin{cases}
L & \infty \ge L >1.0\\
(1.09929682680944 L^{0.45}−(1.09929682680944−1.0) )^{2.4} & 1.0 \ge L \ge 0.018053968510807\\
(4.5L)^{2.4} & 0.018053968510807 > L \ge 0.0\\
L & 0.0 > L \ge -\infty
\end{cases}

Rec. ITU-R BT.1361-0 extended colour gamut system

Rec. ITU-R BT.709-3(02/98)をスーパーホワイト、サブブラックまで拡張した伝達特性。
定義域と値域は

$1.33 > L \ge -0.25$
$1.099 \cdot 1.33^{0.45} - (1.099 - 1.0) > V \ge \frac{-(1.099*(-4 \cdot -0.25)^{0.45}-(1.099-1))}{4}$

である。
Rec. 1361 OETFで規定されている$L<1.33$は、$V<1.15\ldots$であり、リミテッドレンジ$[16,235]$の最大値254($\mbox{L=}1.09\ldots$)を超える。
※0と255は同期信号に使用されるため、リミテッドレンジでの映像信号の最大値は254となる。

線形な値へ変換する場合 (libplaceboの実装に基づく)
もしDisplay-referred7ならば、Rec. 1886 EOTFを適用する。

OOTF8は(Rec. 1886 EOTF ∘ Rec. 1361 OETF)(L)となる。

libplaceboの該当ソースコード

Scene-referredな伝達関数

Rec. 1361 OETF

\mbox{V=}\begin{cases}
1.099 L^{0.45} - (1.099 - 1.0) & 1.33 > L \ge 0.018\\
4.5L & 0.018 > L \ge -0.0045\\
\dfrac{-(1.099\cdot(-4L)^{0.45}-(1.099-1))}{4} & -0.0045 > L \ge -0.25
\end{cases}

Rec. 1361 inverse OETF

\mbox{L=}\begin{cases}
\left ( \dfrac{ V+(1.099 - 1.0) }{1.099} \right ) ^{\frac{1.0}{0.45} } & 1.099 \cdot 1.33^{0.45} - (1.099 - 1.0) > V \ge 4.5\cdot0.018\\
\dfrac{V}{4.5} & 4.5\cdot0.018 > V \ge 4.500\cdot-0.0045\\
\dfrac{-\left({\frac{(-4V + 0.099)} {1.099}}^{ \frac{1} {0.45} }\right)}{4}
 & \dfrac{-(1.099\cdot(-4L)^{0.45}-(1.099-1))}{4}\cdot -0.0045 > V \ge \dfrac{-(1.099\cdot(-4 \cdot -0.25)^{0.45}-(1.099-1))}{4}
\end{cases}

Display-referredな伝達関数

libplacebo Rec. 1886 inverse EOTF
黒レベルが0.0cd/m^2の場合

\mbox{V=}{L}^{\frac{1.0}{2.4}}\qquad{L}\ge 0.0

libplacebo Rec. 1886 EOTF
黒レベルが0.0cd/m^2の場合

\mbox{L=}{L}^{2.4}\qquad {V}\ge 0.0

libplaceboの該当ソースコード

OOTF(L)=(Rec. 1886 EOTF ∘ Rec. 1361 OETF)(L)
Rec. 1361 OETF

\mbox{V=}\begin{cases}
1.099 L^{0.45} - (1.099 - 1.0) & 1.33 > L \ge 0.018\\
4.5L & 0.018 > L \ge -0.0045\\
\dfrac{-(1.099\cdot(-4L)^{0.45}-(1.099-1))}{4} & -0.0045 > L \ge -0.25
\end{cases}

IEC 61966-2-1 sRGB

非線形な値へ変換する場合
sRGB inverse EOTFを適用する。

線形な値へ変換する場合
sRGB EOTFを適用する。

OOTF8は線形となる。

// src/zimg/colorspace/gamma.cppより

switch (transfer) {

case TransferCharacteristics::SRGB:
	func.to_linear = srgb_eotf;
	func.to_gamma = srgb_inverse_eotf;
	break;

sRGB inverse EOTF

\mbox{V=}\begin{cases}
1.055010718947587 L^{\frac{1.0}{2.4}} - (1.055010718947587 - 1.0) & L \ge 0.003041282560128\\
12.92L & 0.003041282560128 > L \ge 0.0
\end{cases}

sRGB EOTF

\mbox{L=}\begin{cases}
\left ( \dfrac{ V+(1.055010718947587 - 1.0) }{1.055010718947587} \right ) ^{2.4} & V \ge 12.92\cdot0.003041282560128\\
\dfrac{V}{12.92} & 12.92\cdot0.003041282560128 > V \ge 0.0
\end{cases}
// src/zimg/colorspace/gamma.cppより

// Adjusted for continuity of first derivative.
constexpr float SRGB_ALPHA = 1.055010718947587f;
constexpr float SRGB_BETA = 0.003041282560128f;

float srgb_eotf(float x) noexcept
{
	x = std::max(x, 0.0f);

	if (x < 12.92f * SRGB_BETA)
		x = x / 12.92f;
	else
		x = zimg_x_powf((x + (SRGB_ALPHA - 1.0f)) / SRGB_ALPHA, 2.4f);

	return x;
}

float srgb_inverse_eotf(float x) noexcept
{
	x = std::max(x, 0.0f);

	if (x < SRGB_BETA)
		x = x * 12.92f;
	else
		x = SRGB_ALPHA * zimg_x_powf(x, 1.0f / 2.4f) - (SRGB_ALPHA - 1.0f);

	return x;
}

Rec. ITU-R BT.2020-2 (10-bit system)

機能的にRec. ITU-R BT.709-6と同じ。

// src/zimg/api/zimg.cppより

zimg::colorspace::TransferCharacteristics translate_transfer(zimg_transfer_characteristics_e transfer)
{
	using zimg::colorspace::TransferCharacteristics;

	static SM_CONSTEXPR_14 const zimg::static_map<zimg_transfer_characteristics_e, TransferCharacteristics, 15> map{
		{ ZIMG_TRANSFER_BT709,         TransferCharacteristics::REC_709 },
		{ ZIMG_TRANSFER_UNSPECIFIED,   TransferCharacteristics::UNSPECIFIED },
		{ ZIMG_TRANSFER_ST240_M,       TransferCharacteristics::SMPTE_240M },
		{ ZIMG_TRANSFER_BT601,         TransferCharacteristics::REC_709 },
		{ ZIMG_TRANSFER_BT470_M,       TransferCharacteristics::REC_470_M },
		{ ZIMG_TRANSFER_BT470_BG,      TransferCharacteristics::REC_470_BG },
		{ ZIMG_TRANSFER_IEC_61966_2_4, TransferCharacteristics::XVYCC },
		{ ZIMG_TRANSFER_IEC_61966_2_1, TransferCharacteristics::SRGB },
		{ ZIMG_TRANSFER_BT2020_10,     TransferCharacteristics::REC_709 },
		{ ZIMG_TRANSFER_BT2020_12,     TransferCharacteristics::REC_709 },
		{ ZIMG_TRANSFER_LINEAR,        TransferCharacteristics::LINEAR },
		{ ZIMG_TRANSFER_LOG_100,       TransferCharacteristics::LOG_100 },
		{ ZIMG_TRANSFER_LOG_316,       TransferCharacteristics::LOG_316 },
		{ ZIMG_TRANSFER_ST2084,        TransferCharacteristics::ST_2084 },
		{ ZIMG_TRANSFER_ARIB_B67,      TransferCharacteristics::ARIB_B67 },
	};
	return search_itu_enum_map(map, transfer, "unrecognized transfer characteristics");
}

Rec. ITU-R BT.2020-2 (12-bit system)

機能的にRec. ITU-R BT.709-6と同じ。

// src/zimg/api/zimg.cppより

zimg::colorspace::TransferCharacteristics translate_transfer(zimg_transfer_characteristics_e transfer)
{
	using zimg::colorspace::TransferCharacteristics;

	static SM_CONSTEXPR_14 const zimg::static_map<zimg_transfer_characteristics_e, TransferCharacteristics, 15> map{
		{ ZIMG_TRANSFER_BT709,         TransferCharacteristics::REC_709 },
		{ ZIMG_TRANSFER_UNSPECIFIED,   TransferCharacteristics::UNSPECIFIED },
		{ ZIMG_TRANSFER_ST240_M,       TransferCharacteristics::SMPTE_240M },
		{ ZIMG_TRANSFER_BT601,         TransferCharacteristics::REC_709 },
		{ ZIMG_TRANSFER_BT470_M,       TransferCharacteristics::REC_470_M },
		{ ZIMG_TRANSFER_BT470_BG,      TransferCharacteristics::REC_470_BG },
		{ ZIMG_TRANSFER_IEC_61966_2_4, TransferCharacteristics::XVYCC },
		{ ZIMG_TRANSFER_IEC_61966_2_1, TransferCharacteristics::SRGB },
		{ ZIMG_TRANSFER_BT2020_10,     TransferCharacteristics::REC_709 },
		{ ZIMG_TRANSFER_BT2020_12,     TransferCharacteristics::REC_709 },
		{ ZIMG_TRANSFER_LINEAR,        TransferCharacteristics::LINEAR },
		{ ZIMG_TRANSFER_LOG_100,       TransferCharacteristics::LOG_100 },
		{ ZIMG_TRANSFER_LOG_316,       TransferCharacteristics::LOG_316 },
		{ ZIMG_TRANSFER_ST2084,        TransferCharacteristics::ST_2084 },
		{ ZIMG_TRANSFER_ARIB_B67,      TransferCharacteristics::ARIB_B67 },
	};
	return search_itu_enum_map(map, transfer, "unrecognized transfer characteristics");
}

SMPTE ST 2084

zimgでは従来のSDRとの相互運用性を考慮し、シーンライト10が100cd/m^2($\mbox{L=}1.0$)に設定されている。
ディスプレイライト9は10000cd/m^2($\mbox{L=}1.0$)に設定されている。
zscaleソースコード中のpeak_luminanceはSDRの公称ピーク輝度を指し、nplオプションで指定できる。

非線形な値へ変換する場合
もしScene-referred5ならば、ST 2084 OETFを適用する、もしDisplay-referred7ならばST 2084 inverse EOTFを適用する。

線形な値へ変換する場合
もしScene-referredならば、ST 2084 inverse OETFを適用する、もしDisplay-referredならばST 2084 EOTFを適用する。

OOTF8は(ST 2084 EOTF ∘ ST 2084 OETF)(L)となる。

// src/zimg/colorspace/gamma.cppより

switch (transfer) {

case TransferCharacteristics::ST_2084:
	func.to_linear = scene_referred ? st_2084_inverse_oetf : st_2084_eotf;
	func.to_gamma = scene_referred ? st_2084_oetf : st_2084_inverse_eotf;
	func.to_linear_scale = static_cast<float>(ST2084_PEAK_LUMINANCE / peak_luminance);
	func.to_gamma_scale = static_cast<float>(peak_luminance / ST2084_PEAK_LUMINANCE);
	break;

Scene-referredな伝達関数

ST 2084 OETF

\DeclareMathOperator{\EOTF}{EOTF}\\
\DeclareMathOperator{\OETF}{OETF}\\
\mbox{V=}\EOTF^{-1}_{ST 2084}\left(\dfrac{\EOTF_{Rec.1886}\left(\OETF_{Rec.709}\left(nL\right)\right)} {100.0}\right) \qquad 1.0 \ge L \ge 0.0

ST 2084 inverse OETF

\DeclareMathOperator{\EOTF}{EOTF}\\
\DeclareMathOperator{\OETF}{OETF}\\
\mbox{L=}\dfrac{\OETF^{-1}_{Rec.709}\left(\EOTF^{-1}_{Rec.1886}\left(\EOTF_{ST 2084}(V) \cdot 100.0\right)\right)} {n} \qquad 1.0 \ge V \ge 0.0

ここで

  • $n=59.49080238715383$14

Display-referredな伝達関数

ST 2084 inverse EOTF

\mbox{V=}\left( \dfrac{c_1 + c_2 \cdot L^{m_1}}{1 + c_3 \cdot L^{m_1} } \right)^{m_2} \qquad 1.0 \ge L \ge 0.0

ST 2084 EOTF

\mbox{L=}\left( \dfrac{max[ (V^{1/m_2} - c_1), 0]} {c_2 - c_3 \cdot V ^ {1/m_2} } \right) ^ {1/ m_1} \qquad 1.0 \ge V \ge 0.0

ここで

  • $m_1 = \dfrac{2610}{16384} = \dfrac{1305}{8192} = 0.1593017578125$
  • $m_2 = \dfrac{2523}{4096}\cdot128 = \dfrac{2523}{32} = 78.84375$
  • $c_1 = \dfrac{3424}{4096} = \dfrac{107}{128} = 0.8359375 = c_3 - c_2 + 1$
  • $c_2 = \dfrac{2413}{4096}\cdot32 = \dfrac{2413}{128} = 18.8515625$
  • $c_3 = \dfrac{2392}{4096}\cdot32 = \dfrac{2392}{128} = 18.6875$

// src/zimg/colorspace/gamma.hより

constexpr float ST2084_PEAK_LUMINANCE = 10000.0f; // Units of cd/m^2.
// src/zimg/colorspace/gamma.cppより

constexpr float ST2084_M1 = 0.1593017578125f;
constexpr float ST2084_M2 = 78.84375f;
constexpr float ST2084_C1 = 0.8359375f;
constexpr float ST2084_C2 = 18.8515625f;
constexpr float ST2084_C3 = 18.6875f;

// Chosen for compatibility with higher precision REC709_ALPHA/REC709_BETA.
// See: ITU-R BT.2390-2 5.3.1
constexpr float ST2084_OOTF_SCALE = 59.49080238715383f;

float ootf_st2084(float x) noexcept
{
	return rec_1886_eotf(rec_709_oetf(x * ST2084_OOTF_SCALE)) / 100.0f;
}

float inverse_ootf_st2084(float x) noexcept
{
	return rec_709_inverse_oetf(rec_1886_inverse_eotf(x * 100.0f)) / ST2084_OOTF_SCALE;
}

float rec_709_oetf(float x) noexcept
{
	x = std::max(x, 0.0f);

	if (x < REC709_BETA)
		x = x * 4.5f;
	else
		x = REC709_ALPHA * zimg_x_powf(x, 0.45f) - (REC709_ALPHA - 1.0f);

	return x;
}

float rec_709_inverse_oetf(float x) noexcept
{
	x = std::max(x, 0.0f);

	if (x < 4.5f * REC709_BETA)
		x = x / 4.5f;
	else
		x = zimg_x_powf((x + (REC709_ALPHA - 1.0f)) / REC709_ALPHA, 1.0f / 0.45f);

	return x;
}

} // namespace
// Ignore the BT.1886 provisions for limited contrast and assume an ideal CRT.
float rec_1886_eotf(float x) noexcept
{
	return x < 0.0f ? 0.0f : zimg_x_powf(x, 2.4f);
}

float rec_1886_inverse_eotf(float x) noexcept
{
	return x < 0.0f ? 0.0f : zimg_x_powf(x, 1.0f / 2.4f);
}

float st_2084_eotf(float x) noexcept
{
	// Filter negative values to avoid NAN.
	if (x > 0.0f) {
		float xpow = zimg_x_powf(x, 1.0f / ST2084_M2);
		float num = std::max(xpow - ST2084_C1, 0.0f);
		float den = std::max(ST2084_C2 - ST2084_C3 * xpow, FLT_MIN);
		x = zimg_x_powf(num / den, 1.0f / ST2084_M1);
	} else {
		x = 0.0f;
	}

	return x;
}

float st_2084_inverse_eotf(float x) noexcept
{
	// Filter negative values to avoid NAN, and also special-case 0 so that (f(g(0)) == 0).
	if (x > 0.0f) {
		float xpow = zimg_x_powf(x, ST2084_M1);
#if 0
		// Original formulation from SMPTE ST 2084:2014 publication.
		float num = ST2084_C1 + ST2084_C2 * xpow;
		float den = 1.0f + ST2084_C3 * xpow;
		x = zimg_x_powf(num / den, ST2084_M2);
#else
		// More stable arrangement that avoids some cancellation error.
		float num = (ST2084_C1 - 1.0f) + (ST2084_C2 - ST2084_C3) * xpow;
		float den = 1.0f + ST2084_C3 * xpow;
		x = zimg_x_powf(1.0f + num / den, ST2084_M2);
#endif
	} else {
		x = 0.0f;
	}

	return x;
}

float st_2084_oetf(float x) noexcept
{
	return st_2084_inverse_eotf(ootf_st2084(x));
}

float st_2084_inverse_oetf(float x) noexcept
{
	return inverse_ootf_st2084(st_2084_eotf(x));
}

OOTF(L)=(ST 2084 EOTF ∘ ST 2084 OETF)(L)
$\DeclareMathOperator{\EOTF}{EOTF}\
\DeclareMathOperator{\OETF}{OETF}\
\mbox{V=}\EOTF_{ST 2084} (\OETF_{ST 2084}(L))$

SMPTE ST 428-1 (2019)

ディスプレイライト9は48cd/m^2($\mbox{L=}1.0$)に設定されている。
スケール係数$\frac{48} {52.37}$によって、EOTFは、単独でリミテッドレンジをフルレンジに圧縮する働きをする。
例えば、pow(48*1/219*239/52.37,1.0/2.6)≒1.00009959139409といったように。

OOTF8は線形となる。

Rec. ITU-T H.273による
H.273 ST 428-1 EOTF

\mbox{V=}(\dfrac{48L} {52.37})^{\frac{1.0}{2.6}}\qquad \text{for all values of }L

H.273 ST 428-1 inverse EOTF

\mbox{L=}\dfrac{52.37V^{2.6}}{48}\qquad \text{for all values of }V

ARIB STD-B67

ディスプレイライト9は1000cd/m^2($\mbox{L=}1.0$)に設定されている。

非線形な値へ変換する場合
もしScene-referred5ならば、ARIB B67 OETFを適用する、もしDisplay-referred7ならばARIB inverse B67 EOTFを適用する。

線形な値へ変換する場合
もしScene-referred5ならば、ARIB B67 inverse OETFを適用する、もしDisplay-referredならばARIB B67 EOTFを適用する。

OOTF8は(ARIB B67 EOTF ∘ ARIB B67 OETF)(L)となる。

// src/zimg/colorspace/gamma.cppより

switch (transfer) {

case TransferCharacteristics::ARIB_B67:
	func.to_linear = scene_referred ? arib_b67_inverse_oetf : arib_b67_eotf;
	func.to_gamma = scene_referred ? arib_b67_oetf : arib_b67_inverse_eotf;
	func.to_linear_scale = scene_referred ? 12.0f : static_cast<float>(1000.0 / peak_luminance);
	func.to_gamma_scale = scene_referred ? 1.0f / 12.0f : static_cast<float>(peak_luminance / 1000.0);
	break;

Scene-referredな伝達関数

ARIB B67 OETF

\mbox{V=}\begin{cases}
a\cdot\ln(12L - b) + c & 1.0 \ge L > \frac{1}{12}\\
\sqrt{3L} & \frac{1}{12} \ge L \ge 0.0
\end{cases}

ARIB B67 inverse OETF

\mbox{L=}\begin{cases}
\dfrac{\exp\left(\dfrac{(V - c)} {a}\right) + b} {12.0} & 1.0 \ge V > \sqrt{3\cdot\frac{1} {12}} = 0.5\\
V^2\cdot\dfrac{1} {3}\ & 0.5 = \sqrt{3\cdot\frac{1} {12}} = \ge V \ge 0.0
\end{cases}

ここで

  • $a=0.17883277$
  • $b=0.28466892$
  • $c=0.55991073$

Display-referredな伝達関数

ARIB B67 inverse EOTF

\mbox{V=}\begin{cases}
a\cdot\ln(12L^{\frac{1.0} {1.2}} - b) + c & 1.0 \ge L > \left(\dfrac{1}{12}\right)^{1.2}\\
\sqrt{3L^{\frac{1.0} {1.2}}} & \left(\dfrac{1}{12}\right)^{1.2} \ge L \ge 0.0
\end{cases}

ARIB B67 EOTF

\mbox{L=}\begin{cases}
\left(\dfrac{\exp\left(\dfrac{(V - c)} {a}\right) + b} {12.0}\right)^{1.2} & 1.0 \ge V > \sqrt{3\cdot\frac{1} {12}} = 0.5\\
\left(V^2\cdot\dfrac{1} {3}\right)^{1.2} & 0.5 = \sqrt{3\cdot\frac{1} {12}} = \ge V \ge 0.0
\end{cases}

ここで

  • $a=0.17883277$
  • $b=0.28466892$
  • $c=0.55991073$
// src/zimg/colorspace/gamma.cppより

constexpr float ARIB_B67_A = 0.17883277f;
constexpr float ARIB_B67_B = 0.28466892f;
constexpr float ARIB_B67_C = 0.55991073f;

float ootf_1_2(float x) noexcept
{
	return x < 0.0f ? x : zimg_x_powf(x, 1.2f);
}

float inverse_ootf_1_2(float x) noexcept
{
	return x < 0.0f ? x : zimg_x_powf(x, 1.0f / 1.2f);
}

float arib_b67_oetf(float x) noexcept
{
	// Prevent negative pixels from yielding NAN.
	x = std::max(x, 0.0f);

	if (x <= (1.0f / 12.0f))
		x = zimg_x_sqrtf(3.0f * x);
	else
		x = ARIB_B67_A * zimg_x_logf(12.0f * x - ARIB_B67_B) + ARIB_B67_C;

	return x;
}

float arib_b67_inverse_oetf(float x) noexcept
{
	// Prevent negative pixels expanding into positive values.
	x = std::max(x, 0.0f);

	if (x <= 0.5f)
		x = (x * x) * (1.0f / 3.0f);
	else
		x = (zimg_x_expf((x - ARIB_B67_C) / ARIB_B67_A) + ARIB_B67_B) / 12.0f;

	return x;
}

// Applies a per-channel correction instead of the iterative method specified in Rec.2100.
float arib_b67_eotf(float x) noexcept
{
	return ootf_1_2(arib_b67_inverse_oetf(x));
}

float arib_b67_inverse_eotf(float x) noexcept
{
	return arib_b67_oetf(inverse_ootf_1_2(x));
}

OOTF(L)=(ARIB B67 EOTF ∘ ARIB B67 OETF)(L)
$\mbox{V=}L^{1.2}$

参照先

参考になったサイト

  1. zimgはWTFPLである。

  2. 相対輝度(Relative luminance)のこと。最大値を1、最小値を0とし、最大値が白色点(White point)の絶対輝度に等しくなるように正規化したデータ。なお、シーンライト10とディスプレイライト9では白色点の絶対輝度が異なることが多いので、混同しないように注意が必要である。例えば、「SDRの白色点の絶対輝度は100cd/m^2」という説明は、ディスプレイライトの白色点を指している。ちなみに、勧告などで指定された白色点の絶対輝度を基準白(Reference white)という。

  3. FFmpegでは、伝達関数をRec. ITU-T H.273 CICP (Coding-independent code points, コーディングに依存しないコードポイント)13で指定することができる。CICPの使用は、MKVコンテナのEBML、MP4コンテナのBOX、HEVCのVUI(Video Usability Information)でも取り入れられている。

  4. Display Light9への変換のみ対応。EOTFはRec. 1886 EOTF。

  5. ディスプレイ参照(Scene-referred)とは、光の基準(参照先)がシーンの輝度10であることを示す。基準には2種類ある。もう一つはディスプレイ基準(Display-referred)と呼ばれるもので、こちらはディスプレイで復元された光の輝度が基準である。ITU-R BT.709-6のようにシーンの輝度とディスプレイの輝度が必ずしも線形関係にあるとは限らないため、2つの異なる基準が存在する。 2 3 4 5 6 7

  6. Rec. ITU-R BT.709-6 (06/2015)は、Recommendation ITU Radiocommunication BT-series 709 version 6の略称である。Rec.709やBT.709も、同じものを指している。

  7. シーン参照(Display-referred)とは、光の基準(参照先)がディスプレイの輝度9であることを示す。基準には2種類ある。もう一つはシーン基準(Scene-referred)と呼ばれるもので、こちらはシーンの光の輝度が基準である。 2 3 4 5 6

  8. OOTF(opto-optical transfer function)とは、シーンの輝度$L$10を入力とし、ディスプレイの輝度を出力とする関数$f(L)$のこと。言い換えるとOETF(opto-electronic transfer function)とEOTF(electro-optical transfer function)の結果としてシーンの輝度にかかる伝達特性を表す伝達関数である。つまり$\DeclareMathOperator{\EOTF}{EOTF}\DeclareMathOperator{\OETF}{OETF}\EOTF(\OETF(L))$ また $\DeclareMathOperator{\EOTF}{EOTF}\DeclareMathOperator{\OETF}{OETF}\EOTF \circ \OETF(L)$を指す。OOTFにおける補正の目的の一つは、視聴環境に応じて輝度特性(広義のレンダリングインテント15)を最適化することである。 2 3 4 5 6 7 8 9 10 11 12

  9. ディスプレイライト(Display Light)とは、ディスプレイが発する光であり、そのディスプレイの輝度(ディスプレイのピーク輝度との混同に注意)、ひいてはディスプレイの輝度に線形な電気信号値である。Scene Light10と対になる概念である。 2 3 4 5 6 7 8 9 10

  10. シーンライト(Scene Light)とは、カメラが捉えた現場(シーン)の光であり、そのシーンの輝度、ひいてはシーンの輝度に線形な電気信号値である。Display Light9と対になる概念である。シーンの輝度とシーンの輝度を示す電気信号値には線形関係があることを強調して、リニアシーンライト(Linear Scene Light)とも呼ばれる。15 2 3 4 5 6 7 8

  11. Rec. ITU-R BT.470-6 (11/98)は、Recommendation ITU Radiocommunication BT-series 470 version 6の略称である。 2

  12. SMPTE ST 240 (1999)は、ST 240:1999 - SMPTE Standard - For Television — 1125-Line High-Definition Production Systems — Signal Parametersの略称である。 2

  13. Rec. ITU-T H.273は、Recommendation ITU Telecommunication H-series 273の略称である。 2 3

  14. ITU-R BT.2390-2 (03/2017)およびReport BT.2390-10 (11/2021)では、REC709ALPHAが1.099、REC709BETAが0.018でn=59.5208という値を採用している。しかし、zimgではREC709ALPHA≒1.09929682680944、REC709BETA≒0.018053968510807からn=59.49080238715383としており、これはRec. ITU-T H.273で述べられている定義に沿ったものである。

  15. Report BT.2390-10 (11/2021)による。 2

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1