diff options
author | Ton Roosendaal <ton@blender.org> | 2006-10-28 00:27:13 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2006-10-28 00:27:13 +0400 |
commit | 129cab4137d2a928e68eec7f7647b1f2b690686a (patch) | |
tree | dbb71785f612bbb1e919f102cfc78213f7302f4e /source/blender/blenkernel/intern/colortools.c | |
parent | a7d3a58ba9e7a42781a21c8015cdd51a76473056 (diff) |
New Curves Widget option: curves can get extrapolated extension.
Especially for Compositing it was annoying that colors always got clipped
in the 0.0-1.0 range. For this reason, extrapolated Curves now is the
default. Old saved files still have horizontal extrapolation.
Set the option with 'Tools' menu (wrench icon). This is a setting per
curve, so you might need to set all 4 curves for an RGBA curves widget.
Diffstat (limited to 'source/blender/blenkernel/intern/colortools.c')
-rw-r--r-- | source/blender/blenkernel/intern/colortools.c | 74 |
1 files changed, 62 insertions, 12 deletions
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 17cba6c2a94..93238137f95 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -73,6 +73,7 @@ CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, floa cumap->bwmul[0]= cumap->bwmul[1]= cumap->bwmul[2]= 1.0f; for(a=0; a<tot; a++) { + cumap->cm[a].flag= CUMA_EXTEND_EXTRAPOLATE; cumap->cm[a].totpoint= 2; cumap->cm[a].curve= MEM_callocN(2*sizeof(CurveMapPoint), "curve points"); @@ -278,6 +279,37 @@ static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *nex } } +/* in X, out Y. + X is presumed to be outside first or last */ +static float curvemap_calc_extend(CurveMap *cuma, float x, float *first, float *last) +{ + if(x <= first[0]) { + if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0) { + /* no extrapolate */ + return first[1]; + } + else { + if(cuma->ext_in[0]==0.0f) + return first[1] + cuma->ext_in[1]*10000.0f; + else + return first[1] + cuma->ext_in[1]*(x - first[0])/cuma->ext_in[0]; + } + } + else if(x >= last[0]) { + if((cuma->flag & CUMA_EXTEND_EXTRAPOLATE)==0) { + /* no extrapolate */ + return last[1]; + } + else { + if(cuma->ext_out[0]==0.0f) + return last[1] - cuma->ext_out[1]*10000.0f; + else + return last[1] + cuma->ext_out[1]*(x - last[0])/cuma->ext_out[0]; + } + } + return 0.0f; +} + /* only creates a table for a single channel in CurveMapping */ static void curvemap_make_table(CurveMap *cuma, rctf *clipr) { @@ -333,6 +365,7 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr) if(nlen>FLT_EPSILON) { VecMulf(vec, hlen/nlen); VecAddf(bezt[0].vec[2], vec, bezt[0].vec[1]); + VecSubf(bezt[0].vec[0], bezt[0].vec[1], vec); } } a= cuma->totpoint-1; @@ -349,6 +382,7 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr) if(nlen>FLT_EPSILON) { VecMulf(vec, hlen/nlen); VecAddf(bezt[a].vec[0], vec, bezt[a].vec[1]); + VecSubf(bezt[a].vec[2], bezt[a].vec[1], vec); } } } @@ -364,8 +398,23 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr) forward_diff_bezier(bezt[a].vec[1][1], bezt[a].vec[2][1], bezt[a+1].vec[0][1], bezt[a+1].vec[1][1], fp+1, CM_RESOL-1, 2); } + /* store first and last handle for extrapolation, unit length */ + cuma->ext_in[0]= bezt[0].vec[0][0] - bezt[0].vec[1][0]; + cuma->ext_in[1]= bezt[0].vec[0][1] - bezt[0].vec[1][1]; + range= sqrt(cuma->ext_in[0]*cuma->ext_in[0] + cuma->ext_in[1]*cuma->ext_in[1]); + cuma->ext_in[0]/= range; + cuma->ext_in[1]/= range; + + a= cuma->totpoint-1; + cuma->ext_out[0]= bezt[a].vec[1][0] - bezt[a].vec[2][0]; + cuma->ext_out[1]= bezt[a].vec[1][1] - bezt[a].vec[2][1]; + range= sqrt(cuma->ext_out[0]*cuma->ext_out[0] + cuma->ext_out[1]*cuma->ext_out[1]); + cuma->ext_out[0]/= range; + cuma->ext_out[1]/= range; + + /* cleanup */ MEM_freeN(bezt); - + range= CM_TABLEDIV*(cuma->maxtable - cuma->mintable); cuma->range= 1.0f/range; @@ -373,10 +422,8 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr) fp= allpoints; lastpoint= allpoints + 2*(totpoint-1); cmp= MEM_callocN((CM_TABLE+1)*sizeof(CurveMapPoint), "dist table"); - cmp[0].x= cuma->mintable; - cmp[0].y= allpoints[1]; - for(a=1; a<CM_TABLE; a++) { + for(a=0; a<=CM_TABLE; a++) { curf= cuma->mintable + range*(float)a; cmp[a].x= curf; @@ -384,8 +431,8 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr) while(curf >= fp[0] && fp!=lastpoint) { fp+=2; } - if(curf >= fp[0] && fp==lastpoint) - cmp[a].y= fp[1]; + if(fp==allpoints || (curf >= fp[0] && fp==lastpoint)) + cmp[a].y= curvemap_calc_extend(cuma, curf, allpoints, lastpoint); else { float fac1= fp[0] - fp[-2]; float fac2= fp[0] - curf; @@ -396,8 +443,6 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr) cmp[a].y= fac1*fp[-1] + (1.0f-fac1)*fp[1]; } } - cmp[CM_TABLE].x= cuma->maxtable; - cmp[CM_TABLE].y= allpoints[2*totpoint-1]; MEM_freeN(allpoints); cuma->table= cmp; @@ -518,11 +563,16 @@ float curvemap_evaluateF(CurveMap *cuma, float value) /* index in table */ fi= (value-cuma->mintable)*cuma->range; i= (int)fi; - if(i<0) return cuma->table[0].y; - if(i>=CM_TABLE) return cuma->table[CM_TABLE].y; - fi= fi-(float)i; - return (1.0f-fi)*cuma->table[i].y + (fi)*cuma->table[i+1].y; + if(fi<0.0f || fi>cuma->range) + return curvemap_calc_extend(cuma, value, &cuma->table[0].x, &cuma->table[CM_TABLE].x); + else { + if(i<0) return cuma->table[0].y; + if(i>=CM_TABLE) return cuma->table[CM_TABLE].y; + + fi= fi-(float)i; + return (1.0f-fi)*cuma->table[i].y + (fi)*cuma->table[i+1].y; + } } /* works with curve 'cur' */ |