View Full Version : Scene Linear RGB originally from rec709 source
Yellow_
23rd August 2011, 13:58
If I understand correctly to get scene linear data from a rec709 source I need to apply the inverse of a rec709 transfer curve.
What would be required to convert RGB data originally from rec709 source to scene linear using Avisynth?
jmac698
23rd August 2011, 14:33
Convert to rgb and inverse of 2.2 gamma. resampleHQ does this internally.
Yellow_
23rd August 2011, 15:29
Convert to rgb and inverse of 2.2 gamma. resampleHQ does this internally.
2.2 gamma is display referred and the curve differs from rec709 at its base, if I apply 0.45 then it will crush shadow detail.
What I'm looking to do is remove the transfer curve to get linear data with exposure and color as close captured by the device from original scene for scene linear compositing and then apply a 1D view lut to preview as sRGB or rec709 etc after.
Thats the theory anyway. :-)
jmac698
23rd August 2011, 17:31
The standard is,
X'709=4.5x, x<=.018
1.099x^.45-.099, r>.018
This is pretty simple, the first 4 values (R'G'B' 0-18) are the 'black crush' you're referring to. Make a spreadsheet, write the numbers 0-255 in the column A. Enter this formula in the column B:
=4.5*A2, drag it down until x=4.
Enter this formula for the remaining columns:
=(POWER(A7/255;0.45)*1.099-0.099)*255
And here is a short table showing the correspondence:
0 0
1 5
2 9
3 14
4 18
5 23
6 27
7 30
8 34
9 37
10 40
20 64
30 82
40 97
50 109
100 159
150 195
200 226
248 252
249 252
250 253
251 253
252 254
253 254
254 255
255 255
As you can see, you will get runs of up to 2 codes that you can't reconstruct. On the other hand, you'll need about 10 bits to store the linear version.
I'll try this in masktools and get back to you (I can see another jmac script on the horizon :)
Update: the inverse formula is:
=POWER((B110/255+0.099)/1.099;1/0.45)*255
When x>.018*4.5*255
Yellow_
23rd August 2011, 19:02
jmac, thanks for explaination and time, including need for greater than 8bit to store, which luckily I'm using Dither 1.95 and exporting 16bit EXR via avs2yuv and Imagemagick so that will cover that.
Dither 1.95 offers linearising but currently only sRGB. Imagemagick can't do it, so need to find how to linearise in Avisynth in stacked msb/lsb or 48bit RGB.
jmac698
25th August 2011, 02:02
Hey,
I'm working on it - just got sidetracked trying to do it fancy :)
Beta - not done yet
#Linear RGB 0.1 by jmac698
#Convert to/from linear RGB
#Requires Masktools 2a48+
#For HD sources, select Rec709 option
#For SD sources, select Rec601 option
#Uses vertically stacked msb/lsb clip format for deepcolor output; compatible with Dither plugin
#Demo
ramp(blankclip(pixel_type="yv12"))
tolinearrgb(last,"rec709",fullrange=false,deepcolor=true)
return last
fromlinearrgb(last,"rec709",fullrange=false,deepcolor=true)
function ramp(clip template){
#Create a luma ramp from 16-235, vertically, with 16 as top line
mt_lutspa(template,mode="absolute",yexpr="y 220 % 16 +")
}
function tolinearrgb(clip v, string std, bool "fullrange", bool "deepcolor"){
#Select formula based on standard
std=(std=="" && v.Width<=720) ? "rec709" : "rec601"
std=lcase(std)
std=="rec709" ? Eval("""
expr="x .018 * 4.5 > x 255 / .099 + 1.099 / 1 .45 / ^ 255 * x 4.5 / ?"
""") : \
std=="smpte240m" ? Eval("""
expr="x .0228 * 4 > x 255 / 0.1115 + 1.1115 / 1 .45 / ^ 255 * x 4 / ?"
""") : \
std=="rec601" ? Eval("""
#I don't know the formula to put here; this is just a reasonable default
expr="x .018 * 4.5 > x 255 / .099 + 1.099 / 1 .45 / ^ 255 * x 4.5 / ?"
""") \
: Eval("""
expr="x"
""")#Else
exprlo=deepcolor ? expr+"256 * 255 &u" : nop
exprhi=deepcolor ? expr+"2 * >>0" : nop
mt_lut(v,yexpr=expr)
}
function tolinearexpr(float cutoff, float linear, float factor, float constant, float gamma, float scalei, float scaleo){
#Create a Masktools expression of a generic transfer function formula.
#Example from Rec709:
#x'=(x<=cutoff*linear) x*linear
#(x>cutoff*linear) (factor*x^gamma-constant)*scaleo
#cutoff=.018, linear=4.5, factor=1.099, constant=-.099, gamma=.45, scalei=255, scaleo=255
"x "+string(cutoff)+" * "+string(linear)+" > x "+string(scalei)+" / "+string(-constant)+ \
" + "+string(factor)+" / 1 "+string(gamma)+" / ^ "+string(scaleo)+" * x "+string(linear)+" / ?"
}
function fromlinearexpr(float cutoff, float linear, float factor, float constant, float gamma, float scalei, float scaleo){
"x "+string(factor)+" * "+string(gamma)+" ^ "+string(constant)+" - x "+string(linear)+"*" \
}
IanB
25th August 2011, 23:10
function tolinearrgb(clip v, string std, bool "fullrange", bool "deepcolor"){
#Select formula based on standard
std=(std=="" && v.Width<=720) ? "rec709" : "rec601"
std=...
2 possible bugs :- Width less than or equal 720 use rec709, really?
std will always be "rec709" or "rec601", check out the script default function.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.