forked from bartvdbraak/blender
Durian request: Added 'Color Balance' node to compositor. uses Lift/Gamma/Gain
similar to sequence editor. --> http://mke3.net/blender/devel/2.5/color_balance_node.jpg Also added 0 key (zero key) shortcut when mouse is over a button, to reset it to its default value. Same as the RMB menu ->Reset to Default, except for color wheels, it only resets the hue/sat/value components that that widget affects. Peter/Xavier: The existing color balance code can generate NaNs (fractional power of a negative), which causes havoc along the image pipeline. I added a check in the node code to prevent this. Still plenty of potential for lots of better colour correction tools in the compositor, just needs time...
This commit is contained in:
parent
8bcf66e1d1
commit
1d3186cbcf
@ -354,6 +354,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat);
|
||||
#define CMP_NODE_DIST_MATTE 257
|
||||
#define CMP_NODE_VIEW_LEVELS 258
|
||||
#define CMP_NODE_COLOR_MATTE 259
|
||||
#define CMP_NODE_COLORBALANCE 260
|
||||
|
||||
#define CMP_NODE_GLARE 301
|
||||
#define CMP_NODE_TONEMAP 302
|
||||
|
@ -2983,6 +2983,7 @@ static void registerCompositNodes(ListBase *ntypelist)
|
||||
nodeRegisterType(ntypelist, &cmp_node_invert);
|
||||
nodeRegisterType(ntypelist, &cmp_node_alphaover);
|
||||
nodeRegisterType(ntypelist, &cmp_node_zcombine);
|
||||
nodeRegisterType(ntypelist, &cmp_node_colorbalance);
|
||||
|
||||
nodeRegisterType(ntypelist, &cmp_node_normal);
|
||||
nodeRegisterType(ntypelist, &cmp_node_curve_vec);
|
||||
|
@ -73,6 +73,10 @@ void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from);
|
||||
|
||||
int constrain_rgb(float *r, float *g, float *b);
|
||||
void minmax_rgb(short c[3]);
|
||||
|
||||
/***************** lift/gamma/gain / ASC-CDL conversion *****************/
|
||||
|
||||
void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power);
|
||||
|
||||
void rgb_byte_to_float(char *in, float *out);
|
||||
void rgb_float_to_byte(float *in, char *out);
|
||||
|
@ -386,3 +386,17 @@ int constrain_rgb(float *r, float *g, float *b)
|
||||
return 0; /* Color within RGB gamut */
|
||||
}
|
||||
|
||||
/* ********************************* lift/gamma/gain / ASC-CDL conversion ********************************* */
|
||||
|
||||
void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power)
|
||||
{
|
||||
int c;
|
||||
for(c=0; c<3; c++) {
|
||||
offset[c]= lift[c]*gain[c];
|
||||
slope[c]= gain[c]*(1.0f-lift[c]);
|
||||
if(gamma[c] == 0)
|
||||
power[c]= FLT_MAX;
|
||||
else
|
||||
power[c]= 1.0f/gamma[c];
|
||||
}
|
||||
}
|
||||
|
@ -1626,6 +1626,17 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ui_set_but_default(bContext *C, uiBut *but)
|
||||
{
|
||||
/* if there is a valid property that is editable... */
|
||||
if (but->rnapoin.data && but->rnaprop && RNA_property_editable(&but->rnapoin, but->rnaprop)) {
|
||||
if(RNA_property_reset(&but->rnapoin, but->rnaprop, -1)) {
|
||||
/* perform updates required for this property */
|
||||
RNA_property_update(C, &but->rnapoin, but->rnaprop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static double soft_range_round_up(double value, double max)
|
||||
{
|
||||
/* round up to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. */
|
||||
|
@ -2781,6 +2781,34 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
|
||||
|
||||
return WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
else if (event->type == ZEROKEY && event->val == KM_PRESS) {
|
||||
if (but->a1==9){
|
||||
float rgb[3], hsv[3], def_hsv[3];
|
||||
float *def;
|
||||
int len;
|
||||
|
||||
/* reset only value */
|
||||
|
||||
len= RNA_property_array_length(&but->rnapoin, but->rnaprop);
|
||||
if (len >= 3) {
|
||||
def= MEM_callocN(sizeof(float)*len, "reset_defaults - float");
|
||||
|
||||
RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def);
|
||||
rgb_to_hsv(def[0], def[1], def[2], def_hsv, def_hsv+1, def_hsv+2);
|
||||
|
||||
ui_get_but_vectorf(but, rgb);
|
||||
rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
|
||||
|
||||
hsv_to_rgb(hsv[0], hsv[1], def_hsv[2], rgb, rgb+1, rgb+2);
|
||||
ui_set_but_vectorf(but, rgb);
|
||||
|
||||
RNA_property_update(C, &but->rnapoin, but->rnaprop);
|
||||
|
||||
MEM_freeN(def);
|
||||
}
|
||||
return WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(data->state == BUTTON_STATE_NUM_EDITING) {
|
||||
if(event->type == ESCKEY) {
|
||||
@ -2849,6 +2877,32 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle
|
||||
|
||||
return WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
else if (event->type == ZEROKEY && event->val == KM_PRESS) {
|
||||
float rgb[3], hsv[3], def_hsv[3];
|
||||
float *def;
|
||||
int len;
|
||||
|
||||
/* reset only saturation */
|
||||
|
||||
len= RNA_property_array_length(&but->rnapoin, but->rnaprop);
|
||||
if (len >= 3) {
|
||||
def= MEM_callocN(sizeof(float)*len, "reset_defaults - float");
|
||||
|
||||
RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def);
|
||||
rgb_to_hsv(def[0], def[1], def[2], def_hsv, def_hsv+1, def_hsv+2);
|
||||
|
||||
ui_get_but_vectorf(but, rgb);
|
||||
rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
|
||||
|
||||
hsv_to_rgb(hsv[0], def_hsv[1], hsv[2], rgb, rgb+1, rgb+2);
|
||||
ui_set_but_vectorf(but, rgb);
|
||||
|
||||
RNA_property_update(C, &but->rnapoin, but->rnaprop);
|
||||
|
||||
MEM_freeN(def);
|
||||
}
|
||||
return WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
}
|
||||
else if(data->state == BUTTON_STATE_NUM_EDITING) {
|
||||
if(event->type == ESCKEY) {
|
||||
@ -3724,6 +3778,11 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
|
||||
|
||||
return WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
/* reset to default */
|
||||
else if(event->type == ZEROKEY && event->val == KM_PRESS) {
|
||||
if (!(ELEM(but->type, HSVCIRCLE, HSVCUBE)))
|
||||
ui_set_but_default(C, but);
|
||||
}
|
||||
/* handle menu */
|
||||
else if(event->type == RIGHTMOUSE && event->val == KM_PRESS) {
|
||||
/* RMB has two options now */
|
||||
|
@ -345,6 +345,8 @@ extern void ui_get_but_string(uiBut *but, char *str, int maxlen);
|
||||
extern int ui_set_but_string(struct bContext *C, uiBut *but, const char *str);
|
||||
extern int ui_get_but_string_max_length(uiBut *but);
|
||||
|
||||
extern void ui_set_but_default(struct bContext *C, uiBut *but);
|
||||
|
||||
extern void ui_set_but_soft_range(uiBut *but, double value);
|
||||
|
||||
extern void ui_check_but(uiBut *but);
|
||||
|
@ -75,6 +75,228 @@
|
||||
|
||||
#include "image_intern.h"
|
||||
|
||||
/**************************** common state *****************************/
|
||||
|
||||
/* note; image_panel_properties() uses pointer to sima->image directly */
|
||||
Image *ED_space_image(SpaceImage *sima)
|
||||
{
|
||||
return sima->image;
|
||||
}
|
||||
|
||||
/* called to assign images to UV faces */
|
||||
void ED_space_image_set(bContext *C, SpaceImage *sima, Scene *scene, Object *obedit, Image *ima)
|
||||
{
|
||||
ED_uvedit_assign_image(scene, obedit, ima, sima->image);
|
||||
|
||||
/* change the space ima after because uvedit_face_visible uses the space ima
|
||||
* to check if the face is displayed in UV-localview */
|
||||
sima->image= ima;
|
||||
|
||||
if(ima == NULL || ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE)
|
||||
sima->flag &= ~SI_DRAWTOOL;
|
||||
|
||||
if(sima->image)
|
||||
BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
|
||||
|
||||
if(sima->image && sima->image->id.us==0)
|
||||
sima->image->id.us= 1;
|
||||
|
||||
if(C) {
|
||||
if(obedit)
|
||||
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
|
||||
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
}
|
||||
}
|
||||
|
||||
ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r)
|
||||
{
|
||||
ImBuf *ibuf;
|
||||
|
||||
if(sima && sima->image) {
|
||||
#if 0
|
||||
if(sima->image->type==IMA_TYPE_R_RESULT && BIF_show_render_spare())
|
||||
return BIF_render_spare_imbuf();
|
||||
else
|
||||
#endif
|
||||
ibuf= BKE_image_acquire_ibuf(sima->image, &sima->iuser, lock_r);
|
||||
|
||||
if(ibuf && (ibuf->rect || ibuf->rect_float))
|
||||
return ibuf;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ED_space_image_release_buffer(SpaceImage *sima, void *lock)
|
||||
{
|
||||
if(sima && sima->image)
|
||||
BKE_image_release_ibuf(sima->image, lock);
|
||||
}
|
||||
|
||||
int ED_space_image_has_buffer(SpaceImage *sima)
|
||||
{
|
||||
ImBuf *ibuf;
|
||||
void *lock;
|
||||
int has_buffer;
|
||||
|
||||
ibuf= ED_space_image_acquire_buffer(sima, &lock);
|
||||
has_buffer= (ibuf != NULL);
|
||||
ED_space_image_release_buffer(sima, lock);
|
||||
|
||||
return has_buffer;
|
||||
}
|
||||
|
||||
void ED_image_size(Image *ima, int *width, int *height)
|
||||
{
|
||||
ImBuf *ibuf= NULL;
|
||||
void *lock;
|
||||
|
||||
if(ima)
|
||||
ibuf= BKE_image_acquire_ibuf(ima, NULL, &lock);
|
||||
|
||||
if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
|
||||
*width= ibuf->x;
|
||||
*height= ibuf->y;
|
||||
}
|
||||
else {
|
||||
*width= 256;
|
||||
*height= 256;
|
||||
}
|
||||
|
||||
if(ima)
|
||||
BKE_image_release_ibuf(ima, lock);
|
||||
}
|
||||
|
||||
void ED_space_image_size(SpaceImage *sima, int *width, int *height)
|
||||
{
|
||||
Scene *scene= sima->iuser.scene;
|
||||
ImBuf *ibuf;
|
||||
void *lock;
|
||||
|
||||
ibuf= ED_space_image_acquire_buffer(sima, &lock);
|
||||
|
||||
if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
|
||||
*width= ibuf->x;
|
||||
*height= ibuf->y;
|
||||
}
|
||||
else if(sima->image && sima->image->type==IMA_TYPE_R_RESULT && scene) {
|
||||
/* not very important, just nice */
|
||||
*width= (scene->r.xsch*scene->r.size)/100;
|
||||
*height= (scene->r.ysch*scene->r.size)/100;
|
||||
}
|
||||
/* I know a bit weak... but preview uses not actual image size */
|
||||
// XXX else if(image_preview_active(sima, width, height));
|
||||
else {
|
||||
*width= 256;
|
||||
*height= 256;
|
||||
}
|
||||
|
||||
ED_space_image_release_buffer(sima, lock);
|
||||
}
|
||||
|
||||
void ED_image_aspect(Image *ima, float *aspx, float *aspy)
|
||||
{
|
||||
*aspx= *aspy= 1.0;
|
||||
|
||||
if((ima == NULL) || (ima->type == IMA_TYPE_R_RESULT) || (ima->type == IMA_TYPE_COMPOSITE) ||
|
||||
(ima->aspx==0.0 || ima->aspy==0.0))
|
||||
return;
|
||||
|
||||
/* x is always 1 */
|
||||
*aspy = ima->aspy/ima->aspx;
|
||||
}
|
||||
|
||||
void ED_space_image_aspect(SpaceImage *sima, float *aspx, float *aspy)
|
||||
{
|
||||
ED_image_aspect(ED_space_image(sima), aspx, aspy);
|
||||
}
|
||||
|
||||
void ED_space_image_zoom(SpaceImage *sima, ARegion *ar, float *zoomx, float *zoomy)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
ED_space_image_size(sima, &width, &height);
|
||||
|
||||
*zoomx= (float)(ar->winrct.xmax - ar->winrct.xmin)/(float)((ar->v2d.cur.xmax - ar->v2d.cur.xmin)*width);
|
||||
*zoomy= (float)(ar->winrct.ymax - ar->winrct.ymin)/(float)((ar->v2d.cur.ymax - ar->v2d.cur.ymin)*height);
|
||||
}
|
||||
|
||||
void ED_space_image_uv_aspect(SpaceImage *sima, float *aspx, float *aspy)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
ED_space_image_aspect(sima, aspx, aspy);
|
||||
ED_space_image_size(sima, &w, &h);
|
||||
|
||||
*aspx *= (float)w/256.0f;
|
||||
*aspy *= (float)h/256.0f;
|
||||
}
|
||||
|
||||
void ED_image_uv_aspect(Image *ima, float *aspx, float *aspy)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
ED_image_aspect(ima, aspx, aspy);
|
||||
ED_image_size(ima, &w, &h);
|
||||
|
||||
*aspx *= (float)w;
|
||||
*aspy *= (float)h;
|
||||
}
|
||||
|
||||
int ED_space_image_show_render(SpaceImage *sima)
|
||||
{
|
||||
return (sima->image && ELEM(sima->image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE));
|
||||
}
|
||||
|
||||
int ED_space_image_show_paint(SpaceImage *sima)
|
||||
{
|
||||
if(ED_space_image_show_render(sima))
|
||||
return 0;
|
||||
|
||||
return (sima->flag & SI_DRAWTOOL);
|
||||
}
|
||||
|
||||
int ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
|
||||
{
|
||||
if(ED_space_image_show_render(sima))
|
||||
return 0;
|
||||
if(ED_space_image_show_paint(sima))
|
||||
return 0;
|
||||
|
||||
if(obedit && obedit->type == OB_MESH) {
|
||||
EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
|
||||
int ret;
|
||||
|
||||
ret = EM_texFaceCheck(em);
|
||||
|
||||
BKE_mesh_end_editmesh(obedit->data, em);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ED_space_image_show_uvshadow(SpaceImage *sima, Object *obedit)
|
||||
{
|
||||
if(ED_space_image_show_render(sima))
|
||||
return 0;
|
||||
|
||||
if(ED_space_image_show_paint(sima))
|
||||
if(obedit && obedit->type == OB_MESH) {
|
||||
EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
|
||||
int ret;
|
||||
|
||||
ret = EM_texFaceCheck(em);
|
||||
|
||||
BKE_mesh_end_editmesh(obedit->data, em);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void image_histogram_tag_refresh(ScrArea *sa)
|
||||
{
|
||||
@ -343,6 +565,8 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn)
|
||||
case ND_MODE:
|
||||
case ND_RENDER_RESULT:
|
||||
case ND_COMPO_RESULT:
|
||||
if (ED_space_image_show_render(sima))
|
||||
image_histogram_tag_refresh(sa);
|
||||
ED_area_tag_refresh(sa);
|
||||
ED_area_tag_redraw(sa);
|
||||
break;
|
||||
@ -650,224 +874,3 @@ void ED_spacetype_image(void)
|
||||
BKE_spacetype_register(st);
|
||||
}
|
||||
|
||||
/**************************** common state *****************************/
|
||||
|
||||
/* note; image_panel_properties() uses pointer to sima->image directly */
|
||||
Image *ED_space_image(SpaceImage *sima)
|
||||
{
|
||||
return sima->image;
|
||||
}
|
||||
|
||||
/* called to assign images to UV faces */
|
||||
void ED_space_image_set(bContext *C, SpaceImage *sima, Scene *scene, Object *obedit, Image *ima)
|
||||
{
|
||||
ED_uvedit_assign_image(scene, obedit, ima, sima->image);
|
||||
|
||||
/* change the space ima after because uvedit_face_visible uses the space ima
|
||||
* to check if the face is displayed in UV-localview */
|
||||
sima->image= ima;
|
||||
|
||||
if(ima == NULL || ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE)
|
||||
sima->flag &= ~SI_DRAWTOOL;
|
||||
|
||||
if(sima->image)
|
||||
BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
|
||||
|
||||
if(sima->image && sima->image->id.us==0)
|
||||
sima->image->id.us= 1;
|
||||
|
||||
if(C) {
|
||||
if(obedit)
|
||||
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
|
||||
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
}
|
||||
}
|
||||
|
||||
ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r)
|
||||
{
|
||||
ImBuf *ibuf;
|
||||
|
||||
if(sima && sima->image) {
|
||||
#if 0
|
||||
if(sima->image->type==IMA_TYPE_R_RESULT && BIF_show_render_spare())
|
||||
return BIF_render_spare_imbuf();
|
||||
else
|
||||
#endif
|
||||
ibuf= BKE_image_acquire_ibuf(sima->image, &sima->iuser, lock_r);
|
||||
|
||||
if(ibuf && (ibuf->rect || ibuf->rect_float))
|
||||
return ibuf;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ED_space_image_release_buffer(SpaceImage *sima, void *lock)
|
||||
{
|
||||
if(sima && sima->image)
|
||||
BKE_image_release_ibuf(sima->image, lock);
|
||||
}
|
||||
|
||||
int ED_space_image_has_buffer(SpaceImage *sima)
|
||||
{
|
||||
ImBuf *ibuf;
|
||||
void *lock;
|
||||
int has_buffer;
|
||||
|
||||
ibuf= ED_space_image_acquire_buffer(sima, &lock);
|
||||
has_buffer= (ibuf != NULL);
|
||||
ED_space_image_release_buffer(sima, lock);
|
||||
|
||||
return has_buffer;
|
||||
}
|
||||
|
||||
void ED_image_size(Image *ima, int *width, int *height)
|
||||
{
|
||||
ImBuf *ibuf= NULL;
|
||||
void *lock;
|
||||
|
||||
if(ima)
|
||||
ibuf= BKE_image_acquire_ibuf(ima, NULL, &lock);
|
||||
|
||||
if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
|
||||
*width= ibuf->x;
|
||||
*height= ibuf->y;
|
||||
}
|
||||
else {
|
||||
*width= 256;
|
||||
*height= 256;
|
||||
}
|
||||
|
||||
if(ima)
|
||||
BKE_image_release_ibuf(ima, lock);
|
||||
}
|
||||
|
||||
void ED_space_image_size(SpaceImage *sima, int *width, int *height)
|
||||
{
|
||||
Scene *scene= sima->iuser.scene;
|
||||
ImBuf *ibuf;
|
||||
void *lock;
|
||||
|
||||
ibuf= ED_space_image_acquire_buffer(sima, &lock);
|
||||
|
||||
if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
|
||||
*width= ibuf->x;
|
||||
*height= ibuf->y;
|
||||
}
|
||||
else if(sima->image && sima->image->type==IMA_TYPE_R_RESULT && scene) {
|
||||
/* not very important, just nice */
|
||||
*width= (scene->r.xsch*scene->r.size)/100;
|
||||
*height= (scene->r.ysch*scene->r.size)/100;
|
||||
}
|
||||
/* I know a bit weak... but preview uses not actual image size */
|
||||
// XXX else if(image_preview_active(sima, width, height));
|
||||
else {
|
||||
*width= 256;
|
||||
*height= 256;
|
||||
}
|
||||
|
||||
ED_space_image_release_buffer(sima, lock);
|
||||
}
|
||||
|
||||
void ED_image_aspect(Image *ima, float *aspx, float *aspy)
|
||||
{
|
||||
*aspx= *aspy= 1.0;
|
||||
|
||||
if((ima == NULL) || (ima->type == IMA_TYPE_R_RESULT) || (ima->type == IMA_TYPE_COMPOSITE) ||
|
||||
(ima->aspx==0.0 || ima->aspy==0.0))
|
||||
return;
|
||||
|
||||
/* x is always 1 */
|
||||
*aspy = ima->aspy/ima->aspx;
|
||||
}
|
||||
|
||||
void ED_space_image_aspect(SpaceImage *sima, float *aspx, float *aspy)
|
||||
{
|
||||
ED_image_aspect(ED_space_image(sima), aspx, aspy);
|
||||
}
|
||||
|
||||
void ED_space_image_zoom(SpaceImage *sima, ARegion *ar, float *zoomx, float *zoomy)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
ED_space_image_size(sima, &width, &height);
|
||||
|
||||
*zoomx= (float)(ar->winrct.xmax - ar->winrct.xmin)/(float)((ar->v2d.cur.xmax - ar->v2d.cur.xmin)*width);
|
||||
*zoomy= (float)(ar->winrct.ymax - ar->winrct.ymin)/(float)((ar->v2d.cur.ymax - ar->v2d.cur.ymin)*height);
|
||||
}
|
||||
|
||||
void ED_space_image_uv_aspect(SpaceImage *sima, float *aspx, float *aspy)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
ED_space_image_aspect(sima, aspx, aspy);
|
||||
ED_space_image_size(sima, &w, &h);
|
||||
|
||||
*aspx *= (float)w/256.0f;
|
||||
*aspy *= (float)h/256.0f;
|
||||
}
|
||||
|
||||
void ED_image_uv_aspect(Image *ima, float *aspx, float *aspy)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
ED_image_aspect(ima, aspx, aspy);
|
||||
ED_image_size(ima, &w, &h);
|
||||
|
||||
*aspx *= (float)w;
|
||||
*aspy *= (float)h;
|
||||
}
|
||||
|
||||
int ED_space_image_show_render(SpaceImage *sima)
|
||||
{
|
||||
return (sima->image && ELEM(sima->image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE));
|
||||
}
|
||||
|
||||
int ED_space_image_show_paint(SpaceImage *sima)
|
||||
{
|
||||
if(ED_space_image_show_render(sima))
|
||||
return 0;
|
||||
|
||||
return (sima->flag & SI_DRAWTOOL);
|
||||
}
|
||||
|
||||
int ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
|
||||
{
|
||||
if(ED_space_image_show_render(sima))
|
||||
return 0;
|
||||
if(ED_space_image_show_paint(sima))
|
||||
return 0;
|
||||
|
||||
if(obedit && obedit->type == OB_MESH) {
|
||||
EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
|
||||
int ret;
|
||||
|
||||
ret = EM_texFaceCheck(em);
|
||||
|
||||
BKE_mesh_end_editmesh(obedit->data, em);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ED_space_image_show_uvshadow(SpaceImage *sima, Object *obedit)
|
||||
{
|
||||
if(ED_space_image_show_render(sima))
|
||||
return 0;
|
||||
|
||||
if(ED_space_image_show_paint(sima))
|
||||
if(obedit && obedit->type == OB_MESH) {
|
||||
EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
|
||||
int ret;
|
||||
|
||||
ret = EM_texFaceCheck(em);
|
||||
|
||||
BKE_mesh_end_editmesh(obedit->data, em);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -913,6 +913,28 @@ static void node_composit_buts_view_levels(uiLayout *layout, bContext *C, Pointe
|
||||
uiItemR(layout, NULL, 0, ptr, "channel", UI_ITEM_R_EXPAND);
|
||||
}
|
||||
|
||||
static void node_composit_buts_colorbalance(uiLayout *layout, bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
uiLayout *split, *col, *row;
|
||||
|
||||
split = uiLayoutSplit(layout, 0, 0);
|
||||
col = uiLayoutColumn(split, 0);
|
||||
uiTemplateColorWheel(col, ptr, "lift", 1);
|
||||
row = uiLayoutRow(col, 0);
|
||||
uiItemR(row, NULL, 0, ptr, "lift", 0);
|
||||
|
||||
col = uiLayoutColumn(split, 0);
|
||||
uiTemplateColorWheel(col, ptr, "gamma", 1);
|
||||
row = uiLayoutRow(col, 0);
|
||||
uiItemR(row, NULL, 0, ptr, "gamma", 0);
|
||||
|
||||
col = uiLayoutColumn(split, 0);
|
||||
uiTemplateColorWheel(col, ptr, "gain", 1);
|
||||
row = uiLayoutRow(col, 0);
|
||||
uiItemR(row, NULL, 0, ptr, "gain", 0);
|
||||
|
||||
}
|
||||
|
||||
/* only once called */
|
||||
static void node_composit_set_butfunc(bNodeType *ntype)
|
||||
{
|
||||
@ -1042,9 +1064,12 @@ static void node_composit_set_butfunc(bNodeType *ntype)
|
||||
case CMP_NODE_PREMULKEY:
|
||||
ntype->uifunc= node_composit_buts_premulkey;
|
||||
break;
|
||||
case CMP_NODE_VIEW_LEVELS:
|
||||
case CMP_NODE_VIEW_LEVELS:
|
||||
ntype->uifunc=node_composit_buts_view_levels;
|
||||
break;
|
||||
case CMP_NODE_COLORBALANCE:
|
||||
ntype->uifunc=node_composit_buts_colorbalance;
|
||||
break;
|
||||
default:
|
||||
ntype->uifunc= NULL;
|
||||
}
|
||||
|
@ -300,6 +300,18 @@ typedef struct NodeLensDist {
|
||||
short jit, proj, fit, pad;
|
||||
} NodeLensDist;
|
||||
|
||||
typedef struct NodeColorBalance {
|
||||
/* for processing */
|
||||
float slope[3];
|
||||
float offset[3];
|
||||
float power[3];
|
||||
|
||||
/* for ui representation */
|
||||
float lift[3];
|
||||
float gamma[3];
|
||||
float gain[3];
|
||||
} NodeColorBalance;
|
||||
|
||||
/* TEX_output */
|
||||
typedef struct TexNodeOutput {
|
||||
char name[32];
|
||||
|
@ -42,6 +42,8 @@
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_texture.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
@ -298,6 +300,23 @@ static void rna_Node_image_layer_update(Main *bmain, Scene *scene, PointerRNA *p
|
||||
rna_Node_update(bmain, scene, ptr);
|
||||
}
|
||||
|
||||
static void rna_Node_colorbalance_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
bNode *node= (bNode*)ptr->data;
|
||||
NodeColorBalance *ncb = node->storage;
|
||||
float lift[3], gamma[3], gain[3];
|
||||
float n_one[3] = {-1.f, -1.f, -1.f};
|
||||
|
||||
mul_v3_v3fl(lift, ncb->lift, 2.f);
|
||||
add_v3_v3(lift, n_one);
|
||||
mul_v3_v3fl(gamma, ncb->gamma, 2.f);
|
||||
mul_v3_v3fl(gain, ncb->gain, 2.f);
|
||||
|
||||
lift_gamma_gain_to_asc_cdl(lift, gamma, gain, ncb->offset, ncb->slope, ncb->power);
|
||||
|
||||
rna_Node_update(bmain, scene, ptr);
|
||||
}
|
||||
|
||||
static EnumPropertyItem *renderresult_layers_add_enum(RenderLayer *rl)
|
||||
{
|
||||
EnumPropertyItem *item= NULL;
|
||||
@ -1854,6 +1873,38 @@ static void def_cmp_lensdist(StructRNA *srna)
|
||||
RNA_def_property_ui_text(prop, "Fit", "For positive distortion factor only: scale image such that black areas are not visible");
|
||||
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_cmp_colorbalance(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
static float default_col[3] = {0.5f, 0.5f, 0.5f};
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodeColorBalance", "storage");
|
||||
|
||||
prop = RNA_def_property(srna, "lift", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_float_sdna(prop, NULL, "lift");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_float_array_default(prop, default_col);
|
||||
RNA_def_property_ui_range(prop, 0, 1, 0.1, 3);
|
||||
RNA_def_property_ui_text(prop, "Lift", "Correction for Shadows");
|
||||
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_colorbalance_update");
|
||||
|
||||
prop = RNA_def_property(srna, "gamma", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_float_sdna(prop, NULL, "gamma");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_float_array_default(prop, default_col);
|
||||
RNA_def_property_ui_range(prop, 0, 1, 0.1, 3);
|
||||
RNA_def_property_ui_text(prop, "Gamma", "Correction for Midtones");
|
||||
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_colorbalance_update");
|
||||
|
||||
prop = RNA_def_property(srna, "gain", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_float_sdna(prop, NULL, "gain");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_float_array_default(prop, default_col);
|
||||
RNA_def_property_ui_range(prop, 0, 1, 0.1, 3);
|
||||
RNA_def_property_ui_text(prop, "Gain", "Correction for Highlights");
|
||||
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_colorbalance_update");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -107,6 +107,7 @@ DefNode( CompositorNode, CMP_NODE_LENSDIST, def_cmp_lensdist, "LENSD
|
||||
DefNode( CompositorNode, CMP_NODE_VIEW_LEVELS, def_cmp_levels, "LEVELS", Levels, "Levels", "" )
|
||||
DefNode( CompositorNode, CMP_NODE_COLOR_MATTE, def_cmp_color_matte, "COLOR_MATTE", ColorMatte, "Color Matte", "" )
|
||||
DefNode( CompositorNode, CMP_NODE_DIST_MATTE, def_cmp_distance_matte, "DISTANCE_MATTE", DistanceMatte, "Distance Matte", "" )
|
||||
DefNode( CompositorNode, CMP_NODE_COLORBALANCE, def_cmp_colorbalance, "COLORBALANCE", ColorBalance, "Color Balance", "" )
|
||||
|
||||
DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
|
||||
DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
|
||||
|
@ -59,6 +59,7 @@ extern bNodeType cmp_node_gamma;
|
||||
extern bNodeType cmp_node_invert;
|
||||
extern bNodeType cmp_node_alphaover;
|
||||
extern bNodeType cmp_node_zcombine;
|
||||
extern bNodeType cmp_node_colorbalance;
|
||||
|
||||
extern bNodeType cmp_node_normal;
|
||||
extern bNodeType cmp_node_curve_vec;
|
||||
|
@ -40,3 +40,14 @@ extern void node_copy_standard_storage(struct bNode *orig_node, struct bNode *ne
|
||||
|
||||
#endif
|
||||
|
||||
// this is needed for inlining behaviour
|
||||
#if defined _WIN32
|
||||
# define DO_INLINE __inline
|
||||
#elif defined (__sgi)
|
||||
# define DO_INLINE
|
||||
#elif defined (__sun) || defined (__sun__)
|
||||
# define DO_INLINE
|
||||
#else
|
||||
# define DO_INLINE static inline
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user