Finished some work from the weekend to keep local tree clean..

* Added a generic 'histogram' ui control, currently available in new image editor 
'scopes' region (shortcut P). Shows the histogram of the currently viewed image.

It's a baby step in unifying the functionality and code from the sequence editor, 
so eventually we can migrate the sequence preview to the image editor too, 
like compositor.

Still a couple of rough edges to tweak, regarding when it updates. Also would 
be very nice to have this region as a partially transparent overlapping region...
This commit is contained in:
Matt Ebb 2010-01-19 01:32:06 +00:00
parent 849024df83
commit aab8196a1c
27 changed files with 438 additions and 7 deletions

@ -35,6 +35,7 @@ class IMAGE_MT_view(bpy.types.Menu):
show_uvedit = sima.show_uvedit show_uvedit = sima.show_uvedit
layout.operator("image.properties", icon='MENU_PANEL') layout.operator("image.properties", icon='MENU_PANEL')
layout.operator("image.scopes", icon='MENU_PANEL')
layout.separator() layout.separator()
@ -386,6 +387,21 @@ class IMAGE_PT_game_properties(bpy.types.Panel):
col.separator() col.separator()
col.prop(ima, "mapping", expand=True) col.prop(ima, "mapping", expand=True)
class IMAGE_PT_view_histogram(bpy.types.Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'PREVIEW'
bl_label = "Histogram"
def poll(self, context):
sima = context.space_data
return (sima and sima.image)
def draw(self, context):
layout = self.layout
sima = context.space_data
layout.template_histogram(sima, "histogram")
class IMAGE_PT_view_properties(bpy.types.Panel): class IMAGE_PT_view_properties(bpy.types.Panel):
bl_space_type = 'IMAGE_EDITOR' bl_space_type = 'IMAGE_EDITOR'
@ -417,6 +433,7 @@ class IMAGE_PT_view_properties(bpy.types.Panel):
col.prop(sima, "draw_repeated", text="Repeat") col.prop(sima, "draw_repeated", text="Repeat")
if show_uvedit: if show_uvedit:
col.prop(uvedit, "normalized_coordinates", text="Normalized") col.prop(uvedit, "normalized_coordinates", text="Normalized")
elif show_uvedit: elif show_uvedit:
col.label(text="Coordinates:") col.label(text="Coordinates:")
col.prop(uvedit, "normalized_coordinates", text="Normalized") col.prop(uvedit, "normalized_coordinates", text="Normalized")
@ -562,3 +579,4 @@ bpy.types.register(IMAGE_PT_paint_stroke)
bpy.types.register(IMAGE_PT_paint_curve) bpy.types.register(IMAGE_PT_paint_curve)
bpy.types.register(IMAGE_PT_game_properties) bpy.types.register(IMAGE_PT_game_properties)
bpy.types.register(IMAGE_PT_view_properties) bpy.types.register(IMAGE_PT_view_properties)
bpy.types.register(IMAGE_PT_view_histogram)

@ -735,6 +735,7 @@ class USERPREF_PT_theme(bpy.types.Panel):
col = split.column() col = split.column()
col.prop(image, "back") col.prop(image, "back")
col.prop(image, "scope_back")
col.prop(image, "button") col.prop(image, "button")
col = split.column() col = split.column()

@ -31,6 +31,7 @@
struct CurveMapping; struct CurveMapping;
struct CurveMap; struct CurveMap;
struct Histogram;
struct ImBuf; struct ImBuf;
struct rctf; struct rctf;
@ -70,6 +71,7 @@ void curvemapping_initialize(struct CurveMapping *cumap);
void curvemapping_table_RGBA(struct CurveMapping *cumap, float **array, int *size); void curvemapping_table_RGBA(struct CurveMapping *cumap, float **array, int *size);
void colorcorrection_do_ibuf(struct ImBuf *ibuf, const char *profile); void colorcorrection_do_ibuf(struct ImBuf *ibuf, const char *profile);
void histogram_update(struct Histogram *hist, struct ImBuf *ibuf);
#endif #endif

@ -878,3 +878,85 @@ void curvemapping_table_RGBA(CurveMapping *cumap, float **array, int *size)
} }
} }
/* ***************** Histogram **************** */
static inline int get_bin_float(float f)
{
CLAMP(f, 0.0, 1.0);
//return (int) (((f + 0.25) / 1.5) * 512);
return (int)(f * 511);
}
void histogram_update(Histogram *hist, ImBuf *ibuf)
{
int x, y, n;
double div;
float *rf;
unsigned char *rc;
unsigned int *bin_r, *bin_g, *bin_b;
if (hist->ok == 1 ) return;
/* hmmmm */
if (!(ELEM(ibuf->channels, 3, 4))) return;
hist->channels = 3;
bin_r = MEM_callocN(512 * sizeof(unsigned int), "temp historgram bins");
bin_g = MEM_callocN(512 * sizeof(unsigned int), "temp historgram bins");
bin_b = MEM_callocN(512 * sizeof(unsigned int), "temp historgram bins");
if (ibuf->rect_float) {
hist->x_resolution = 512;
/* divide into bins */
rf = ibuf->rect_float;
for (y = 0; y < ibuf->y; y++) {
for (x = 0; x < ibuf->x; x++) {
bin_r[ get_bin_float(rf[0]) ] += 1;
bin_g[ get_bin_float(rf[1]) ] += 1;
bin_b[ get_bin_float(rf[2]) ] += 1;
rf+= ibuf->channels;
}
}
}
else if (ibuf->rect) {
hist->x_resolution = 256;
rc = (unsigned char *)ibuf->rect;
for (y = 0; y < ibuf->y; y++) {
for (x = 0; x < ibuf->x; x++) {
bin_r[ rc[0] ] += 1;
bin_g[ rc[1] ] += 1;
bin_b[ rc[2] ] += 1;
rc += ibuf->channels;
}
}
}
/* convert to float */
n=0;
for (x=0; x<512; x++) {
if (bin_r[x] > n)
n = bin_r[x];
if (bin_g[x] > n)
n = bin_g[x];
if (bin_b[x] > n)
n = bin_b[x];
}
div = 1.f/(double)n;
for (x=0; x<512; x++) {
hist->data_r[x] = bin_r[x] * div;
hist->data_g[x] = bin_g[x] * div;
hist->data_b[x] = bin_b[x] * div;
}
MEM_freeN(bin_r);
MEM_freeN(bin_g);
MEM_freeN(bin_b);
hist->ok=1;
}

