2013年5月15日水曜日
<画像処理>グレースケール化した画像を濃度ヒスとラム化<メモ>
グレースケール化した画像を濃度ヒストグラム化させた際のソースプログラムを下記へ記した。
実行結果
前回のグレースケールのプログラムに濃度ヒストグラムの表示を追加しました。
ソース↓
#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,is,ie,imo,wid,hei;
unsigned char White = 0xFF,Black = 0x00;
unsigned char no_color[N2][N1][N3] = {};
unsigned char gray[N2+2][N1+2];
unsigned char data[N2][N3]={};
/*プロトタイプ宣言*/
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*);
void hist_glay(GtkWidget *widget);
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;
drawLine(100,100,200,200);
for(i=0;i<100;i++)
{
drawLine(100+i,100,100+i,100+i);
}
describe(widget);
/*
gint i, x, y;
gint w = gdk_pixbuf_get_width(gpIm);
gint h = gdk_pixbuf_get_height(gpIm);
guchar *data = gdk_pixbuf_get_pixels(gpIm);
gfloat gray;
gint rowstride = gdk_pixbuf_get_rowstride(gpIm);
for (y=0; y<N2; y++){
for (x=0; x<N1; x++){
i = y*rowstride + x*3;
gray = 0.299*(gfloat)data[i] + 0.587*(gfloat)data[i+1] + 0.114*(gfloat)data[i+2];
data[i]=data[i+1]=data[i+2]=gray;
}
}
*/
}
void hist_glay(GtkWidget *widget)
{
int hist[256]={};
long cou = 0;
int indig[256];
int he=1;
char string[5];
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;
for(y=0;y<N2;y++){
for(x=0;x<N1;x++){
hist[gray[y][x]]++;
}
}
for(i=0;i<256;i++)
{
drawLine(50+i,400,50+i,400-hist[i]/120);
}
describe(widget);
/*
he=hei-50;
for(i=0;i<256;i+=64){
drawLine(i+50,he,i+50,he+5);
}
drawLine(i+50,he,i+50,he+5);
for (i=0;i<256;i++){
drawLine(i+50,he-indig[i],(i+1)+50,he-indig[i]);
drawLine(i+50,he-indig[i],i+50,he);
drawLine((i+1)+50,he-indig[i],(i+1)+50,he);
}
*/
/* drawLine(100,100,300,300);
*/
/*ヒストグラムの初期化*/
/*
for(i=0;i<256;i++)
{
hist[i]=0;
}
for(i=0; i<*pinData; i++)
{
hist[gpBufData->data[i]]++;
}
for(i=0; i<256; i++){
for(j=0; j<(int)(256*hist[i]/(double)300); j++){
pinData->data[(256-j)*256 + i] = 255;
}
}
*/
}
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,*submenu2_2;
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("濃淡画像変換");
submenu2_2=gtk_menu_item_new_with_label("濃淡ヒストグラム");
gtk_menu_append(GTK_MENU(submenu2),submenu2_1);
gtk_menu_append(GTK_MENU(submenu2),submenu2_2);
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_signal_connect_object(GTK_OBJECT(submenu2_2),"activate",GTK_SIGNAL_FUNC(hist_glay),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);
}
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