Commit fd035a54 authored by Arnaud Blanchard's avatar Arnaud Blanchard

- Add option min and max

- Fix histogram for Y800 FL32
- Separate image code from histogram code
parent 567faf5f
# Copyright ETIS — ENSEA, Université de Cergy-Pontoise, CNRS (2011 - 2016)
# Author: Arnaud Blanchard (November 2016)
# This software is governed by the CeCILL v2.1 license under French law and abiding by the rules of distribution of free software.
# You can use, modify and/ or redistribute the software under the terms of the CeCILL v2.1 license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info".
# As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
# users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability.
# In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software,
# that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge.
# Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured  and, more generally, to use and operate it in the same conditions as regards security.
# The fact that you are presently reading this means that you have had knowledge of the CeCILL v2.1 license and that you accept its terms.
cd `dirname $0`
echo
echo "Checking `basename $PWD`"
echo "===================="
echo
echo "No check for now"
echo
......@@ -18,7 +18,7 @@ add_definitions(-Wall ${BL_DEFINITIONS} -Wno-deprecated-declarations) #device_ma
include_directories(${GTK3_INCLUDE_DIRS} ${BL_INCLUDE_DIRS} ${JPEG_INCLUDE_DIR})
link_directories(${GTK3_LIBRARY_DIRS})
add_definitions(${GTK3_CFLAGS_OTHER})
add_executable(o_gtk_image src/o_gtk_image.cpp src/image_display.cpp)
add_executable(o_gtk_image src/o_gtk_image.cpp src/image_display.cpp src/histogram.cpp)
target_link_libraries(o_gtk_image ${GTK3_LIBRARIES} ${BL_LIBRARIES} ${JPEG_LIBRARIES} )
......
#ifndef COMMON_H
#define COMMON_H
#include <gtk/gtk.h>
#include <blc_channel.h>
extern float min, max;
extern blc_channel *channel;
extern GtkWidget *legend;
extern u_int32_t false_colors[256];
extern uint32_t gray_colors[256];
extern uint32_t u_colors[256];
extern uint32_t v_colors[256];
extern uint32_t r_colors[256];
extern uint32_t g_colors[256];
extern uint32_t b_colors[256];
extern uint32_t *color_map;
extern GtkWidget *paned;
extern GdkDevice *pointer_device;
extern blc_channel mouse_channel;
extern char const *fullscreen_option;
void histogram_cb(GtkToolButton *toolbutton, gpointer pointer_statusbar );
GtkWidget *create_image_display(blc_channel *channel);
#endif
#include "common.h"
#include "blgtk.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;
GtkWidget *histogram_image, *histogram, *histogram_scrolled_window;
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 (channel->format){
case 'Y800':
switch (channel->type){
case 'UIN8':
FOR(i, channel->size) histogram[channel->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)channel->size);
gtk_statusbar_push(GTK_STATUSBAR(pointer_statusbar), 0, text);
}
break;
case 'FL32':
FOR(i, channel->total_length) histogram[(int)CLIP_UCHAR(((channel->floats[i]-min)/(max-min)*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-min-0.5)/256+min, histogram[x]*100/(float)channel->total_length);
gtk_statusbar_push(GTK_STATUSBAR(pointer_statusbar), 0, text);
}
break;
default: EXIT_ON_ARRAY_ERROR( channel, "Type not managed for format 'Y800'. Only 'UIN8' is");
}
break;
case 'RGB3':
FOR_INV(i, channel->size/3){
histogram[channel->uchars[i*3]]++;
histogram1[channel->uchars[i*3+1]]++;
histogram2[channel->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)channel->size);
else if (y<170) SPRINTF(text, "G[%d]=%.2f%%", x, histogram1[x]*100*4/(float)channel->size);
else SPRINTF(text, "B[%d]=%.2f%%", x, histogram2[x]*100*4/(float)channel->size);
gtk_statusbar_push(GTK_STATUSBAR(pointer_statusbar), 0, text);
}
break;
case 'YUYV':
for(i=channel->size-2;i!=-1;i-=2) histogram[channel->uchars[i]]++;
for(i=channel->size-1;i!=-2;i-=4) histogram1[channel->uchars[i]]++;
for(i=channel->size-3;i!=-4;i-=4) histogram2[channel->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)channel->size);
else if (y<192) SPRINTF(text, "U[%d]=%.2f%%", x, histogram1[x]*100*4/(float)channel->size);
else SPRINTF(text, "V[%d]=%.2f%%", x, histogram2[x]*100*4/(float)channel->size);
gtk_statusbar_push(GTK_STATUSBAR(pointer_statusbar), 0, text);
}
break;
case 'yuv2':
for(i=channel->size-1;i!=-1;i-=2) histogram[channel->uchars[i]]++;
for(i=channel->size-2;i!=-2;i-=4) histogram1[channel->uchars[i]]++;
for(i=channel->size-4;i!=-4;i-=4) histogram2[channel->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)channel->size);
else if (y<192) SPRINTF(text, "U[%d]=%.2f%%", x, histogram1[x]*100*4/(float)channel->size);
else SPRINTF(text, "V[%d]=%.2f%%", x, histogram2[x]*100*4/(float)channel->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;
}
static void histogram_resize_cb(GtkWidget *widget, GdkRectangle *allocation, gpointer user_data)
{
(void) widget;
(void) user_data;
cairo_surface_set_device_scale(histogram_surface, (double)256/(double)allocation->width, (double)256/(double)allocation->height);
}
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);
label=gtk_label_new(text);
gtk_box_pack_start(GTK_BOX(legend_box), label, FALSE, FALSE, 0);
SPRINTF(text, "%f", max);
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);
// gtk_widget_destroy(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;
}
}
This diff is collapsed.
#ifndef BYTE_DISPLAY_H
#define BYTE_DISPLAY_H
#include <gtk/gtk.h>
#include <blc_channel.h>
GtkWidget *create_image_display(blc_channel *channel);
#endif
\ No newline at end of file
#include "o_gtk_image.hpp"
#include "common.h"
#include <fcntl.h> // O_RDONLY ...
#include <stdio.h>
......@@ -10,8 +10,7 @@
#include <errno.h> //errno
#include "blc_core.h"
#include "blc_program.h"
#include "image_display.hpp"
float min, max;
const char *channel_name, *fullscreen_option, *keyboard_mode;
GtkWidget *window;
......@@ -43,7 +42,7 @@ void ask_quit()
}
void on_key_press(GtkWidget *widget, GdkEventKey *event){
char key;
if (event->type == GDK_KEY_PRESS){
......@@ -53,10 +52,8 @@ void on_key_press(GtkWidget *widget, GdkEventKey *event){
}
}
void activate_cb(GApplication *app)
{
char tmp_title[NAME_MAX*2+1];
GtkWidget *display=NULL;
GtkWidget *grid;
......@@ -65,19 +62,18 @@ void activate_cb(GApplication *app)
pointer_device = gdk_device_manager_get_client_pointer (device_manager);
window=gtk_application_window_new(GTK_APPLICATION(app));
SPRINTF(tmp_title, "%s", blc_program_name);
gtk_window_set_title(GTK_WINDOW(window), tmp_title);
gtk_window_set_title(GTK_WINDOW(window), input.name);
grid=gtk_grid_new();
// for(i=0; input_names[i]; i++){ This is for displaying multiple images
// input=new blc_channel(/*input_names[i]*/ input_name, BLC_CHANNEL_READ);
display=create_image_display(&input);
if (display==NULL) EXIT_ON_CHANNEL_ERROR(&input, "Format not managed.");
gtk_widget_set_hexpand(display, 1);
gtk_widget_set_vexpand(display, 1);
gtk_container_add(GTK_CONTAINER(grid), display);
// }
// for(i=0; input_names[i]; i++){ This is for displaying multiple images
// input=new blc_channel(/*input_names[i]*/ input_name, BLC_CHANNEL_READ);
display=create_image_display(&input);
if (display==NULL) EXIT_ON_CHANNEL_ERROR(&input, "Format not managed.");
gtk_widget_set_hexpand(display, 1);
gtk_widget_set_vexpand(display, 1);
gtk_container_add(GTK_CONTAINER(grid), display);
// }
gtk_container_add(GTK_CONTAINER(window), grid);
gtk_widget_show_all(window);
if (keyboard_mode) g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK (on_key_press), NULL);
......@@ -90,24 +86,37 @@ void activate_cb(GApplication *app)
int main(int argc, char *argv[])
{
int status=0;
char const *g_debug, *mouse_name;
char const *g_debug, *mouse_name, *min_str, *max_str;
blc_channel channel_info;
blc_program_set_description("Display the content of the blc_channel depending on its type on format");
blc_program_add_option(&keyboard_mode, 'k', "keyboard", NULL, "Send keyboard input to stdout", NULL);
blc_program_add_option(&mouse_name, 'm', "mouse", "blc_channel-out", "return the mouse coordinates and status in the channel", NULL);
blc_program_add_option(&min_str, 'm', "min", "FL32", "minimal value", NULL);
blc_program_add_option(&max_str, 'M', "max", "FL32", "maximal value", NULL);
// blc_program_add_option(&mouse_name, 'm', "mouse", "blc_channel-out", "return the mouse coordinates and status in the channel", NULL);
blc_program_add_option(&fullscreen_option, 'F', "fullscreen", NULL, "Set the window in fullscreen", NULL);
blc_program_add_option(&g_debug, ' ', "g-fatal-warnings", NULL, "Debug gtk.", NULL);
// This function is not yer operaiotnal blc_program_add_multiple_parameters(&input_names, "blc_channel", 1, "channel name you want to display");
// This function is not yer operaiotnal blc_program_add_multiple_parameters(&input_names, "blc_channel", 1, "channel name you want to display");
blc_program_add_parameter(&input_name, "blc_channel-in", 1, "channel name you want to display", NULL);
blc_program_init(&argc, &argv, ask_quit);
input.open(input_name, mode);
/*
while (sem_trywait(input.sem_ack_data)==0);
while (sem_trywait(input.sem_new_data)==0);
*/
min=0;
if (input.type=='UIN8') max=256;
if (input.type=='INT8'){
min=-128;
max=128;
}
if (input.type=='FL32' && input.format=='Y800'){
if (min_str) SSCANF(1, min_str, "%f", &min);
else min=0;
if (max_str) SSCANF(1, max_str, "%f", &max);
else max=1;
}else if (min_str || max_str) EXIT_ON_ARRAY_ERROR(&input, "Min (-m) and max (-M) have only effect for type FL32 format Y800");
gtk_disable_setlocale();
gtk_init(&argc, &argv);
......@@ -116,6 +125,6 @@ int main(int argc, char *argv[])
status = g_application_run(G_APPLICATION(app), 0, NULL);
g_object_unref(app);
return (status);
return EXIT_SUCCESS;
}
#ifndef MAIN_HPP
#define MAIN_HPP
#include <gtk/gtk.h>
#include <blc_channel.h>
extern GtkWidget *window;
extern GdkDisplay *main_display;
extern GdkDevice *pointer_device;
extern GtkApplication *app;
extern blc_channel mouse_channel;
extern int interactive_mode;
extern uint32_t format;
extern char const *fullscreen_option;
void quit();
#endif
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment