@@ -136,7 +136,6 @@ namespace coder {
136136 }
137137
138138 float Evaluate (float v) {
139- // Spec: http://www.arib.or.jp/english/html/overview/doc/2-STD-B67v1_0.pdf
140139 v = std::max (0 .0f , v);
141140 constexpr float a = 0 .17883277f ;
142141 constexpr float b = 0 .28466892f ;
@@ -161,6 +160,15 @@ namespace coder {
161160 return IfThenElse (cmp, branch1, branch2);
162161 }
163162
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+
164172 float bt2020HLGGammaCorrection (float linear) {
165173 static const float betaRec2020 = 0 .018053968510807f ;
166174 static const float alphaRec2020 = 1 .09929682680944f ;
@@ -172,28 +180,45 @@ namespace coder {
172180 return linear;
173181 }
174182
175- void TransferROWHLGU8 (uint8_t *data, float maxColors) {
183+ void TransferROWHLGU8 (uint8_t *data, float maxColors, HLGGammaCorrection gammaCorrection ) {
176184 auto r = (float ) data[0 ] / (float ) maxColors;
177185 auto g = (float ) data[1 ] / (float ) maxColors;
178186 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+ }
185202 }
186203
187- void TransferROWHLGU16 (uint16_t *data, float maxColors) {
204+ void
205+ TransferROWHLGU16 (uint16_t *data, float maxColors, HLGGammaCorrection gammaCorrection) {
188206 auto r = (float ) data[0 ] / (float ) maxColors;
189207 auto g = (float ) data[1 ] / (float ) maxColors;
190208 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+ }
194218 }
195219
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) {
197222 const FixedTag<float32_t , 4 > df32;
198223 FixedTag<uint16_t , 4 > d;
199224
@@ -222,9 +247,19 @@ namespace coder {
222247 VF32 g32 = BitCast (rebind32, PromoteTo (signed32, GURow));
223248 VF32 b32 = BitCast (rebind32, PromoteTo (signed32, BURow));
224249
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;
228263
229264 VU16 rNew = BitCast (du16, DemoteTo (rebind16, pqR));
230265 VU16 gNew = BitCast (du16, DemoteTo (rebind16, pqG));
@@ -236,14 +271,15 @@ namespace coder {
236271 }
237272
238273 for (; x < width; ++x) {
239- TransferROWHLGU16 (reinterpret_cast <uint16_t *>(ptr16), maxColors);
274+ TransferROWHLGU16 (reinterpret_cast <uint16_t *>(ptr16), maxColors, gammaCorrection );
240275 ptr16 += 4 ;
241276 }
242277 }
243278
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) {
245281 const FixedTag<float32_t , 4 > df32;
246- hwy::HWY_NAMESPACE:: FixedTag<uint8_t , 4 > d;
282+ FixedTag<uint8_t , 4 > d;
247283
248284 const Rebind<uint32_t , decltype (d)> signed32;
249285 const Rebind<int32_t , decltype (df32)> floatToSigned;
@@ -271,14 +307,24 @@ namespace coder {
271307 VF32 g32 = Div (ConvertTo (rebind32, PromoteTo (signed32, GURow)), vColors);
272308 VF32 b32 = Div (ConvertTo (rebind32, PromoteTo (signed32, BURow)), vColors);
273309
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+
274320 VF32 pqR = Max (
275- Min (Mul (bt2020HLGGammaCorrection (df32, HLGEotf ( r32)) , vColors), vColors),
321+ Min (Mul (r32, vColors), vColors),
276322 Zero (df32));
277323 VF32 pqG = Max (
278- Min (Mul (bt2020HLGGammaCorrection (df32, HLGEotf ( g32)) , vColors), vColors),
324+ Min (Mul (g32, vColors), vColors),
279325 Zero (df32));
280326 VF32 pqB = Max (
281- Min (Mul (bt2020HLGGammaCorrection (df32, HLGEotf ( b32)) , vColors), vColors),
327+ Min (Mul (b32, vColors), vColors),
282328 Zero (df32));
283329
284330 VU16 rNew = DemoteTo (rebindOrigin, ConvertTo (floatToSigned, pqR));
@@ -291,13 +337,14 @@ namespace coder {
291337 }
292338
293339 for (; x < width; ++x) {
294- TransferROWHLGU8 (reinterpret_cast <uint8_t *>(ptr16), maxColors);
340+ TransferROWHLGU8 (reinterpret_cast <uint8_t *>(ptr16), maxColors, gammaCorrection );
295341 ptr16 += 4 ;
296342 }
297343 }
298344
299345 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) {
301348 float maxColors = powf (2 , (float ) depth) - 1 ;
302349 ThreadPool pool;
303350 std::vector<std::future<void >> results;
@@ -306,13 +353,13 @@ namespace coder {
306353 auto ptr16 = reinterpret_cast <uint16_t *>(data + y * stride);
307354 auto r = pool.enqueue (ProcessHLGF16Row, reinterpret_cast <uint16_t *>(ptr16),
308355 width,
309- (float ) maxColors);
356+ (float ) maxColors, correction );
310357 results.push_back (std::move (r));
311358 } else {
312359 auto ptr16 = reinterpret_cast <uint8_t *>(data + y * stride);
313360 auto r = pool.enqueue (ProcessHLGu8Row, reinterpret_cast <uint8_t *>(ptr16),
314361 width,
315- (float ) maxColors);
362+ (float ) maxColors, correction );
316363 results.push_back (std::move (r));
317364 }
318365 }
@@ -331,8 +378,10 @@ HWY_AFTER_NAMESPACE();
331378namespace coder {
332379 HWY_EXPORT (ProcessHLG);
333380 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);
336385 }
337386}
338387#endif
0 commit comments