histogram.cpp 9.08 KB
Newer Older
Arnaud Blanchard's avatar
Arnaud Blanchard committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include "common.h"

#include <fcntl.h> // O_RDONLY ...
#include <stdio.h>
#include <gtk/gtk.h>
#include <string.h>
#include <stdint.h> //uint32_t
#include <jpeglib.h>
#include <sys/mman.h>
#include <errno.h> //errno
#include "blc_image.h"
#include "blc_realtime.h"
#include "blc_program.h" //blc_status

//cairo_surface_t *legend_surface;
guint histogram_tick_id;
uint32_t *histogram_data=NULL;
cairo_surface_t *histogram_surface;

static void draw_histogram(uint32_t *drawing, int height, int histogram[256], uint32_t color_map[256], int max){
    int i, j, val;
    FOR_INV(i, 256)
    {
        val = height-histogram[i]*(height-1)/max;
        for(j=height; j!=val; j--) drawing[j*256+i]=color_map[i];
        drawing[val*256+i]=255<<24;
        FOR_INV(j, val) drawing[j*256+i]=0;
    }
}

static gboolean update_histogram_cb(GtkImage *image, GdkFrameClock *, gpointer pointer_statusbar){
    int i, j, x, y;
    double sx, sy;
    int histogram[256]={0}, histogram1[256]={0}, histogram2[256]={0}, hist_max=0, max1=0, max2=0;
    char text[64];
    struct timeval timer;
    
    CLEAR(timer);
    gdk_window_get_device_position(gtk_widget_get_window(GTK_WIDGET(image)), pointer_device, &x, &y, NULL);
    cairo_surface_get_device_scale(histogram_surface, &sx, &sy);
    
    x*=sx;
    y*=sy;
    
    switch (array->format){
        case 'Y800':
            switch (array->type){
                case 'UIN8':
                    FOR(i, array->size) histogram[array->uchars[i]]++;
                    FOR(i, 256) hist_max=MAX(histogram[i], hist_max);
                    
                    FOR(i, 256)
                {
                    FOR_INV(j, histogram[i]*255/hist_max) histogram_data[(255-j)*256+i]=color_map[i];
                    histogram_data[(255-histogram[i]*255/hist_max)*256+i]=255<<24;
                    FOR_INV(j, 255-histogram[i]*255/hist_max) histogram_data[j*256+i]=0;
                }
                    if (y>=0 && y<256 && x >=0 && x<256)
                    {
                        SPRINTF(text, "Y[%d]=%f.2%%", x, histogram[x]*100/(float)array->size);
                        gtk_statusbar_push(GTK_STATUSBAR(pointer_statusbar), 0, text);
                    }
                    break;
                case 'FL32':
                    FOR(i, array->total_length) histogram[(int)CLIP_UCHAR(((array->floats[i]-min_val)/(max_val-min_val)*256+0.5))]++;
                    FOR(i, 256) hist_max=MAX(histogram[i], hist_max);
                    FOR(i, 256)
                {
                    FOR_INV(j, histogram[i]*255/hist_max) histogram_data[(255-j)*256+i]=color_map[i];
                    histogram_data[(255-histogram[i]*255/hist_max)*256+i]=255<<24;
                    FOR_INV(j, 255-histogram[i]*255/hist_max) histogram_data[j*256+i]=0;
                }
                    if (y>=0 && y<256 && x >=0 && x<256)
                    {
                        SPRINTF(text, "Y[%f]=%f.2%%", x*(max_val-min_val-0.5)/256+min_val, histogram[x]*100/(float)array->total_length);
                        gtk_statusbar_push(GTK_STATUSBAR(pointer_statusbar), 0, text);
                    }
                    break;
                default: EXIT_ON_ARRAY_ERROR( array, "Type not managed for format 'Y800'. Only 'UIN8' is");
            }
            break;
        case 'RGB3':
            FOR_INV(i, array->size/3){
                histogram[array->uchars[i*3]]++;
                histogram1[array->uchars[i*3+1]]++;
                histogram2[array->uchars[i*3+2]]++;
            }
            
            FOR_INV(i, 256)
        {
            hist_max=MAX(histogram[i], hist_max);
            max1=MAX(histogram1[i], max1);
            max2=MAX(histogram2[i], max2);
        }
            draw_histogram(histogram_data, 85, histogram, r_colors, hist_max);
            draw_histogram(histogram_data+256*85, 85, histogram1, g_colors, max1);
            draw_histogram(histogram_data+256*170, 85, histogram2, b_colors, max2);
            
            if (y>=0 && y<256 && x >=0 && x<256)
            {
                if (y<85)  SPRINTF(text, "R[%d]=%f.2%%", x, histogram[x]*100*2/(float)array->size);
                else if (y<170)  SPRINTF(text, "G[%d]=%.2f%%", x, histogram1[x]*100*4/(float)array->size);
                else  SPRINTF(text, "B[%d]=%.2f%%", x, histogram2[x]*100*4/(float)array->size);
                gtk_statusbar_push(GTK_STATUSBAR(pointer_statusbar), 0, text);
            }
            
            break;
        case 'YUYV':
            for(i=array->size-2;i!=-1;i-=2) histogram[array->uchars[i]]++;
            for(i=array->size-1;i!=-2;i-=4) histogram1[array->uchars[i]]++;
            for(i=array->size-3;i!=-4;i-=4) histogram2[array->uchars[i]]++;
            
            FOR_INV(i, 256)
        {
            hist_max=MAX(histogram[i], hist_max);
            max1=MAX(histogram1[i], max1);
            max2=MAX(histogram2[i], max2);
        }
            
            draw_histogram(histogram_data, 127, histogram, gray_colors, hist_max);
            draw_histogram(histogram_data+256*128, 63, histogram1, u_colors, max1);
            draw_histogram(histogram_data+256*192, 63, histogram2, v_colors, max2);
            
            if (y>=0 && y<256 && x >=0 && x<256)
            {
                if (y<128)  SPRINTF(text, "Y[%d]=%f.2%%", x, histogram[x]*100*2/(float)array->size);
                else if (y<192)  SPRINTF(text, "U[%d]=%.2f%%", x, histogram1[x]*100*4/(float)array->size);
                else  SPRINTF(text, "V[%d]=%.2f%%", x, histogram2[x]*100*4/(float)array->size);
                gtk_statusbar_push(GTK_STATUSBAR(pointer_statusbar), 0, text);
            }
            break;
        case 'yuv2':
            for(i=array->size-1;i!=-1;i-=2) histogram[array->uchars[i]]++;
            for(i=array->size-2;i!=-2;i-=4) histogram1[array->uchars[i]]++;
            for(i=array->size-4;i!=-4;i-=4) histogram2[array->uchars[i]]++;
            
            FOR_INV(i, 256)
        {
            hist_max=MAX(histogram[i], hist_max);
            max1=MAX(histogram1[i], max1);
            max2=MAX(histogram2[i], max2);
        }
            
            draw_histogram(histogram_data, 127, histogram, gray_colors, hist_max);
            draw_histogram(histogram_data+256*128, 63, histogram1, u_colors, max1);
            draw_histogram(histogram_data+256*192, 63, histogram2, v_colors, max2);
            
            if (y>=0 && y<256 && x >=0 && x<256)
            {
                if (y<128)  SPRINTF(text, "Y[%d]=%f.2%%", x, histogram[x]*100*2/(float)array->size);
                else if (y<192)  SPRINTF(text, "U[%d]=%.2f%%", x, histogram1[x]*100*4/(float)array->size);
                else  SPRINTF(text, "V[%d]=%.2f%%", x, histogram2[x]*100*4/(float)array->size);
                gtk_statusbar_push(GTK_STATUSBAR(pointer_statusbar), 0, text);
                
            }
            break;
            
        default:
            gtk_statusbar_push(GTK_STATUSBAR(pointer_statusbar), 0, "No histogram for this format. Only Y800,RGB3 or yuv2.");
            
    }
    gtk_image_set_from_surface(image, histogram_surface);
    return G_SOURCE_CONTINUE;
}




