diff options
19 files changed, 1168 insertions, 114 deletions
diff --git a/release/scripts/ui/space_image.py b/release/scripts/ui/space_image.py index 1c48b99939d..b29151563d3 100644 --- a/release/scripts/ui/space_image.py +++ b/release/scripts/ui/space_image.py @@ -406,8 +406,43 @@ class IMAGE_PT_view_histogram(bpy.types.Panel): sima = context.space_data - layout.template_histogram(sima, "histogram") + layout.template_histogram(sima.scopes, "histogram") + layout.prop(sima.scopes.histogram, "mode", icon_only=True) +class IMAGE_PT_view_waveform(bpy.types.Panel): + bl_space_type = 'IMAGE_EDITOR' + bl_region_type = 'PREVIEW' + bl_label = "Waveform" + + 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_waveform(sima, "scopes") + sub = layout.row().split(percentage=0.75) + sub.prop(sima.scopes, "waveform_alpha") + sub.prop(sima.scopes, "waveform_mode", text="", icon_only=True) + + +class IMAGE_PT_view_vectorscope(bpy.types.Panel): + bl_space_type = 'IMAGE_EDITOR' + bl_region_type = 'PREVIEW' + bl_label = "Vectorscope" + + 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_vectorscope(sima, "scopes") + layout.prop(sima.scopes, "vectorscope_alpha") class IMAGE_PT_sample_line(bpy.types.Panel): bl_space_type = 'IMAGE_EDITOR' @@ -423,7 +458,26 @@ class IMAGE_PT_sample_line(bpy.types.Panel): layout.operator("image.sample_line") sima = context.space_data layout.template_histogram(sima, "sample_histogram") + layout.prop(sima.sample_histogram, "mode") + +class IMAGE_PT_scope_sample(bpy.types.Panel): + bl_space_type = 'IMAGE_EDITOR' + bl_region_type = 'PREVIEW' + bl_label = "Scope Samples" + + def poll(self, context): + sima = context.space_data + return sima + def draw(self, context): + layout = self.layout + sima = context.space_data + split = layout.split() + row = split.row() + row.prop(sima.scopes, "use_full_resolution") + row = split.row() + row.active = not sima.scopes.use_full_resolution + row.prop(sima.scopes, "accuracy") class IMAGE_PT_view_properties(bpy.types.Panel): bl_space_type = 'IMAGE_EDITOR' @@ -614,7 +668,10 @@ classes = [ IMAGE_PT_game_properties, IMAGE_PT_view_properties, IMAGE_PT_view_histogram, - IMAGE_PT_sample_line] + IMAGE_PT_view_waveform, + IMAGE_PT_view_vectorscope, + IMAGE_PT_sample_line, + IMAGE_PT_scope_sample] def register(): diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index dca8ccb6dbf..f78389fe4de 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -31,7 +31,7 @@ struct CurveMapping; struct CurveMap; -struct Histogram; +struct Scopes; struct ImBuf; struct rctf; @@ -74,7 +74,8 @@ void curvemapping_initialize(struct CurveMapping *cumap); void curvemapping_table_RGBA(struct CurveMapping *cumap, float **array, int *size); void colorcorrection_do_ibuf(struct ImBuf *ibuf, const char *profile); -void histogram_update(struct Histogram *hist, struct ImBuf *ibuf); +void scopes_update(struct Scopes *scopes, struct ImBuf *ibuf, int use_color_management); +void scopes_free(struct Scopes *scopes); #endif diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 4c0c10c127a..2da527d467a 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -885,6 +885,8 @@ void curvemapping_table_RGBA(CurveMapping *cumap, float **array, int *size) /* ***************** Histogram **************** */ +#define INV_255 (1.f/255.f) + DO_INLINE int get_bin_float(float f) { int bin= (int)(f*255); @@ -897,59 +899,219 @@ DO_INLINE int get_bin_float(float f) return bin; } +DO_INLINE void save_sample_line(Scopes *scopes, const int idx, const float fx, float *rgb, float *ycc, float *ycc709) +{ + switch (scopes->wavefrm_mode) { + case SCOPES_WAVEFRM_RGB: + scopes->waveform_1[idx + 0] = fx; + scopes->waveform_1[idx + 1] = rgb[0]; + scopes->waveform_2[idx + 0] = fx; + scopes->waveform_2[idx + 1] = rgb[1]; + scopes->waveform_3[idx + 0] = fx; + scopes->waveform_3[idx + 1] = rgb[2]; + break; + case SCOPES_WAVEFRM_LUM: + scopes->waveform_1[idx + 0] = fx; + scopes->waveform_1[idx + 1] = 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2]; + break; + case SCOPES_WAVEFRM_YCC_JPEG: + scopes->waveform_1[idx + 0] = fx; + scopes->waveform_1[idx + 1] = ycc[0] * INV_255; + scopes->waveform_2[idx + 0] = fx; + scopes->waveform_2[idx + 1] = ycc[1] * INV_255; + scopes->waveform_3[idx + 0] = fx; + scopes->waveform_3[idx + 1] = ycc[2] * INV_255; + break; + case SCOPES_WAVEFRM_YCC_709: + scopes->waveform_1[idx + 0] = fx; + scopes->waveform_1[idx + 1] = ycc709[0] * INV_255; + scopes->waveform_2[idx + 0] = fx; + scopes->waveform_2[idx + 1] = ycc709[1] * INV_255; + scopes->waveform_3[idx + 0] = fx; + scopes->waveform_3[idx + 1] = ycc709[2] * INV_255; + break; + case SCOPES_WAVEFRM_YCC_601: + { + float ycc601[3]; + rgb_to_ycc(rgb[0], rgb[1], rgb[2], &ycc601[0], &ycc601[1], &ycc601[2], BLI_YCC_ITU_BT601); + scopes->waveform_1[idx + 0] = fx; + scopes->waveform_1[idx + 1] = ycc601[0] * INV_255; + scopes->waveform_2[idx + 0] = fx; + scopes->waveform_2[idx + 1] = ycc601[1] * INV_255; + scopes->waveform_3[idx + 0] = fx; + scopes->waveform_3[idx + 1] = ycc601[2] * INV_255; + } + break; + } +} -void histogram_update(Histogram *hist, ImBuf *ibuf) +void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) { - int x, y, n; - double div; - float *rf; - unsigned char *rc; - unsigned int *bin_r, *bin_g, *bin_b; - - if (hist->ok == 1 ) return; - - if (hist->xmax == 0.f) hist->xmax = 1.f; - if (hist->ymax == 0.f) hist->ymax = 1.f; - + int x, y, c, n, nl; + double div, divl; + float *rf, *drf; + unsigned char *rc, *drc; + unsigned int *bin_r, *bin_g, *bin_b, *bin_lum; + int savedlines, saveline; + float rgb[3], ycc[3], ycc709[3]; + + if (scopes->ok == 1 ) return; + + if (scopes->hist.ymax == 0.f) scopes->hist.ymax = 1.f; + /* hmmmm */ if (!(ELEM(ibuf->channels, 3, 4))) return; - - hist->channels = 3; - + scopes->hist.channels = 3; + scopes->hist.x_resolution = 256; + + /* temp table to count pix value for histo */ bin_r = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); bin_g = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); bin_b = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); + bin_lum = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); + + /* convert to number of lines with logarithmic scale */ + scopes->sample_lines = (scopes->accuracy*0.01) * (scopes->accuracy*0.01) * ibuf->y; + + if (scopes->sample_full) + scopes->sample_lines = ibuf->y; + + if( scopes->samples_ibuf) { + IMB_freeImBuf(scopes->samples_ibuf); + scopes->samples_ibuf=NULL; + } + /* scan the image */ + savedlines=0; + for (c=0; c<3; c++) { + scopes->rgbminmax[c][0]=100.0f; + scopes->rgbminmax[c][1]=-100.0f; + scopes->yccminmax[c][0]=25500.0f; + scopes->yccminmax[c][1]=-25500.0f; + scopes->ycc709minmax[c][0]=25500.0f; + scopes->ycc709minmax[c][1]=-25500.0f; + } + + scopes->waveform_tot = ibuf->x*scopes->sample_lines; + + if (scopes->waveform_1) + MEM_freeN(scopes->waveform_1); + if (scopes->waveform_2) + MEM_freeN(scopes->waveform_2); + if (scopes->waveform_3) + MEM_freeN(scopes->waveform_3); + + scopes->waveform_1= MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 1"); + scopes->waveform_2= MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 2"); + scopes->waveform_3= MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 3"); if (ibuf->rect_float) { - hist->x_resolution = 256; - - /* divide into bins */ + scopes->samples_ibuf = IMB_allocImBuf(ibuf->x, scopes->sample_lines, 32, IB_rectfloat, 0 ); rf = ibuf->rect_float; + drf= scopes->samples_ibuf->rect_float; + for (y = 0; y < ibuf->y; y++) { + if (savedlines<scopes->sample_lines && y>=((savedlines)*ibuf->y)/(scopes->sample_lines+1)) { + saveline=1; + } else saveline=0; 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; + + if (use_color_management) + linearrgb_to_srgb_v3_v3(rgb, rf); + else + copy_v3_v3(rgb, rf); + + rgb_to_ycc(rgb[0],rgb[1],rgb[2],&ycc[0],&ycc[1],&ycc[2],BLI_YCC_JFIF_0_255); + rgb_to_ycc(rgb[0],rgb[1],rgb[2],&ycc709[0],&ycc709[1],&ycc709[2],BLI_YCC_ITU_BT709); + + /* check for min max */ + for (c=0; c<3; c++) { + if (rgb[c] < scopes->rgbminmax[c][0]) scopes->rgbminmax[c][0] = rgb[c]; + if (rgb[c] > scopes->rgbminmax[c][1]) scopes->rgbminmax[c][1] = rgb[c]; + if (ycc[c] < scopes->yccminmax[c][0]) scopes->yccminmax[c][0] = ycc[c]; + if (ycc[c] > scopes->yccminmax[c][1]) scopes->yccminmax[c][1] = ycc[c]; + if (ycc709[c] < scopes->ycc709minmax[c][0]) scopes->ycc709minmax[c][0] = ycc709[c]; + if (ycc709[c] > scopes->ycc709minmax[c][1]) scopes->ycc709minmax[c][1] = ycc709[c]; + } + /* increment count for histo*/ + bin_r[ get_bin_float(rgb[0]) ] += 1; + bin_g[ get_bin_float(rgb[1]) ] += 1; + bin_b[ get_bin_float(rgb[2]) ] += 1; + bin_lum[ get_bin_float(ycc[0] * INV_255) ] += 1; + + /* save sample if needed */ + if(saveline) { + const float fx = (float)x / (float)ibuf->x; + const int idx = 2*(ibuf->x*savedlines+x); + + save_sample_line(scopes, idx, fx, rgb, ycc, ycc709); + + drf[0]=rgb[0]; + drf[1]=rgb[1]; + drf[2]=rgb[2]; + drf+= scopes->samples_ibuf->channels; + } rf+= ibuf->channels; } + if (saveline) + savedlines +=1; } + } else if (ibuf->rect) { - hist->x_resolution = 256; - + scopes->samples_ibuf = IMB_allocImBuf(ibuf->x, scopes->sample_lines, 32, IB_rect, 0 ); rc = (unsigned char *)ibuf->rect; + drc= (unsigned char *) scopes->samples_ibuf->rect; + for (y = 0; y < ibuf->y; y++) { + if (savedlines<scopes->sample_lines && y>=((savedlines)*ibuf->y)/(scopes->sample_lines+1)) { + saveline=1; + } else saveline=0; + for (x = 0; x < ibuf->x; x++) { + + for (c=0; c<3; c++) + rgb[c] = rc[c] * INV_255; + rgb_to_ycc(rgb[0],rgb[1],rgb[2],&ycc[0],&ycc[1],&ycc[2],BLI_YCC_JFIF_0_255); + rgb_to_ycc(rgb[0],rgb[1],rgb[2],&ycc709[0],&ycc709[1],&ycc709[2],BLI_YCC_ITU_BT709); + + /* check for min max */ + for (c=0; c<3; c++) { + if (rgb[c] < scopes->rgbminmax[c][0]) scopes->rgbminmax[c][0] = rgb[c]; + if (rgb[c] > scopes->rgbminmax[c][1]) scopes->rgbminmax[c][1] = rgb[c]; + if (ycc[c] < scopes->yccminmax[c][0]) scopes->yccminmax[c][0] = ycc[c]; + if (ycc[c] > scopes->yccminmax[c][1]) scopes->yccminmax[c][1] = ycc[c]; + if (ycc709[c] < scopes->ycc709minmax[c][0]) scopes->ycc709minmax[c][0] = ycc709[c]; + if (ycc709[c] > scopes->ycc709minmax[c][1]) scopes->ycc709minmax[c][1] = ycc709[c]; + } + + /* increment count for histo */ bin_r[ rc[0] ] += 1; bin_g[ rc[1] ] += 1; bin_b[ rc[2] ] += 1; + bin_lum[ get_bin_float(ycc[0] * INV_255) ] += 1; + + /* save sample if needed */ + if(saveline) { + const float fx = (float)x / (float)ibuf->x; + const int idx = 2*(ibuf->x*savedlines+x); + + save_sample_line(scopes, idx, fx, rgb, ycc, ycc709); + + drc[0]=rc[0]; + drc[1]=rc[1]; + drc[2]=rc[2]; + drc+= 4; + } rc += ibuf->channels; } + if (saveline) + savedlines +=1; } } - - /* convert to float */ + + /* convert hist data to float (proportional to max count) */ n=0; + nl=0; for (x=0; x<256; x++) { if (bin_r[x] > n) n = bin_r[x]; @@ -957,17 +1119,42 @@ void histogram_update(Histogram *hist, ImBuf *ibuf) n = bin_g[x]; if (bin_b[x] > n) n = bin_b[x]; + if (bin_lum[x] > nl) + nl = bin_lum[x]; } div = 1.f/(double)n; + divl = 1.f/(double)nl; for (x=0; x<256; 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; + scopes->hist.data_r[x] = bin_r[x] * div; + scopes->hist.data_g[x] = bin_g[x] * div; + scopes->hist.data_b[x] = bin_b[x] * div; + scopes->hist.data_luma[x] = bin_lum[x] * divl; } - MEM_freeN(bin_r); MEM_freeN(bin_g); MEM_freeN(bin_b); - - hist->ok=1; + MEM_freeN(bin_lum); + + scopes->ok = 1; } + +void scopes_free(Scopes *scopes) +{ + if (scopes->waveform_1) { + MEM_freeN(scopes->waveform_1); + scopes->waveform_1 = NULL; + } + if (scopes->waveform_2) { + MEM_freeN(scopes->waveform_2); + scopes->waveform_2 = NULL; + } + if (scopes->waveform_3) { + MEM_freeN(scopes->waveform_3); + scopes->waveform_3 = NULL; + } + + if( scopes->samples_ibuf) { + IMB_freeImBuf(scopes->samples_ibuf); + scopes->samples_ibuf=NULL; + } +}
\ No newline at end of file diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 6aa85d14084..6637d74dbb1 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -110,7 +110,7 @@ void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb) } /* The RGB inputs are supposed gamma corrected and in the range 0 - 1.0f */ -/* Output YCC have a range of 16-235 and 16-240 exepect with JFIF_0_255 where the range is 0-255 */ +/* Output YCC have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */ void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace) { float sr,sg, sb; @@ -132,7 +132,7 @@ void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, in cr=(0.439f*sr)-(0.399f*sg)-(0.040f*sb)+128.0f; break; case BLI_YCC_JFIF_0_255 : - y=(0.299f*sr)+(0.587f*sg)+(0.114f*sb)+16.0f; + y=(0.299f*sr)+(0.587f*sg)+(0.114f*sb); cb=(-0.16874f*sr)-(0.33126f*sg)+(0.5f*sb)+128.0f; cr=(0.5f*sr)-(0.41869f*sg)-(0.08131f*sb)+128.0f; break; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 1f6d36dc957..6dcfb7f0ec7 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4836,6 +4836,9 @@ void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene) SpaceImage *sima= (SpaceImage *)sl; sima->image= restore_pointer_by_name(newmain, (ID *)sima->image, 1); + + sima->scopes.samples_ibuf = NULL; + sima->scopes.ok = 0; /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data * so assume that here we're doing for undo only... @@ -5108,6 +5111,8 @@ static void direct_link_screen(FileData *fd, bScreen *sc) sima->iuser.scene= NULL; sima->iuser.ok= 1; + sima->scopes.samples_ibuf = NULL; + sima->scopes.ok = 0; /* WARNING: gpencil data is no longer stored directly in sima after 2.5 * so sacrifice a few old files for now to avoid crashes with new files! @@ -10731,7 +10736,26 @@ static void do_versions(FileData *fd, Library *lib, Main *main) /* put 2.50 compatibility code here until next subversion bump */ { + bScreen *sc; + /* Image editor scopes */ + for(sc= main->screen.first; sc; sc= sc->id.next) { + ScrArea *sa; + for(sa= sc->areabase.first; sa; sa= sa->next) { + SpaceLink *sl; + for (sl= sa->spacedata.first; sl; sl= sl->next) { + if(sl->spacetype==SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)sl; + sima->scopes.accuracy = 30.0; + sima->scopes.hist.mode=HISTO_MODE_RGB; + sima->scopes.wavefrm_alpha=0.3; + sima->scopes.vecscope_alpha=0.3; + sima->scopes.wavefrm_height= 100; + sima->scopes.hist.height= 100; + } + } + } + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index dfc89ea16df..110f69d7f02 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -218,6 +218,8 @@ typedef struct uiLayout uiLayout; #define HOTKEYEVT (45<<9) #define BUT_IMAGE (46<<9) #define HISTOGRAM (47<<9) +#define WAVEFORM (48<<9) +#define VECTORSCOPE (49<<9) #define BUTTYPE (63<<9) @@ -676,6 +678,8 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr); 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 uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand); +void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand); +void uiTemplateVectorscope(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 uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider, int lock); void uiTemplateTriColorSet(uiLayout *layout, struct PointerRNA *ptr, char *propname); diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 893c479c7e9..574bb87f963 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -35,6 +35,7 @@ #include "BLI_math.h" #include "BKE_colortools.h" +#include "BKE_global.h" #include "BKE_texture.h" #include "BKE_utildefines.h" @@ -44,6 +45,8 @@ #include "BIF_gl.h" #include "BIF_glutil.h" +#include "BLF_api.h" + #include "UI_interface.h" #include "interface_intern.h" @@ -685,6 +688,38 @@ static void ui_draw_but_CHARTAB(uiBut *but) #endif // INTERNATIONAL #endif +void histogram_draw_one(float r, float g, float b, float alpha, float x, float y, float w, float h, float *data, int res) +{ + int i; + + /* under the curve */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glColor4f(r, g, b, alpha); + + glShadeModel(GL_FLAT); + glBegin(GL_QUAD_STRIP); + glVertex2f(x, y); + glVertex2f(x, y + (data[0]*h)); + for (i=1; i < res; i++) { + float x2 = x + i * (w/(float)res); + glVertex2f(x2, y + (data[i]*h)); + glVertex2f(x2, y); + } + glEnd(); + + /* curve outline */ + 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 x2 = x + i * (w/(float)res); + glVertex2f(x2, y + (data[i]*h)); + } + glEnd(); + glDisable(GL_LINE_SMOOTH); +} void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti *recti) { @@ -692,10 +727,9 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti * int res = hist->x_resolution; rctf rect; int i; - int rgb; float w, h; float scaler_x1, scaler_x2; - float alpha; + //float alpha; GLint scissor[4]; if (hist==NULL) { printf("hist is null \n"); return; } @@ -726,43 +760,410 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti * /* need scissor test, histogram can draw outside of boundary */ glGetIntegerv(GL_VIEWPORT, scissor); glScissor(ar->winrct.xmin + (rect.xmin-1), ar->winrct.ymin+(rect.ymin-1), (rect.xmax+1)-(rect.xmin-1), (rect.ymax+1)-(rect.ymin-1)); + + if (hist->mode == HISTO_MODE_LUMA) + histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res); + else { + if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_R) + histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res); + if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_G) + histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res); + if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_B) + histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res); + } + /* restore scissortest */ + glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); + + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + + /* height scaling widget */ + scaler_x1 = rect.xmin + w/2 - SCOPE_RESIZE_PAD; + scaler_x2 = rect.xmin + w/2 + SCOPE_RESIZE_PAD; + + glColor4f(0.f, 0.f, 0.f, 0.25f); + fdrawline(scaler_x1, rect.ymin-4, scaler_x2, rect.ymin-4); + fdrawline(scaler_x1, rect.ymin-7, scaler_x2, rect.ymin-7); + glColor4f(1.f, 1.f, 1.f, 0.25f); + fdrawline(scaler_x1, rect.ymin-5, scaler_x2, rect.ymin-5); + fdrawline(scaler_x1, rect.ymin-8, scaler_x2, rect.ymin-8); + + glColor4f(0.f, 0.f, 0.f, 0.5f); + uiSetRoundBox(15); + gl_round_box(GL_LINE_LOOP, rect.xmin-1, rect.ymin, rect.xmax+1, rect.ymax+1, 3.0f); + + glDisable(GL_BLEND); +} + +void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti *recti) +{ + Scopes *scopes = (Scopes *)but->poin; + rctf rect; + int i, c; + float w, w3, h, alpha, yofs; + GLint scissor[4]; + float colors[3][3] = {{1,0,0},{0,1,0},{0,0,1}}; + float colorsycc[3][3] = {{1,0,1},{1,1,0},{0,1,1}}; + float colors_alpha[3][3], colorsycc_alpha[3][3]; /* colors pre multiplied by alpha for speed up */ + float min, max; + float scaler_x1, scaler_x2; + + if (scopes==NULL || scopes->samples_ibuf==NULL) return; + + rect.xmin = (float)recti->xmin+1; + rect.xmax = (float)recti->xmax-1; + rect.ymin = (float)recti->ymin+SCOPE_RESIZE_PAD+2; + rect.ymax = (float)recti->ymax-1; + + if (scopes->wavefrm_yfac < 0.5f ) + scopes->wavefrm_yfac =1.0f; + w = rect.xmax - rect.xmin-7; + h = (rect.ymax - rect.ymin)/scopes->wavefrm_yfac; + yofs= rect.ymin + (rect.ymax - rect.ymin -h)/2.0f; + w3=w/3.0f; + + /* log scale for alpha */ + alpha = scopes->wavefrm_alpha*scopes->wavefrm_alpha; + + for(c=0; c<3; c++) { + for(i=0; i<3; i++) { + colors_alpha[c][i] = colors[c][i] * alpha; + colorsycc_alpha[c][i] = colorsycc[c][i] * alpha; + } + } + + 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); + + + /* need scissor test, histogram can draw outside of boundary */ + glGetIntegerv(GL_VIEWPORT, scissor); + glScissor(ar->winrct.xmin + (rect.xmin-1), ar->winrct.ymin+(rect.ymin-1), (rect.xmax+1)-(rect.xmin-1), (rect.ymax+1)-(rect.ymin-1)); + + glColor4f(1.f, 1.f, 1.f, 0.08f); + /* draw grid lines here */ + for (i=0; i<6; i++) { + char str[4]; + sprintf(str,"%-3d",i*20); + str[3]='\0'; + fdrawline(rect.xmin+22, yofs+(i/5.f)*h, rect.xmax+1, yofs+(i/5.f)*h); + BLF_draw_default(rect.xmin+1, yofs-5+(i/5.f)*h, 0, str); + /* in the loop because blf_draw reset it */ + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + } + /* 3 vertical separation */ + if (scopes->wavefrm_mode!= SCOPES_WAVEFRM_LUM) { + for (i=1; i<3; i++) { + fdrawline(rect.xmin+i*w3, rect.ymin, rect.xmin+i*w3, rect.ymax); + } + } + /* separate min max zone on the right */ + fdrawline(rect.xmin+w, rect.ymin, rect.xmin+w, rect.ymax); + /* 16-235-240 level in case of ITU-R BT601/709 */ + glColor4f(1.f, 0.4f, 0.f, 0.2f); + if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)){ + fdrawline(rect.xmin+22, yofs+h*16.0f/255.0f, rect.xmax+1, yofs+h*16.0f/255.0f); + fdrawline(rect.xmin+22, yofs+h*235.0f/255.0f, rect.xmin+w3, yofs+h*235.0f/255.0f); + fdrawline(rect.xmin+3*w3, yofs+h*235.0f/255.0f, rect.xmax+1, yofs+h*235.0f/255.0f); + fdrawline(rect.xmin+w3, yofs+h*240.0f/255.0f, rect.xmax+1, yofs+h*240.0f/255.0f); + } + + + /* LUMA (1 channel) */ + glBlendFunc(GL_ONE,GL_ONE); + glColor3f(alpha, alpha, alpha); + if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUM){ + + glBlendFunc(GL_ONE,GL_ONE); - for (rgb=0; rgb<3; rgb++) { - float *data = NULL; + glPushMatrix(); - if (rgb==0) data = hist->data_r; - else if (rgb==1) data = hist->data_g; - else if (rgb==2) data = hist->data_b; + glEnableClientState(GL_VERTEX_ARRAY); - 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); + glTranslatef(rect.xmin, yofs, 0.f); + glScalef(w, h, 0.f); - 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(); + glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); + glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + + glDisableClientState(GL_VERTEX_ARRAY); + + glPopMatrix(); + + /* min max */ + glColor3f(.5f, .5f, .5f); + min= yofs+scopes->yccminmax[0][0]*h/255.0f; + max= yofs+scopes->yccminmax[0][1]*h/255.0f; + CLAMP(min, rect.ymin, rect.ymax); + CLAMP(max, rect.ymin, rect.ymax); + fdrawline(rect.xmax-3,min,rect.xmax-3,max); + } + + /* RGB / YCC (3 channels) */ + else if (ELEM4(scopes->wavefrm_mode, SCOPES_WAVEFRM_RGB, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709, SCOPES_WAVEFRM_YCC_JPEG)) { + int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB); + + glBlendFunc(GL_ONE,GL_ONE); - glColor4f(0.f, 0.f, 0.f, 0.25f); + glPushMatrix(); + + glEnableClientState(GL_VERTEX_ARRAY); + + glTranslatef(rect.xmin, yofs, 0.f); + glScalef(w3, h, 0.f); + + glColor3fv((rgb)?colors_alpha[0]:colorsycc_alpha[0]); + + glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); + glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + + glTranslatef(1.f, 0.f, 0.f); + glColor3fv((rgb)?colors_alpha[1]:colorsycc_alpha[1]); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_LINE_SMOOTH); + glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2); + glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + + glTranslatef(1.f, 0.f, 0.f); + glColor3fv((rgb)?colors_alpha[2]:colorsycc_alpha[2]); + + glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3); + glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + + glDisableClientState(GL_VERTEX_ARRAY); + + glPopMatrix(); + + + /* min max */ + if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) { + for (c=0; c<3; c++) { + glColor3f(colors[c][0]*0.75, colors[c][1]*0.75, colors[c][2]*0.75); + min= yofs+scopes->rgbminmax[c][0]*h; + max= yofs+scopes->rgbminmax[c][1]*h; + CLAMP(min, rect.ymin, rect.ymax); + CLAMP(max, rect.ymin, rect.ymax); + fdrawline(rect.xmin+w+2+c*2,min,rect.xmin+w+2+c*2,max); + } + } else { + if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_JPEG)) { + for (c=0; c<3; c++) { + glColor3f(colorsycc[c][0]*0.75, colorsycc[c][1]*0.75, colorsycc[c][2]*0.75); + /* we get ITU 601 min max from remapping JPEG*/ + if (scopes->wavefrm_mode== SCOPES_WAVEFRM_YCC_601) { + if(c==0) { + min= yofs+(16+(219*scopes->yccminmax[c][0]/255))*h/255.0f; + max= yofs+(16+(219*scopes->yccminmax[c][1]/255))*h/255.0f; + } + else { + min= yofs+(16+(224*scopes->yccminmax[c][0]/255))*h/255.0f; + max= yofs+(16+(224*scopes->yccminmax[c][1]/255))*h/255.0f; + } + } + /* rescale ycc to 0-1*/ + else { + min= yofs+scopes->yccminmax[c][0]*h/255.0f; + max= yofs+scopes->yccminmax[c][1]*h/255.0f; + } + CLAMP(min, rect.ymin, rect.ymax); + CLAMP(max, rect.ymin, rect.ymax); + fdrawline(rect.xmin+2+w+c*2,min,rect.xmin+2+w+c*2,max); + } + } + else if (scopes->wavefrm_mode== SCOPES_WAVEFRM_YCC_709) { + for (c=0; c<3; c++) { + glColor3f(colorsycc[c][0]*0.75, colorsycc[c][1]*0.75, colorsycc[c][2]*0.75); + min= yofs+scopes->ycc709minmax[c][0]*h/255.0f; + max= yofs+scopes->ycc709minmax[c][1]*h/255.0f; + CLAMP(min, rect.ymin, rect.ymax); + CLAMP(max, rect.ymin, rect.ymax); + fdrawline(rect.xmin+2+w+c*2,min,rect.xmin+2+w+c*2,max); + } + } + } + } + + /* restore scissortest */ + glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); + + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + + /* height scaling widget */ + scaler_x1 = rect.xmin + w/2 - SCOPE_RESIZE_PAD; + scaler_x2 = rect.xmin + w/2 + SCOPE_RESIZE_PAD; + + glColor4f(0.f, 0.f, 0.f, 0.25f); + fdrawline(scaler_x1, rect.ymin-4, scaler_x2, rect.ymin-4); + fdrawline(scaler_x1, rect.ymin-7, scaler_x2, rect.ymin-7); + glColor4f(1.f, 1.f, 1.f, 0.25f); + fdrawline(scaler_x1, rect.ymin-5, scaler_x2, rect.ymin-5); + fdrawline(scaler_x1, rect.ymin-8, scaler_x2, rect.ymin-8); + + 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); +} + +float polar_to_x(float center, float diam, float ampli, float angle) +{ + return center + diam * ampli * cosf(angle); +} + +float polar_to_y(float center, float diam, float ampli, float angle) +{ + return center + diam * ampli * sinf(angle); +} + +void vectorscope_draw_target(float centerx, float centery, float diam, float r, float g, float b) +{ + float y,u,v; + float tangle, tampli; + float dangle, dampli, dangle2, dampli2; + + rgb_to_yuv(r,g,b, &y, &u, &v); + if (u>0 && v>=0) tangle=atanf(v/u); + else if (u>0 && v<0) tangle=atanf(v/u)+2*M_PI; + else if (u<0) tangle=atanf(v/u)+M_PI; + else if (u==0 && v>0) tangle=M_PI/2.0f; + else if (u==0 && v<0) tangle=-M_PI/2.0f; + tampli= sqrtf(u*u+v*v); + + /* small target vary by 2.5 degree and 2.5 IRE unit */ + glColor4f(1.0f, 1.0f, 1.0, 0.12f); + dangle= 2.5*M_PI/180.0f; + dampli= 2.5f/200.0f; + glBegin(GL_LINE_STRIP); + glVertex2f(polar_to_x(centerx,diam,tampli+dampli,tangle+dangle), polar_to_y(centery,diam,tampli+dampli,tangle+dangle)); + glVertex2f(polar_to_x(centerx,diam,tampli-dampli,tangle+dangle), polar_to_y(centery,diam,tampli-dampli,tangle+dangle)); + glVertex2f(polar_to_x(centerx,diam,tampli-dampli,tangle-dangle), polar_to_y(centery,diam,tampli-dampli,tangle-dangle)); + glVertex2f(polar_to_x(centerx,diam,tampli+dampli,tangle-dangle), polar_to_y(centery,diam,tampli+dampli,tangle-dangle)); + glVertex2f(polar_to_x(centerx,diam,tampli+dampli,tangle+dangle), polar_to_y(centery,diam,tampli+dampli,tangle+dangle)); + glEnd(); + /* big target vary by 10 degree and 20% amplitude */ + glColor4f(1.0f, 1.0f, 1.0, 0.12f); + dangle= 10*M_PI/180.0f; + dampli= 0.2*tampli; + dangle2= 5.0f*M_PI/180.0f; + dampli2= 0.5f*dampli; + glBegin(GL_LINE_STRIP); + glVertex2f(polar_to_x(centerx,diam,tampli+dampli-dampli2,tangle+dangle), polar_to_y(centery,diam,tampli+dampli-dampli2,tangle+dangle)); + glVertex2f(polar_to_x(centerx,diam,tampli+dampli,tangle+dangle), polar_to_y(centery,diam,tampli+dampli,tangle+dangle)); + glVertex2f(polar_to_x(centerx,diam,tampli+dampli,tangle+dangle-dangle2), polar_to_y(centery,diam,tampli+dampli,tangle+dangle-dangle2)); + glEnd(); + glBegin(GL_LINE_STRIP); + glVertex2f(polar_to_x(centerx,diam,tampli-dampli+dampli2,tangle+dangle), polar_to_y(centery ,diam,tampli-dampli+dampli2,tangle+dangle)); + glVertex2f(polar_to_x(centerx,diam,tampli-dampli,tangle+dangle), polar_to_y(centery,diam,tampli-dampli,tangle+dangle)); + glVertex2f(polar_to_x(centerx,diam,tampli-dampli,tangle+dangle-dangle2), polar_to_y(centery,diam,tampli-dampli,tangle+dangle-dangle2)); + glEnd(); + glBegin(GL_LINE_STRIP); + glVertex2f(polar_to_x(centerx,diam,tampli-dampli+dampli2,tangle-dangle), polar_to_y(centery,diam,tampli-dampli+dampli2,tangle-dangle)); + glVertex2f(polar_to_x(centerx,diam,tampli-dampli,tangle-dangle), polar_to_y(centery,diam,tampli-dampli,tangle-dangle)); + glVertex2f(polar_to_x(centerx,diam,tampli-dampli,tangle-dangle+dangle2), polar_to_y(centery,diam,tampli-dampli,tangle-dangle+dangle2)); + glEnd(); + glBegin(GL_LINE_STRIP); + glVertex2f(polar_to_x(centerx,diam,tampli+dampli-dampli2,tangle-dangle), polar_to_y(centery,diam,tampli+dampli-dampli2,tangle-dangle)); + glVertex2f(polar_to_x(centerx,diam,tampli+dampli,tangle-dangle), polar_to_y(centery,diam,tampli+dampli,tangle-dangle)); + glVertex2f(polar_to_x(centerx,diam,tampli+dampli,tangle-dangle+dangle2), polar_to_y(centery,diam,tampli+dampli,tangle-dangle+dangle2)); + glEnd(); +} + +void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti *recti) +{ + Scopes *scopes = (Scopes *)but->poin; + rctf rect; + int i, j, x, y; + int skina= 123; /* angle in degree of the skin tone line */ + float w, h, centerx, centery, diam; + float alpha; + float colors[6][3]={{.75,0,0},{.75,.75,0},{0,.75,0},{0,.75,.75},{0,0,.75},{.75,0,.75}}; + unsigned char *rc; + float *rf; + GLint scissor[4]; + float u, v; + float scaler_x1, scaler_x2; + + if (scopes==NULL || scopes->samples_ibuf==NULL) return; + + rect.xmin = (float)recti->xmin+1; + rect.xmax = (float)recti->xmax-1; + rect.ymin = (float)recti->ymin+SCOPE_RESIZE_PAD+2; + rect.ymax = (float)recti->ymax-1; + + w = rect.xmax - rect.xmin; + h = rect.ymax - rect.ymin; + centerx = rect.xmin + w/2; + centery = rect.ymin + h/2; + diam= h; + if (w<diam) diam=w; + + alpha = scopes->vecscope_alpha*scopes->vecscope_alpha*scopes->vecscope_alpha; + + 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); + + /* need scissor test, hvectorscope can draw outside of boundary */ + glGetIntegerv(GL_VIEWPORT, scissor); + glScissor(ar->winrct.xmin + (rect.xmin-1), ar->winrct.ymin+(rect.ymin-1), (rect.xmax+1)-(rect.xmin-1), (rect.ymax+1)-(rect.ymin-1)); + + glColor4f(1.f, 1.f, 1.f, 0.08f); + /* draw grid elements */ + /* cross */ + fdrawline(centerx - (diam/2)-5, centery, centerx + (diam/2)+5, centery); + fdrawline(centerx, centery - (diam/2)-5, centerx, centery + (diam/2)+5); + /* circles */ + for(j=0; j<5; j++) { 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)); + for(i=0; i<=360; i=i+15) { + float a= i*M_PI/180.0; + float r= (j+1)/10.0f; + glVertex2f( polar_to_x(centerx,diam,r,a), polar_to_y(centery,diam,r,a)); } glEnd(); - glDisable(GL_LINE_SMOOTH); } + /* skin tone line */ + glColor4f(1.f, 0.4f, 0.f, 0.2f); + fdrawline( polar_to_x(centerx, diam, 0.5f, skina*M_PI/180.0), polar_to_y(centery,diam,0.5,skina*M_PI/180.0), + polar_to_x(centerx, diam, 0.1f, skina*M_PI/180.0), polar_to_y(centery,diam,0.1,skina*M_PI/180.0)); + /* saturation points */ + for(i=0; i<6; i++) + vectorscope_draw_target(centerx, centery, diam, colors[i][0], colors[i][1], colors[i][2]); + + /* pixel point cloud */ + glBlendFunc(GL_ONE,GL_ONE); + glBegin(GL_POINTS); + glColor4f(alpha, alpha, alpha, alpha); + if (scopes->samples_ibuf->rect_float) { + rf = scopes->samples_ibuf->rect_float; + for (y=0; y<scopes->samples_ibuf->y; y++) { + for (x=0; x<scopes->samples_ibuf->x; x++) { + u=-0.147f*rf[0] - 0.289f*rf[1] + 0.436f*rf[2]; + v= 0.615f*rf[0] - 0.515f*rf[1] - 0.100f*rf[2]; + glVertex2f(centerx+u*diam, centery+v*diam); + rf+=scopes->samples_ibuf->channels; + } + } + } + else if(scopes->samples_ibuf->rect) { + rc = (unsigned char *)(scopes->samples_ibuf->rect); + for (y=0; y<scopes->samples_ibuf->y; y++) { + for (x=0; x<scopes->samples_ibuf->x; x++) { + u=-0.147f*rc[0]/255.0f - 0.289f*rc[1]/255.0f + 0.436f*rc[2]/255.0f; + v= 0.615f*rc[0]/255.0f - 0.515f*rc[1]/255.0f - 0.100f*rc[2]/255.0f; + glVertex2f(centerx+u*diam, centery+v*diam); + rc+=4; + } + } + } + glEnd(); /* restore scissortest */ @@ -773,7 +1174,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti * /* height scaling widget */ scaler_x1 = rect.xmin + w/2 - SCOPE_RESIZE_PAD; scaler_x2 = rect.xmin + w/2 + SCOPE_RESIZE_PAD; - + glColor4f(0.f, 0.f, 0.f, 0.25f); fdrawline(scaler_x1, rect.ymin-4, scaler_x2, rect.ymin-4); fdrawline(scaler_x1, rect.ymin-7, scaler_x2, rect.ymin-7); @@ -781,7 +1182,6 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti * fdrawline(scaler_x1, rect.ymin-5, scaler_x2, rect.ymin-5); fdrawline(scaler_x1, rect.ymin-8, scaler_x2, rect.ymin-8); - glColor4f(0.f, 0.f, 0.f, 0.5f); uiSetRoundBox(15); gl_round_box(GL_LINE_LOOP, rect.xmin-1, rect.ymin, rect.xmax+1, rect.ymax+1, 3.0f); @@ -789,7 +1189,6 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti * glDisable(GL_BLEND); } - void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *wcol, rcti *rect) { ColorBand *coba; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index fc69fc6fafa..9bd29532628 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -801,6 +801,14 @@ static void ui_apply_but_HISTOGRAM(bContext *C, uiBut *but, uiHandleButtonData * data->applied= 1; } +static void ui_apply_but_WAVEFORM(bContext *C, uiBut *but, uiHandleButtonData *data) +{ + ui_apply_but_func(C, but); + data->retval= but->retval; + data->applied= 1; +} + + static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, int interactive) { char *editstr; @@ -926,6 +934,9 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut case HISTOGRAM: ui_apply_but_HISTOGRAM(C, but, data); break; + case WAVEFORM: + ui_apply_but_WAVEFORM(C, but, data); + break; default: break; } @@ -3460,7 +3471,7 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt return WM_UI_HANDLER_CONTINUE; } -static int in_histogram_resize_zone(uiBut *but, int x, int y) +static int in_scope_resize_zone(uiBut *but, int x, int y) { // bottom corner return (x > but->x2 - SCOPE_RESIZE_PAD) && (y < but->y1 + SCOPE_RESIZE_PAD); return (y < but->y1 + SCOPE_RESIZE_PAD); @@ -3480,7 +3491,7 @@ static int ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int mx dy = my - data->draglasty; - if (in_histogram_resize_zone(but, data->dragstartx, data->dragstarty)) { + if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) { /* resize histogram widget itself */ hist->height = (but->y2 - but->y1) + (data->dragstarty - my); } else { @@ -3548,6 +3559,156 @@ static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandle return WM_UI_HANDLER_CONTINUE; } +static int ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx, int my) +{ + Scopes *scopes = (Scopes *)but->poin; + rcti rect; + int changed= 1; + float dx, dy, yfac=1.f; + + rect.xmin= but->x1; rect.xmax= but->x2; + rect.ymin= but->y1; rect.ymax= but->y2; + + dx = mx - data->draglastx; + dy = my - data->draglasty; + + + if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) { + /* resize waveform widget itself */ + scopes->wavefrm_height = (but->y2 - but->y1) + (data->dragstarty - my); + } else { + /* scale waveform values */ + yfac = scopes->wavefrm_yfac; + scopes->wavefrm_yfac += dy/200.0f; + + CLAMP(scopes->wavefrm_yfac, 0.5f, 2.f); + } + + data->draglastx= mx; + data->draglasty= my; + + return changed; +} + +static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event) +{ + int mx, my; + + mx= event->x; + my= event->y; + ui_window_to_block(data->region, block, &mx, &my); + + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(event->type==LEFTMOUSE && event->val==KM_PRESS) { + data->dragstartx= mx; + data->dragstarty= my; + data->draglastx= mx; + data->draglasty= my; + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + + /* also do drag the first time */ + if(ui_numedit_but_WAVEFORM(but, data, mx, my)) + ui_numedit_apply(C, block, but, data); + + return WM_UI_HANDLER_BREAK; + } + else if (event->type == ZEROKEY && event->val == KM_PRESS) { + Scopes *scopes = (Scopes *)but->poin; + scopes->wavefrm_yfac = 1.f; + + button_activate_state(C, but, BUTTON_STATE_EXIT); + return WM_UI_HANDLER_BREAK; + } + } + else if(data->state == BUTTON_STATE_NUM_EDITING) { + if(event->type == ESCKEY) { + data->cancel= 1; + data->escapecancel= 1; + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + else if(event->type == MOUSEMOVE) { + if(mx!=data->draglastx || my!=data->draglasty) { + if(ui_numedit_but_WAVEFORM(but, data, mx, my)) + ui_numedit_apply(C, block, but, data); + } + } + else if(event->type==LEFTMOUSE && event->val!=KM_PRESS) { + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + return WM_UI_HANDLER_BREAK; + } + + return WM_UI_HANDLER_CONTINUE; +} + +static int ui_numedit_but_VECTORSCOPE(uiBut *but, uiHandleButtonData *data, int mx, int my) +{ + Scopes *scopes = (Scopes *)but->poin; + rcti rect; + int changed= 1; + float dx, dy; + + rect.xmin= but->x1; rect.xmax= but->x2; + rect.ymin= but->y1; rect.ymax= but->y2; + + dx = mx - data->draglastx; + dy = my - data->draglasty; + + if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) { + /* resize vectorscope widget itself */ + scopes->vecscope_height = (but->y2 - but->y1) + (data->dragstarty - my); + } + + data->draglastx= mx; + data->draglasty= my; + + return changed; +} + +static int ui_do_but_VECTORSCOPE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event) +{ + int mx, my; + + mx= event->x; + my= event->y; + ui_window_to_block(data->region, block, &mx, &my); + + if(data->state == BUTTON_STATE_HIGHLIGHT) { + if(event->type==LEFTMOUSE && event->val==KM_PRESS) { + data->dragstartx= mx; + data->dragstarty= my; + data->draglastx= mx; + data->draglasty= my; + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + + /* also do drag the first time */ + if(ui_numedit_but_VECTORSCOPE(but, data, mx, my)) + ui_numedit_apply(C, block, but, data); + + return WM_UI_HANDLER_BREAK; + } + } + else if(data->state == BUTTON_STATE_NUM_EDITING) { + if(event->type == ESCKEY) { + data->cancel= 1; + data->escapecancel= 1; + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + else if(event->type == MOUSEMOVE) { + if(mx!=data->draglastx || my!=data->draglasty) { + if(ui_numedit_but_VECTORSCOPE(but, data, mx, my)) + ui_numedit_apply(C, block, but, data); + } + } + else if(event->type==LEFTMOUSE && event->val!=KM_PRESS) { + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + return WM_UI_HANDLER_BREAK; + } + + return WM_UI_HANDLER_CONTINUE; +} + #ifdef INTERNATIONAL static int ui_do_but_CHARTAB(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event) { @@ -4137,6 +4298,12 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) case HISTOGRAM: retval= ui_do_but_HISTOGRAM(C, block, but, data, event); break; + case WAVEFORM: + retval= ui_do_but_WAVEFORM(C, block, but, data, event); + break; + case VECTORSCOPE: + retval= ui_do_but_VECTORSCOPE(C, block, but, data, event); + break; case TEX: case IDPOIN: case SEARCH_MENU: diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index f90b711cc09..77f18115c73 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -443,6 +443,8 @@ extern void gl_round_box_vertical_shade(int mode, float minx, float miny, float void ui_draw_gradient(rcti *rect, float *rgb, int type, float alpha); void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect); +void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect); +void ui_draw_but_VECTORSCOPE(ARegion *ar, 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_CURVE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 200ef1fa501..bf7ab9fcdce 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1596,12 +1596,85 @@ void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, char *propname, int block= uiLayoutAbsoluteBlock(layout); //colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb); - + hist = (Histogram *)cptr.data; + + hist->height= (hist->height<=0)?100:hist->height; + + bt= uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, hist->height, hist, 0, 0, 0, 0, ""); + uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + + MEM_freeN(cb); +} + +/********************* Waveform Template ************************/ + +void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, char *propname, int expand) +{ + PropertyRNA *prop= RNA_struct_find_property(ptr, propname); + PointerRNA cptr; + RNAUpdateCb *cb; + uiBlock *block; + uiBut *bt; + Scopes *scopes; + rctf rect; + + if(!prop || RNA_property_type(prop) != PROP_POINTER) + return; - hist->height= (hist->height==0)?100:hist->height; + cptr= RNA_property_pointer_get(ptr, prop); + if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes)) + return; + scopes = (Scopes *)cptr.data; + + 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); + + scopes->wavefrm_height= (scopes->wavefrm_height<=0)?100:scopes->wavefrm_height; + + bt= uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->wavefrm_height, scopes, 0, 0, 0, 0, ""); + + MEM_freeN(cb); +} + +/********************* Vectorscope Template ************************/ + +void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, char *propname, int expand) +{ + PropertyRNA *prop= RNA_struct_find_property(ptr, propname); + PointerRNA cptr; + RNAUpdateCb *cb; + uiBlock *block; + uiBut *bt; + Scopes *scopes; + 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_Scopes)) + return; + scopes = (Scopes *)cptr.data; + + 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); + + scopes->vecscope_height= (scopes->vecscope_height<=0)?100:scopes->vecscope_height; - bt= uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, hist->height, hist, 0, 0, 0, 0, ""); + bt= uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->vecscope_height, scopes, 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); MEM_freeN(cb); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 1c75a05e084..af990214686 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2727,6 +2727,14 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct ui_draw_but_HISTOGRAM(ar, but, &tui->wcol_regular, rect); break; + case WAVEFORM: + ui_draw_but_WAVEFORM(ar, but, &tui->wcol_regular, rect); + break; + + case VECTORSCOPE: + ui_draw_but_VECTORSCOPE(ar, but, &tui->wcol_regular, rect); + break; + case BUT_CURVE: ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect); break; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index c9daeb09f25..55e6ac356c6 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -177,7 +177,7 @@ static void view_pan_exit(bContext *C, wmOperator *op, int cancel) if(cancel) { sima->xof= vpd->xof; sima->yof= vpd->yof; - ED_area_tag_redraw(CTX_wm_area(C)); + ED_region_tag_redraw(CTX_wm_region(C)); } WM_cursor_restore(CTX_wm_window(C)); @@ -193,7 +193,7 @@ static int view_pan_exec(bContext *C, wmOperator *op) sima->xof += offset[0]; sima->yof += offset[1]; - ED_area_tag_redraw(CTX_wm_area(C)); + ED_region_tag_redraw(CTX_wm_region(C)); /* XXX notifier? */ #if 0 @@ -309,7 +309,7 @@ static void view_zoom_exit(bContext *C, wmOperator *op, int cancel) if(cancel) { sima->zoom= vpd->zoom; - ED_area_tag_redraw(CTX_wm_area(C)); + ED_region_tag_redraw(CTX_wm_region(C)); } WM_cursor_restore(CTX_wm_window(C)); @@ -323,7 +323,7 @@ static int view_zoom_exec(bContext *C, wmOperator *op) sima_zoom_set_factor(sima, ar, RNA_float_get(op->ptr, "factor")); - ED_area_tag_redraw(CTX_wm_area(C)); + ED_region_tag_redraw(CTX_wm_region(C)); /* XXX notifier? */ #if 0 @@ -347,7 +347,7 @@ static int view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) factor= 1.0 + (event->x-event->prevx+event->y-event->prevy)/300.0f; RNA_float_set(op->ptr, "factor", factor); sima_zoom_set(sima, ar, sima->zoom*factor); - ED_area_tag_redraw(CTX_wm_area(C)); + ED_region_tag_redraw(CTX_wm_region(C)); return OPERATOR_FINISHED; } @@ -369,7 +369,7 @@ static int view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event) factor= 1.0 + (vpd->x-event->x+vpd->y-event->y)/300.0f; RNA_float_set(op->ptr, "factor", factor); sima_zoom_set(sima, ar, vpd->zoom*factor); - ED_area_tag_redraw(CTX_wm_area(C)); + ED_region_tag_redraw(CTX_wm_region(C)); break; case MIDDLEMOUSE: case LEFTMOUSE: @@ -452,7 +452,7 @@ static int view_all_exec(bContext *C, wmOperator *op) sima->xof= sima->yof= 0.0f; - ED_area_tag_redraw(CTX_wm_area(C)); + ED_region_tag_redraw(CTX_wm_region(C)); return OPERATOR_FINISHED; } @@ -504,7 +504,7 @@ static int view_selected_exec(bContext *C, wmOperator *op) if(size<=0.01) size= 0.01; sima_zoom_set(sima, ar, 0.7/size); - ED_area_tag_redraw(CTX_wm_area(C)); + ED_region_tag_redraw(CTX_wm_region(C)); return OPERATOR_FINISHED; } @@ -529,7 +529,7 @@ static int view_zoom_in_exec(bContext *C, wmOperator *op) sima_zoom_set_factor(sima, ar, 1.25f); - ED_area_tag_redraw(CTX_wm_area(C)); + ED_region_tag_redraw(CTX_wm_region(C)); return OPERATOR_FINISHED; } @@ -552,7 +552,7 @@ static int view_zoom_out_exec(bContext *C, wmOperator *op) sima_zoom_set_factor(sima, ar, 0.8f); - ED_area_tag_redraw(CTX_wm_area(C)); + ED_region_tag_redraw(CTX_wm_region(C)); return OPERATOR_FINISHED; } @@ -590,7 +590,7 @@ static int view_zoom_ratio_exec(bContext *C, wmOperator *op) } #endif - ED_area_tag_redraw(CTX_wm_area(C)); + ED_region_tag_redraw(CTX_wm_region(C)); return OPERATOR_FINISHED; } @@ -1688,16 +1688,17 @@ static int sample_line_exec(bContext *C, wmOperator *op) hist->data_r[i] = fp[0]; hist->data_g[i] = fp[1]; hist->data_b[i] = fp[2]; + hist->data_luma[i] = (0.299f*fp[0] + 0.587f*fp[1] + 0.114f*fp[2]); } else if (ibuf->rect) { cp= (unsigned char *)(ibuf->rect + y*ibuf->x + x); hist->data_r[i] = (float)cp[0]/255.0f; hist->data_g[i] = (float)cp[1]/255.0f; hist->data_b[i] = (float)cp[2]/255.0f; + hist->data_luma[i] = (0.299f*cp[0] + 0.587f*cp[1] + 0.114f*cp[2])/255; } } } - hist->ok=1; ED_space_image_release_buffer(sima, lock); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 0eb377450e9..45903c8079d 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -47,6 +47,7 @@ #include "BKE_screen.h" #include "BKE_utildefines.h" +#include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "ED_mesh.h" @@ -98,6 +99,7 @@ void ED_space_image_set(bContext *C, SpaceImage *sima, Scene *scene, Object *obe WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); ED_area_tag_redraw(CTX_wm_area(C)); + } } @@ -289,21 +291,21 @@ int ED_space_image_show_uvshadow(SpaceImage *sima, Object *obedit) } - -static void image_histogram_tag_refresh(ScrArea *sa) +static void image_scopes_tag_refresh(ScrArea *sa) { SpaceImage *sima= (SpaceImage *)sa->spacedata.first; ARegion *ar; - + /* only while histogram is visible */ for (ar=sa->regionbase.first; ar; ar=ar->next) { if (ar->regiontype == RGN_TYPE_PREVIEW && ar->flag & RGN_FLAG_HIDDEN) return; } - - sima->hist.ok=0; + + sima->scopes.ok=0; } + /* ******************** manage regions ********************* */ ARegion *image_has_buttons_region(ScrArea *sa) @@ -356,8 +358,8 @@ ARegion *image_has_scope_region(ScrArea *sa) arnew->alignment= RGN_ALIGN_RIGHT; arnew->flag = RGN_FLAG_HIDDEN; - - image_histogram_tag_refresh(sa); + + image_scopes_tag_refresh(sa); return arnew; } @@ -400,6 +402,13 @@ static SpaceLink *image_new(const bContext *C) ar->regiontype= RGN_TYPE_PREVIEW; ar->alignment= RGN_ALIGN_RIGHT; ar->flag = RGN_FLAG_HIDDEN; + + simage->scopes.accuracy=30.0; + simage->scopes.hist.mode=HISTO_MODE_RGB; + simage->scopes.wavefrm_alpha=0.3; + simage->scopes.vecscope_alpha=0.3; + simage->scopes.wavefrm_height= 100; + simage->scopes.hist.height= 100; /* main area */ ar= MEM_callocN(sizeof(ARegion), "main area for image"); @@ -417,9 +426,7 @@ static void image_free(SpaceLink *sl) if(simage->cumap) curvemapping_free(simage->cumap); -// if(simage->gpd) -// XXX free_gpencil_data(simage->gpd); - + scopes_free(&simage->scopes); } @@ -590,7 +597,7 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn) case NC_SCENE: switch(wmn->data) { case ND_FRAME: - image_histogram_tag_refresh(sa); + image_scopes_tag_refresh(sa); ED_area_tag_refresh(sa); ED_area_tag_redraw(sa); break; @@ -598,7 +605,7 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn) case ND_RENDER_RESULT: case ND_COMPO_RESULT: if (ED_space_image_show_render(sima)) - image_histogram_tag_refresh(sa); + image_scopes_tag_refresh(sa); ED_area_tag_refresh(sa); ED_area_tag_redraw(sa); break; @@ -606,14 +613,14 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn) break; case NC_IMAGE: if (wmn->reference == sima->image || !wmn->reference) { - image_histogram_tag_refresh(sa); + image_scopes_tag_refresh(sa); ED_area_tag_refresh(sa); ED_area_tag_redraw(sa); } break; case NC_SPACE: if(wmn->data == ND_SPACE_IMAGE) { - image_histogram_tag_refresh(sa); + image_scopes_tag_refresh(sa); ED_area_tag_redraw(sa); } break; @@ -837,10 +844,12 @@ static void image_scope_area_init(wmWindowManager *wm, ARegion *ar) static void image_scope_area_draw(const bContext *C, ARegion *ar) { SpaceImage *sima= CTX_wm_space_image(C); + Scene *scene= CTX_data_scene(C); void *lock; ImBuf *ibuf= ED_space_image_acquire_buffer(sima, &lock); - if(ibuf) - histogram_update(&sima->hist, ibuf); + if(ibuf) { + scopes_update(&sima->scopes, ibuf, scene->r.color_mgt_flag & R_COLOR_MANAGEMENT ); + } ED_space_image_release_buffer(sima, lock); ED_region_panels(C, ar, 1, NULL, -1); diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index 2a6dcfcb64e..dd31c349615 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -90,18 +90,57 @@ typedef enum CurveMappingPreset { CURVE_PRESET_MID9 } CurveMappingPreset; +/* histogram->mode */ +#define HISTO_MODE_LUMA 0 +#define HISTO_MODE_RGB 1 +#define HISTO_MODE_R 2 +#define HISTO_MODE_G 3 +#define HISTO_MODE_B 4 + typedef struct Histogram { int channels; int x_resolution; float data_r[256]; float data_g[256]; float data_b[256]; + float data_luma[256]; float xmax, ymax; + int mode; int height; +} Histogram; + +struct ImBuf; + +typedef struct Scopes { int ok; - int flag; + int sample_full; + int sample_lines; + float accuracy; + int wavefrm_mode; + float wavefrm_alpha; + float wavefrm_yfac; + int wavefrm_height; + float vecscope_alpha; + int vecscope_height; + float rgbminmax[3][2]; + float yccminmax[3][2]; + float ycc709minmax[3][2]; + struct ImBuf *samples_ibuf; + struct Histogram hist; + float *waveform_1; + float *waveform_2; + float *waveform_3; + int waveform_tot; int pad; -} Histogram; +} Scopes; + +/* scopes->wavefrm_mode */ +#define SCOPES_WAVEFRM_LUM 0 +#define SCOPES_WAVEFRM_RGB 1 +#define SCOPES_WAVEFRM_YCC_601 2 +#define SCOPES_WAVEFRM_YCC_709 3 +#define SCOPES_WAVEFRM_YCC_JPEG 4 + #endif diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 00ade3156c5..6cb22f3b08f 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -44,6 +44,7 @@ struct Text; struct Script; struct ImBuf; struct Image; +struct Scopes; struct Histogram; struct SpaceIpo; struct BlendHandle; @@ -260,8 +261,10 @@ typedef struct SpaceImage { struct bGPdata *gpd; /* grease pencil data */ - struct Histogram hist; /* viewer histogram */ + struct Scopes scopes; /* histogram waveform and vectorscope */ + struct Histogram sample_line_hist; /* sample line histogram */ + } SpaceImage; typedef struct SpaceNla { diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index e72c5eb9a4d..3ee251c4437 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -383,6 +383,7 @@ extern StructRNA RNA_Scene; extern StructRNA RNA_SceneGameData; extern StructRNA RNA_SceneRenderLayer; extern StructRNA RNA_SceneSequence; +extern StructRNA RNA_Scopes; extern StructRNA RNA_Screen; extern StructRNA RNA_ScrewModifier; extern StructRNA RNA_Sculpt; diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index daf3f73a3d7..6e409f4b613 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -26,6 +26,7 @@ #include <stdio.h> #include "RNA_define.h" +#include "rna_internal.h" #include "DNA_color_types.h" @@ -269,6 +270,11 @@ static void rna_ColorRamp_update(Main *bmain, Scene *scene, PointerRNA *ptr) } } +static void rna_Scopes_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + Scopes *s= (Scopes*)ptr->data; + s->ok = 0; +} #else @@ -443,12 +449,77 @@ static void rna_def_color_ramp(BlenderRNA *brna) static void rna_def_histogram(BlenderRNA *brna) { StructRNA *srna; + PropertyRNA *prop; + static EnumPropertyItem prop_mode_items[] = { + {HISTO_MODE_LUMA, "Luma", ICON_COLOR, "Luma", ""}, + {HISTO_MODE_RGB, "RGB", ICON_COLOR, "RGB", ""}, + {HISTO_MODE_R, "R", ICON_COLOR, "R", ""}, + {HISTO_MODE_G, "G", ICON_COLOR, "G", ""}, + {HISTO_MODE_B, "B", ICON_COLOR, "B", ""}, + {0, NULL, 0, NULL, NULL}}; + srna= RNA_def_struct(brna, "Histogram", NULL); RNA_def_struct_ui_text(srna, "Histogram", "Statistical view of the levels of color in an image"); + prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mode"); + RNA_def_property_enum_items(prop, prop_mode_items); + RNA_def_property_ui_text(prop, "Mode", "Channels to display when drawing the histogram"); + +} + +static void rna_def_scopes(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem prop_wavefrm_mode_items[] = { + {SCOPES_WAVEFRM_LUM, "LUMINANCE", ICON_COLOR, "Luminance", ""}, + {SCOPES_WAVEFRM_RGB, "RGB", ICON_COLOR, "Red Green Blue", ""}, + {SCOPES_WAVEFRM_YCC_601, "YCBCR601", ICON_COLOR, "YCbCr (ITU 601)", ""}, + {SCOPES_WAVEFRM_YCC_709, "YCBCR709", ICON_COLOR, "YCbCr (ITU 709)", ""}, + {SCOPES_WAVEFRM_YCC_JPEG, "YCBCRJPG", ICON_COLOR, "YCbCr (Jpeg)", ""}, + {0, NULL, 0, NULL, NULL}}; + + srna= RNA_def_struct(brna, "Scopes", NULL); + RNA_def_struct_ui_text(srna, "Scopes", "Scopes for statistical view of an image"); + + prop= RNA_def_property(srna, "use_full_resolution", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, "Scopes", "sample_full", 1); + RNA_def_property_ui_text(prop, "Full Sample", "Sample every pixel of the image"); + RNA_def_property_update(prop, 0, "rna_Scopes_update"); + + prop= RNA_def_property(srna, "accuracy", PROP_FLOAT, PROP_PERCENTAGE); + RNA_def_property_float_sdna(prop, "Scopes", "accuracy"); + RNA_def_property_range(prop, 0.0, 100.0); + RNA_def_property_ui_range(prop, 0.0, 100.0, 10, 1); + RNA_def_property_ui_text(prop, "Accuracy", "Proportion of original image source pixel lines to sample"); + RNA_def_property_update(prop, 0, "rna_Scopes_update"); + + prop= RNA_def_property(srna, "histogram", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, "Scopes", "hist"); + RNA_def_property_struct_type(prop, "Histogram"); + RNA_def_property_ui_text(prop, "Histogram", "Histogram for viewing image statistics"); + + prop= RNA_def_property(srna, "waveform_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, "Scopes", "wavefrm_mode"); + RNA_def_property_enum_items(prop, prop_wavefrm_mode_items); + RNA_def_property_ui_text(prop, "Wavefrom Mode", ""); + RNA_def_property_update(prop, 0, "rna_Scopes_update"); + + prop= RNA_def_property(srna, "waveform_alpha", PROP_FLOAT, PROP_PERCENTAGE); + RNA_def_property_float_sdna(prop, "Scopes", "wavefrm_alpha"); + RNA_def_property_range(prop, 0, 1); + RNA_def_property_ui_text(prop, "Waveform Opacity", "Opacity of the points"); + + prop= RNA_def_property(srna, "vectorscope_alpha", PROP_FLOAT, PROP_PERCENTAGE); + RNA_def_property_float_sdna(prop, "Scopes", "vecscope_alpha"); + RNA_def_property_range(prop, 0, 1); + RNA_def_property_ui_text(prop, "Vectorscope Opacity", "Opacity of the points"); } + void RNA_def_color(BlenderRNA *brna) { rna_def_curvemappoint(brna); @@ -457,6 +528,7 @@ void RNA_def_color(BlenderRNA *brna) rna_def_color_ramp_element(brna); rna_def_color_ramp(brna); rna_def_histogram(brna); + rna_def_scopes(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 8b3a54af4c2..b7165234ef2 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -458,7 +458,7 @@ static void rna_SpaceImageEditor_curves_update(Main *bmain, Scene *scene, Pointe WM_main_add_notifier(NC_IMAGE, sima->image); } -static void rna_SpaceImageEditor_histogram_update(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_SpaceImageEditor_scopes_update(Main *bmain, Scene *scene, PointerRNA *ptr) { SpaceImage *sima= (SpaceImage*)ptr->data; ImBuf *ibuf; @@ -466,13 +466,12 @@ static void rna_SpaceImageEditor_histogram_update(Main *bmain, Scene *scene, Poi ibuf= ED_space_image_acquire_buffer(sima, &lock); if(ibuf) { - histogram_update(&sima->hist, ibuf); + scopes_update(&sima->scopes, ibuf, scene->r.color_mgt_flag & R_COLOR_MANAGEMENT); WM_main_add_notifier(NC_IMAGE, sima->image); } ED_space_image_release_buffer(sima, lock); } - /* Space Text Editor */ static void rna_SpaceTextEditor_word_wrap_set(PointerRNA *ptr, int value) @@ -1215,12 +1214,12 @@ static void rna_def_space_image(BlenderRNA *brna) 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_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, "scopes", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "scopes"); + RNA_def_property_struct_type(prop, "Scopes"); + RNA_def_property_ui_text(prop, "Scopes", "Scopes to visualize image statistics."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_IMAGE, "rna_SpaceImageEditor_scopes_update"); prop= RNA_def_property(srna, "image_pin", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "pin", 0); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 89c7876f6e0..7c78d8a74e7 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -335,6 +335,14 @@ void RNA_api_ui_layout(StructRNA *srna) api_ui_item_rna_common(func); RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail."); + func= RNA_def_function(srna, "template_waveform", "uiTemplateWaveform"); + api_ui_item_rna_common(func); + RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail."); + + func= RNA_def_function(srna, "template_vectorscope", "uiTemplateVectorscope"); + 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"); api_ui_item_rna_common(func); parm= RNA_def_pointer(func, "used_layers_data", "AnyType", "", "Data from which to take property."); |