@ -216,6 +216,7 @@ typedef struct uiLayout uiLayout;
#define LISTROW (44<<9) #define LISTROW (44<<9)
#define HOTKEYEVT (45<<9) #define HOTKEYEVT (45<<9)
#define BUT_IMAGE (46<<9) #define BUT_IMAGE (46<<9)
#define HISTOGRAM (47<<9)
#define BUTTYPE (63<<9) #define BUTTYPE (63<<9)
@ -654,6 +655,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, struct PointerRNA *ptr);
uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr); uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr);
void uiTemplatePreview(uiLayout *layout, struct ID *id, struct ID *parent, struct MTex *slot); void uiTemplatePreview(uiLayout *layout, struct ID *id, struct ID *parent, struct MTex *slot);
void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand); void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand);
void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand);
void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, char *propname, int type, int levels, int brush); void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, char *propname, int type, int levels, int brush);
void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider); void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider);
void uiTemplateTriColorSet(uiLayout *layout, struct PointerRNA *ptr, char *propname); void uiTemplateTriColorSet(uiLayout *layout, struct PointerRNA *ptr, char *propname);

@ -207,6 +207,8 @@ enum {
TH_DOPESHEET_CHANNELOB, TH_DOPESHEET_CHANNELOB,
TH_DOPESHEET_CHANNELSUBOB, TH_DOPESHEET_CHANNELSUBOB,
TH_PREVIEW_BACK,
}; };
/* XXX WARNING: previous is saved in file, so do not change order! */ /* XXX WARNING: previous is saved in file, so do not change order! */

