/* * imgproc.c: * * [1999/02/24] OSHIRO Naoki. * * $Log:$ */ /*----------------------------------------------------------------------* * see also. http://www.geocities.co.jp/SiliconValley/4137/candtcl1.html *----------------------------------------------------------------------*/ static char rcsid[]="$Id:$"; #include #include #include #include #include #include #include "tcl.h" #include "tk.h" /*----------------------------------------------------------------------*/ int createSameBlock(Tk_PhotoImageBlock *db, Tk_PhotoImageBlock *sb) { int i; /********************************************** * Tk_PhotoImageBlock は次のような形をしています。 typedef struct { unsigned char *pixelPtr; int width; int height; int pitch; int pixelSize; int offset[3]; } Tk_PhotoImageBlock; ***********************************************/ /* db を初期化 */ db->width = sb->width; db->pixelSize = sb->pixelSize; if (sb->width == 0 && sb->height == 0) { db->pitch = sb->pitch; db->height = sb->height; free(db->pixelPtr); return 0; } if (db->pitch != sb->pitch || db->height != sb->height) { if (db->pitch!=0 && db->height!=0) free(db->pixelPtr); db->pitch = sb->pitch; db->height = sb->height; db->pixelPtr = (unsigned char *)malloc(sb->pitch*sb->height); } for(i=0; i<3; i++){ db->offset[i] = sb->offset[i]; } return 0; } /* 輝度値の取得 */ static int getp(Tk_PhotoImageBlock* b, int x, int y, int* rgb) { unsigned char* pixelp; if(x < 0 || x >= b->width || y < 0 || y >= b->height) { return 0; } pixelp = (b->pixelPtr) + y * (b->pitch) + x * (b->pixelSize); * (rgb+0) = * (pixelp+(b->offset[0])); * (rgb+1) = * (pixelp+(b->offset[1])); * (rgb+2) = * (pixelp+(b->offset[2])); return 1; } /* 輝度値の設定 */ static int setp(Tk_PhotoImageBlock* b, int x, int y, int* rgb) { unsigned char* pixelp; if(x < 0 || x >= b->width || y < 0 || y >= b->height) { return 0; } pixelp = b->pixelPtr + y * (b->pitch) + x * (b->pixelSize); * (pixelp+(b->offset[0])) = (unsigned char)(* (rgb + 0)); * (pixelp+(b->offset[1])) = (unsigned char)(* (rgb + 1)); * (pixelp+(b->offset[2])) = (unsigned char)(* (rgb + 2)); return 1; } /*----------------------------------------------------------------------*/ static void filtering3x3( Tk_PhotoImageBlock* db, Tk_PhotoImageBlock* sb, int m[3][3]) { int x, y, sx, sy; int rgb[3]; /* 縁は処理できないのでゼロにする */ rgb[0]=rgb[1]=rgb[2]=0; for(y=0; y<(sb->height); y++){ setp(db, 0, y, rgb); setp(db, sb->width-1, y, rgb); } for(x=1; x<(sb->width-1); x++){ setp(db, x, 0, rgb); setp(db, x, db->height-1, rgb); } /* フィルタ処理 */ for(y=1; y<(sb->height-1); y++){ for(x=1; x<(sb->width-1); x++){ int r, g, b, ctr; r=0; g=0; b=0; ctr=0; for(sy=0; sy<3; sy++){ for(sx=0; sx<3; sx++){ if(getp(sb, x+sx-1, y+sy-1, rgb) == 1){ r += m[sy][sx] * rgb[0]; g += m[sy][sx] * rgb[1]; b += m[sy][sx] * rgb[2]; ctr+=(m[sy][sx]>=0)? m[sy][sx]:-m[sy][sx]; } } } if (r<0) r=-r; if (g<0) g=-g; if (b<0) b=-b; rgb[0] = (int)(r / ctr); rgb[1] = (int)(g / ctr); rgb[2] = (int)(b / ctr); setp(db, x, y, rgb); } } } /*----------------------------------------------------------------------*/ /* db と sb は同じサイズで確保されていることが前提 */ void copy(Tk_PhotoImageBlock *db, Tk_PhotoImageBlock *sb) { int x, y; int rgb[3]; for(y=0; yheight; y++){ for(x=0; xwidth; x++){ if (getp(sb, x, y, rgb) == 1) setp(db, x, y, rgb); } } } void binarize(Tk_PhotoImageBlock *sb, int thresh) { int x, y; int rgb[3]; for(y=0; yheight; y++){ for(x=0; xwidth; x++){ if (getp(sb, x, y, rgb) == 1) { if (rgb[0]>thresh && rgb[1]>thresh && rgb[2]>thresh) { rgb[0]=rgb[1]=rgb[2]=255; } else { rgb[0]=rgb[1]=rgb[2]=0; } setp(sb, x, y, rgb); } } } } static void sobel(Tk_PhotoImageBlock* db, Tk_PhotoImageBlock* sb) { static int mv[3][3] = { {1, 0, -1}, {2, 0, -2}, {1, 0, -1}, }; filtering3x3(db, sb, mv); } /*----------------------------------------------------------------------* * Tcl/Tk 側から呼び出される関数 * * Usage: sobel imgdest imgsrc ?thresh? *----------------------------------------------------------------------*/ int sobelInterp(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) { char *src, *dest; Tk_PhotoHandle sp, dp; Tk_PhotoImageBlock sb, db; int thresh; int i; /* 引数のチェック */ if (argc!=3 && argc!=4) { char buf[256]; sprintf(buf, "Invalid number of arguments."); Tcl_SetResult(interp, buf, NULL); return TCL_ERROR; } /* 画像データの割り付け */ dest = argv[1]; src = argv[2]; thresh = (argc==4)? atoi(argv[3]):128; sp = Tk_FindPhoto(interp, src ); dp = Tk_FindPhoto(interp, dest); Tk_PhotoGetImage(sp, &sb); Tk_PhotoGetImage(dp, &db); createSameBlock(&db, &sb); /* 画像処理 */ sobel(&db, &sb); binarize(&db, thresh); /* 処理結果の出力 */ Tk_PhotoPutBlock(dp, &db, 0, 0, db.width, db.height); return TCL_OK; } /*----------------------------------------------------------------------* * Tcl コマンドの生成 * * Tcl/Tk 側で "load libXXX.so imgproc" としたときにこの関数が呼ばれる *----------------------------------------------------------------------*/ int Imgproc_Init(Tcl_Interp* interp) { Tcl_CreateCommand(interp, "img_sobel", sobelInterp, NULL, NULL); Tcl_SetResult(interp, "Imgproc loaded.", NULL); return TCL_OK; }