#define VERSIONE_PROGRAMMA "Webcam Viewer v0.01.01" #include #include #include #include #include #include using namespace std; //webcam #include #pragma comment(lib,"Vfw32.lib") //gtk+ #include #pragma comment(lib,"atk-1.0.lib") #pragma comment(lib,"cairo.lib") #pragma comment(lib,"gio-2.0.lib") #pragma comment(lib,"glib-2.0.lib") #pragma comment(lib,"gmodule-2.0.lib") #pragma comment(lib,"gobject-2.0.lib") #pragma comment(lib,"gthread-2.0.lib") #pragma comment(lib,"gailutil.lib") #pragma comment(lib,"gdk_pixbuf-2.0.lib") #pragma comment(lib,"gdk-win32-2.0.lib") #pragma comment(lib,"gtk-win32-2.0.lib") #pragma comment(lib,"pango-1.0.lib") #pragma comment(lib,"pangocairo-1.0.lib") #pragma comment(lib,"pangoft2-1.0.lib") #pragma comment(lib,"pangowin32-1.0.lib") //macro inline char char_conversion(int c){ return ( (c)<255) ? (c) : 255; } //variabili GtkWidget *finestra1; GtkWidget *draw_area, *draw_area_sobel; GtkWidget *area_box; PangoLayout *testo_draw_area; long frame_count = 0; int global_frame_width; int global_frame_row_size; char *video_text; clock_t global_time_start, global_time_current; guchar * bit24format; guchar * bit24format_sobel; long bit24format_size; unsigned char ****tabella_yuy2_rgb; //funzioni int webcam(); gboolean expose_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data); //callback per drawing area LRESULT FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr); //callback per cap int main(int argc, char *argv[]) { GError ** thread_error; thread_error = NULL; if( ! g_thread_supported() ) g_thread_init( NULL ); gtk_init (&argc, &argv); //********** FINESTRA1 *************// finestra1 = gtk_window_new(GTK_WINDOW_TOPLEVEL); //creo la finestra principale gtk_window_set_title(GTK_WINDOW(finestra1), VERSIONE_PROGRAMMA); //setto il titolo della finestra principale gtk_container_set_border_width(GTK_CONTAINER(finestra1), 3); //setto il bordo della finestra principale gtk_window_set_resizable(GTK_WINDOW(finestra1), FALSE); //rendo non resizable la finestra principale g_signal_connect(G_OBJECT(finestra1), "delete_event", G_CALLBACK(gtk_main_quit), NULL); //box area_box = gtk_hbox_new(FALSE, 1); draw_area = gtk_drawing_area_new(); gtk_widget_set_size_request(draw_area, 640, 400); gtk_box_pack_start(GTK_BOX(area_box), draw_area, TRUE, TRUE, 0); g_signal_connect (G_OBJECT (draw_area), "expose_event", G_CALLBACK (expose_event_callback), NULL); testo_draw_area = gtk_widget_create_pango_layout(draw_area, "PangoLayout"); draw_area_sobel = gtk_drawing_area_new(); gtk_widget_set_size_request(draw_area_sobel, 640, 400); gtk_box_pack_start(GTK_BOX(area_box), draw_area_sobel, TRUE, TRUE, 0); g_signal_connect (G_OBJECT (draw_area_sobel), "expose_event", G_CALLBACK (expose_event_callback), NULL); gtk_container_add(GTK_CONTAINER(finestra1), area_box); gtk_widget_show_all(finestra1); g_thread_create((GThreadFunc) webcam, NULL, 0, thread_error); gtk_main(); return EXIT_SUCCESS; } int webcam(){ long x,y,z,h; CAPSTATUS status; LPBITMAPINFO video_format; DWORD dwSize; HWND hwnd = capCreateCaptureWindow("Explorer", WS_ICONIC, 0, 0, 640, 400, NULL, 0); capDriverConnect(hwnd, 0); capPreviewRate(hwnd, 66); // rate, in milliseconds capPreview(hwnd, TRUE); // starts preview capSetCallbackOnFrame(hwnd, FrameCallbackProc); //video format dwSize = capGetVideoFormatSize(hwnd); video_format = (LPBITMAPINFO) malloc (dwSize * sizeof(char)); video_text = (char *) malloc(200 * sizeof(char)); capGetVideoFormat(hwnd, video_format, dwSize); printf("video format: bit per pixel: %d compressione: %d\n", video_format->bmiHeader.biBitCount, video_format->bmiHeader.biCompression); if(video_format->bmiHeader.biBitCount != 16 || video_format->bmiHeader.biCompression != 844715353){ printf("Video format non compatibile.\n"); printf("formati supportati:\n"); printf("1 - 16bit con compressione 844715353\n"); return 0; } //cap status capGetStatus(hwnd, &status, sizeof(CAPSTATUS)); printf("cap status: %dx%d preview_status: %d\n", status.uiImageWidth, status.uiImageHeight, status.fLiveWindow); bit24format_size = status.uiImageWidth*status.uiImageHeight*3; bit24format = new guchar[bit24format_size]; bit24format_sobel = new guchar[bit24format_size]; global_frame_width = status.uiImageWidth; global_frame_row_size = status.uiImageWidth*2; //creazione tabella di conversione yuy2 to rgb printf("preparazione tabella yuy2 to rgb... "); tabella_yuy2_rgb = new unsigned char ***[3]; for(h=0;h<3;h++){ tabella_yuy2_rgb[h] = new unsigned char **[256]; for(x=0;x<256;x++){ tabella_yuy2_rgb[h][x] = new unsigned char *[256]; for(y=0;y<256;y++) tabella_yuy2_rgb[h][x][y] = new unsigned char[256]; } } for(x=0;x<256;x++) for(y=0;y<256;y++) for(z=0;z<256;z++){ tabella_yuy2_rgb[0][x][y][z] = char_conversion(abs( x + 1.371*(y - 128) )); tabella_yuy2_rgb[1][x][y][z] = char_conversion(abs( x - 0.698*(y - 128) - 0.336*(z - 128) )); tabella_yuy2_rgb[2][x][y][z] = char_conversion(abs( x + 1.732*(z - 128) )); } printf("fatto!\n"); //inizio visualizzazione immagini global_time_start = clock(); for(x=0;x<1000;x++){ capGrabFrameNoStop(hwnd); //Sleep(5); } capCaptureStop(hwnd); capSetCallbackOnFrame(hwnd, NULL); capDriverDisconnect(hwnd); return 1; } gboolean expose_event_callback(GtkWidget *widget, GdkEventExpose *event, gpointer data) { gdk_draw_arc (widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], TRUE, 0, 0, widget->allocation.width, widget->allocation.height, 0, 64 * 360); return TRUE; } LRESULT FrameCallbackProc(HWND hWnd, LPVIDEOHDR frame) { register long x,y=0, dietro=0; int Y1, Y2, Cb, Cr; int vsobel, hsobel; unsigned char sobel; float angolo; global_time_current = clock()-global_time_start; sprintf(video_text, "frame count: %d\ntime: %d ms\navarage frame rate: %.2f", frame_count, global_time_current, (float)frame_count*1000/global_time_current); for(x=0;xlpData[y] Y1 = frame->lpData[y++]; Cb = frame->lpData[y++]; Y2 = frame->lpData[y++]; Cr = frame->lpData[y++]; //***** normal video part bit24format[x++] = tabella_yuy2_rgb[0][Y1][Cr][Cb]; //red bit24format[x++] = tabella_yuy2_rgb[1][Y1][Cr][Cb]; //green bit24format[x++] = tabella_yuy2_rgb[2][Y1][Cr][Cb]; //blue bit24format[x++] = tabella_yuy2_rgb[0][Y2][Cr][Cb]; //red bit24format[x++] = tabella_yuy2_rgb[1][Y2][Cr][Cb]; //green bit24format[x++] = tabella_yuy2_rgb[2][Y2][Cr][Cb]; //blue //****** sobel part if(y > global_frame_row_size && y < frame->dwBytesUsed-global_frame_row_size){ x -= 6; //algoritmo di sobel hsobel = (int) frame->lpData[y-6-global_frame_row_size] - frame->lpData[y-2-global_frame_row_size] + frame->lpData[y-6] + frame->lpData[y-6] - frame->lpData[y-2] - frame->lpData[y-2] + frame->lpData[y-6+global_frame_row_size] - frame->lpData[y-2+global_frame_row_size] ; vsobel = (int) frame->lpData[y-6-global_frame_row_size] + frame->lpData[y-4-global_frame_row_size] + frame->lpData[y-4-global_frame_row_size] + frame->lpData[y-2-global_frame_row_size] - frame->lpData[y-6+global_frame_row_size] - frame->lpData[y-4+global_frame_row_size] - frame->lpData[y-4+global_frame_row_size] - frame->lpData[y-2+global_frame_row_size] ; sobel = char_conversion(abs(hsobel) + abs(vsobel)); bit24format_sobel[x++] = sobel; bit24format_sobel[x++] = sobel; bit24format_sobel[x++] = sobel; hsobel = (int) frame->lpData[y-4-global_frame_row_size] - frame->lpData[y-global_frame_row_size] + frame->lpData[y-4] + frame->lpData[y-4] - frame->lpData[y] - frame->lpData[y] + frame->lpData[y-4+global_frame_row_size] - frame->lpData[y+global_frame_row_size] ; vsobel = (int) frame->lpData[y-4-global_frame_row_size] + frame->lpData[y-2-global_frame_row_size] + frame->lpData[y-2-global_frame_row_size] + frame->lpData[y-global_frame_row_size] - frame->lpData[y-4+global_frame_row_size] - frame->lpData[y-2+global_frame_row_size] - frame->lpData[y-2+global_frame_row_size] - frame->lpData[y+global_frame_row_size] ; sobel = char_conversion(abs(hsobel) + abs(vsobel)); bit24format_sobel[x++] = sobel; bit24format_sobel[x++] = sobel; bit24format_sobel[x++] = sobel; } } gdk_draw_rgb_image(draw_area->window, draw_area->style->fg_gc[GTK_WIDGET_STATE(draw_area)], 0, 0, 640, 400, GDK_RGB_DITHER_NORMAL, bit24format, 640 * 3); gdk_draw_rgb_image(draw_area_sobel->window, draw_area_sobel->style->fg_gc[GTK_WIDGET_STATE(draw_area_sobel)], 0, 0, 640, 400, GDK_RGB_DITHER_NORMAL, bit24format_sobel, 640 * 3); pango_layout_set_text(testo_draw_area, video_text, strlen(video_text)); gdk_draw_layout(draw_area->window, draw_area->style->fg_gc[GTK_WIDGET_STATE(draw_area)], 10, 10, testo_draw_area); frame_count++; return (LRESULT) TRUE ; }