@ -691,6 +691,87 @@ static void ui_draw_but_CHARTAB(uiBut *but)
#endif // INTERNATIONAL #endif // INTERNATIONAL
#endif #endif
void ui_draw_but_HISTOGRAM(uiBut *but, uiWidgetColors *wcol, rcti *recti)
{
Histogram *hist = (Histogram *)but->poin;
int res = hist->x_resolution;
rctf rect;
int i;
int rgb;
float w, h;
float alpha;
if (hist==NULL) { printf("hist is null \n"); return; }
rect.xmin = (float)recti->xmin;
rect.xmax = (float)recti->xmax;
rect.ymin = (float)recti->ymin;
rect.ymax = (float)recti->ymax;
w = rect.xmax - rect.xmin;
h = rect.ymax - rect.ymin;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0.f, 0.f, 0.f, 0.3f);
uiSetRoundBox(15);
gl_round_box(GL_POLYGON, rect.xmin-1, rect.ymin-1, rect.xmax+1, rect.ymax+1, 3.0f);
glColor4f(1.f, 1.f, 1.f, 0.08f);
/* draw grid lines here */
for (i=1; i<4; i++) {
fdrawline(rect.xmin, rect.ymin+(i/4.f)*h, rect.xmax, rect.ymin+(i/4.f)*h);
fdrawline(rect.xmin+(i/4.f)*w, rect.ymin, rect.xmin+(i/4.f)*w, rect.ymax);
}
for (rgb=0; rgb<3; rgb++) {
float *data;
if (rgb==0) data = hist->data_r;
else if (rgb==1) data = hist->data_g;
else if (rgb==2) data = hist->data_b;
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
alpha = 0.75;
if (rgb==0) glColor4f(1.f, 0.f, 0.f, alpha);
else if (rgb==1) glColor4f(0.f, 1.f, 0.f, alpha);
else if (rgb==2) glColor4f(0.f, 0.f, 1.f, alpha);
glShadeModel(GL_FLAT);
glBegin(GL_QUAD_STRIP);
glVertex2f(rect.xmin, rect.ymin);
glVertex2f(rect.xmin, rect.ymin + (data[0]*h));
for (i=1; i < res; i++) {
float x = rect.xmin + i * (w/(float)res);
glVertex2f(x, rect.ymin + (data[i]*h));
glVertex2f(x, rect.ymin);
}
glEnd();
glColor4f(0.f, 0.f, 0.f, 0.25f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
glBegin(GL_LINE_STRIP);
for (i=0; i < res; i++) {
float x = rect.xmin + i * (w/(float)res);
glVertex2f(x, rect.ymin + (data[i]*h));
}
glEnd();
glDisable(GL_LINE_SMOOTH);
}
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0.f, 0.f, 0.f, 0.5f);
uiSetRoundBox(15);
gl_round_box(GL_LINE_LOOP, rect.xmin-1, rect.ymin-1, rect.xmax+1, rect.ymax+1, 3.0f);
glDisable(GL_BLEND);
}
void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *wcol, rcti *rect) void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *wcol, rcti *rect)
{ {
ColorBand *coba; ColorBand *coba;

@ -751,7 +751,13 @@ static void ui_apply_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data)
static void ui_apply_but_IMAGE(bContext *C, uiBut *but, uiHandleButtonData *data) static void ui_apply_but_IMAGE(bContext *C, uiBut *but, uiHandleButtonData *data)
{ {
ui_apply_but_func(C, but); ui_apply_but_func(C, but);
data->retval= but->retval;
data->applied= 1;
}
static void ui_apply_but_HISTOGRAM(bContext *C, uiBut *but, uiHandleButtonData *data)
{
ui_apply_but_func(C, but);
data->retval= but->retval; data->retval= but->retval;
data->applied= 1; data->applied= 1;
} }
@ -878,6 +884,9 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
case BUT_IMAGE: case BUT_IMAGE:
ui_apply_but_IMAGE(C, but, data); ui_apply_but_IMAGE(C, but, data);
break; break;
case HISTOGRAM:
ui_apply_but_HISTOGRAM(C, but, data);
break;
default: default:
break; break;
} }
@ -3782,6 +3791,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
case ROW: case ROW:
case LISTROW: case LISTROW:
case BUT_IMAGE: case BUT_IMAGE:
case HISTOGRAM:
retval= ui_do_but_EXIT(C, but, data, event); retval= ui_do_but_EXIT(C, but, data, event);
break; break;
case TEX: case TEX:

