@@ -41,74 +41,162 @@ Saturate01(const float v)
41
41
}
42
42
}
43
43
44
+ // ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
45
+ // YUV ⇔ RGB
46
+ // https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.2020_conversion
47
+
48
+ #define Yuv_i8_to_f32 \
49
+ const float y = y8 / 255 .0f ; \
50
+ const float u = u8 / 255 .0f ; \
51
+ const float v = v8 / 255 .0f ; \
52
+
53
+ #define Yuv_i10_to_f32 \
54
+ const float y = y10 / 1023 .0f ; \
55
+ const float u = u10 / 1023 .0f ; \
56
+ const float v = v10 / 1023 .0f ;
57
+
58
+ #define Rgb_f32_to_i8_return \
59
+ *r8_return = (uint8_t )(r * 255 .0f ); \
60
+ *g8_return = (uint8_t )(g * 255 .0f ); \
61
+ *b8_return = (uint8_t )(b * 255 .0f );
62
+
63
+ #define Rgb_f32_to_i10_return \
64
+ *r10_return = (uint16_t )(r * 1023 .0f ); \
65
+ *g10_return = (uint16_t )(g * 1023 .0f ); \
66
+ *b10_return = (uint16_t )(b * 1023 .0f );
67
+
68
+ #define BT601_YuvRgb \
69
+ const float r = Saturate01(1 .1644f * y + 0 .0000f * u + 1 .5960f * v - 0 .8742f ); \
70
+ const float g = Saturate01(1 .1644f * y - 0 .3918f * u - 0 .8130f * v + 0 .5317f ); \
71
+ const float b = Saturate01(1 .1644f * y + 2 .0172f * u + 0 .0000f * v - 1 .0856f );
72
+
73
+ #define Rec709_YuvRgb \
74
+ const float r = Saturate01(1 .1646f * y + 0 .0005f * u + 1 .7928f * v - 0 .9733f ); \
75
+ const float g = Saturate01(1 .1646f * y - 0 .2134f * u - 0 .5331f * v + 0 .3017f ); \
76
+ const float b = Saturate01(1 .1646f * y + 2 .1125f * u + 0 .0002f * v - 1 .1336f );
77
+
78
+ #define Rec2020_YuvRgb \
79
+ const float r = Saturate01(1 .1644f * y + 0 .0002f * u + 1 .6786f * v - 0 .9156f ); \
80
+ const float g = Saturate01(1 .1644f * y - 0 .1873f * u - 0 .6504f * v + 0 .3474f ); \
81
+ const float b = Saturate01(1 .1644f * y + 2 .1417f * u + 0 .0001f * v - 1 .1481f );
82
+
44
83
// / <summary>
45
- // / 0~1の範囲のfloat値のYUVを0~1の範囲のfloat値のRGBにする。
84
+ // / BT.601 8bit YUV → 8bit RGB
46
85
// / </summary>
47
86
static void
48
- YuvToRgb (
49
- const float y , const float u , const float v ,
50
- float * r_return, float *g_return, float *b_return )
87
+ Bt601_Yuv8ToRgb8 (
88
+ const uint8_t y8 , const uint8_t u8 , const uint8_t v8 ,
89
+ uint8_t * r8_return, uint8_t * g8_return, uint8_t * b8_return )
51
90
{
52
- *r_return = Saturate01 ( 1 . 1644f * y + 0 . 0000f * u + 1 . 5960f * v - 0 . 8742f ) ;
53
- *g_return = Saturate01 ( 1 . 1644f * y - 0 . 3918f * u - 0 . 8130f * v + 0 . 5317f ) ;
54
- *b_return = Saturate01 ( 1 . 1644f * y + 2 . 0172f * u + 0 . 0000f * v - 1 . 0856f ) ;
91
+ Yuv_i8_to_f32 ;
92
+ BT601_YuvRgb ;
93
+ Rgb_f32_to_i8_return ;
55
94
}
56
95
57
96
// / <summary>
58
- // / 8bit YUV → 8bit RGB
97
+ // / BT.601 10bit YUV → 10bit RGB
59
98
// / </summary>
60
99
static void
61
- Yuv8ToRgb8 (
62
- const uint8_t y8 , const uint8_t u8 , const uint8_t v8 ,
63
- uint8_t * r8_return, uint8_t * g8_return, uint8_t * b8_return )
100
+ Bt601_Yuv10ToRgb10 (
101
+ const uint16_t y10 , const uint16_t u10 , const uint16_t v10 ,
102
+ uint16_t * r10_return, uint16_t * g10_return, uint16_t * b10_return )
64
103
{
65
- const float y = y8 / 255 .0f ;
66
- const float u = u8 / 255 .0f ;
67
- const float v = v8 / 255 .0f ;
68
-
69
- const float r = Saturate01 (1 .1644f * y + 0 .0000f * u + 1 .5960f * v - 0 .8742f );
70
- const float g = Saturate01 (1 .1644f * y - 0 .3918f * u - 0 .8130f * v + 0 .5317f );
71
- const float b = Saturate01 (1 .1644f * y + 2 .0172f * u + 0 .0000f * v - 1 .0856f );
72
-
73
- *r8_return = (uint8_t )(r * 255 .0f );
74
- *g8_return = (uint8_t )(g * 255 .0f );
75
- *b8_return = (uint8_t )(b * 255 .0f );
104
+ Yuv_i10_to_f32;
105
+ BT601_YuvRgb;
106
+ Rgb_f32_to_i10_return;
76
107
}
77
108
78
109
// / <summary>
79
- // / 10bit YUV → 10bit RGB
110
+ // / Rec.709 8bit YUV → 8bit RGB
80
111
// / </summary>
81
112
static void
82
- Yuv10ToRgb10 (
83
- const uint16_t y10 , const uint16_t u10 , const uint16_t v10 ,
84
- uint16_t * r10_return, uint16_t * g10_return, uint16_t * b10_return )
113
+ Rec709_Yuv8ToRgb8 (
114
+ const uint8_t y8 , const uint8_t u8 , const uint8_t v8 ,
115
+ uint8_t * r8_return, uint8_t * g8_return, uint8_t * b8_return )
85
116
{
86
- const float y = y10 / 1023 .0f ;
87
- const float u = u10 / 1023 .0f ;
88
- const float v = v10 / 1023 .0f ;
117
+ Yuv_i8_to_f32;
118
+ Rec709_YuvRgb;
119
+ Rgb_f32_to_i8_return;
120
+ }
89
121
90
- const float r = Saturate01 (1 .1644f * y + 0 .0000f * u + 1 .5960f * v - 0 .8742f );
91
- const float g = Saturate01 (1 .1644f * y - 0 .3918f * u - 0 .8130f * v + 0 .5317f );
92
- const float b = Saturate01 (1 .1644f * y + 2 .0172f * u + 0 .0000f * v - 1 .0856f );
122
+ // / <summary>
123
+ // / Rec.709 10bit YUV → 10bit RGB
124
+ // / </summary>
125
+ static void
126
+ Rec709_Yuv10ToRgb10 (
127
+ const uint16_t y10, const uint16_t u10, const uint16_t v10,
128
+ uint16_t * r10_return, uint16_t * g10_return, uint16_t * b10_return)
129
+ {
130
+ Yuv_i10_to_f32;
131
+ Rec709_YuvRgb;
132
+ Rgb_f32_to_i10_return;
133
+ }
93
134
94
- *r10_return = (uint16_t )(r * 1023 .0f );
95
- *g10_return = (uint16_t )(g * 1023 .0f );
96
- *b10_return = (uint16_t )(b * 1023 .0f );
135
+ // / <summary>
136
+ // / Rec.2020 8bit YUV → 8bit RGB
137
+ // / </summary>
138
+ static void
139
+ Rec2020_Yuv8ToRgb8 (
140
+ const uint8_t y8, const uint8_t u8 , const uint8_t v8,
141
+ uint8_t * r8_return, uint8_t * g8_return, uint8_t * b8_return) {
142
+ Yuv_i8_to_f32;
143
+ Rec2020_YuvRgb;
144
+ Rgb_f32_to_i8_return;
97
145
}
98
146
99
147
// / <summary>
100
- // / 0~1の範囲のfloat値のRGBを0~1の範囲のfloat値のYUVにする。
148
+ // / Rec.2020 10bit YUV → 10bit RGB
101
149
// / </summary>
102
150
static void
103
- RgbToYuv (
104
- const float r, const float g, const float b,
105
- float * y_return, float * u_return, float * v_return)
151
+ Rec2020_Yuv10ToRgb10 (
152
+ const uint16_t y10, const uint16_t u10, const uint16_t v10,
153
+ uint16_t * r10_return, uint16_t * g10_return, uint16_t * b10_return) {
154
+ Yuv_i10_to_f32;
155
+ Rec2020_YuvRgb;
156
+ Rgb_f32_to_i10_return;
157
+ }
158
+
159
+ static void
160
+ Yuv8ToRgb8 (
161
+ MLConverter::ColorSpace colorSpace,
162
+ const uint8_t y8, const uint8_t u8 , const uint8_t v8,
163
+ uint8_t * r8_return, uint8_t * g8_return, uint8_t * b8_return)
106
164
{
107
- *y_return = Saturate01 ( 0 .2568f * r + 0 .5041f * g + 0 .0979f * b + 0 .0627f );
108
- *u_return = Saturate01 (-0 .1482f * r - 0 .2910f * g + 0 .4392f * b + 0 .5020f );
109
- *v_return = Saturate01 ( 0 .4392f * r - 0 .3678f * g - 0 .0714f * b + 0 .5020f );
165
+ switch (colorSpace) {
166
+ case MLConverter::CS_Rec601:
167
+ Bt601_Yuv8ToRgb8 (y8, u8 , v8, r8_return, g8_return, b8_return);
168
+ break ;
169
+ case MLConverter::CS_Rec709:
170
+ Rec709_Yuv8ToRgb8 (y8, u8 , v8, r8_return, g8_return, b8_return);
171
+ break ;
172
+ case MLConverter::CS_Rec2020:
173
+ Rec2020_Yuv8ToRgb8 (y8, u8 , v8, r8_return, g8_return, b8_return);
174
+ break ;
175
+ }
110
176
}
111
177
178
+ static void
179
+ Yuv10ToRgb10 (
180
+ MLConverter::ColorSpace colorSpace,
181
+ const uint16_t y10, const uint16_t u10, const uint16_t v10,
182
+ uint16_t * r10_return, uint16_t * g10_return, uint16_t * b10_return)
183
+ {
184
+ switch (colorSpace) {
185
+ case MLConverter::CS_Rec601:
186
+ Bt601_Yuv10ToRgb10 (y10, u10, v10, r10_return, g10_return, b10_return);
187
+ break ;
188
+ case MLConverter::CS_Rec709:
189
+ Rec709_Yuv10ToRgb10 (y10, u10, v10, r10_return, g10_return, b10_return);
190
+ break ;
191
+ case MLConverter::CS_Rec2020:
192
+ Rec2020_Yuv10ToRgb10 (y10, u10, v10, r10_return, g10_return, b10_return);
193
+ break ;
194
+ }
195
+ }
196
+
197
+ // ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
198
+ // ガンマカーブ
199
+
112
200
static const float pq_m1 = 0 .1593017578125f ; // ( 2610.0 / 4096.0 ) / 4.0;
113
201
static const float pq_m2 = 78 .84375f ; // ( 2523.0 / 4096.0 ) * 128.0;
114
202
static const float pq_c1 = 0 .8359375f ; // 3424.0 / 4096.0 or pq_c3 - pq_c2 + 1.0;
@@ -149,7 +237,7 @@ MLConverter::MLConverter(void)
149
237
}
150
238
151
239
void
152
- MLConverter::Uyvy8bitToR8G8B8A8 (const uint32_t * pFrom, uint32_t * pTo, const int width, const int height)
240
+ MLConverter::Uyvy8bitToR8G8B8A8 (ColorSpace colorSpace, const uint32_t * pFrom, uint32_t * pTo, const int width, const int height)
153
241
{
154
242
// widthは2で割り切れる。
155
243
assert ((width & 1 ) == 0 );
@@ -182,10 +270,10 @@ MLConverter::Uyvy8bitToR8G8B8A8(const uint32_t* pFrom, uint32_t* pTo, const int
182
270
// yuv → RGB
183
271
uint8_t r, g, b;
184
272
185
- Yuv8ToRgb8 (y0, u, v, &r, &g, &b);
273
+ Yuv8ToRgb8 (colorSpace, y0, u, v, &r, &g, &b);
186
274
pTo[writeP + 0 ] = (a << 24 ) + (b << 16 ) + (g << 8 ) + r;
187
275
188
- Yuv8ToRgb8 (y1, u, v, &r, &g, &b);
276
+ Yuv8ToRgb8 (colorSpace, y1, u, v, &r, &g, &b);
189
277
pTo[writeP + 1 ] = (a << 24 ) + (b << 16 ) + (g << 8 ) + r;
190
278
}
191
279
}
@@ -194,7 +282,7 @@ MLConverter::Uyvy8bitToR8G8B8A8(const uint32_t* pFrom, uint32_t* pTo, const int
194
282
// / bmdFormat10BitYUV v210 → DXGI_FORMAT_R10G10B10A2_UNORM
195
283
// / </summary>
196
284
void
197
- MLConverter::Yuv422_10bitToR10G10B10A2 (const uint32_t * pFrom, uint32_t * pTo, const int width, const int height, const uint8_t alpha)
285
+ MLConverter::Yuv422_10bitToR10G10B10A2 (ColorSpace colorSpace, const uint32_t * pFrom, uint32_t * pTo, const int width, const int height, const uint8_t alpha)
198
286
{
199
287
const uint32_t a = (alpha >> 6 ) & 0x3 ;
200
288
@@ -255,22 +343,22 @@ MLConverter::Yuv422_10bitToR10G10B10A2(const uint32_t* pFrom, uint32_t* pTo, con
255
343
// yuv → RGB
256
344
uint16_t r, g, b;
257
345
258
- Yuv10ToRgb10 (y0, u0, v0, &r, &g, &b);
346
+ Yuv10ToRgb10 (colorSpace, y0, u0, v0, &r, &g, &b);
259
347
pTo[writeP + 0 ] = (a << 30 ) + (b << 20 ) + (g << 10 ) + r;
260
348
261
- Yuv10ToRgb10 (y1, u0, v0, &r, &g, &b);
349
+ Yuv10ToRgb10 (colorSpace, y1, u0, v0, &r, &g, &b);
262
350
pTo[writeP + 1 ] = (a << 30 ) + (b << 20 ) + (g << 10 ) + r;
263
351
264
- Yuv10ToRgb10 (y2, u2, v2, &r, &g, &b);
352
+ Yuv10ToRgb10 (colorSpace, y2, u2, v2, &r, &g, &b);
265
353
pTo[writeP + 2 ] = (a << 30 ) + (b << 20 ) + (g << 10 ) + r;
266
354
267
- Yuv10ToRgb10 (y3, u2, v2, &r, &g, &b);
355
+ Yuv10ToRgb10 (colorSpace, y3, u2, v2, &r, &g, &b);
268
356
pTo[writeP + 3 ] = (a << 30 ) + (b << 20 ) + (g << 10 ) + r;
269
357
270
- Yuv10ToRgb10 (y4, u4, v4, &r, &g, &b);
358
+ Yuv10ToRgb10 (colorSpace, y4, u4, v4, &r, &g, &b);
271
359
pTo[writeP + 4 ] = (a << 30 ) + (b << 20 ) + (g << 10 ) + r;
272
360
273
- Yuv10ToRgb10 (y5, u4, v4, &r, &g, &b);
361
+ Yuv10ToRgb10 (colorSpace, y5, u4, v4, &r, &g, &b);
274
362
pTo[writeP + 5 ] = (a << 30 ) + (b << 20 ) + (g << 10 ) + r;
275
363
}
276
364
}
0 commit comments