@@ -136,7 +136,6 @@ namespace coder {
136
136
}
137
137
138
138
float Evaluate (float v) {
139
- // Spec: http://www.arib.or.jp/english/html/overview/doc/2-STD-B67v1_0.pdf
140
139
v = std::max (0 .0f , v);
141
140
constexpr float a = 0 .17883277f ;
142
141
constexpr float b = 0 .28466892f ;
@@ -161,6 +160,15 @@ namespace coder {
161
160
return IfThenElse (cmp, branch1, branch2);
162
161
}
163
162
163
+ template <class D , typename T = Vec<D>>
164
+ inline T dciP3GammaCorrection (const D d, T color) {
165
+ return PowHLG (color, Set (d, 1 / 2 .6f ));
166
+ }
167
+
168
+ inline float dciP3HLGGammaCorrection (float linear) {
169
+ return powf (linear, 1 / 2 .6f );
170
+ }
171
+
164
172
float bt2020HLGGammaCorrection (float linear) {
165
173
static const float betaRec2020 = 0 .018053968510807f ;
166
174
static const float alphaRec2020 = 1 .09929682680944f ;
@@ -172,28 +180,45 @@ namespace coder {
172
180
return linear;
173
181
}
174
182
175
- void TransferROWHLGU8 (uint8_t *data, float maxColors) {
183
+ void TransferROWHLGU8 (uint8_t *data, float maxColors, HLGGammaCorrection gammaCorrection ) {
176
184
auto r = (float ) data[0 ] / (float ) maxColors;
177
185
auto g = (float ) data[1 ] / (float ) maxColors;
178
186
auto b = (float ) data[2 ] / (float ) maxColors;
179
- data[0 ] = (uint8_t ) std::clamp (
180
- (float ) bt2020HLGGammaCorrection (Evaluate (r)) * maxColors, 0 .0f , maxColors);
181
- data[1 ] = (uint8_t ) std::clamp (
182
- (float ) bt2020HLGGammaCorrection (Evaluate (g)) * maxColors, 0 .0f , maxColors);
183
- data[2 ] = (uint8_t ) std::clamp (
184
- (float ) bt2020HLGGammaCorrection (Evaluate (b)) * maxColors, 0 .0f , maxColors);
187
+ if (gammaCorrection == Rec2020) {
188
+ data[0 ] = (uint8_t ) std::clamp (
189
+ (float ) bt2020HLGGammaCorrection (Evaluate (r)) * maxColors, 0 .0f , maxColors);
190
+ data[1 ] = (uint8_t ) std::clamp (
191
+ (float ) bt2020HLGGammaCorrection (Evaluate (g)) * maxColors, 0 .0f , maxColors);
192
+ data[2 ] = (uint8_t ) std::clamp (
193
+ (float ) bt2020HLGGammaCorrection (Evaluate (b)) * maxColors, 0 .0f , maxColors);
194
+ } else if (gammaCorrection == DCIP3) {
195
+ data[0 ] = (uint8_t ) std::clamp (
196
+ (float ) dciP3HLGGammaCorrection (Evaluate (r)) * maxColors, 0 .0f , maxColors);
197
+ data[1 ] = (uint8_t ) std::clamp (
198
+ (float ) dciP3HLGGammaCorrection (Evaluate (g)) * maxColors, 0 .0f , maxColors);
199
+ data[2 ] = (uint8_t ) std::clamp (
200
+ (float ) dciP3HLGGammaCorrection (Evaluate (b)) * maxColors, 0 .0f , maxColors);
201
+ }
185
202
}
186
203
187
- void TransferROWHLGU16 (uint16_t *data, float maxColors) {
204
+ void
205
+ TransferROWHLGU16 (uint16_t *data, float maxColors, HLGGammaCorrection gammaCorrection) {
188
206
auto r = (float ) data[0 ] / (float ) maxColors;
189
207
auto g = (float ) data[1 ] / (float ) maxColors;
190
208
auto b = (float ) data[2 ] / (float ) maxColors;
191
- data[0 ] = (uint16_t ) float_to_half ((float ) bt2020HLGGammaCorrection (Evaluate (r)));
192
- data[1 ] = (uint16_t ) float_to_half ((float ) bt2020HLGGammaCorrection (Evaluate (g)));
193
- data[2 ] = (uint16_t ) float_to_half ((float ) bt2020HLGGammaCorrection (Evaluate (b)));
209
+ if (gammaCorrection == Rec2020) {
210
+ data[0 ] = (uint16_t ) float_to_half ((float ) bt2020HLGGammaCorrection (Evaluate (r)));
211
+ data[1 ] = (uint16_t ) float_to_half ((float ) bt2020HLGGammaCorrection (Evaluate (g)));
212
+ data[2 ] = (uint16_t ) float_to_half ((float ) bt2020HLGGammaCorrection (Evaluate (b)));
213
+ } else if (gammaCorrection == DCIP3) {
214
+ data[0 ] = (uint16_t ) float_to_half ((float ) dciP3HLGGammaCorrection (Evaluate (r)));
215
+ data[1 ] = (uint16_t ) float_to_half ((float ) dciP3HLGGammaCorrection (Evaluate (g)));
216
+ data[2 ] = (uint16_t ) float_to_half ((float ) dciP3HLGGammaCorrection (Evaluate (b)));
217
+ }
194
218
}
195
219
196
- void ProcessHLGF16Row (uint16_t *HWY_RESTRICT data, int width, float maxColors) {
220
+ void ProcessHLGF16Row (uint16_t *HWY_RESTRICT data, int width, float maxColors,
221
+ HLGGammaCorrection gammaCorrection) {
197
222
const FixedTag<float32_t , 4 > df32;
198
223
FixedTag<uint16_t , 4 > d;
199
224
@@ -222,9 +247,19 @@ namespace coder {
222
247
VF32 g32 = BitCast (rebind32, PromoteTo (signed32, GURow));
223
248
VF32 b32 = BitCast (rebind32, PromoteTo (signed32, BURow));
224
249
225
- VF32 pqR = bt2020HLGGammaCorrection (df32, HLGEotf (r32));
226
- VF32 pqG = bt2020HLGGammaCorrection (df32, HLGEotf (g32));
227
- VF32 pqB = bt2020HLGGammaCorrection (df32, HLGEotf (b32));
250
+ if (gammaCorrection == Rec2020) {
251
+ r32 = bt2020HLGGammaCorrection (df32, HLGEotf (r32));
252
+ g32 = bt2020HLGGammaCorrection (df32, HLGEotf (g32));
253
+ b32 = bt2020HLGGammaCorrection (df32, HLGEotf (b32));
254
+ } else if (gammaCorrection == DCIP3) {
255
+ r32 = dciP3GammaCorrection (df32, HLGEotf (r32));
256
+ g32 = dciP3GammaCorrection (df32, HLGEotf (g32));
257
+ b32 = dciP3GammaCorrection (df32, HLGEotf (b32));
258
+ }
259
+
260
+ VF32 pqR = r32;
261
+ VF32 pqG = g32;
262
+ VF32 pqB = b32;
228
263
229
264
VU16 rNew = BitCast (du16, DemoteTo (rebind16, pqR));
230
265
VU16 gNew = BitCast (du16, DemoteTo (rebind16, pqG));
@@ -236,14 +271,15 @@ namespace coder {
236
271
}
237
272
238
273
for (; x < width; ++x) {
239
- TransferROWHLGU16 (reinterpret_cast <uint16_t *>(ptr16), maxColors);
274
+ TransferROWHLGU16 (reinterpret_cast <uint16_t *>(ptr16), maxColors, gammaCorrection );
240
275
ptr16 += 4 ;
241
276
}
242
277
}
243
278
244
- void ProcessHLGu8Row (uint8_t *HWY_RESTRICT data, int width, float maxColors) {
279
+ void ProcessHLGu8Row (uint8_t *HWY_RESTRICT data, int width, float maxColors,
280
+ HLGGammaCorrection gammaCorrection) {
245
281
const FixedTag<float32_t , 4 > df32;
246
- hwy::HWY_NAMESPACE:: FixedTag<uint8_t , 4 > d;
282
+ FixedTag<uint8_t , 4 > d;
247
283
248
284
const Rebind<uint32_t , decltype (d)> signed32;
249
285
const Rebind<int32_t , decltype (df32)> floatToSigned;
@@ -271,14 +307,24 @@ namespace coder {
271
307
VF32 g32 = Div (ConvertTo (rebind32, PromoteTo (signed32, GURow)), vColors);
272
308
VF32 b32 = Div (ConvertTo (rebind32, PromoteTo (signed32, BURow)), vColors);
273
309
310
+ if (gammaCorrection == Rec2020) {
311
+ r32 = bt2020HLGGammaCorrection (df32, HLGEotf (r32));
312
+ g32 = bt2020HLGGammaCorrection (df32, HLGEotf (g32));
313
+ b32 = bt2020HLGGammaCorrection (df32, HLGEotf (b32));
314
+ } else if (gammaCorrection == DCIP3) {
315
+ r32 = dciP3GammaCorrection (df32, HLGEotf (r32));
316
+ g32 = dciP3GammaCorrection (df32, HLGEotf (g32));
317
+ b32 = dciP3GammaCorrection (df32, HLGEotf (b32));
318
+ }
319
+
274
320
VF32 pqR = Max (
275
- Min (Mul (bt2020HLGGammaCorrection (df32, HLGEotf ( r32)) , vColors), vColors),
321
+ Min (Mul (r32, vColors), vColors),
276
322
Zero (df32));
277
323
VF32 pqG = Max (
278
- Min (Mul (bt2020HLGGammaCorrection (df32, HLGEotf ( g32)) , vColors), vColors),
324
+ Min (Mul (g32, vColors), vColors),
279
325
Zero (df32));
280
326
VF32 pqB = Max (
281
- Min (Mul (bt2020HLGGammaCorrection (df32, HLGEotf ( b32)) , vColors), vColors),
327
+ Min (Mul (b32, vColors), vColors),
282
328
Zero (df32));
283
329
284
330
VU16 rNew = DemoteTo (rebindOrigin, ConvertTo (floatToSigned, pqR));
@@ -291,13 +337,14 @@ namespace coder {
291
337
}
292
338
293
339
for (; x < width; ++x) {
294
- TransferROWHLGU8 (reinterpret_cast <uint8_t *>(ptr16), maxColors);
340
+ TransferROWHLGU8 (reinterpret_cast <uint8_t *>(ptr16), maxColors, gammaCorrection );
295
341
ptr16 += 4 ;
296
342
}
297
343
}
298
344
299
345
void
300
- ProcessHLG (uint8_t *data, bool halfFloats, int stride, int width, int height, int depth) {
346
+ ProcessHLG (uint8_t *data, bool halfFloats, int stride, int width, int height, int depth,
347
+ HLGGammaCorrection correction) {
301
348
float maxColors = powf (2 , (float ) depth) - 1 ;
302
349
ThreadPool pool;
303
350
std::vector<std::future<void >> results;
@@ -306,13 +353,13 @@ namespace coder {
306
353
auto ptr16 = reinterpret_cast <uint16_t *>(data + y * stride);
307
354
auto r = pool.enqueue (ProcessHLGF16Row, reinterpret_cast <uint16_t *>(ptr16),
308
355
width,
309
- (float ) maxColors);
356
+ (float ) maxColors, correction );
310
357
results.push_back (std::move (r));
311
358
} else {
312
359
auto ptr16 = reinterpret_cast <uint8_t *>(data + y * stride);
313
360
auto r = pool.enqueue (ProcessHLGu8Row, reinterpret_cast <uint8_t *>(ptr16),
314
361
width,
315
- (float ) maxColors);
362
+ (float ) maxColors, correction );
316
363
results.push_back (std::move (r));
317
364
}
318
365
}
@@ -331,8 +378,10 @@ HWY_AFTER_NAMESPACE();
331
378
namespace coder {
332
379
HWY_EXPORT (ProcessHLG);
333
380
HWY_DLLEXPORT void
334
- ProcessHLG (uint8_t *data, bool halfFloats, int stride, int width, int height, int depth) {
335
- HWY_DYNAMIC_DISPATCH (ProcessHLG)(data, halfFloats, stride, width, height, depth);
381
+ ProcessHLG (uint8_t *data, bool halfFloats, int stride, int width, int height, int depth,
382
+ HLGGammaCorrection gammaCorrection) {
383
+ HWY_DYNAMIC_DISPATCH (ProcessHLG)(data, halfFloats, stride, width, height, depth,
384
+ gammaCorrection);
336
385
}
337
386
}
338
387
#endif
0 commit comments