@ -426,12 +426,12 @@ extern void gl_round_box(int mode, float minx, float miny, float maxx, float max
extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown); extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown);
extern void gl_round_box_vertical_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeLeft, float shadeRight); extern void gl_round_box_vertical_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeLeft, float shadeRight);
void ui_draw_but_HISTOGRAM(uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_COLORBAND(uiBut *but, struct uiWidgetColors *wcol, rcti *rect); void ui_draw_but_COLORBAND(uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_NORMAL(uiBut *but, struct uiWidgetColors *wcol, rcti *rect); void ui_draw_but_NORMAL(uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_CURVE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect); void ui_draw_but_CURVE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect); void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
/* interface_handlers.c */ /* interface_handlers.c */
extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but); extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but);
extern void ui_button_active_cancel(const struct bContext *C, uiBut *but); extern void ui_button_active_cancel(const struct bContext *C, uiBut *but);

@ -108,6 +108,8 @@ static int panel_aligned(ScrArea *sa, ARegion *ar)
return BUT_VERTICAL; return BUT_VERTICAL;
else if(sa->spacetype==SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS) else if(sa->spacetype==SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS)
return BUT_VERTICAL; return BUT_VERTICAL;
else if(sa->spacetype==SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW)
return BUT_VERTICAL;
else if(ELEM3(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS)) else if(ELEM3(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS))
return BUT_VERTICAL; return BUT_VERTICAL;
@ -130,6 +132,8 @@ static int panels_re_align(ScrArea *sa, ARegion *ar, Panel **r_pa)
} }
else if(ar->regiontype==RGN_TYPE_UI) else if(ar->regiontype==RGN_TYPE_UI)
return 1; return 1;
else if(sa->spacetype==SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW)
return 1;
else if(sa->spacetype==SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS) else if(sa->spacetype==SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS)
return 1; return 1;

@ -28,6 +28,7 @@
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
#include "DNA_color_types.h"
#include "DNA_scene_types.h" #include "DNA_scene_types.h"
#include "DNA_screen_types.h" #include "DNA_screen_types.h"
@ -1527,9 +1528,45 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, char *propname, int
MEM_freeN(cb); MEM_freeN(cb);
} }
/********************* Histogram Template ************************/
void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, char *propname, int expand)
{
PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
PointerRNA cptr;
RNAUpdateCb *cb;
uiBlock *block;
uiBut *bt;
Histogram *hist;
rctf rect;
if(!prop || RNA_property_type(prop) != PROP_POINTER)
return;
cptr= RNA_property_pointer_get(ptr, prop);
if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Histogram))
return;
cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
cb->ptr= *ptr;
cb->prop= prop;
rect.xmin= 0; rect.xmax= 200;
rect.ymin= 0; rect.ymax= 190;
block= uiLayoutAbsoluteBlock(layout);
//colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
hist = (Histogram *)cptr.data;
bt= uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, 100.0f, hist, 0, 0, 0, 0, "");
uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
MEM_freeN(cb);
}
/********************* CurveMapping Template ************************/ /********************* CurveMapping Template ************************/
#include "DNA_color_types.h"
#include "BKE_colortools.h" #include "BKE_colortools.h"
static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *unused) static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *unused)

@ -1796,6 +1796,7 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
} }
/* ************ separator, for menus etc ***************** */ /* ************ separator, for menus etc ***************** */
static void ui_draw_separator(uiBut *but, rcti *rect, uiWidgetColors *wcol) static void ui_draw_separator(uiBut *but, rcti *rect, uiWidgetColors *wcol)
{ {
@ -2663,6 +2664,10 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
case BUT_IMAGE: case BUT_IMAGE:
ui_draw_but_IMAGE(ar, but, &tui->wcol_regular, rect); ui_draw_but_IMAGE(ar, but, &tui->wcol_regular, rect);
break; break;
case HISTOGRAM:
ui_draw_but_HISTOGRAM(but, &tui->wcol_regular, rect);
break;
case BUT_CURVE: case BUT_CURVE:
ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect); ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect);

