サンプルロゴ

2013年5月9日木曜日

<メモ>Linuxによる画像処理画像のグレースケール化<メモ>


Linuxでの画像処理の練習のソースコードを下記へ示しました。

実行結果は、



 の画像が、

機能内容
ファイル:「保存」、「展開」、「終了」
描画:「円の描画」、「直線の描画」
変換:「画像のグレースケール化」



ソースコード↓

#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define N1 640
#define N2 480
#define N3 3
//外部変数
GdkPixbuf* gpIm = NULL;
GdkPixmap* gpPixmap = NULL;
GdkPixbuf* gpPixbuf;
GtkWidget* Window,*gpDrawing;
GdkEventExpose ev;
/*graphic.c*/
GdkDrawable *drawing_area;
GdkColor color={0,0xffff,0x0000,0x0000}; /*declire GdkColor*/
GdkGC *gc=NULL;
/*gr*/
unsigned char *pinData,*pData,*gpBufData = NULL;
int size,i,j,k,x,y;
unsigned char White = 0xFF,Black = 0x00;
unsigned char no_color[N2][N1][N3] = {};
unsigned char gray[N2+2][N1+2];
/*プロトタイプ宣言*/
gint cofigured(GtkWidget*,GdkEventConfigure*);    //定番(画面の構築)
gint exposed(GtkWidget*,GdkEventExpose*,gpointer);    //画面の再描画
void Line(GtkWidget*);                //直線の描写
void drawLine(int,int,int,int);    //直線の描画関数
void describe();    //準定番
void quit();        //終了処理
void gui_config();    //メニューの設定
void memory_com();
/*濃淡画像*/
void effect_gray(GdkPixbuf*);
gint main(int argc,char *argv[])
{
    gtk_set_locale();    //日本語を表示できるようにする
    gtk_init(&argc,&argv);
    memory_com();        //画像データ用メモリ量の確保と初期化
    gui_config();
    gtk_main();
    return TRUE;
}
void memory_com()
{
    size = N1 * N2 * N3;
    gpBufData = (unsigned char*)malloc(size);
    memset(gpBufData,0,sizeof(size));
}
/*file_op*/
void FileOpen(GtkWidget *widget)
{
    if((gpIm = gdk_pixbuf_new_from_file("image.bmp",NULL)) == 0)
    {
        fprintf(stderr,"Cant load back image.bmp\n");
        exit(1);
    }
    gpBufData=gdk_pixbuf_get_pixels(gpIm);    //画像データの先頭ポインタの取得
    describe(widget);
}
void Line(GtkWidget *widget)
{
    long cou = 0;
    pinData = gpBufData;
    gdk_color_alloc(gdk_colormap_get_system(),&color);
    drawing_area = widget->window;
    gc = gdk_gc_new(drawing_area);
    gdk_gc_set_foreground(gc,&color);
  
    for(j = 0;j < N2; j++)
    {
        for(i = 0;i < N1; i++)
        {
            for(k = 0;k < N3; k++)
            {
                *(pinData + cou) = White;
                cou++;
            }
        }
    }
    drawLine(100,40,90,70);
    drawLine(50,30,400,300);
    describe(widget);
}
//直線の描画関数
void drawLine(int x1,int y1,int x2, int y2)
{

    int t,xv,yv;
    t = abs(x1 - x2);
    if(t < abs(y1 -y2)) t = abs(y1 -y2);
    if(t > 0)
    {
        for(j=0;j < t;j++)
        {
            xv = (int)(j*(x2-x1)/t) + x1;
            yv = (int)(j*(y2-y1)/t) + y1;
            *(pinData + yv * N3 + xv * N3) = White;
            *(pinData + yv * N1 * N3 + xv * N3 + 1) = Black;
            *(pinData + yv * N1 * N3 + xv * N3 + 2) = White;
        }
    }
}
//宴の描写
void drawcircle(int xco,int yco,int rad)
{
    float thi,pi=3.14;
    int xv,yv;
    for(j=0;j<2000;j++)
    {
        xv = (int)(rad*cos(pi*j/1000))+xco;
        yv = (int)(rad*sin(pi*j/1000))+yco;
        *(pinData+yv*N1*N3+xv*N3) = White;
        *(pinData+yv*N1*N3+xv*N3+1)=Black;
        *(pinData+yv*N1*N3+xv*N3+2)=White;//Black;
    }
}
void effect_gray(GdkPixbuf *widget) {
    long cou = 0;
    if((gpIm = gdk_pixbuf_new_from_file("image.bmp",NULL)) == 0)
         {
                 fprintf(stderr,"Cant load back image.bmp\n");
                 exit(1);
         }
    gpBufData=gdk_pixbuf_get_pixels(gpIm);  //画像データの先頭ポインタの取得
        pinData = gpBufData;
    for(i=0;i<N2;i++){
        for(j=0;j<N1;j++){
            for(k=0;k<N3;k++){
                no_color[i][j][k] = *(pinData + cou); /*[y軸][x軸][RGB] pinData 色の値*/
                cou++;
            }
        }
    }
    for(y=0;y<N2;y++){
        for(x=0;x<N1;x++){
            gray[y][x]=(unsigned char)(0.299 * no_color[y][x][0]+0.587 * no_color[y][x][1]+0.114*no_color[y][x][2]);
            for(k=0;k<N3;k++){
                    *(pinData++) = gray[y][x];
            }
        }
    }
    pinData = gpBufData;
    describe(widget);
}
void Circle(GtkWidget *widget)
{
    long cou=0;
    pinData = gpBufData;
    for(j=0;j<N2;j++)
        for(i=0;i<N1;i++)
            for(k=0;k<N3;k++){
                *(pinData + cou)=White;
                cou++;
            }
    drawcircle(300,200,100);
    describe(widget);
}
void Exit()
{
    quit();
}
void Savedata(GtkWidget *widget)
{
    gboolean nRet;
    if(gpIm) g_object_unref(gpIm);
    gpIm = gdk_pixbuf_new_from_data(gpBufData,GDK_COLORSPACE_RGB,FALSE,8,
        N1,N2,N1*3,NULL,NULL);
    nRet = gdk_pixbuf_save(gpIm,"image.bmp","bmp",NULL,NULL);
    if(nRet != TRUE)
    {
        printf("noninterlace data is preserved in the file.\n");
        exit(1);
    }
}
void describe(GtkWidget *widget)
{
    if(gpBufData == NULL) return;    //描画の準備
    ev.type = GDK_EXPOSE;
    ev.window = widget->window;
    ev.area.x = ev.area.y = 0;
    ev.area.width = widget->allocation.width;
    ev.area.height = widget->allocation.height;
    ev.send_event = ev.count = 0;
    if(ev.window != NULL)
    {
        gpIm = gdk_pixbuf_new_from_data(gpBufData,GDK_COLORSPACE_RGB,FALSE,8,N1,N2,N1*3,NULL,NULL);
        exposed(widget,&ev,NULL);
    }
}
gint exposed(GtkWidget* widget,GdkEventExpose* event,gpointer data){ //画面の再描画
    if(gpIm){
        gdk_draw_pixbuf(
        widget->window,    //描画するウインド
        widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
        gpIm,        //画像データ
        event->area.x,event->area.y,    //画像を更新するデータ
        event->area.x,event->area.y,    //の座標、幅、高さ
        event->area.width,event->area.height,
        GDK_RGB_DITHER_NORMAL,0,0
        );
    }
    return 0;
}
void quit(){ //終了
    if(gpBufData)    free(gpBufData);
    if(pData)    free(pData);
    gtk_exit(0);
}
void gui_config(){    //メニューの設定
    GtkWidget *vbox,*menubar,*gpWindow;
    GtkWidget *file_menu;    //表示するボタン
    GtkWidget *graphic_menu;    //表示するボタン
    /*追加*/
    GtkWidget *noutan_hen;    //演習2ボタン
    GtkWidget *submenu2,*submenu2_1;
    GtkWidget *submenu0,*submenu0_file,*submenu0_save,*submenu0_exit;
    GtkWidget *submenu1, *submenu1_line, *submenu1_circle;//サブメニュー
    GtkWidget *menuitem;    //メニュー項目
    GtkWidget *aframe;    //メニューを貼り付ける
    /*トップレベルウインドウを生成*/
    gpWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    /*タイトルの設定*/
    gtk_window_set_title(GTK_WINDOW(gpWindow),"画像処理");
    /*closed window*/
    gtk_signal_connect(GTK_OBJECT(gpWindow),"destroy",GTK_SIGNAL_FUNC(quit),NULL);
    vbox = gtk_vbox_new(FALSE,0);//vboxを作成
    gtk_container_border_width(GTK_CONTAINER(vbox),5);//vboxのサイズを設定する
    gtk_container_add(GTK_CONTAINER(gpWindow),vbox);//vboxをウインド
    /*create menu*/
    menubar = gtk_menu_bar_new();
    /*file menu*/
    file_menu = gtk_menu_item_new_with_label("ファイル");
    gtk_menu_bar_append(GTK_MENU_BAR(menubar),file_menu);
    /*menu item*/
    submenu0 = gtk_menu_new();
    submenu0_file = gtk_menu_item_new_with_label("開く");
    submenu0_save = gtk_menu_item_new_with_label("保存");
    submenu0_exit = gtk_menu_item_new_with_label("終了");
    gtk_menu_append(GTK_MENU(submenu0),submenu0_file);
    gtk_menu_append(GTK_MENU(submenu0),submenu0_save);
    gtk_menu_append(GTK_MENU(submenu0),submenu0_exit);
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_menu),submenu0);
    /*graphic menu*/
    graphic_menu = gtk_menu_item_new_with_label("描画");
    gtk_menu_bar_append(GTK_MENU_BAR(menubar),graphic_menu);
    /*menu item*/
    submenu1 = gtk_menu_new();
    submenu1_line = gtk_menu_item_new_with_label("直線");
    submenu1_circle = gtk_menu_item_new_with_label("円");
    gtk_menu_append(GTK_MENU(submenu1),submenu1_line);
    gtk_menu_append(GTK_MENU(submenu1),submenu1_circle);
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(graphic_menu),submenu1);
    /*noutan_hen*/
    noutan_hen = gtk_menu_item_new_with_label("変換");
        gtk_menu_bar_append(GTK_MENU_BAR(menubar),noutan_hen);
    /*menu itm*/
    submenu2 = gtk_menu_new();
    submenu2_1=gtk_menu_item_new_with_label("濃淡画像変換");
    gtk_menu_append(GTK_MENU(submenu2),submenu2_1);
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(noutan_hen),submenu2);
    aframe = gtk_aspect_frame_new(NULL,0.5,0.5,1.0,TRUE);
    gtk_frame_set_shadow_type(GTK_FRAME(aframe),GTK_SHADOW_NONE);
    gpDrawing = gtk_drawing_area_new();
    gtk_drawing_area_size(GTK_DRAWING_AREA(gpDrawing),N1,N2);
    gtk_container_add(GTK_CONTAINER(aframe),gpDrawing);
    gtk_signal_connect(GTK_OBJECT(gpWindow),"destroy",GTK_SIGNAL_FUNC(gtk_main_quit),NULL);
    gtk_signal_connect(GTK_OBJECT(gpDrawing),"expose_event",GTK_SIGNAL_FUNC(exposed),NULL);
    gtk_widget_set_events(gpDrawing,GDK_EXPOSURE_MASK);
    gtk_signal_connect_object(GTK_OBJECT(submenu0_file),"activate",GTK_SIGNAL_FUNC(FileOpen),GTK_OBJECT(gpDrawing));
    gtk_signal_connect_object(GTK_OBJECT(submenu0_save),"activate",GTK_SIGNAL_FUNC(Savedata),GTK_OBJECT(gpDrawing));
    gtk_signal_connect_object(GTK_OBJECT(submenu0_exit),"activate",GTK_SIGNAL_FUNC(Exit),GTK_OBJECT(gpDrawing));
    gtk_signal_connect_object(GTK_OBJECT(submenu1_line),"activate",GTK_SIGNAL_FUNC(Line),GTK_OBJECT(gpDrawing));
    gtk_signal_connect_object(GTK_OBJECT(submenu1_circle),"activate",GTK_SIGNAL_FUNC(Circle),GTK_OBJECT(gpDrawing));
    gtk_signal_connect_object(GTK_OBJECT(submenu2_1),"activate",GTK_SIGNAL_FUNC(effect_gray),GTK_OBJECT(gpDrawing));
    gtk_box_pack_start(GTK_BOX(vbox),menubar,FALSE,TRUE,0);
    gtk_box_pack_start(GTK_BOX(vbox),aframe,TRUE,TRUE,0);
    /*ウインドウ表示*/
    gtk_widget_show_all(gpWindow);
}

0 件のコメント:

コメントを投稿