View Single Post
Old 9th May 2021, 15:38   #6  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 2,361
Updated to RC2, small fix.
I tested running it through only 3 lutxyz expressions and curiously it is less than half the speed. Not sure why. Should optimize the math instead.

Code:
function ColorSpace_fast (clip clp, string "source", string "target", string "kernel_up", string "kernel_down", bool "gamut", bool "gamma" \
                       , string "cplace", bool "tv_range_in", bool "tv_range_out", float "b_up", float "c_up", float "p_up", float "b_down", float "c_down", float "p_down") {

    gamut       = Default (gamut, true)           # convert gamut
    gamma       = Default (gamma, true)           # convert gamma
    tv_range_in = Default (tv_range_in,  !isRGB(clp) )
    tv_range_out= Default (tv_range_out, tv_range_in )
    kernelu     = Default (kernel_up, "bicubic")
    kerneld     = Default (kernel_down, kernelu)
    cplace      = Default (cplace, "MPEG2")
    bu          = Default (b_up, 0.00)
    cu          = Default (c_up, 0.75)   # Precise Bicubic
    pu          = Default (p_up, 0.25)
    bd          = Default (b_down, -0.5)
    cd          = Default (c_down, 0.25) # Didée's Bicubic
    pd          = Default (p_down, 0.25)

    source = Matrix_fuzzy_search (source)
    target = Matrix_fuzzy_search (target)

    s_num =
\     (source == "sRGB"      ) ? 0
\   : (source == "Rec601"    ) ? 1
\   : (source == "240M"      ) ? 2
\   : (source == "470BG"     ) ? 3
\   : (source == "Rec2020"   ) ? 4
\   : (source == "Rec709"    ) ? 5
\   : (source == "1886a"     ) ? 6
\   : (source == "AdobeRGB"  ) ? 7
\   : (source == "Display-P3") ? 0
\   : (source == "DCI-P3"    ) ? 8
\   : (source == "ACEScg"    ) ? 9
\   : (source == "ACES2065"  ) ? 9
\   : Assert (false, "Unsupported Color Space.")

    t_num =
\     (target == "sRGB"      ) ? 0
\   : (target == "Rec601"    ) ? 1
\   : (target == "240M"      ) ? 2
\   : (target == "470BG"     ) ? 3
\   : (target == "Rec2020"   ) ? 4
\   : (target == "Rec709"    ) ? 5
\   : (target == "1886a"     ) ? 6
\   : (target == "AdobeRGB"  ) ? 7
\   : (target == "Display-P3") ? 0
\   : (target == "DCI-P3"    ) ? 8
\   : (target == "ACEScg"    ) ? 9
\   : (target == "ACES2065"  ) ? 9
\   : Assert (false, "Unsupported Color Space.")

    bdpth = BitsPerComponent(clp) > 10 ? 0.09929682680944 : 0.099

    #                                  SMPTE-C     Y’PbPr 601  PAL/SECAM BT-2020    Rec.709    BT-1886a  AdobeRGB     DCI-P3   AP1/AP0
    #                         sRGB     SMPTE 170M  SMPTE 240M  BT-470BG  BT-2020    BT-1886    BT-1886a  AdobeRGB     DCI-P3      ACES
    t_temp  = Select (t_num,  6504   ,  6504   ,   6504   ,    6504   ,      6504,   6504   ,   6504   ,     6504 ,   6305  ,     6000 )
    s_off   = Select (s_num,  0.055  ,  0.099  ,   0.1115 ,    0.099  ,     bdpth,   0      ,   0      ,   0      ,   0     ,      0   )
    s_gamma = Select (s_num,  2.40   ,  2.22222,   2.22222,    2.80   ,   2.22222,   2.40   ,   2.60   ,   2.1992 ,   2.60  ,      1.0 )

    t_off   = Select (t_num,  0.055  ,  0.099  ,   0.1115 ,    0.099  ,     bdpth,   0      ,   0      ,   0      ,   0     ,      0   )
    t_gamma = Select (t_num,  2.40   ,  2.22222,   2.22222,    2.80   ,   2.22222,   2.40   ,   2.60   ,   2.1992 ,   2.60  ,      1.0 )


    clp

    # YUV to RGB
    RGBc = YCbCrToRGB_mat(source)
    RGB =  ["x ymin - "+string(RGBc[0])+" * y range_half - "+string(RGBc[1])+" * + z range_half - "+string(RGBc[2])+" * +", \
            "x ymin - "+string(RGBc[3])+" * y range_half - "+string(RGBc[4])+" * + z range_half - "+string(RGBc[5])+" * +", \
            "x ymin - "+string(RGBc[6])+" * y range_half - "+string(RGBc[7])+" * + z range_half - "+string(RGBc[8])+" * +"]


    # Linearization
    fs  = "{s_gamma} 1.0 - {s_off} / {s_off} {s_gamma} * {s_gamma} 1.0 - 1.0 {s_off} + * / {s_gamma} ^ *"
    xb  = "{s_off} {s_gamma} 1.0 - /"
    outR = s_off > 0.0 ? Format(""+RGB[0] + " range_max / A@ "+xb+" > A {s_off} + 1.0 {s_off} + / {s_gamma} ^ range_max * A "+fs+" * range_max * ? ") : \
                         Format(""+RGB[0] + " range_max / {s_gamma} ^ range_max * ")
    outG = s_off > 0.0 ? Format(""+RGB[1] + " range_max / A@ "+xb+" > A {s_off} + 1.0 {s_off} + / {s_gamma} ^ range_max * A "+fs+" * range_max * ? ") : \
                         Format(""+RGB[1] + " range_max / {s_gamma} ^ range_max * ")
    outB = s_off > 0.0 ? Format(""+RGB[2] + " range_max / A@ "+xb+" > A {s_off} + 1.0 {s_off} + / {s_gamma} ^ range_max * A "+fs+" * range_max * ? ") : \
                         Format(""+RGB[2] + " range_max / {s_gamma} ^ range_max * ")

    # Gamut conversion
    mata = RGB_to_XYZ(source, list=true)
    matb = XYZ_to_RGB(target, list=true)
    mat = MatrixDot(mata, matb)

    toMATR = outR + string(mat[0])+" * " + outG + string(mat[3])+" * + " + outB + string(mat[6])+" * +"
    toMATG = outR + string(mat[1])+" * " + outG + string(mat[4])+" * + " + outB + string(mat[7])+" * +"
    toMATB = outR + string(mat[2])+" * " + outG + string(mat[5])+" * + " + outB + string(mat[8])+" * +"

    # Gamma conversion
    yb  = "{t_off} {t_gamma} * {t_gamma} 1.0 - 1.0 {t_off} + * / {t_gamma} ^"
    rs  = "{t_gamma} 1.0 - {t_off} / {t_gamma} 1.0 - ^ 1.0 {t_off} + {t_gamma} / {t_gamma} ^ *"
    outR = t_off > 0.0 ? Format(""+toMATR+" range_max / A@ "+yb+" > 1.0 {t_off} + A 1.0 {t_gamma} / ^ * {t_off} - range_max * A "+rs+" * range_max * ? ") : \
                         Format(""+toMATR+" range_max / 1.0 {t_gamma} / ^ range_max * ")
    outG = t_off > 0.0 ? Format(""+toMATG+" range_max / A@ "+yb+" > 1.0 {t_off} + A 1.0 {t_gamma} / ^ * {t_off} - range_max * A "+rs+" * range_max * ? ") : \
                         Format(""+toMATG+" range_max / 1.0 {t_gamma} / ^ range_max * ")
    outB = t_off > 0.0 ? Format(""+toMATB+" range_max / A@ "+yb+" > 1.0 {t_off} + A 1.0 {t_gamma} / ^ * {t_off} - range_max * A "+rs+" * range_max * ? ") : \
                         Format(""+toMATB+" range_max / 1.0 {t_gamma} / ^ range_max * ")
    # RGB to YUV
    YUVc = RGBToYCbCr_mat(target)
    YUV =  ["      ymin " + outR + string(YUVc[0])+" * + " + outG + string(YUVc[1])+" * + " + outB + string(YUVc[2])+" * + ", \
            "range_half " + outR + string(YUVc[3])+" * + " + outG + string(YUVc[4])+" * + " + outB + string(YUVc[5])+" * + ",  \
            "range_half " + outR + string(YUVc[6])+" * + " + outG + string(YUVc[7])+" * + " + outB + string(YUVc[8])+" * + "]


    w =  width(clp)
    h = height(clp)
    cplace = is444(clp) ? ",src_left=0.0" : cplace=="MPEG2" ? ",src_left=0.25" : ",src_left=0.0"
    resampler = kernelu == "nnedi3" ? "nnedi3_resize16(" + String(w) + "," + String(h) + cplace +")"         : \
                kernelu == "bicubic"?   "BicubicResize(" + String(w) + "," + String(h) + cplace +",b=bu,c=cu)" : \
                kernelu == "gauss"  ?     "GaussResize(" + String(w) + "," + String(h) + cplace +",p=pu)"     : \
                                     kernelu + "Resize(" + String(w) + "," + String(h) + cplace +")"

    Y = ExtractY(clp)
    U = Eval("ExtractU(clp)." + resampler)
    V = Eval("ExtractV(clp)." + resampler)


    Yo  = Expr(Y, U, V, YUV[0])
    Cbo = Expr(Y, U, V, YUV[1])
    Cro = Expr(Y, U, V, YUV[2])

    p_type = PixelType(clp)

    p_type4 = FindStr(p_type, "44")>0
    p_type2 = FindStr(p_type, "22")>0

    nw = round(w/2.0)
    nh = round(h/2.0)
    cplace = p_type4 || cplace=="MPEG2" ? ",src_left=-0.50" : ",src_left=0.0"
    resampler = kerneld == "nnedi3" ? "nnedi3_resize16(" + String(nw+nw%2) + "," + String(p_type2 ? h : nh+nh%2) + cplace + ")"         : \
                kerneld == "bicubic"?   "BicubicResize(" + String(nw+nw%2) + "," + String(p_type2 ? h : nh+nh%2) + cplace + ",b=bd,c=cd)" : \
                kerneld == "gauss"  ?     "GaussResize(" + String(nw+nw%2) + "," + String(p_type2 ? h : nh+nh%2) + cplace + ",p=pd)"     : \
                                     kerneld + "Resize(" + String(nw+nw%2) + "," + String(p_type2 ? h : nh+nh%2) + cplace + ")"

    Cbo = p_type4 ? Cbo : Eval("Cbo." + resampler)
    Cro = p_type4 ? Cro : Eval("Cro." + resampler)

    CombinePlanes(Yo, Cbo, Cro, planes="YUV", pixel_type=p_type) }
Dogway is offline   Reply With Quote