As i was mainly to blame for the original underlying parameters used in AcesCC (and AcesCCT), i thought i’d try and come up with an initial strawman candidate for this newly proposed AcesLog which hopefully will address the requirement to extend the range in the hightlights, IN ADDITION to insuring that current production/post-production grading operations will still work effectively.
my two main goals were:
-
answer the requirement to extend the linear dynamic range which is represented by 0.0 - 1.0 in the new log encoding space
-
insure that log value for midgrey and the “steps_per_stop” will allow acceptable results with current grading operations (e.g. asc-cdl/etc). (some of the newer extended camera log encodings have not realize that this is an issue affecting onset cdl grading/dailies/etc.)
as a starting point, let’s examine the current acesCCT/CC encodings:
they have:
- 17.52 stops total range (in pure acesCC log without the acesCCT linear toe)
- 58.4 steps per stop (in 10 bit code values) above lin/log crossover point
- “midgrey” 2^{-2.5} at ~422 (10bit code value)
- linear max @ 222.860944 (~10.3 stops above “midgrey”)
btw - just for comparison - the new alexa35 logcv4 has a max linear value of 460.8 - which is ~1.08 stops above current AcesCCT max. this was probably one of several reasons behind the desire for a new aces log encoding.
one side note - i’m using a value of 2^{-2.5} as “midgrey” - this value is ~0.176777 and has been a good linear target for midgrey - it’s really close to “18%”, but more important, it’s a nice “round” power of 2. (you can think of it as "…we’ll use a linear value 2.5 stops below 1.0 as a good target for “middle grey’…”)
my first proposal is that we set the steps_per_stop to 50.0 10bit_cvs/stop - which will allow for extra highlight range. (it was 58.4 for acesCCT/CC) and that we adjust the log value for midgrey slightly to compensate for shifts in where “linear 0.0” falls in the new log space.
i) 50.0 steps per stop (in 10bit code values) above lin/log crossover point
ii) set ~midgrey (2^{-2.5}) @ a 400 10bit code value (it was at 422 for AcesCCT)
iii) linear max corresponding to a normalized log value of 1.0 would now be at:
2^{(-2.5 + (1023-400)/50)} =~ 995.998666
(12.46 stops above midgrey)
iv) integer linear powers of 2 would be at convenient exact 10bit cv’s -
for example:
10bitcv 325 == linear 0.125
10bitcv 425 == linear 0.250
10bitcv 475 == linear 0.500
10bitcv 525 == linear 1.000
10bitcv 575 == linear 2.000
10bitcv 625 == linear 4.000
this results in the lin_to_log formula (pure log - without any linear toe):
`normalized_log_val = (log2(linear_val) + 10.5) / 20.46;``
(full maths derivation are at the end of this diatribe…)
with that in place, now we have to add the “linear toe” strategy
that was done for AcesCCT -
for AcesCCT the log/lin crossover point was at 0.007812500000 - (which corresponded to a log 10bit code value of exactly 175) but with the new slope, this would result in linear 0.0 mapping to a corresponding log 10bit code value of approximately 102 - which is a tad high. normally, linear 0.0 maps to something in the low 90’s in log 10bit code values. so, instead of placing this log/lin crossover point at a 10bit log cv value of 175, i’ve lowered it to a 10bit log cv value of 165. this corresponds to a linear crossover value of 0.006801176276. and now maps linear 0.0 to a 10bit log code value of approx 93.
here are the parameters for this proposed lin_to_log and log_to_lin transforms:
lin_xover = 0.006801176276 ;
log_xover = 165/1023 = .16129032258064516129 ;
the slope of the lin-to-log curve at this crossover point is:
lin_to_log_slope = 10.36773919972907075549 ;
and the y-intercept of this linear toe portion of the lin-to-log curve is:
y_intercept = .09077750069969257965 ;
this results in 0.0 - 1.0 in the new log encoding corresponding to a linear range of (approx) -0.008756 to 995.998666. for comparison, the corresponding linear range for 0.0 - 1.0 in AcesCCT was -0.006917 to 222.860944. so we have extended the highlight range by over two stops, and also extended the negative range slightly.
comparison between AcesCCT and this “AcesLog_strawman1” (dubbed “AcesLogSM1”)
linear value corresponding to log 0.0
AcesCCT -0.006917
AcesLogSM1 -0.008756
linear value corresponding to log 1.0
AcesCCT 222.860944
AcesLogSM1 995.998666
log 10bit code value corresponding to linear 0.0
AcesCCT 74.582
AcesLogSM1 92.865
midgrey (2 ^{-2.5}) placement
AcesCCT 422 (10 bit code value)
AcesLogSM1 400 (10 bit code value)
steps per stop (above lin/log crossover point)
AcesCCT 58.4 (10 bit code value steps_per_stop)
AcesLogSM1 50.0 (10 bit code value steps_per_stop)
and here’s the maths in plain vanilla C code :
double ALOGSM1_LIN_BRKPNT = 0.006801176276;
double ALOGSM1_LOG_BRKPNT = .16129032258064516129; /* 10bit cv = 165 */
double ALOGSM1_LINTOLOG_SLOPE = 10.36773919972907075549;
double ALOGSM1_LINTOLOG_YINT = .09077750069969257965;
double lin_to_AcesLogSM1(in)
double in;
{
if (in <= ALOGSM1_LIN_BRKPNT)
return ALOGSM1_LINTOLOG_SLOPE * in + ALOGSM1_LINTOLOG_YINT;
else /* (in > ALOGSM1_LIN_BRKPNT) */
return ( log(in)/log(2.0) + 10.5 ) / 20.46;
}
double AcesLogSM1_to_lin(in)
double in;
{
if (in <= ALOGSM1_LOG_BRKPNT)
return (in - ALOGSM1_LINTOLOG_YINT) / ALOGSM1_LINTOLOG_SLOPE;
else /* (in > ALOGSM1_LOG_BRKPNT) */
return pow( 2.0 , in * 20.46 - 10.5 );
}
and, as promised, here’s the algebra for the underlying lin-to-log parameters:
the basic equation for a pure lin-to-log is:
logval = (log2(linval) + offset) / total_range_in_stops
the first decision was to have 50 10bit log code values per stop, this corresponds to a total_range_in_stops to be `
1023/50 = 20.460
the second decision was to have a linear “midgrey” value of 2^{-2.5} produce a 10bit log code value of 400. this 10bit log code value of 400 corresponds to a “normalized” (0.0-1.0) log value of
400/1023 = 0.39100684261974584555...
substituting this into the above equaation , we have
logval = (log2(linval) + offset) / total_range_in_stops
0.39100684261974584555... = (log2(2^-2.5) + offset) / 20.460
and through the magic of algebra -
offset = 0.39100684261974584555... * 20.460 + 2.5
offset = 10.50
et voila - our underlying linear-to-log formula (without any linear toe) is:
normalized_log_val = (log2(linear_val) + 10.5) / 20.46;
sorry for all the boring math…
-joshie
AcesLog_SM1-AcesCCT_vs_AcesCC_vs_AcesLogSM1notoe_vs_AcesLogSM1_logtolin.xlsx (132.1 KB)