Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorMatt Ebb <matt@mke3.net>2010-04-06 06:05:54 +0400
committerMatt Ebb <matt@mke3.net>2010-04-06 06:05:54 +0400
commitbfe248b3d629d28fed3798e9f6a42bccb5d40f9e (patch)
treed4b75ad54067d790cdabaa7e843624b1d423a5af /source
parentea7fdb55a3e8f088161b218b96220c1cba9380a1 (diff)
Patch [#21750] Add luma waveform and vectorscope to image view
by Xavier Thomas This adds the waveform monitor and vectorscope to the image editor 'scopes' region, bringing it inline (plus a bit more) with sequence editor functionality, and a big step closer to the end goal of unifying the display code for image/ comp/sequence editor. It's non-intrusive, using the same code paths as the histogram. There's still room for more tweaks - I modified the original patch, changing the openGL immediate mode drawing of the waveform display to vertex arrays for speed optimisation. Xavier can look at doing this for the vectorscope now too. Thanks very much Xavier!
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_colortools.h5
-rw-r--r--source/blender/blenkernel/intern/colortools.c249
-rw-r--r--source/blender/blenlib/intern/math_color.c4
-rw-r--r--source/blender/blenloader/intern/readfile.c24
-rw-r--r--source/blender/editors/include/UI_interface.h4
-rw-r--r--source/blender/editors/interface/interface_draw.c463
-rw-r--r--source/blender/editors/interface/interface_handlers.c171
-rw-r--r--source/blender/editors/interface/interface_intern.h2
-rw-r--r--source/blender/editors/interface/interface_templates.c79
-rw-r--r--source/blender/editors/interface/interface_widgets.c8
-rw-r--r--source/blender/editors/space_image/image_ops.c25
-rw-r--r--source/blender/editors/space_image/space_image.c41
-rw-r--r--source/blender/makesdna/DNA_color_types.h43
-rw-r--r--source/blender/makesdna/DNA_space_types.h5
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_color.c72
-rw-r--r--source/blender/makesrna/intern/rna_space.c17
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c8
18 files changed, 1109 insertions, 112 deletions
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.");