@ -368,7 +368,10 @@ char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_DOPESHEET_CHANNELSUBOB: case TH_DOPESHEET_CHANNELSUBOB:
cp= ts->ds_subchannel; cp= ts->ds_subchannel;
break; break;
case TH_PREVIEW_BACK:
cp= ts->preview_back;
break;
} }
} }
} }
@ -569,6 +572,7 @@ void ui_theme_init_userdef(void)
SETCOL(btheme->tima.face, 255, 255, 255, 10); SETCOL(btheme->tima.face, 255, 255, 255, 10);
SETCOL(btheme->tima.face_select, 255, 133, 0, 60); SETCOL(btheme->tima.face_select, 255, 133, 0, 60);
SETCOL(btheme->tima.editmesh_active, 255, 255, 255, 128); SETCOL(btheme->tima.editmesh_active, 255, 255, 255, 128);
SETCOLF(btheme->tima.preview_back, 0.45, 0.45, 0.45, 1.0);
/* space imageselect */ /* space imageselect */
btheme->timasel= btheme->tv3d; btheme->timasel= btheme->tv3d;

@ -1318,7 +1318,11 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, char *contex
} }
/* clear */ /* clear */
UI_GetThemeColor3fv(TH_BACK, col); if (ar->type->regionid == RGN_TYPE_PREVIEW)
UI_GetThemeColor3fv(TH_PREVIEW_BACK, col);
else
UI_GetThemeColor3fv(TH_BACK, col);
glClearColor(col[0], col[1], col[2], 0.0); glClearColor(col[0], col[1], col[2], 0.0);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);

@ -1036,5 +1036,26 @@ void IMAGE_OT_properties(wmOperatorType *ot)
ot->flag= 0; ot->flag= 0;
} }
static int image_scopes(bContext *C, wmOperator *op)
{
ScrArea *sa= CTX_wm_area(C);
ARegion *ar= image_has_scope_region(sa);
if(ar)
ED_region_toggle_hidden(C, ar);
return OPERATOR_FINISHED;
}
void IMAGE_OT_scopes(wmOperatorType *ot)
{
ot->name= "Scopes";
ot->idname= "IMAGE_OT_scopes";
ot->exec= image_scopes;
ot->poll= ED_operator_image_active;
/* flags */
ot->flag= 0;
}

