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
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/blender/blenkernel/intern/colortools.c
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/blender/blenkernel/intern/colortools.c')
-rw-r--r--source/blender/blenkernel/intern/colortools.c249
1 files changed, 218 insertions, 31 deletions
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