diff options
author | Matt Ebb <matt@mke3.net> | 2010-04-06 06:05:54 +0400 |
---|---|---|
committer | Matt Ebb <matt@mke3.net> | 2010-04-06 06:05:54 +0400 |
commit | bfe248b3d629d28fed3798e9f6a42bccb5d40f9e (patch) | |
tree | d4b75ad54067d790cdabaa7e843624b1d423a5af /source/blender/blenkernel | |
parent | ea7fdb55a3e8f088161b218b96220c1cba9380a1 (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')
-rw-r--r-- | source/blender/blenkernel/BKE_colortools.h | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/colortools.c | 249 |
2 files changed, 221 insertions, 33 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 |