@ -204,6 +204,16 @@ void draw_image_info(ARegion *ar, int channels, int x, int y, char *cp, float *f
UI_DrawString(10, 10, str); UI_DrawString(10, 10, str);
} }
static inline int get_bin_float(float f)
{
CLAMP(f, 0.0, 1.0);
//return (int) (((f + 0.25) / 1.5) * 512);
return (int)(f * 511);
}
/* image drawing */ /* image drawing */
static void draw_image_grid(ARegion *ar, float zoomx, float zoomy) static void draw_image_grid(ARegion *ar, float zoomx, float zoomy)
@ -702,6 +712,11 @@ void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene)
if(ibuf && ima && show_render) if(ibuf && ima && show_render)
draw_render_info(ima, ar); draw_render_info(ima, ar);
/* histogram */
if (ibuf) {
histogram_update(&sima->hist, ibuf);
}
/* XXX integrate this code */ /* XXX integrate this code */
#if 0 #if 0
if(ibuf) { if(ibuf) {

@ -44,6 +44,7 @@ struct bNodeTree;
/* space_image.c */ /* space_image.c */
struct ARegion *image_has_buttons_region(struct ScrArea *sa); struct ARegion *image_has_buttons_region(struct ScrArea *sa);
struct ARegion *image_has_scope_region(struct ScrArea *sa);
/* image_header.c */ /* image_header.c */
void image_header_buttons(const struct bContext *C, struct ARegion *ar); void image_header_buttons(const struct bContext *C, struct ARegion *ar);
@ -88,6 +89,7 @@ void draw_uvedit_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene
struct ImageUser *ntree_get_active_iuser(struct bNodeTree *ntree); struct ImageUser *ntree_get_active_iuser(struct bNodeTree *ntree);
void image_buttons_register(struct ARegionType *art); void image_buttons_register(struct ARegionType *art);
void IMAGE_OT_properties(struct wmOperatorType *ot); void IMAGE_OT_properties(struct wmOperatorType *ot);
void IMAGE_OT_scopes(struct wmOperatorType *ot);
#endif /* ED_IMAGE_INTERN_H */ #endif /* ED_IMAGE_INTERN_H */

@ -704,7 +704,8 @@ static int open_exec(bContext *C, wmOperator *op)
// XXX other users? // XXX other users?
BKE_image_signal(ima, (sima)? &sima->iuser: NULL, IMA_SIGNAL_RELOAD); BKE_image_signal(ima, (sima)? &sima->iuser: NULL, IMA_SIGNAL_RELOAD);
WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, ima);
MEM_freeN(op->customdata); MEM_freeN(op->customdata);
return OPERATOR_FINISHED; return OPERATOR_FINISHED;

@ -104,6 +104,33 @@ ARegion *image_has_buttons_region(ScrArea *sa)
return arnew; return arnew;
} }
ARegion *image_has_scope_region(ScrArea *sa)
{
ARegion *ar, *arnew;
for(ar= sa->regionbase.first; ar; ar= ar->next)
if(ar->regiontype==RGN_TYPE_PREVIEW)
return ar;
/* add subdiv level; after buttons */
for(ar= sa->regionbase.first; ar; ar= ar->next)
if(ar->regiontype==RGN_TYPE_UI)
break;
/* is error! */
if(ar==NULL) return NULL;
arnew= MEM_callocN(sizeof(ARegion), "scopes for image");
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
arnew->regiontype= RGN_TYPE_PREVIEW;
arnew->alignment= RGN_ALIGN_RIGHT;
arnew->flag = RGN_FLAG_HIDDEN;
return arnew;
}
/* ******************** default callbacks for image space ***************** */ /* ******************** default callbacks for image space ***************** */
static SpaceLink *image_new(const bContext *C) static SpaceLink *image_new(const bContext *C)
@ -135,6 +162,14 @@ static SpaceLink *image_new(const bContext *C)
ar->alignment= RGN_ALIGN_LEFT; ar->alignment= RGN_ALIGN_LEFT;
ar->flag = RGN_FLAG_HIDDEN; ar->flag = RGN_FLAG_HIDDEN;
/* scopes */
ar= MEM_callocN(sizeof(ARegion), "buttons for image");
BLI_addtail(&simage->regionbase, ar);
ar->regiontype= RGN_TYPE_PREVIEW;
ar->alignment= RGN_ALIGN_RIGHT;
ar->flag = RGN_FLAG_HIDDEN;
/* main area */ /* main area */
ar= MEM_callocN(sizeof(ARegion), "main area for image"); ar= MEM_callocN(sizeof(ARegion), "main area for image");
@ -201,6 +236,7 @@ void image_operatortypes(void)
WM_operatortype_append(IMAGE_OT_toolbox); WM_operatortype_append(IMAGE_OT_toolbox);
WM_operatortype_append(IMAGE_OT_properties); WM_operatortype_append(IMAGE_OT_properties);
WM_operatortype_append(IMAGE_OT_scopes);
} }
void image_keymap(struct wmKeyConfig *keyconf) void image_keymap(struct wmKeyConfig *keyconf)
@ -213,6 +249,7 @@ void image_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "IMAGE_OT_save", SKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "IMAGE_OT_save", SKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_save_as", F3KEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "IMAGE_OT_save_as", F3KEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_properties", NKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "IMAGE_OT_properties", NKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_scopes", PKEY, KM_PRESS, 0, 0);
keymap= WM_keymap_find(keyconf, "Image", SPACE_IMAGE, 0); keymap= WM_keymap_find(keyconf, "Image", SPACE_IMAGE, 0);
@ -278,8 +315,16 @@ static void image_refresh(const bContext *C, ScrArea *sa)
} }
} }
static void image_histogram_tag_refresh(ScrArea *sa)
{
SpaceImage *sima= (SpaceImage *)sa->spacedata.first;
sima->hist.ok=0;
}
static void image_listener(ScrArea *sa, wmNotifier *wmn) static void image_listener(ScrArea *sa, wmNotifier *wmn)
{ {
SpaceImage *sima= (SpaceImage *)sa->spacedata.first;
/* context changes */ /* context changes */
switch(wmn->category) { switch(wmn->category) {
case NC_SCENE: case NC_SCENE:
@ -293,7 +338,11 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn)
} }
break; break;
case NC_IMAGE: case NC_IMAGE:
ED_area_tag_redraw(sa); if (wmn->reference == sima->image) {
image_histogram_tag_refresh(sa);
ED_area_tag_refresh(sa);
ED_area_tag_redraw(sa);
}
break; break;
case NC_SPACE: case NC_SPACE:
if(wmn->data == ND_SPACE_IMAGE) if(wmn->data == ND_SPACE_IMAGE)
@ -486,6 +535,31 @@ static void image_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
} }
} }
/* *********************** scopes region ************************ */
/* add handlers, stuff you only do once or on area/region changes */
static void image_scope_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
ED_region_panels_init(wm, ar);
keymap= WM_keymap_find(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void image_scope_area_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar, 1, NULL, -1);
}
static void image_scope_area_listener(ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch(wmn->category) {
}
}
/************************* header region **************************/ /************************* header region **************************/
/* add handlers, stuff you only do once or on area/region changes */ /* add handlers, stuff you only do once or on area/region changes */
@ -541,6 +615,16 @@ void ED_spacetype_image(void)
BLI_addhead(&st->regiontypes, art); BLI_addhead(&st->regiontypes, art);
image_buttons_register(art); image_buttons_register(art);
/* regions: statistics/scope buttons */
art= MEM_callocN(sizeof(ARegionType), "spacetype image region");
art->regionid = RGN_TYPE_PREVIEW;
art->minsizex= 220; // XXX
art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
art->listener= image_scope_area_listener;
art->init= image_scope_area_init;
art->draw= image_scope_area_draw;
BLI_addhead(&st->regiontypes, art);
/* regions: header */ /* regions: header */
art= MEM_callocN(sizeof(ARegionType), "spacetype image region"); art= MEM_callocN(sizeof(ARegionType), "spacetype image region");

@ -80,5 +80,16 @@ typedef struct CurveMapping {
#define CUMA_DRAW_CFRA 4 #define CUMA_DRAW_CFRA 4
#define CUMA_DRAW_SAMPLE 8 #define CUMA_DRAW_SAMPLE 8
typedef struct Histogram {
int channels;
int x_resolution;
float data_r[512];
float data_g[512];
float data_b[512];
float min, max;
int ok;
int pad;
} Histogram;
#endif #endif

@ -32,6 +32,7 @@
#define DNA_SPACE_TYPES_H #define DNA_SPACE_TYPES_H
#include "DNA_listBase.h" #include "DNA_listBase.h"
#include "DNA_color_types.h" /* for Histogram */
#include "DNA_vec_types.h" #include "DNA_vec_types.h"
#include "DNA_outliner_types.h" /* for TreeStoreElem */ #include "DNA_outliner_types.h" /* for TreeStoreElem */
#include "DNA_image_types.h" /* ImageUser */ #include "DNA_image_types.h" /* ImageUser */
@ -43,6 +44,7 @@ struct Text;
struct Script; struct Script;
struct ImBuf; struct ImBuf;
struct Image; struct Image;
struct Histogram;
struct SpaceIpo; struct SpaceIpo;
struct BlendHandle; struct BlendHandle;
struct RenderInfo; struct RenderInfo;
@ -255,6 +257,8 @@ typedef struct SpaceImage {
float centx, centy; /* storage for offset while render drawing */ float centx, centy; /* storage for offset while render drawing */
struct bGPdata *gpd; /* grease pencil data */ struct bGPdata *gpd; /* grease pencil data */
struct Histogram hist; /* viewer histogram */
} SpaceImage; } SpaceImage;
typedef struct SpaceNla { typedef struct SpaceNla {

@ -219,7 +219,7 @@ typedef struct ThemeSpace {
char handle_vertex_size; char handle_vertex_size;
char hpad[3]; char hpad[3];
char pad[4]; char preview_back[4];
} ThemeSpace; } ThemeSpace;

@ -235,6 +235,7 @@ extern StructRNA RNA_GreasePencil;
extern StructRNA RNA_Group; extern StructRNA RNA_Group;
extern StructRNA RNA_Header; extern StructRNA RNA_Header;
extern StructRNA RNA_HemiLamp; extern StructRNA RNA_HemiLamp;
extern StructRNA RNA_Histogram;
extern StructRNA RNA_HookModifier; extern StructRNA RNA_HookModifier;
extern StructRNA RNA_ID; extern StructRNA RNA_ID;
extern StructRNA RNA_IDProperty; extern StructRNA RNA_IDProperty;

@ -229,11 +229,22 @@ static void rna_def_curvemapping(BlenderRNA *brna)
RNA_def_property_float_funcs(prop, NULL, "rna_CurveMapping_white_level_set", NULL); RNA_def_property_float_funcs(prop, NULL, "rna_CurveMapping_white_level_set", NULL);
} }
static void rna_def_histogram(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna= RNA_def_struct(brna, "Histogram", NULL);
RNA_def_struct_ui_text(srna, "Histogram", "Statistical view of the levels of color in an image");
}
void RNA_def_color(BlenderRNA *brna) void RNA_def_color(BlenderRNA *brna)
{ {
rna_def_curvemappoint(brna); rna_def_curvemappoint(brna);
rna_def_curvemap(brna); rna_def_curvemap(brna);
rna_def_curvemapping(brna); rna_def_curvemapping(brna);
rna_def_histogram(brna);
} }
#endif #endif