void histogram_cb(GtkToolButton *toolbutton, gpointer pointer_statusbar )
{
    char text[NAME_MAX];
    GtkWidget *legend_box, *label;
    
    if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(toolbutton)))
    {
        histogram_data=MANY_ALLOCATIONS(256*256, uint32_t);
        histogram_surface=cairo_image_surface_create_for_data ((uchar*)histogram_data, CAIRO_FORMAT_ARGB32, 256, 256, 256*4);
        histogram_image=gtk_image_new_from_surface(histogram_surface);
        histogram_scrolled_window=gtk_scrolled_window_new(NULL, NULL);
        histogram=gtk_box_new(GTK_ORIENTATION_VERTICAL, 1);
        legend_box=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 1);
        gtk_container_add(GTK_CONTAINER(histogram_scrolled_window), histogram_image);
        gtk_container_add(GTK_CONTAINER(histogram), histogram_scrolled_window);
        gtk_container_add(GTK_CONTAINER(histogram), legend_box);
        
        SPRINTF(text, "%f", min_val);
        label=gtk_label_new(text);
        gtk_box_pack_start(GTK_BOX(legend_box), label, FALSE, FALSE, 0);
        SPRINTF(text, "%f", max_val);
        label=gtk_label_new(text);
        gtk_box_pack_end(GTK_BOX(legend_box), label, FALSE, FALSE, 0);
        
        if (legend){
            gtk_container_remove(GTK_CONTAINER(paned), legend);
            legend=NULL;
        }
        
        gtk_paned_add2(GTK_PANED(paned), histogram);
        gtk_widget_set_vexpand(histogram_image, TRUE);
        gtk_paned_set_position(GTK_PANED(paned), gtk_widget_get_allocated_height(paned)-256);
        gtk_widget_show_all(paned);
        g_signal_connect(G_OBJECT(histogram_scrolled_window), "size-allocate", G_CALLBACK(histogram_resize_cb), NULL);
        histogram_tick_id = gtk_widget_add_tick_callback(GTK_WIDGET(histogram_image), (GtkTickCallback) update_histogram_cb, pointer_statusbar, NULL);
    }
    else
    {
        gtk_widget_remove_tick_callback(GTK_WIDGET(histogram_image), histogram_tick_id);
        gtk_container_remove(GTK_CONTAINER(paned), histogram);
        FREE(histogram_data);
        //    gtk_widget_destroy(histogram);
        histogram=NULL;
    }
}