/* * ***************************************************************** * * * * * Copyright (c) Fast Corporation, 1997 * * * * * * All Rights Reserved. Unpublished rights reserved under * * * the copyright laws of the Japan. * * * * * * The software contained on this media is proprietary to * * * and embodies the confidential technology of Fast * * * Corporation. Possession, use, duplication or * * * dissemination of the software and media is authorized only * * * pursuant to a valid written license from Fast Corporation. * * * * * ***************************************************************** */ /* CSC90X 円形物の中心 & 半径抽出 CIR_MEAS.C */ /*[作成者]S.Kodama */ /* 目的: 関数: 履歴: Ver 1.0 97/11/07 注記:m_menu.hをインクルードして下さい。 m_menu.c及びm_note.cをリンクして下さい。 */ /* * Include compiler runtime library */ #include #include #include /* * Include CSC90X library */ #include "f_stdlib.h" #include "f_time.h" #include "f_gui.h" #include "f_stdio.h" #include "f_graph.h" #include "f_image.h" #include "f_pinf.h" #include "f_video.h" #include "f_system.h" #include "f_math.h" #include "f_file.h" /* * Include CSC90X common local */ #include "m_menu.h" /* * プロトタイプ宣言 */ void main( void ); void main_menu_disp( void ); void disp_help( void ); int prog_init( void ); /* 初期処理、初期設定 */ void set( void ); /* メニュー・パッドの表示 */ void sub_cir_set( int, int, PARADIGM * ); /* 走査範囲(円)の設定 */ void sub_level_set( int, int, PARADIGM * ); /* 濃度境界値の設定 */ void sub_noise_set( int, int, PARADIGM * ); /* ノイズ画素の設定 */ void sub_color_set( int, int, PARADIGM * ); /* 対象物の色の設定 */ void sub_scan_set( int, int, PARADIGM * ); /* 走査方向の設定 */ void sub_line_set( int, int, PARADIGM * ); /* 走査線本数の設定 */ void sub_exclude_set( int, int, PARADIGM * );/* 除去点距離の設定 */ void sub_save( int, int, PARADIGM * ); /* データ・セーブ */ void sub_gray_graph( int, int, PARADIGM * ); /* 濃度グラフ表示 */ void exec( void ); /* 処理実行 */ void get_gray_data( int, int, int, int, int *, int * ); /* 1ラインの濃淡データを得る */ void light_to_dark_border( int *, int *, int * ); /* 濃淡の境界座標を得る */ void dark_to_light_border( int *, int *, int * ); /* 濃淡の境界座標を得る */ extern int message_note( void ); /* * メニュー項目 */ #define LANG_N 2 #define MAIN_MENU_N 4 static const char *str_main_menu[MAIN_MENU_N][LANG_N] = { { " SET ", " 設 定 " }, { " EXEC ", " 実 行 " }, { " PROC3 ", " 処理3 " }, { " PROC4 ", " 処理4 " } }; #define INIT_CUR_POS_X 255 #define INIT_CUR_POS_Y 239 #define ALLOC_SIZE 128L /* 保存用パラメータ領域として確保するメモリサイズ */ #define EXECUTE 1 /* トラックボール EXECUTE キー */ #define CANCEL 2 /* トラックボール CANCEL キー */ /*--------------------------------------*/ /* 内容保持(ファイル化)パラメータ群 */ /*--------------------------------------*/ static struct { int x_center; /* 円の中心X座標 */ int y_center; /* 円の中心Y座標 */ int radius; /* 円の半径 */ int edge_level; /* 境界濃度 */ int noise_pixel; /* ノイズと見なす幅(画素単位) */ int work_color; /* 対象物の色 */ int scan_direction; /* 走査方向 */ int scan_line; /* 走査の本数(3〜16) */ int exclude_point; /* 最小自乗法円計算時の除去点 */ } *userp; /*--------------------------------*/ /* (サブルーチン間)共用エリア */ /*--------------------------------*/ static char *graphic_data_buffer; /* グラフィック メモリ データ退避エリア */ static int gray_table[710]; /* 濃淡データ格納エリア */ static int address_table[1024]; /* 濃淡データ採取アドレス群格納エリア */ /* * メイン */ void main( void ) { int sts; int xpos; int ypos; int s_xpos; int s_ypos; /* 初期メッセージ表示 */ if( NORMAL_RETURN != message_note() ) return; /* パラメタ初期化 */ xpos = INIT_CUR_POS_X; ypos = INIT_CUR_POS_Y; s_xpos = INIT_CUR_POS_X; s_ypos = INIT_CUR_POS_Y; /* 入力ビデオ制御 */ Lib_input_video_control( GRAY_PLANE ); /* ビデオ出力表示項目制御 */ Lib_display_control( GRAY_PLANE | LINE_PLANE | CHAR_PLANE ); /* ビデオ表示項目クリア */ Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); /* カーソル初期化 */ Lib_init_cursor(); /* メインメニューの表示 */ main_menu_disp(); /* マウスカーソルの表示 */ Lib_draw_cursor( INIT_CUR_POS_X, INIT_CUR_POS_Y ); if( -1 == prog_init() ) return; /* イニシャライザーが -1=ERROR を返答 */ /* したらシステムへ戻る(動作不能)。 */ /* メニュー制御 */ for (;;) { sts = 0; /* マウス位置読みとり */ sts = Lib_see_current_position( &xpos, &ypos ); if ( s_xpos != xpos || s_ypos != ypos ) { /* マウス表示位置移動 */ Lib_move_cursor( xpos, ypos ); s_xpos = xpos; s_ypos = ypos; } /* 処理振り分け */ if( CURSOR_EXECUTE == sts ) { if ( xpos > MENU_1_XS && xpos < MENU_1_XE && ypos > MENU_1_YS && ypos < MENU_1_YE ) { Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); set(); /*設定*/ Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); main_menu_disp(); } else if ( xpos > MENU_2_XS && xpos < MENU_2_XE && ypos > MENU_2_YS && ypos < MENU_2_YE ) { Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); exec( ); /*実行*/ Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); main_menu_disp(); } else if ( xpos > MENU_H_XS && xpos < MENU_H_XE && ypos > MENU_H_YS && ypos < MENU_H_YE ) { Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); disp_help(); /* ヘルプ */ main_menu_disp(); } else if ( xpos > MENU_E_XS && xpos < MENU_E_XE && ypos > MENU_E_YS && ypos < MENU_E_YE ) { break; /* 終了 */ } } } } /* * メインメニュー表示 */ static void main_menu_disp( void ) { int iLanguage; /* 日本語/英語表示文字列切替情報取得 */ iLanguage = Lib_get_disp_language(); /* 整列キー表示 -> ( m_menu.c ) */ SUB_menu_disp4he( (char *)str_main_menu[0][iLanguage], (char *)str_main_menu[1][iLanguage], (char *)NULL, (char *)NULL ); } /* * ヘルプ表示 */ static void disp_help( void ) { Lib_chrdisp( 10, 8, "【機能\概要】 CIR_MEAS" ); Lib_chrdisp( 11, 10, "<円形物の中心 & 半径計測>" ); Lib_chrdisp( 11, 12, "処理範囲を表\す円を設定し、その円を3〜16分割した" ); Lib_chrdisp( 11, 14, "角度位置に直線(中心から円周までの)を張り、その直線" ); Lib_chrdisp( 11, 16, "に沿って濃度エッジを抽出した後抽出された濃度エッジ" ); Lib_chrdisp( 11, 18, "群から近似円(最小自乗法円近似)を求めます。" ); Lib_chrdisp( 11, 20, "走査方向は下記のいずれかが選択できます。" ); Lib_chrdisp( 11, 22, " ○中心から外側に向かって走査" ); Lib_chrdisp( 11, 24, " ○円周から内側に向かって走査" ); } /**************************************************************/ /**** 初期処理、初期設定 **************************************/ /**************************************************************/ int prog_init() { static unsigned long size; Lib_gray_memory_cls( 0 ); userp = (void *)Lib_malloc( ALLOC_SIZE ); if( NULL == userp ) { Lib_invdisp( 2, 10, "ERROR:ユーザーパラメータ領域が確保できません" ); for( Lib_strtclk(); Lib_readclk() < 200; ) ; return( -1 ); } if( 0L == ( size = Lib_fload( "\\FS0\\CIR_MEAS.DAT", (char *)userp, ALLOC_SIZE )) ) { userp->x_center = 256; userp->y_center = 240; userp->radius = 100; userp->edge_level = 128; userp->noise_pixel = 5; userp->work_color = 0; userp->scan_direction = 0; userp->scan_line = 8; userp->exclude_point = 20; Lib_fsave( "\\FS0\\CIR_MEAS.DAT", (char *)userp, ALLOC_SIZE ); } return( 0 ); } /**************************************************************/ /**** パラメータ関係設定 **************************************/ /**************************************************************/ void set() { static char *select_color[2]={"黒","白"}; static char *select_scan[2]={"中心から","外側から"}; static int pad_level; static int width, height; PVAL value[8]; Lib_get_standard_key_size( &width, &height ); pad_level = Lib_view_open(); Lib_view_set_title( pad_level, "設定 & 実行" ); Lib_view_set_null( pad_level, 5, 5, " 領域設定 ", 0 ); Lib_view_set_uniq_numeral( pad_level, 5, 35, " 境界濃度 ", (long)userp->edge_level, 0L, 255L, 1 ); Lib_view_set_uniq_numeral( pad_level, 5, 65, "ノイズ画素", (long)userp->noise_pixel, 0L, 15L, 2 ); Lib_view_set_select( pad_level, 5, 95, "対象物の色", userp->work_color, 2, select_color, 3 ); Lib_view_set_select( pad_level, 5,125, " 走査方向 ", userp->scan_direction, 2, select_scan, 4 ); Lib_view_set_uniq_numeral( pad_level, 5,155, "走査線本数", (long)userp->scan_line, 3L, 16L, 5 ); Lib_view_set_uniq_numeral( pad_level, 5,185, "除去点距離", (long)userp->exclude_point, 0L, 99L, 6 ); Lib_view_set_null( pad_level, 5,215, "濃度グラフ", 7 ); Lib_view_set_null( pad_level, 5,250, " セーブ ", 8 ); Lib_set_paradigm( pad_level, 0, START_TIMING, sub_cir_set ); Lib_set_paradigm( pad_level, 1, END_TIMING, sub_level_set ); Lib_set_paradigm( pad_level, 2, END_TIMING, sub_noise_set ); Lib_set_paradigm( pad_level, 3, END_TIMING, sub_color_set ); Lib_set_paradigm( pad_level, 4, END_TIMING, sub_scan_set ); Lib_set_paradigm( pad_level, 5, END_TIMING, sub_line_set ); Lib_set_paradigm( pad_level, 6, END_TIMING, sub_exclude_set ); Lib_set_paradigm( pad_level, 7, START_TIMING, sub_gray_graph ); Lib_set_paradigm( pad_level, 8, START_TIMING, sub_save ); Lib_view_set_size( pad_level, 15, 35, 8, 5 ); Lib_draw_menu( pad_level ); Lib_process_menu( pad_level, value ); Lib_erase_menu( pad_level ); Lib_view_close( pad_level ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /** 走査範囲(円)の設定 *************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void sub_cir_set( timing, no, val ) int timing, no; PARADIGM val[]; { int center_x, center_y, x, y, old_x, old_y, r, mode, keydata; Lib_erase_cursor(); graphic_data_buffer = Lib_mlalloc( 31220 ); Lib_get( 0, 0, 511, 479, CHAR_PLANE, graphic_data_buffer ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); center_x = x = userp->x_center; center_y = y = userp->y_center; r = userp->radius; mode = keydata = 0; Lib_chrdisp( 1, 28, "円操作・・・・・・トラックボール回転操作" ); Lib_chrdisp( 1, 29, "モード変更・・オレンジキー押下" ); Lib_chrdisp( 1, 30, "終了・・・・・・・・赤色キー押下" ); Lib_move_cursor( x, y ); while( keydata != EXECUTE ) { Lib_drawcircle( center_x, center_y, r ); Lib_drawline( center_x - 15, center_y, center_x + 15, center_y ); Lib_drawline( center_x, center_y - 15, center_x, center_y + 15 ); old_x = x; old_y = y; keydata = Lib_see_current_position( &x, &y ); if( old_x != x || old_y != y ) { Lib_erascircle( center_x, center_y, r ); Lib_erasline( center_x - 15, center_y, center_x + 15, center_y ); Lib_erasline( center_x, center_y - 15, center_x, center_y + 15 ); } if( keydata == CANCEL ) { if( mode == 0 ) { mode = 1; x = r * 2; Lib_move_cursor( x, 0 ); } else { mode = 0; x = center_x; y = center_y; Lib_move_cursor( center_x, center_y ); } } if( mode == 0 ) center_x = x, center_y = y; if( mode == 1 ) r = x / 2; } if( 239 < r ) r = 239; userp->radius = r; userp->x_center = center_x; userp->y_center = center_y; Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); Lib_put( graphic_data_buffer ); Lib_lfree( graphic_data_buffer ); Lib_draw_cursor( 256, 240 ); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /** 背景と対象物の境界濃度設定 *******/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void sub_level_set( timing, no, val ) int timing, no; PARADIGM val[]; { userp->edge_level = (int)val[0].long_type; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /** ノイズ画素の設定 *****************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void sub_noise_set( timing, no, val ) int timing, no; PARADIGM val[]; { userp->noise_pixel = (int)val[0].long_type; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /** 対象物の色の設定 *****************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void sub_color_set( timing, no, val ) int timing, no; PARADIGM val[]; { userp->work_color = val[0].int_type; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /** 走査方向の設定 ******************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void sub_scan_set( timing, no, val ) int timing, no; PARADIGM val[]; { userp->scan_direction = val[0].int_type; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /** 走査線本数の設定 *****************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void sub_line_set( timing, no, val ) int timing, no; PARADIGM val[]; { userp->scan_line = (int)val[0].long_type; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /** 除去点距離の設定 *****************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void sub_exclude_set( timing, no, val ) int timing, no; PARADIGM val[]; { userp->exclude_point = (int)val[0].long_type; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /**** データセーブ *******************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void sub_save( timing, no, val ) int timing, no; PARADIGM val[]; { Lib_invdisp( 1, 30, "設定パラメータ・データをセーブ中です....." ); Lib_fsave( "\\FS0\\CIR_MEAS.DAT", (char *)userp, ALLOC_SIZE ); Lib_chrdisp( 1, 30, "                       " ); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /** 1ライン濃度のグラフ表示 *********/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void sub_gray_graph( timing, no, val ) int timing, no; PARADIGM val[]; { register int *table_addr; static int i, count, x, y; static int xs, ys, xe, ye, key, old_x, old_y; static int g_data1, g_data2; graphic_data_buffer = Lib_mlalloc( 31000 ); Lib_get( 0, 0, 511, 479, CHAR_PLANE, graphic_data_buffer ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); for( ; ; ) { Lib_chrdisp(11, 30, "------->終点を設定" ); Lib_invdisp( 1, 30, "始点を設定" ); Lib_draw_cursor( 256, 240 ); for( key = 0; key != EXECUTE; key = Lib_get_current_position( &xs, &ys )) ; Lib_chrdisp( 1, 30, "始点を設定" ); Lib_invdisp( 19, 30, "終点を設定" ); Lib_erase_cursor(); xe = xs + 2; ye = ys + 2; old_x = xe; old_y = ye; for( key = 0; key != EXECUTE; ) { Lib_drawline( xs, ys, xe, ye ); key = Lib_see_current_position( &xe, &ye ); if( old_x != xe || old_y != ye ) { Lib_erasline( xs, ys, old_x, old_y ); old_x = xe; old_y = ye; } } Lib_drawline( xs, ys, xe, ye ); /* 濃淡データ取得 & グラフ表示 */ Lib_chrdisp( 1, 30, "     " ); Lib_freeze( NOT_TRANSMIT ); get_gray_data( xs, ys, xe, ye, gray_table, address_table ); Lib_freerun(); table_addr = &gray_table[1]; count = gray_table[0] - 1; for( x = i = 0; i < count; i++, x++, table_addr++ ) { g_data1 = 479 - *table_addr; g_data2 = 479 - *( table_addr + 1 ); Lib_drawline( x, g_data1, x + 1, g_data2 ); } Lib_drawline( 0, 479 - userp->edge_level, gray_table[0], 479 - userp->edge_level ); Lib_chrdisp( 1, 30, "終了ならトラックボールの赤キー、再設定ならオレンジキーを押下" ); i = Lib_get_current_position( &x, &y ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); if( i == EXECUTE ) break; } Lib_put( graphic_data_buffer ); Lib_lfree( graphic_data_buffer ); Lib_draw_cursor( 256, 240 ); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /**** 処理の実行 *********************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void exec( ) { char chr_buff[10]; int i, j, k, x, y, angle; int sx[16], sy[16], cx, cy, r; int boundary_data[2], count; POINT_T point[16]; POINT_T retry_point[16]; double ax, ay, ar; int ix, iy, ir; int time; Lib_erase_cursor(); graphic_data_buffer = Lib_mlalloc( 31000 ); Lib_get( 0, 0, 511, 479, CHAR_PLANE, graphic_data_buffer ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); Lib_strtclk_count(); /* タイマースタート */ Lib_freeze( TRANSMIT ); cx = userp->x_center; cy = userp->y_center; r = userp->radius; Lib_drawcircle( cx, cy, r ); j = 3600 / userp->scan_line; for( angle = i = 0; i < userp->scan_line; i++, angle += j ) { x = Lib_cosfunc( angle ); y = Lib_sinfunc( angle ); x = ( r * x ) / 32767; y = ( r * y ) / 32767; sx[i] = cx + x; sy[i] = cy - y; Lib_line( sx[i], sy[i], cx, cy, DOTTED_LINE ); } if( userp->scan_direction == 0 ) /* 中心 → 外側 */ { for( j = i = 0; i < userp->scan_line; i++ ) { get_gray_data( cx, cy, sx[i], sy[i], gray_table, address_table ); if( userp->work_color == 0 ) /* 対象物は黒 */ dark_to_light_border( gray_table, address_table, boundary_data ); else /* 対象物は白 */ light_to_dark_border( gray_table, address_table, boundary_data ); if( boundary_data[0] != -1 ) { point[j].x = boundary_data[0]; point[j].y = boundary_data[1]; j++; } } } else /* 外側 → 中心 */ { for( j = i = 0; i < userp->scan_line; i++ ) { get_gray_data( sx[i], sy[i], cx, cy, gray_table, address_table ); if( userp->work_color == 0 ) /* 対象物は黒 */ light_to_dark_border( gray_table, address_table, boundary_data ); else /* 対象物は白 */ dark_to_light_border( gray_table, address_table, boundary_data ); if( boundary_data[0] != -1 ) { point[j].x = boundary_data[0]; point[j].y = boundary_data[1]; j++; } } } count = j; for( i = 0; i < count; i++ ) Lib_drawcircle( point[i].x, point[i].y, 3 ); if( 2 < count ) { Lib_fcalcircl( count, point, &ax, &ay, &ar ); ix = (int)ax; iy = (int)ay; ir = (int)ar; for( k = i = 0; i < count; i++ ) { x = ix - point[i].x; y = iy - point[i].y; j = Lib_sqrt32( x * x + y * y ); j = abs( j - ir ); if( j <= userp->exclude_point ) { retry_point[k].x = point[i].x; retry_point[k].y = point[i].y; k++; Lib_drawcircle( point[i].x, point[i].y, 1 ); Lib_drawcircle( point[i].x, point[i].y, 2 ); } } if( 2 < k ) { Lib_fcalcircl( k, retry_point, &ax, &ay, &ar ); Lib_chrdisp( 47, 2, "中心X座標=" ); Lib_chrdisp( 47, 3, "中心Y座標=" ); Lib_chrdisp( 47, 4, "   半径=" ); Lib_sprintf( chr_buff, "%.1lf", ax ); Lib_chrdisp( 58, 2, chr_buff ); Lib_sprintf( chr_buff, "%.1lf", ay ); Lib_chrdisp( 58, 3, chr_buff ); Lib_sprintf( chr_buff, "%.1lf", ar ); Lib_chrdisp( 58, 4, chr_buff ); x = (int)ax; y = (int)ay; Lib_drawline( x - 10, y, x + 10, y ); Lib_drawline( x, y - 10, x, y + 10 ); Lib_drawcircle( x, y, (int)ar ); } else Lib_invdisp( 9, 29, "ERROR:精密計測ができませんでした。" ); } else Lib_invdisp( 9, 29, "ERROR:計測できませんでした。" ); /* 処理時間表示 */ time = ( Lib_readclk_count() * 8138 ) / 10000; Lib_sprintf( chr_buff, "%4dmsec", time ); Lib_chrdisp( 1, 1, chr_buff ); Lib_chrdisp( 9, 30, "トラックボールのキーを押下してください" ); Lib_get_current_position( &x, &y ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); Lib_freerun(); Lib_put( graphic_data_buffer ); Lib_lfree( graphic_data_buffer ); Lib_draw_cursor( 256, 240 ); } /**********************************************************/ /**** 1ラインの濃淡データ及びそのアドレス群を取り出す ****/ /**********************************************************/ void get_gray_data( xs, ys, xe, ye, gray_table, address_table ) int xs, ys, xe, ye, *gray_table, *address_table; { register char *mem_base, *gmem_addr; register int i, x, y, xx, yy; register int x_size, y_size, x_add, y_add; mem_base = ( char * )Lib_adrs_gray_memory( 0 ); x = abs( xe - xs ) + 1; y = abs( ye - ys ) + 1; if( x >= y ) { *gray_table++ = x; /* 参照点数 */ x_size = x; y_add = ( y << 22 ) / x; if( ys == ye ) y_add = 0; if( ys > ye ) y_add = 0 - y_add; if( xs == xe ) x_add = 0; if( xs > xe ) x_add = -1; else x_add = 1; x = xs; y = ys; yy = ys << 22; for( i = 0; i < x_size; i++ ) { gmem_addr = y * 512 + x + mem_base; *gray_table++ = *gmem_addr & 0x00ff; *address_table++ = x; *address_table++ = y; x += x_add; yy += y_add; y = yy >> 22; } } else { *gray_table++ = y; /* 参照点数 */ y_size = y; x_add = ( x << 22 ) / y; if( xs == xe ) x_add = 0; if( xs > xe ) x_add = 0 - x_add; if( ys == ye ) y_add = 0; if( ys > ye ) y_add = -1; else y_add = 1; y = ys; x = xs; xx = xs << 22; for( i = 0; i < y_size; i++ ) { gmem_addr = y * 512 + x + mem_base; *gray_table++ = *gmem_addr & 0x00ff; *address_table++ = x; *address_table++ = y; y += y_add; xx += x_add; x = xx >> 22; } } *gray_table = -1; /* ストッパ */ } /**************************************************************************/ /**** 濃淡データ群から濃度境界(明から暗に変わる変化点)座標を見つける ****/ /**************************************************************************/ void light_to_dark_border( gray_table, address_table, boundary_data ) int *gray_table, *address_table, *boundary_data; { register int i, g_data, flag, brack_counter, white_counter, edge; int limit, x, y, noise; flag = brack_counter = white_counter = 0; x = y = -1; noise = userp->noise_pixel; edge = userp->edge_level; limit = *gray_table; gray_table += 1; for( i = 0; i < limit; i++, gray_table++, address_table += 2 ) { g_data = *gray_table; if( edge >= g_data ) { if( flag == 0 ) { if( white_counter > noise ) { x = *address_table; y = *( address_table + 1 ); flag = 1; white_counter = 0; } } brack_counter += 1; if( brack_counter > noise ) break; } if( edge < g_data ) { if( flag == 1 ) { flag = 0; brack_counter = 0; } white_counter += 1; } } *boundary_data++ = x; /* 変化点X */ *boundary_data = y; /* 変化点Y */ } /**************************************************************************/ /**** 濃淡データ群から濃度境界(暗から明に変わる変化点)座標を見つける ****/ /**************************************************************************/ void dark_to_light_border( gray_table, address_table, boundary_data ) int *gray_table, *address_table, *boundary_data; { register int i, g_data, flag, brack_counter, white_counter, edge; int limit, x, y, noise; flag = brack_counter = white_counter = 0; x = y = -1; noise = userp->noise_pixel; edge = userp->edge_level; limit = *gray_table; gray_table += 1; for( i = 0; i < limit; i++, gray_table++, address_table += 2 ) { g_data = *gray_table; if( edge <= g_data ) { if( flag == 0 ) { if( brack_counter > noise ) { x = *address_table; y = *( address_table + 1 ); flag = 1; brack_counter = 0; } } white_counter += 1; if( white_counter > noise ) break; } if( edge > g_data ) { if( flag == 1 ) { flag = 0; white_counter = 0; } brack_counter += 1; } } *boundary_data++ = x; /* 変化点X */ *boundary_data = y; /* 変化点Y */ }