@ -333,6 +333,19 @@ static void rna_SpaceImageEditor_curves_update(Main *bmain, Scene *scene, Pointe
WM_main_add_notifier(NC_IMAGE, sima->image); WM_main_add_notifier(NC_IMAGE, sima->image);
} }
static void rna_SpaceImageEditor_histogram_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
SpaceImage *sima= (SpaceImage*)ptr->data;
ImBuf *ibuf;
void *lock;
ibuf= ED_space_image_acquire_buffer(sima, &lock);
histogram_update(&sima->hist, ibuf);
ED_space_image_release_buffer(sima, lock);
WM_main_add_notifier(NC_IMAGE, sima->image);
}
/* Space Text Editor */ /* Space Text Editor */
@ -1004,6 +1017,12 @@ static void rna_def_space_image(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "cumap"); RNA_def_property_pointer_sdna(prop, NULL, "cumap");
RNA_def_property_ui_text(prop, "Curves", "Color curve mapping to use for displaying the image."); RNA_def_property_ui_text(prop, "Curves", "Color curve mapping to use for displaying the image.");
RNA_def_property_update(prop, NC_SPACE|ND_SPACE_IMAGE, "rna_SpaceImageEditor_curves_update"); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_IMAGE, "rna_SpaceImageEditor_curves_update");
prop= RNA_def_property(srna, "histogram", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "hist");
RNA_def_property_struct_type(prop, "Histogram");
RNA_def_property_ui_text(prop, "Histogram", "Histogram for viewing image statistics");
RNA_def_property_update(prop, NC_SPACE|ND_SPACE_IMAGE, "rna_SpaceImageEditor_histogram_update");
prop= RNA_def_property(srna, "image_pin", PROP_BOOLEAN, PROP_NONE); prop= RNA_def_property(srna, "image_pin", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "pin", 0); RNA_def_property_boolean_sdna(prop, NULL, "pin", 0);

@ -326,6 +326,10 @@ void RNA_api_ui_layout(StructRNA *srna)
api_ui_item_rna_common(func); api_ui_item_rna_common(func);
RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail."); RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail.");
func= RNA_def_function(srna, "template_histogram", "uiTemplateHistogram");
api_ui_item_rna_common(func);
RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail.");
func= RNA_def_function(srna, "template_layers", "uiTemplateLayers"); func= RNA_def_function(srna, "template_layers", "uiTemplateLayers");
api_ui_item_rna_common(func); api_ui_item_rna_common(func);
parm= RNA_def_pointer(func, "used_layers_data", "AnyType", "", "Data from which to take property."); parm= RNA_def_pointer(func, "used_layers_data", "AnyType", "", "Data from which to take property.");

@ -1202,6 +1202,12 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
RNA_def_property_array(prop, 4); RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Active Vert/Edge/Face", ""); RNA_def_property_ui_text(prop, "Active Vert/Edge/Face", "");
RNA_def_property_update(prop, 0, "rna_userdef_update"); RNA_def_property_update(prop, 0, "rna_userdef_update");
prop= RNA_def_property(srna, "scope_back", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "preview_back");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Scope region background color", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
} }
static void rna_def_userdef_theme_space_seq(BlenderRNA *brna) static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)