|
|
|
@ -12,122 +12,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GtkWidget *histogram_da = NULL;
|
|
|
|
|
GdkPixbuf *histogram_pixbuf = NULL;
|
|
|
|
|
int *hist_minmax = NULL; // 2* hist_width min, max, min , max.....
|
|
|
|
|
int hist_width = 0;
|
|
|
|
|
int histogram[3][256]; // 6* hist_width min, max, min , max.....
|
|
|
|
|
int histogram_max; // max vlaue
|
|
|
|
|
|
|
|
|
|
extern GtkBuilder *_builder_; // work around for threads
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define S_X(_x_) (((_x_) * clientw / pixbufw))
|
|
|
|
|
#define S_Y(_y_) (((_y_) * clienth / pixbufh))
|
|
|
|
|
void cb_histogramda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data) {
|
|
|
|
|
int clientw, clienth, pixbufw, pixbufh;
|
|
|
|
|
int clientw, clienth, px, py2;
|
|
|
|
|
GdkRGBA color;
|
|
|
|
|
char txt[255];
|
|
|
|
|
|
|
|
|
|
if (histogram_da == NULL) // should only be called once
|
|
|
|
|
histogram_da = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "histogram-da"));
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// create or resize pixbuf if needed
|
|
|
|
|
clienth = gtk_widget_get_allocated_height(histogram_da);
|
|
|
|
|
clientw = gtk_widget_get_allocated_width(histogram_da);
|
|
|
|
|
if (histogram_pixbuf == NULL) {
|
|
|
|
|
histogram_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, false, 8, clientw, clienth);
|
|
|
|
|
memset (gdk_pixbuf_get_pixels(histogram_pixbuf), 0, 3 * gdk_pixbuf_get_height(histogram_pixbuf) * gdk_pixbuf_get_width(histogram_pixbuf));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pixbufh = gdk_pixbuf_get_height(histogram_pixbuf);
|
|
|
|
|
pixbufw = gdk_pixbuf_get_width(histogram_pixbuf);
|
|
|
|
|
if (pixbufw != clientw || pixbufh != clienth) {
|
|
|
|
|
g_object_unref(histogram_pixbuf);
|
|
|
|
|
histogram_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, false, 8, clientw, clienth);
|
|
|
|
|
memset (gdk_pixbuf_get_pixels(histogram_pixbuf), 0, 3 * gdk_pixbuf_get_height(histogram_pixbuf) * gdk_pixbuf_get_width(histogram_pixbuf));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// put the drawing area on the screen
|
|
|
|
|
gdk_cairo_set_source_pixbuf(cr, histogram_pixbuf, 0, 0);
|
|
|
|
|
cairo_paint(cr);
|
|
|
|
|
cairo_fill (cr);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// draw cross
|
|
|
|
|
color.blue = 1.0;
|
|
|
|
|
color.red = 0.0;
|
|
|
|
|
color.green = 1.0;
|
|
|
|
|
color.alpha = 1.0;
|
|
|
|
|
gdk_cairo_set_source_rgba(cr, &color);
|
|
|
|
|
|
|
|
|
|
cairo_move_to(cr, 0, 0);
|
|
|
|
|
cairo_line_to(cr, pixbufw, pixbufh);
|
|
|
|
|
cairo_move_to(cr, pixbufw, 0);
|
|
|
|
|
cairo_line_to(cr, 0, pixbufh);
|
|
|
|
|
|
|
|
|
|
cairo_stroke(cr);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// draw basic histogram
|
|
|
|
|
if (hist_minmax != NULL) {
|
|
|
|
|
//
|
|
|
|
|
// draw cross
|
|
|
|
|
color.blue = 0.75;
|
|
|
|
|
color.red = 0.75;
|
|
|
|
|
color.green = 0.75;
|
|
|
|
|
color.alpha = 0.8;
|
|
|
|
|
if (histogram_max == 0) return;
|
|
|
|
|
|
|
|
|
|
for (int chan = 0; chan < 3; chan++) {
|
|
|
|
|
switch (chan) {
|
|
|
|
|
case 0:
|
|
|
|
|
color.blue = 0.0;
|
|
|
|
|
color.red = 1.0;
|
|
|
|
|
color.green = 0.0;
|
|
|
|
|
color.alpha = 0.5;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
color.blue = 0.0;
|
|
|
|
|
color.red = 0.0;
|
|
|
|
|
color.green = 1.0;
|
|
|
|
|
color.alpha = 0.5;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
color.blue = 1.0;
|
|
|
|
|
color.red = 0.0;
|
|
|
|
|
color.green = 0.0;
|
|
|
|
|
color.alpha = 0.5;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
gdk_cairo_set_source_rgba(cr, &color);
|
|
|
|
|
|
|
|
|
|
int x, i; // position in histogram
|
|
|
|
|
int px, py1, py2; // screen pos x and line from to
|
|
|
|
|
for (int i = 0; i < 256; i++) {
|
|
|
|
|
px = 16 + ((clientw-32) * i) / 256;
|
|
|
|
|
py2 = (clienth-16) - ((clienth-32) * histogram[chan][i]) / histogram_max;
|
|
|
|
|
|
|
|
|
|
for (i = 0, x = 0; x < hist_width; x++) {
|
|
|
|
|
if (i == 0) cairo_move_to(cr, px, py2);
|
|
|
|
|
else cairo_line_to(cr, px, py2);
|
|
|
|
|
|
|
|
|
|
px = (pixbufw * x) / hist_width;
|
|
|
|
|
py1 = (pixbufh * hist_minmax[i++]) / 255;
|
|
|
|
|
py2 = (pixbufh * hist_minmax[i++]) / 255;
|
|
|
|
|
|
|
|
|
|
cairo_move_to(cr, px, py1);
|
|
|
|
|
cairo_line_to(cr, px, py2);
|
|
|
|
|
}
|
|
|
|
|
cairo_stroke(cr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cairo_stroke(cr);
|
|
|
|
|
// draw some text
|
|
|
|
|
snprintf (txt, 255, "%d", histogram_max);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
|
|
|
int dx, dy;
|
|
|
|
|
|
|
|
|
|
switch (i) {
|
|
|
|
|
case 0:
|
|
|
|
|
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
|
|
|
|
dx = -1;
|
|
|
|
|
dy = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
dx = +1;
|
|
|
|
|
dy = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
dx = 0;
|
|
|
|
|
dy = -1;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
dx = 0;
|
|
|
|
|
dy = +1;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
|
|
|
|
|
dx = 0;
|
|
|
|
|
dy = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// draw some text
|
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
|
|
|
int dx, dy;
|
|
|
|
|
|
|
|
|
|
switch (i) {
|
|
|
|
|
case 0:
|
|
|
|
|
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
|
|
|
|
dx = -1;
|
|
|
|
|
dy = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
dx = +1;
|
|
|
|
|
dy = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
dx = 0;
|
|
|
|
|
dy = -1;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
dx = 0;
|
|
|
|
|
dy = +1;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
|
|
|
|
|
dx = 0;
|
|
|
|
|
dy = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
|
|
|
|
|
cairo_set_font_size (cr, 12);
|
|
|
|
|
cairo_move_to (cr, 10+dx, 15+dy);
|
|
|
|
|
cairo_show_text(cr, "Test");
|
|
|
|
|
cairo_stroke(cr);
|
|
|
|
|
}
|
|
|
|
|
cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
|
|
|
|
|
cairo_set_font_size (cr, 12);
|
|
|
|
|
cairo_move_to (cr, 10+dx, 15+dy);
|
|
|
|
|
cairo_show_text(cr, txt);
|
|
|
|
|
cairo_stroke(cr);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -135,39 +112,26 @@ void cb_histogramda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer da
|
|
|
|
|
* test function
|
|
|
|
|
*/
|
|
|
|
|
void histogram_update(VideoFrame *vf) {
|
|
|
|
|
int i, x, y, min, max, v;
|
|
|
|
|
int chan, i, x, y;
|
|
|
|
|
|
|
|
|
|
if (vf == NULL) return;
|
|
|
|
|
if (vf->w <= 0 ) return;
|
|
|
|
|
|
|
|
|
|
if (hist_minmax == NULL ) {
|
|
|
|
|
hist_minmax = (int*) malloc (2 * sizeof(int) * vf->w);
|
|
|
|
|
hist_width = vf->w;
|
|
|
|
|
}
|
|
|
|
|
if (hist_width != vf->w) {
|
|
|
|
|
free (hist_minmax);
|
|
|
|
|
hist_minmax = (int*) malloc (2 * sizeof(int) * vf->w);
|
|
|
|
|
hist_width = vf->w;
|
|
|
|
|
}
|
|
|
|
|
for (chan = 0; chan < 3; chan++) for (i = 0; i < 256; i++)
|
|
|
|
|
histogram[chan][i] = 0;
|
|
|
|
|
|
|
|
|
|
for (i = 0, x = 0; x < vf->w; x++) {
|
|
|
|
|
for (y = 0; y < vf->h; y++) {
|
|
|
|
|
v = (vf->data[3*y*vf->w+x + 0] +
|
|
|
|
|
vf->data[3*y*vf->w+x + 1] +
|
|
|
|
|
vf->data[3*y*vf->w+x + 2]) / 3;
|
|
|
|
|
if (y == 0) {
|
|
|
|
|
min = v;
|
|
|
|
|
max = v;
|
|
|
|
|
for (chan = 0; chan < 3; chan++) {
|
|
|
|
|
histogram[chan][vf->data[3*(y*vf->w+x) + chan]]++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (v < min) min = v;
|
|
|
|
|
if (v > max) max = v;
|
|
|
|
|
}
|
|
|
|
|
hist_minmax[i++] = min;
|
|
|
|
|
hist_minmax[i++] = max;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (histogram_da)
|
|
|
|
|
gdk_window_invalidate_rect(gtk_widget_get_window(histogram_da), NULL, true);
|
|
|
|
|
|
|
|
|
|
for (histogram_max = 0, chan = 0; chan < 3; chan++) for (i = 0; i < 256; i++)
|
|
|
|
|
if (histogram_max < histogram[chan][i]) histogram_max = histogram[chan][i];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|