見出し画像

孤立点除去・収縮・膨脹

孤立点除去・収縮・膨脹


2024年11月3初稿

注視点

解説エッセイ『2値画像と4連結・8連結』で孤立点除去は
2値画像処理の典型的な例と図示して説明しましたが、良く
使われる処理として収縮・膨脹も図示して説明し、
孤立点除去・収縮・膨脹のソースコードも説明します!

1.孤立点除去

4連結孤立点除去

注視点に隣接する点≪上・左・下≫が有る(1)あれば、
変化無しだが、全て無い(0)の状態ならば、注視点が、
有る(1)でも消滅(0)に成る!

8連結孤立点除去

注視点に隣接する点≪上・左・右・下・左上・右上・左下・
右下≫が有る(1)あれば、変化無しだが、
全て無い(0)の状態ならば、注視点が、有る(1)でも
消滅(0)に成る!

孤立点除去例題元画像

細かい、点≪これが孤立点≫が有る2値化画像

孤立点除去例題結果画像

孤立点除去した結果を示す?!ノイズ的な孤立点が除去され
ている事に注意!

1-1.孤立点除去ソースコード

code:孤立点除去ソースコード

/************************************************************************/
/*****      孤立点除去                      :実行部:4連結:x方向*****/
/*****      REM_ISOLATION,s,d,4                  *****/
/************************************************************************/

void            Filter::rem_isolation_4_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         data,                               // 描画データ
    int         h                                   // 水平幅
){
    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps ){                                  // 注視点有効時
            if( *( ps - 1 ) || *( ps - inc )        // 左か上か
             || *( ps + 1 ) || *( ps + inc ) ){     // 右か下が有効なら
                *pd = data;                         // ば、書き込む
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}





//page
/************************************************************************/
/*****      孤立点除去                              :実行部:4連結*****/
/*****      REM_ISOLATION,s,d,4                  *****/
/************************************************************************/

void            Filter::rem_isolation_4(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         data                                // 描画データ
){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        rem_isolation_4_x( ptrs, ptrd, incs, data,  // 水平方向の処理
                                            h );    //
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}





//page
/************************************************************************/
/*****      孤立点除去                      :実行部:8連結:x方向*****/
/*****      REM_ISOLATION,s,d,8                  *****/
/************************************************************************/

void            Filter::rem_isolation_8_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         data,                               // 描画データ
    int         h                                   // 水平幅
){
    BYTE        *p;                                 // S画像Ptr

    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps ){                                  // 注視点有効時
            if( *( ps - 1 ) || *( ps + 1 ) ){       // 左右が有効なら
                *pd = data;                         // 書き込む
            }else{                                  // 上記以外の場合
                p = ps - inc - 1;                   // 左上をセットし
                if( *p || *(p+1) || *(p+2) ){       // 上側が有効なら
                    *pd = data;                     // 書き込む
                }else{                              // 上記以外で
                    p = ps + inc - 1;               // 左下をセットし
                    if( *p || *(p+1) || *(p+2) ){   // 下側が有効なら
                        *pd = data;                 // 書き込む
                    }                               //
                }                                   //
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}





//page
/************************************************************************/
/*****      孤立点除去                              :実行部:8連結*****/
/*****      REM_ISOLATION,s,d,8                  *****/
/************************************************************************/

void            Filter::rem_isolation_8(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         data                                // 描画データ
){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        rem_isolation_8_x( ptrs, ptrd, incs, data,  // 水平方向の処理
                                            h );    //
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}





//page
/************************************************************************/
/*****      孤立点除去                              :実行部:基本部*****/
/*****      REM_ISOLATION,s,d,c                  *****/
/************************************************************************/

int             Filter::rem_isolation(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         c,                                  // 連結性
    int         data                                // 描画データ
){
    TypeArray   s;                                  // S画像情報:局所
    TypeArray   d;                                  // D画像情報:局所
    int         sti;                                // ステータス情報

    sti = Clear( pd, 0 );                           // D画像0クリア
    if( sti != END_STI ){                           // エラーがある場合
        return( sti );                              // ステータスを返す
    }                                               //
    s   = *ps;                                      // 一旦、S画像情報
    ps  = &s;                                       // を局所化
    d   = *pd;                                      // 一旦、D画像情報
    pd  = &d;                                       // を局所化
    sti = PreProcessor3By3( ps, pd );               // 前処理
    if( sti != END_STI ){                           // エラーがある場合
        return( sti );                              // ステータスを返す
    }                                               //
    if( c == 4 ){                                   // 4連結なら
        rem_isolation_4( ps, pd, data );            // 左記で処理
    }else{                                          // 8連結なら
        rem_isolation_8( ps, pd, data );            // 左記で処理
    }                                               //
    return( END_STI );                              // 正常終了
}





//page
/************************************************************************/
/*****      孤立点除去                                      :実行部*****/
/*****      REM_ISOLATION,s,d,c                  *****/
/************************************************************************/

int             Filter::RemoveIsolation(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         c,                                  // 連結性
    int         data                                // 描画データ(省略時255)
){
    int         sti;                                // ステータス情報

    if( c != 4 && c != 8 ){                         // 連結性間違い時
        return( STI_FLG );                          // 左記を返す
    }                                               //
    sti = rem_isolation( ps, pd, c, data );         // 基本部で処理
    if( sti == END_STI ){                           // 処理成功の場合
        ClearRoundImage( pd, 0, 1 );                // 1周周囲クリア
    }                                               //
    return( sti );                                  // ステータスを返す
}

(1)RemoveIsolation(仮引数){アルゴリズム}

code:RemoveIsolation(仮引数){

/************************************************************************/
/*****      孤立点除去                                      :実行部*****/
/*****      REM_ISOLATION,s,d,c                  *****/
/************************************************************************/

int             Filter::RemoveIsolation(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         c,                                  // 連結性
    int         data                                // 描画データ(省略時255)
){
    int         sti;                                // ステータス情報

    if( c != 4 && c != 8 ){                         // 連結性間違い時
        return( STI_FLG );                          // 左記を返す
    }                                               //
    sti = rem_isolation( ps, pd, c, data );         // 基本部で処理
    if( sti == END_STI ){                           // 処理成功の場合
        ClearRoundImage( pd, 0, 1 );                // 1周周囲クリア
    }                                               //
    return( sti );                                  // ステータスを返す
}

(1-1)関数名

「Remove」は、取り除くとの意味です!
「Isolation」は、分離と言う動詞で品詞とし孤立を意味!

(1-2)仮引数

code:仮引数

int             Filter::RemoveIsolation(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         c,                                  // 連結性
    int         data                                // 描画データ(省略時255)
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int data)」は、結果書き込み画素の値です!

(1-3)ローカル変数

code:ローカル変数

){
    int         sti;                                // ステータス情報

「int sti;」は、関数のステータス情報(エラーコード)で
す!

(1-4)アルゴリズム

code:アルゴリズム

    if( c != 4 && c != 8 ){                         // 連結性間違い時
        return( STI_FLG );                          // 左記を返す
    }                                               //
    sti = rem_isolation( ps, pd, c, data );         // 基本部で処理
    if( sti == END_STI ){                           // 処理成功の場合
        ClearRoundImage( pd, 0, 1 );                // 1周周囲クリア
    }                                               //
    return( sti );                                  // ステータスを返す
}

「if(c!=4&&c!=8){return(STI_FLG);}」は、連結性が4でも
8でも無い場合はエラーとし「STI_FLG」を関数辺値とし返
し終了!
「sti=rem_isolation(ps,pd,c,data);」は、下請け関数「
rem_isolation(ps,pd,c,data);」で処理しステータスを一旦
格納、
「if(sti==END_STI){ClearRoundImage(pd,0,1);}」は、実行
成功ならば、「ClearRoundImage(pd,0,1);」で結果画像の
外周を0クリア
「return(sti);」は、ステータス(成功)を関数辺値とし
返し終了!

(2)rem_isolation(仮引数){アルゴリズム}

code:rem_isolation(仮引数){

/************************************************************************/
/*****      孤立点除去                              :実行部:基本部*****/
/*****      REM_ISOLATION,s,d,c                  *****/
/************************************************************************/

int             Filter::rem_isolation(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         c,                                  // 連結性
    int         data                                // 描画データ
){
    TypeArray   s;                                  // S画像情報:局所
    TypeArray   d;                                  // D画像情報:局所
    int         sti;                                // ステータス情報

    sti = Clear( pd, 0 );                           // D画像0クリア
    if( sti != END_STI ){                           // エラーがある場合
        return( sti );                              // ステータスを返す
    }                                               //
    s   = *ps;                                      // 一旦、S画像情報
    ps  = &s;                                       // を局所化
    d   = *pd;                                      // 一旦、D画像情報
    pd  = &d;                                       // を局所化
    sti = PreProcessor3By3( ps, pd );               // 前処理
    if( sti != END_STI ){                           // エラーがある場合
        return( sti );                              // ステータスを返す
    }                                               //
    if( c == 4 ){                                   // 4連結なら
        rem_isolation_4( ps, pd, data );            // 左記で処理
    }else{                                          // 8連結なら
        rem_isolation_8( ps, pd, data );            // 左記で処理
    }                                               //
    return( END_STI );                              // 正常終了
}

(2-1)関数名

「rem_」は、「Remove」の省略で取り除くとの意味です!
「isolation」は、分離と言う動詞で品詞とし孤立を意味!

(2-2)仮引数

code:仮引数

int             Filter::rem_isolation(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         c,                                  // 連結性
    int         data                                // 描画データ
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int data)」は、結果書き込み画素の値です!

(2-3)ローカル変数

code:ローカル変数

){
    TypeArray   s;                                  // S画像情報:局所
    TypeArray   d;                                  // D画像情報:局所
    int         sti;                                // ステータス情報

「TypeArray s;」は、元画像情報のローカル変数です!
「TypeArray d;」は、結果画像情報のローカル変数です!
「int sti;」は、関数のステータス情報(エラーコード)で
す!

(2-4)アルゴリズム

code:アルゴリズム

    sti = Clear( pd, 0 );                           // D画像0クリア
    if( sti != END_STI ){                           // エラーがある場合
        return( sti );                              // ステータスを返す
    }                                               //
    s   = *ps;                                      // 一旦、S画像情報
    ps  = &s;                                       // を局所化
    d   = *pd;                                      // 一旦、D画像情報
    pd  = &d;                                       // を局所化
    sti = PreProcessor3By3( ps, pd );               // 前処理
    if( sti != END_STI ){                           // エラーがある場合
        return( sti );                              // ステータスを返す
    }                                               //
    if( c == 4 ){                                   // 4連結なら
        rem_isolation_4( ps, pd, data );            // 左記で処理
    }else{                                          // 8連結なら
        rem_isolation_8( ps, pd, data );            // 左記で処理
    }                                               //
    return( END_STI );                              // 正常終了
}

「sti=Clear(pd,0);if(sti!=END_STI){return(sti);」は、
結果画像を0クリア!エラーが有れば終了!
「s=*ps;ps=&s;d=*pd;pd=&d;」は、画像情報をローカル変数
にセット※備考:元の情報を弄るので影響が無い様にする為
「sti=PreProcessor3By3(ps,pd);if(sti!=END_STI){
return(sti);}」は、2値画像変換用の前処理として「
S・D画像情報をS・D画像情報の最小幅に補正&検査」を
行う!
「if(c==4){rem_isolation_4(ps,pd,data);}」は、4連結時
でサブルーチン関数「rem_isolation_4(ps,pd,data);」で
処理!
「}else{if(c==8){rem_isolation_4(ps,pd,data);}」は、
8連結時でサブルーチン関数「
rem_isolation_8(ps,pd,data);」で処理
「return(END_STI);」は、正常終了を関数辺値とし返す!

(3)rem_isolation_4(仮引数){アルゴリズム}

code:rem_isolation_4(仮引数){

/************************************************************************/
/*****      孤立点除去                              :実行部:4連結*****/
/*****      REM_ISOLATION,s,d,4                  *****/
/************************************************************************/

void            Filter::rem_isolation_4(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         data                                // 描画データ
){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        rem_isolation_4_x( ptrs, ptrd, incs, data,  // 水平方向の処理
                                            h );    //
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}

(3-1)関数名

「rem_」は、「Remove」の省略で取り除くとの意味です!
「isolation」は、分離と言う動詞で品詞とし孤立を意味!
「_4」は、4連結の処理を意味!

(3-2)仮引数

code:仮引数

void            Filter::rem_isolation_4(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         data                                // 描画データ
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int data)」は、結果書き込み画素の値です!

(3-3)ローカル変数

code:ローカル変数

){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

「BYTE* ptrs;」は、元画像画素ポインタ変数です!
「BYTE* ptrd;」は、結果画像画素ポインタ変数です!
「int h;」は、水平幅
「int v;」は、垂直幅
「int incs;」は、元画像の垂直方向増加幅
「int incd;」は、結果画像の垂直方向増加幅

(3-4)アルゴリズム

code:アルゴリズム

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        rem_isolation_4_x( ptrs, ptrd, incs, data,  // 水平方向の処理
                                            h );    //
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}

「h=ps->h;v=ps->v;」は、水平幅・垂直幅取り出し!
「incs=ps->inc;incd=pd->inc;」は、元画像・結果画像の
垂直方向増加幅取り出し!
「ptrs=(BYTE*)ps->adr;ptrd=(BYTE*)pd->adr;」は、
元画像・結果画像のポインタの値をローカル変数にセットと
高速化の為にローカル変数変数にセットする6行!
「while(--v>=0){・・ループ中身・・}」は、垂直方向に
垂直幅分繰り返し処理、そしてループ中身
は、「rem_isolation_4_x(ptrs,ptrd,incs,data,h);」で
水平方向処理として画像1行分処理、
「ptrs+=incs;ptrd+=incd;」で元画像・結果画像のポイン
タの値をソレゾレの垂直幅分増加

(4)rem_isolation_4_x(仮引数){アルゴリズム}

code:rem_isolation_4_x(仮引数){

/************************************************************************/
/*****      孤立点除去                      :実行部:4連結:x方向*****/
/*****      REM_ISOLATION,s,d,4                  *****/
/************************************************************************/

void            Filter::rem_isolation_4_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         data,                               // 描画データ
    int         h                                   // 水平幅
){
    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps ){                                  // 注視点有効時
            if( *( ps - 1 ) || *( ps - inc )        // 左か上か
             || *( ps + 1 ) || *( ps + inc ) ){     // 右か下が有効なら
                *pd = data;                         // ば、書き込む
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}

(4-1)関数名

「rem_」は、「Remove」の省略で取り除くとの意味です!
「isolation」は、分離と言う動詞で品詞とし孤立を意味!
「_4」は、4連結の処理を意味!
「_x」は、X座標方向(水平方向)の処理を意味!

(4-2)仮引数

code:仮引数

void            Filter::rem_isolation_4_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         data,                               // 描画データ
    int         h                                   // 水平幅
){

「BYTE* ps,」は、元画像(S≒ソース画像)画素実行ポイ
ンタ「BYTE」型(1バイト単位)のポインタ変数です!
「BYTE* pd,」は、結果画像(D≒ディスティネーション
画像)画素実行ポインタ「BYTE」型(1バイト単位)の
ポインタ変数です!
「int data)」は、結果書き込み画素の値です!
「int h」は、水平方向処理幅です!

(4-3)アルゴリズム

code:アルゴリズム

){
    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps ){                                  // 注視点有効時
            if( *( ps - 1 ) || *( ps - inc )        // 左か上か
             || *( ps + 1 ) || *( ps + inc ) ){     // 右か下が有効なら
                *pd = data;                         // ば、書き込む
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}

「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の
「if(ps){・・分岐中身・・}」は、「if(ps){」で元画像
が条件「(≠0)」で分岐中身を処理と「ps++;pd++;」で
元画像・結果画像のポインタを水平方向に進める!つまり、
水平方向の処理として繰り返し、条件有効な場合で分岐中身
を処理します?!そして分岐中身は、
「if((ps-1)||(ps-inc)||(ps+1)||(ps+inc)){
*pd=data;}」で条件として「元画像画素ポインタから相対的
に4連結で隣接(左・上・右・下)の何れかが有効(≠0)
ならば」、「*pd=data;」と結果画像画素に結果書き込み
画素の値をセットします!

(5)rem_isolation_8(仮引数){アルゴリズム}

code:rem_isolation_8(仮引数){

/************************************************************************/
/*****      孤立点除去                              :実行部:8連結*****/
/*****      REM_ISOLATION,s,d,8                  *****/
/************************************************************************/

void            Filter::rem_isolation_8(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         data                                // 描画データ
){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        rem_isolation_8_x( ptrs, ptrd, incs, data,  // 水平方向の処理
                                            h );    //
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}

(5-1)関数名

「rem_」は、「Remove」の省略で取り除くとの意味です!
「isolation」は、分離と言う動詞で品詞とし孤立を意味!
「_8」は、8連結の処理を意味!

(5-2)仮引数

code:仮引数

void            Filter::rem_isolation_8(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         data                                // 描画データ
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int data)」は、結果書き込み画素の値です!

(5-3)ローカル変数

code:ローカル変数

){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

「BYTE* ptrs;」は、元画像画素ポインタ変数です!
「BYTE* ptrd;」は、結果画像画素ポインタ変数です!
「int h;」は、水平幅
「int v;」は、垂直幅
「int incs;」は、元画像の垂直方向増加幅
「int incd;」は、結果画像の垂直方向増加幅

(5-4)アルゴリズム

code:アルゴリズム

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        rem_isolation_8_x( ptrs, ptrd, incs, data,  // 水平方向の処理
                                            h );    //
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //

「h=ps->h;v=ps->v;」は、水平幅・垂直幅取り出し!
「incs=ps->inc;incd=pd->inc;」は、元画像・結果画像の
垂直方向増加幅取り出し!
「ptrs=(BYTE*)ps->adr;ptrd=(BYTE*)pd->adr;」は、
元画像・結果画像のポインタの値をローカル変数にセットと
高速化の為にローカル変数変数にセットする6行!
「while(--v>=0){・・ループ中身・・}」は、垂直方向に
垂直幅分繰り返し処理、そしてループ中身
は、「rem_isolation_8_x(ptrs,ptrd,incs,data,h);」で
水平方向処理として画像1行分処理、
「ptrs+=incs;ptrd+=incd;」で元画像・結果画像のポイン
タの値をソレゾレの垂直幅分増加

(6)rem_isolation_8_x(仮引数){アルゴリズム}

code:rem_isolation_8_x(仮引数){

/************************************************************************/
/*****      孤立点除去                      :実行部:8連結:x方向*****/
/*****      REM_ISOLATION,s,d,8                  *****/
/************************************************************************/

void            Filter::rem_isolation_8_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         data,                               // 描画データ
    int         h                                   // 水平幅
){
    BYTE        *p;                                 // S画像Ptr

    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps ){                                  // 注視点有効時
            if( *( ps - 1 ) || *( ps + 1 ) ){       // 左右が有効なら
                *pd = data;                         // 書き込む
            }else{                                  // 上記以外の場合
                p = ps - inc - 1;                   // 左上をセットし
                if( *p || *(p+1) || *(p+2) ){       // 上側が有効なら
                    *pd = data;                     // 書き込む
                }else{                              // 上記以外で
                    p = ps + inc - 1;               // 左下をセットし
                    if( *p || *(p+1) || *(p+2) ){   // 下側が有効なら
                        *pd = data;                 // 書き込む
                    }                               //
                }                                   //
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}

(6-1)関数名

「rem_」は、「Remove」の省略で取り除くとの意味です!
「isolation」は、分離と言う動詞で品詞とし孤立を意味!
「_8」は、8連結の処理を意味!
「_x」は、X座標方向(水平方向)の処理を意味!

(6-2)仮引数

code:仮引数

void            Filter::rem_isolation_8_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         data,                               // 描画データ
    int         h                                   // 水平幅
){

「BYTE* ps,」は、元画像(S≒ソース画像)画素実行ポイ
ンタ「BYTE」型(1バイト単位)のポインタ変数です!
「BYTE* pd,」は、結果画像(D≒ディスティネーション
画像)画素実行ポインタ「BYTE」型(1バイト単位)の
ポインタ変数です!
「int data)」は、結果書き込み画素の値です!
「int h」は、水平方向処理幅です!

(6-3)ローカル変数

code:ローカル変数

){
    BYTE        *p;                                 // S画像Ptr

「BYTE *p;」は、元画像画素から左上・左下位置を使用する
為のポインタ

(6-4)アルゴリズム

code:アルゴリズム

    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps ){                                  // 注視点有効時
            if( *( ps - 1 ) || *( ps + 1 ) ){       // 左右が有効なら
                *pd = data;                         // 書き込む
            }else{                                  // 上記以外の場合
                p = ps - inc - 1;                   // 左上をセットし
                if( *p || *(p+1) || *(p+2) ){       // 上側が有効なら
                    *pd = data;                     // 書き込む
                }else{                              // 上記以外で
                    p = ps + inc - 1;               // 左下をセットし
                    if( *p || *(p+1) || *(p+2) ){   // 下側が有効なら
                        *pd = data;                 // 書き込む
                    }                               //
                }                                   //
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}

「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の
「if(ps){・・分岐中身・・}」は、「if(ps){」で元画像
が条件「(≠0)」で分岐中身を処理と「ps++;pd++;」で
元画像・結果画像のポインタを水平方向に進める!つまり、
水平方向の処理として繰り返し、条件有効な場合で分岐中身
を処理します?!そして分岐中身は、
「if((ps-1)||(ps+1)){*pd=data;}」で条件として
「元画像画素ポインタから相対的に左右隣接」ならば、
「pd=data;」と結果画像画素に結果書き込み
画素の値をセットします!
しして「}else{・・非条件分岐・・}」で左右隣接が無かっ
た時の非条件分岐ブロックで
「p=ps-inc-1;」と左上ポインタをセットし、
「if(p||(p+1)||(p+2)){*pd=data;}」で条件として
「元画像画素ポインタから相対的に左上・右上隣接」ならば
「pd=data;」と結果画像画素に結果書き込み、
「}else{」でその条件ではずれ場合、
「p=ps+inc-1;」と左下ポインタをセットし、
「if(p||(p+1)||(p+2)){*pd=data;}」で条件として
「元画像画素ポインタから相対的に左下・右下隣接」ならば
「*pd=data;」と結果画像画素に結果書き込む!

2.収縮

4連結収縮

注視点に隣接する点≪上・左・下≫が全部有る(1)なれ
ば、変化無しだが、一つでも無い(0)状態ならば、
注視点が、消滅(0)に成る!

8連結収縮

注視点に隣接する点≪上・左・下・左上・右上・左下・
右下≫が全部有る(1)なれば、変化無しだが、一つでも無
注視点が、消滅(0)に成る!

収縮例題元画像

収縮を行う前の2値化画像

収縮例題結果画像

収縮した結果を示す?!一回り細く成ったり、消えた事に
注意!

2-1.収縮ソースコード

code:収縮ソースコード

/************************************************************************/
/*****      収縮                            :実行部:4連結:x方向*****/
/*****      COMPACTION,s,d,4,r                    *****/
/************************************************************************/

void            Filter::compaction_4_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         h                                   // 水平幅
){
    BYTE        zero;                               // 0データ

    zero = 0;                                       // 0データセット
    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps ){                                  // 注視点有効時
            if( *( ps - inc ) == 0                  // 上か
                        || *( ps - 1 ) == 0         // 左か
                        || *( ps + 1 ) == 0         // 右か
                        || *( ps + inc ) == 0 ){    // 下が0ならば
                *pd = zero;                         // 0を書き込む
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}





//page
/************************************************************************/
/*****      収縮                                    :実行部:4連結*****/
/*****      COMPACTION,s,d,4,r                    *****/
/************************************************************************/

void            Filter::compaction_4(
    TypeArray   *ps,                                // S画像Ptr
    TypeArray   *pd                                 // D画像情報
){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        compaction_4_x( ptrs, ptrd, incs, h );      // 水平方向の処理
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}





//page
/************************************************************************/
/*****      収縮                            :実行部:8連結:x方向*****/
/*****      COMPACTION,s,d,8,r                    *****/
/************************************************************************/

void            Filter::compaction_8_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         h                                   // 水平幅
){
    BYTE        *p;                                 // S画像Ptr
    BYTE        zero;                               // 0データ

    zero = 0;                                       // 0データセット
    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps ){                                  // 注視点有効時
            if( *( ps - 1 ) == 0                    // 左右に0が
                            || *( ps + 1 ) == 0 ){  // あれば
                *pd = zero;                         // 0を書き込む
            }else{                                  // 上記以外の場合
                p = ps - inc - 1;                   // 左上をセットし
                if( *p == 0 || *( p + 1 ) == 0      // 上側に0が
                            || *( p + 2 ) == 0 ){   // あれば
                    *pd = zero;                     // 0を書き込む
                }else{                              // 上記以外で
                    p = ps + inc - 1;               // 左下をセットし
                    if( *p == 0 || *( p + 1 ) == 0  // 下側に0が
                            || *( p + 2 ) == 0 ){   // あれば
                        *pd = zero;                 // 0を書き込む
                    }                               //
                }                                   //
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}





//page
/************************************************************************/
/*****      収縮                                    :実行部:8連結*****/
/*****      COMPACTION,s,d,8,r                    *****/
/************************************************************************/

void            Filter::compaction_8(
    TypeArray   *ps,                                // S画像Ptr
    TypeArray   *pd                                 // D画像情報
){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        compaction_8_x( ptrs, ptrd, incs, h );      // 水平方向の処理
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}





//page
/************************************************************************/
/*****      収縮                        :実行部:基本部:1回専用  *****/
/*****      COMPACTION,s,d,c,1                    *****/
/************************************************************************/

int             Filter::compactionSingle(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         c                                   // 連結性
){
    TypeArray   s;                                  // S画像情報:局所
    TypeArray   d;                                  // D画像情報:局所
    TypeArray   s1;                                 // T画像情報:局所:内側
    TypeArray   d1;                                 // T画像情報:局所:内側
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅

    h = ( ps->h <= pd->h ) ? ps->h : pd->h;         // 有効水平幅算出
    v = ( ps->v <= pd->v ) ? ps->v : pd->v;         // 有効垂直幅算出
    if( h < 3 ){                                    // 水平サイズ3未満
        return( STI_ARY_2 );                        // 左記を返す
    }                                               //
    if( v < 3 ){                                    // 垂直サイズ3未満
        return( STI_ARY_3 );                        // 左記を返す
    }                                               //
    s.subset( ps, 0, 0, h, v );                     // 有効画像情報セット
    d.subset( pd, 0, 0, h, v );                     // 有効画像情報セット
    ps = &s1;                                       // 一旦、ptr付け替え
    pd = &d1;                                       // 一旦、ptr付け替え
    ps->subset( &s, 1, 1, h - 2, v - 2 );           // S画像情報ptr:内側
    pd->subset( &d, 1, 1, h - 2, v - 2 );           // D画像情報ptr:内側
    Copy( ps, pd );                                 // 予め、S→D実行
    if( c == 4 ){                                   // 4連結なら
        compaction_4( ps, pd );                     // 左記で処理
    }else{                                          // 8連結なら
        compaction_8( ps, pd );                     // 左記で処理
    }                                               //
    ClearRoundImage( &d, 0, 1 );                    // 1周周囲クリア:D:全体
    return( END_STI );                              // 正常終了
}





//page
/************************************************************************/
/*****      収縮                        :実行部:複数回(2回以上)*****/
/*****      COMPACTION,s,d,c,r                    *****/
/************************************************************************/

int             Filter::compaction(
    TypeArray   *ps,                                    // S画像情報
    TypeArray   *pd,                                    // D画像情報
    int         c,                                      // 連結性
    int         r                                       // 繰返回数(2以上)
){
    TypeArray   *pt;                                    // T画像情報ptr    
    TypeArray   s;                                      // S画像情報:局所
    TypeArray   d;                                      // D画像情報:局所
    TypeArray   t;                                      // T画像情報:局所:ここでメモリ確保
    TypeArray   s1;                                     // T画像情報:局所:内側
    TypeArray   d1;                                     // T画像情報:局所:内側
    TypeArray   t1;                                     // T画像情報:局所:内側
    int         h;                                      // 水平幅
    int         v;                                      // 垂直幅
    int         i;                                      // カウンタ
    int         sti;                                    // ステータス情報

    h = ( ps->h <= pd->h ) ? ps->h : pd->h;             // 有効水平幅算出
    v = ( ps->v <= pd->v ) ? ps->v : pd->v;             // 有効垂直幅算出
    if( h < 3 ){                                        // 水平サイズ3未満
        return( STI_ARY_2 );                            // 左記を返す
    }                                                   //
    if( v < 3 ){                                        // 垂直サイズ3未満
        return( STI_ARY_3 );                            // 左記を返す
    }                                                   //
    s.subset( ps, 0, 0, h, v );                         // 有効画像情報セット
    d.subset( pd, 0, 0, h, v );                         // 有効画像情報セット
    sti = t.MallocByte( h, v );                         // 有効画像メモリ確保
    if( sti != END_STI ){                               // エラー時
        return( sti );                                  // ステータスを返す
    }                                                   // 
    pt = &t1;                                           // 一旦、ptrセット
    ps = &s1;                                           // 一旦、ptr付け替え
    pd = &d1;                                           // 一旦、ptr付け替え
    ps->subset( &s, 1, 1, h - 2, v - 2 );               // S画像情報ptr:内側
    pd->subset( &d, 1, 1, h - 2, v - 2 );               // D画像情報ptr:内側
    pt->subset( &t, 1, 1, h - 2, v - 2 );               // T画像情報ptr:内側
    Copy( &s, &d );                                     // 予め、S→D実行:全体
    Copy( &s, &t );                                     // 予め、S→T実行:全体
    if( ( r & 0x01 ) != 0 ){                            // 奇数回処理なら
        if( c == 4 ){                                   // 4連結なら
            compaction_4( pt, pd );                     // 左記処理:T→D
        }else{                                          // 8連結なら
            compaction_8( pt, pd );                     // 左記処理:T→D
        }                                               //
        Copy( pd, pt );                                 // 処理結果→T
        r--;                                            // 処理回数をダウン→偶数回
    }                                                   // 
    ClearRoundImage( &d, 0, 1 );                        // 1周周囲クリア:D:全体
    ClearRoundImage( &t, 0, 1 );                        // 1周周囲クリア:T:全体
    r /= 2;                                             // 2回を一組として組数算出
    for( i = 1; i <= r; i++ ){                          // 組数分以下繰返す
        if( c == 4 ){                                   // 4連結なら
            compaction_4( pd, pt );                     // 左記処理:D→T
            Copy( pt, pd );                             // 処理結果→D
            compaction_4( pt, pd );                     // 左記処理:T→D
        }else{                                          // 8連結なら
            compaction_8( pd, pt );                     // 左記処理:D→T
            Copy( pt, pd );                             // 処理結果→D
            compaction_8( pt, pd );                     // 左記処理:T→D
        }                                               //
        if( i < r ){                                    // 次の回も有る場合
            Copy( pd, pt );                             // 処理結果→T
        }                                               //
    }                                                   //
    t.freeMem();                                        // T画像メモリ解放
    return( END_STI );                                  // 正常終了
}




//page
/************************************************************************/
/*****      収縮                                            :実行部*****/
/*****      COMPACTION,s,d,c,r                    *****/
/************************************************************************/

int             Filter::Compaction(
    TypeArray   *ps,                                //  S画像情報
    TypeArray   *pd,                                //  D画像情報
    int         c,                                  //  連結性
    int         r                                   //  繰り返し回数(省略時1)
){
    if( ps->w != 1 || pd->w != 1 ){                 // 画素単位=1バイト
        return( STI_ARY_5 );                        // 以外→左記を返す
    }                                               //
    if( c != 4 && c != 8 ){                         // 連結性間違い時
        return( STI_FLG );                          // 左記を返す
    }                                               //
    if( r <= 0 ){                                   // 回数省略時は
        r = 1;                                      // 1をセット
    }                                               //
    if( r == 1 ){                                   // 1回実行時は
        return( compactionSingle( ps, pd, c ) );    // 左記で実行
    }else{                                          // 複数回実行時は
        return( compaction( ps, pd, c, r ) );       // 左記で処理
    }                                               //
}

(1)Compaction(仮引数){アルゴリズム}

code:Compaction(仮引数){

/************************************************************************/
/*****      収縮                                            :実行部*****/
/*****      COMPACTION,s,d,c,r                    *****/
/************************************************************************/

int             Filter::Compaction(
    TypeArray   *ps,                                //  S画像情報
    TypeArray   *pd,                                //  D画像情報
    int         c,                                  //  連結性
    int         r                                   //  繰り返し回数(省略時1)
){
    if( ps->w != 1 || pd->w != 1 ){                 // 画素単位=1バイト
        return( STI_ARY_5 );                        // 以外→左記を返す
    }                                               //
    if( c != 4 && c != 8 ){                         // 連結性間違い時
        return( STI_FLG );                          // 左記を返す
    }                                               //
    if( r <= 0 ){                                   // 回数省略時は
        r = 1;                                      // 1をセット
    }                                               //
    if( r == 1 ){                                   // 1回実行時は
        return( compactionSingle( ps, pd, c ) );    // 左記で実行
    }else{                                          // 複数回実行時は
        return( compaction( ps, pd, c, r ) );       // 左記で処理
    }                                               //
}

(1-1)関数名

「Compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!

(1-2)仮引数

code:仮引数

int             Filter::Compaction(
    TypeArray   *ps,                                //  S画像情報
    TypeArray   *pd,                                //  D画像情報
    int         c,                                  //  連結性
    int         r                                   //  繰り返し回数(省略時1)
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int r)」は、処理を繰り返す回数です!

(1-3)アルゴリズム

code:アルゴリズム

){
    if( ps->w != 1 || pd->w != 1 ){                 // 画素単位=1バイト
        return( STI_ARY_5 );                        // 以外→左記を返す
    }                                               //
    if( c != 4 && c != 8 ){                         // 連結性間違い時
        return( STI_FLG );                          // 左記を返す
    }                                               //
    if( r <= 0 ){                                   // 回数省略時は
        r = 1;                                      // 1をセット
    }                                               //
    if( r == 1 ){                                   // 1回実行時は
        return( compactionSingle( ps, pd, c ) );    // 左記で実行
    }else{                                          // 複数回実行時は
        return( compaction( ps, pd, c, r ) );       // 左記で処理
    }                                               //
}

「if(ps->w!=1||pd->w!=1){return(STI_ARY_5);}」は、
元画像(S≒ソース)も結果画像(D≒ディスティネーショ
ン)も画素単位が1バイト以外ならエラー「STI_ARY_5」を
関数辺値とし返し終了!
「if(c!=4&&c!=8){return(STI_FLG);}」は、連結性が4でも
8でも無い場合はエラーとし「STI_FLG」を関数辺値とし返
し終了!
「if(r<=0){r=1;}」は、回数「r」が「0以下」ならば、
「1」にする!
「if(r==1){return(compactionSingle(ps,pd,c));}」は、
回数「r」が「1」ならば、下請け関数「
compactionSingle(ps,pd,c)」で処理し、その辺値を辺値と
し返す!
「else{return(compaction(ps,pd,c,r));}」は、回数「r」
が「1」を超える場合、下請け関数「
compaction(ps,pd,c,r)」で処理し、その辺値を辺値とし返
す!

(2)compaction(仮引数){アルゴリズム}

code:compaction(仮引数){

/************************************************************************/
/*****      収縮                        :実行部:複数回(2回以上)*****/
/*****      COMPACTION,s,d,c,r                    *****/
/************************************************************************/

int             Filter::compaction(
    TypeArray   *ps,                                    // S画像情報
    TypeArray   *pd,                                    // D画像情報
    int         c,                                      // 連結性
    int         r                                       // 繰返回数(2以上)
){
    TypeArray   *pt;                                    // T画像情報ptr    
    TypeArray   s;                                      // S画像情報:局所
    TypeArray   d;                                      // D画像情報:局所
    TypeArray   t;                                      // T画像情報:局所:ここでメモリ確保
    TypeArray   s1;                                     // T画像情報:局所:内側
    TypeArray   d1;                                     // T画像情報:局所:内側
    TypeArray   t1;                                     // T画像情報:局所:内側
    int         h;                                      // 水平幅
    int         v;                                      // 垂直幅
    int         i;                                      // カウンタ
    int         sti;                                    // ステータス情報

    h = ( ps->h <= pd->h ) ? ps->h : pd->h;             // 有効水平幅算出
    v = ( ps->v <= pd->v ) ? ps->v : pd->v;             // 有効垂直幅算出
    if( h < 3 ){                                        // 水平サイズ3未満
        return( STI_ARY_2 );                            // 左記を返す
    }                                                   //
    if( v < 3 ){                                        // 垂直サイズ3未満
        return( STI_ARY_3 );                            // 左記を返す
    }                                                   //
    s.subset( ps, 0, 0, h, v );                         // 有効画像情報セット
    d.subset( pd, 0, 0, h, v );                         // 有効画像情報セット
    sti = t.MallocByte( h, v );                         // 有効画像メモリ確保
    if( sti != END_STI ){                               // エラー時
        return( sti );                                  // ステータスを返す
    }                                                   // 
    pt = &t1;                                           // 一旦、ptrセット
    ps = &s1;                                           // 一旦、ptr付け替え
    pd = &d1;                                           // 一旦、ptr付け替え
    ps->subset( &s, 1, 1, h - 2, v - 2 );               // S画像情報ptr:内側
    pd->subset( &d, 1, 1, h - 2, v - 2 );               // D画像情報ptr:内側
    pt->subset( &t, 1, 1, h - 2, v - 2 );               // T画像情報ptr:内側
    Copy( &s, &d );                                     // 予め、S→D実行:全体
    Copy( &s, &t );                                     // 予め、S→T実行:全体
    if( ( r & 0x01 ) != 0 ){                            // 奇数回処理なら
        if( c == 4 ){                                   // 4連結なら
            compaction_4( pt, pd );                     // 左記処理:T→D
        }else{                                          // 8連結なら
            compaction_8( pt, pd );                     // 左記処理:T→D
        }                                               //
        Copy( pd, pt );                                 // 処理結果→T
        r--;                                            // 処理回数をダウン→偶数回
    }                                                   // 
    ClearRoundImage( &d, 0, 1 );                        // 1周周囲クリア:D:全体
    ClearRoundImage( &t, 0, 1 );                        // 1周周囲クリア:T:全体
    r /= 2;                                             // 2回を一組として組数算出
    for( i = 1; i <= r; i++ ){                          // 組数分以下繰返す
        if( c == 4 ){                                   // 4連結なら
            compaction_4( pd, pt );                     // 左記処理:D→T
            Copy( pt, pd );                             // 処理結果→D
            compaction_4( pt, pd );                     // 左記処理:T→D
        }else{                                          // 8連結なら
            compaction_8( pd, pt );                     // 左記処理:D→T
            Copy( pt, pd );                             // 処理結果→D
            compaction_8( pt, pd );                     // 左記処理:T→D
        }                                               //
        if( i < r ){                                    // 次の回も有る場合
            Copy( pd, pt );                             // 処理結果→T
        }                                               //
    }                                                   //
    t.freeMem();                                        // T画像メモリ解放
    return( END_STI );                                  // 正常終了
}

(2-1)関数名

「compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!
備考※「compaction」と「Compaction」で識別して居る事
に注意!

(2-2)仮引数

code:仮引数

int             Filter::compaction(
    TypeArray   *ps,                                    // S画像情報
    TypeArray   *pd,                                    // D画像情報
    int         c,                                      // 連結性
    int         r                                       // 繰返回数(2以上)
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int r)」は、処理を繰り返す回数です!

(2-3)ローカル変数

code:ローカル変数

){
    TypeArray   *pt;                                    // T画像情報ptr    
    TypeArray   s;                                      // S画像情報:局所
    TypeArray   d;                                      // D画像情報:局所
    TypeArray   t;                                      // T画像情報:局所:ここでメモリ確保
    TypeArray   s1;                                     // T画像情報:局所:内側
    TypeArray   d1;                                     // T画像情報:局所:内側
    TypeArray   t1;                                     // T画像情報:局所:内側
    int         h;                                      // 水平幅
    int         v;                                      // 垂直幅
    int         i;                                      // カウンタ
    int         sti;                                    // ステータス情報

「TypeArray* pt;」は、T画像≪テンポラリ画像と
一時的な使用領域≫情報へのポインタ!
「TypeArray s;」は、S画像(元画像)の変更用局所変数
「TypeArray d;」は、D画像(結果画像)の変更用局所変数
「TypeArray t;」は、T画像(テンポラリ画像)を格納する
局所変数
「TypeArray s1;」は、S画像(元画像)の変更用局所変数
「TypeArray d1;」は、D画像(結果画像)の変更用局所
変数
「TypeArray t1;」は、T画像(テンポラリ画像)を格納
「int h;」は、水平幅
「int v;」は、垂直幅
「int i;」は、ループ用のカウンター
「int sti;」は、ステータス(エラーコード)情報

(2-4)アルゴリズム

code:アルゴリズム

    h = ( ps->h <= pd->h ) ? ps->h : pd->h;             // 有効水平幅算出
    v = ( ps->v <= pd->v ) ? ps->v : pd->v;             // 有効垂直幅算出
    if( h < 3 ){                                        // 水平サイズ3未満
        return( STI_ARY_2 );                            // 左記を返す
    }                                                   //
    if( v < 3 ){                                        // 垂直サイズ3未満
        return( STI_ARY_3 );                            // 左記を返す
    }                                                   //
    s.subset( ps, 0, 0, h, v );                         // 有効画像情報セット
    d.subset( pd, 0, 0, h, v );                         // 有効画像情報セット
    sti = t.MallocByte( h, v );                         // 有効画像メモリ確保
    if( sti != END_STI ){                               // エラー時
        return( sti );                                  // ステータスを返す
    }                                                   // 
    pt = &t1;                                           // 一旦、ptrセット
    ps = &s1;                                           // 一旦、ptr付け替え
    pd = &d1;                                           // 一旦、ptr付け替え
    ps->subset( &s, 1, 1, h - 2, v - 2 );               // S画像情報ptr:内側
    pd->subset( &d, 1, 1, h - 2, v - 2 );               // D画像情報ptr:内側
    pt->subset( &t, 1, 1, h - 2, v - 2 );               // T画像情報ptr:内側
    Copy( &s, &d );                                     // 予め、S→D実行:全体
    Copy( &s, &t );                                     // 予め、S→T実行:全体
    if( ( r & 0x01 ) != 0 ){                            // 奇数回処理なら
        if( c == 4 ){                                   // 4連結なら
            compaction_4( pt, pd );                     // 左記処理:T→D
        }else{                                          // 8連結なら
            compaction_8( pt, pd );                     // 左記処理:T→D
        }                                               //
        Copy( pd, pt );                                 // 処理結果→T
        r--;                                            // 処理回数をダウン→偶数回
    }                                                   // 
    ClearRoundImage( &d, 0, 1 );                        // 1周周囲クリア:D:全体
    ClearRoundImage( &t, 0, 1 );                        // 1周周囲クリア:T:全体
    r /= 2;                                             // 2回を一組として組数算出
    for( i = 1; i <= r; i++ ){                          // 組数分以下繰返す
        if( c == 4 ){                                   // 4連結なら
            compaction_4( pd, pt );                     // 左記処理:D→T
            Copy( pt, pd );                             // 処理結果→D
            compaction_4( pt, pd );                     // 左記処理:T→D
        }else{                                          // 8連結なら
            compaction_8( pd, pt );                     // 左記処理:D→T
            Copy( pt, pd );                             // 処理結果→D
            compaction_8( pt, pd );                     // 左記処理:T→D
        }                                               //
        if( i < r ){                                    // 次の回も有る場合
            Copy( pd, pt );                             // 処理結果→T
        }                                               //
    }                                                   //
    t.freeMem();                                        // T画像メモリ解放
    return( END_STI );                                  // 正常終了
}

「h=(ps->h<=pd->h)?ps->h:pd->h;」は、水平幅の元画像・
結果画像の最小値を有効な処理幅とし産出!
「v=(ps->v<=pd->v)?ps->v:pd->v;」は、垂直幅の元画像・
結果画像の最小値を有効な処理幅とし産出!
「if(h<3){return(STI_ARY_2);}」は、水平幅が3未満なら
エラーコード「STI_ARY_2」を関数辺値とし返し終了!
「if(v<3){return(STI_ARY_3);}」は、垂直幅が3未満なら
エラーコード「STI_ARY_3」を関数辺値とし返し終了!
「s.subset(ps,0,0,h,v);d.subset(pd,0,0,h,v);」は、
ローカル変数として元画像・結果画像のサイズを調整!
「sti=t.MallocByte(h,v);」は、T画像をメモリ確保!
「if(sti!=END_STI){return(sti);}」は、メモリ確保が
失敗したらエラーコードを関数辺値とし返し終了!
「pt=&t1;ps=&s1;pd=&d1;」は、T画像・S画像・D画像の
ポインタをセット!
「ps->subset(&s,1,1,h-2,v-2);」は、部分画像とし一回り
内側を作成!
「pd->subset(&s,1,1,h-2,v-2);」は、部分画像とし一回り
内側を作成!
「pt->subset(&s,1,1,h-2,v-2);」は、部分画像とし一回り
内側を作成!
「Copy(&s,&d);Copy(&s,&t);」は、S(元)画像を
D(結果)画像とT画像にコピー
「if((r&0x01)!=0){・・条件成立・・}」は、
条件「(r&0x01)!=0」で回数「r」が奇数回の場合で成立が
「if(c==4){compaction_4(pt,pd);}」で4連結ならば、
下請け関数「compaction_4(pt,pd);」で処理!
「}else{compaction_8(pt,pd);}」で84連結ならば、
下請け関数「compaction_8(pt,pd);」で処理!
そして「Copy(pd,pt);」結果画像を一旦、T画像にコピー
「r--;」で回数「r」を1回処理したと減らす!
「ClearRoundImage(&d,0,1);」は、結果画像の外周一回り
クリア!
「ClearRoundImage(&t,0,1);」は、T画像の外周一回り
クリア!
「r/=2;」は、回数「r」を半分にする≪処理一組として「
結果画像⇒T画像とT画像⇒結果画像」とするのでコノ回数
にする≫!
「for(i=1;i<=r;i++){・・ループ中身・・}」は、お馴染み
教科書的な繰り返しで回数「r」繰り返す!
そしてループ中身は、
「if(c==4){・4連結処理・}else{・8連結処理・}」で
4連結処理は、
「compaction_4(pd,pt);Copy(pt,pd);
compaction_4(pt,pd);」で「結果画像⇒T画像」しT画像
を結果画像にコピーし、「T画像⇒結果画像」を実行!
8連結処理は、
「compaction_8(pd,pt);Copy(pt,pd);
compaction_8(pt,pd);」で「結果画像⇒T画像」しT画像
を結果画像にコピーし、「T画像⇒結果画像」を実行!
「if(i<r){Copy(pd,pt);}」は、次の回も存在する場合は、
結果画像をT画像にコピーする!
「t.freeMem();」は、「t.MallocByte(h,v);」でメモリ
確保したメモリを後始末!
「return(END_STI);」は、正常終了を関数辺値とし返し終了

(3)compactionSingle(仮引数){アルゴリズム}

code:compactionSingle(仮引数){

/************************************************************************/
/*****      収縮                        :実行部:基本部:1回専用  *****/
/*****      COMPACTION,s,d,c,1                    *****/
/************************************************************************/

int             Filter::compactionSingle(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         c                                   // 連結性
){
    TypeArray   s;                                  // S画像情報:局所
    TypeArray   d;                                  // D画像情報:局所
    TypeArray   s1;                                 // T画像情報:局所:内側
    TypeArray   d1;                                 // T画像情報:局所:内側
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅

    h = ( ps->h <= pd->h ) ? ps->h : pd->h;         // 有効水平幅算出
    v = ( ps->v <= pd->v ) ? ps->v : pd->v;         // 有効垂直幅算出
    if( h < 3 ){                                    // 水平サイズ3未満
        return( STI_ARY_2 );                        // 左記を返す
    }                                               //
    if( v < 3 ){                                    // 垂直サイズ3未満
        return( STI_ARY_3 );                        // 左記を返す
    }                                               //
    s.subset( ps, 0, 0, h, v );                     // 有効画像情報セット
    d.subset( pd, 0, 0, h, v );                     // 有効画像情報セット
    ps = &s1;                                       // 一旦、ptr付け替え
    pd = &d1;                                       // 一旦、ptr付け替え
    ps->subset( &s, 1, 1, h - 2, v - 2 );           // S画像情報ptr:内側
    pd->subset( &d, 1, 1, h - 2, v - 2 );           // D画像情報ptr:内側
    Copy( ps, pd );                                 // 予め、S→D実行
    if( c == 4 ){                                   // 4連結なら
        compaction_4( ps, pd );                     // 左記で処理
    }else{                                          // 8連結なら
        compaction_8( ps, pd );                     // 左記で処理
    }                                               //
    ClearRoundImage( &d, 0, 1 );                    // 1周周囲クリア:D:全体
    return( END_STI );                              // 正常終了
}

(3-1)関数名

「compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!
「Single」は、シングル、繰り返すで無くシンプルに1回
だけ処理!

(3-2)仮引数

code:仮引数

int             Filter::compactionSingle(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         c                                   // 連結性
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を
示す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティ
ネーション画像)情報を示す「TypeArray」型の情報への
ポインタ変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!

(3-3)ローカル変数

code:ローカル変数

){
    TypeArray   s;                                  // S画像情報:局所
    TypeArray   d;                                  // D画像情報:局所
    TypeArray   s1;                                 // T画像情報:局所:内側
    TypeArray   d1;                                 // T画像情報:局所:内側
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅

「TypeArray s;」は、S画像(元画像)の変更用局所
変数「TypeArray d;」は、D画像(結果画像)の変更用
局所変数
「TypeArray s1;」は、S画像(元画像)の変更用局所変数
「TypeArray d1;」は、D画像(結果画像)の変更用局所変数
「int h;」は、水平幅
「int v;」は、垂直幅
「int i;」は、ループ用のカウンター

(3-4)アルゴリズム

code:アルゴリズム

    h = ( ps->h <= pd->h ) ? ps->h : pd->h;         // 有効水平幅算出
    v = ( ps->v <= pd->v ) ? ps->v : pd->v;         // 有効垂直幅算出
    if( h < 3 ){                                    // 水平サイズ3未満
        return( STI_ARY_2 );                        // 左記を返す
    }                                               //
    if( v < 3 ){                                    // 垂直サイズ3未満
        return( STI_ARY_3 );                        // 左記を返す
    }                                               //
    s.subset( ps, 0, 0, h, v );                     // 有効画像情報セット
    d.subset( pd, 0, 0, h, v );                     // 有効画像情報セット
    ps = &s1;                                       // 一旦、ptr付け替え
    pd = &d1;                                       // 一旦、ptr付け替え
    ps->subset( &s, 1, 1, h - 2, v - 2 );           // S画像情報ptr:内側
    pd->subset( &d, 1, 1, h - 2, v - 2 );           // D画像情報ptr:内側
    Copy( ps, pd );                                 // 予め、S→D実行
    if( c == 4 ){                                   // 4連結なら
        compaction_4( ps, pd );                     // 左記で処理
    }else{                                          // 8連結なら
        compaction_8( ps, pd );                     // 左記で処理
    }                                               //
    ClearRoundImage( &d, 0, 1 );                    // 1周周囲クリア:D:全体
    return( END_STI );                              // 正常終了
}

「h=(ps->h<=pd->h)?ps->h:pd->h;」は、水平幅の元画像・
結果画像の最小値を有効な処理幅とし産出!
「v=(ps->v<=pd->v)?ps->v:pd->v;」は、垂直幅の元画像・
結果画像の最小値を有効な処理幅とし産出!
「if(h<3){return(STI_ARY_2);}」は、水平幅が3未満なら
エラーコード「STI_ARY_2」を関数辺値とし返し終了!
「if(v<3){return(STI_ARY_3);}」は、垂直幅が3未満なら
エラーコード「STI_ARY_3」を関数辺値とし返し終了!
「s.subset(ps,0,0,h,v);d.subset(pd,0,0,h,v);」は、
有効な画像範囲に処理範囲を調整!
「ps=&s1;pd=&d1;」は、ポインタ変数を付け替え、
「ps->subset(&s,1,1,h-2,v-2);
pd->subset(&d,1,1,h-2,v-2);」は、部分画像とし一回り
内側を処理範囲にセット
「Copy(ps,pd);」は、予め、元画像を結果画像にコピー!
「if(c==4){・4連結処理・}else{・8連結処理・}」は、
連結性「c」で処理を分け4連結処理は、
「compaction_4(ps,pd);」で処理し、8連結処理は、
「compaction_8(ps,pd);」で処理!
「ClearRoundImage(&d,0,1);」は、外周一回り0クリア!
「return(END_STI);」は、正常終了を関数辺値とし返し終了

(4)compaction_4(仮引数){アルゴリズム}

code:compaction_4(仮引数){

/************************************************************************/
/*****      収縮                                    :実行部:4連結*****/
/*****      COMPACTION,s,d,4,r                    *****/
/************************************************************************/

void            Filter::compaction_4(
    TypeArray   *ps,                                // S画像Ptr
    TypeArray   *pd                                 // D画像情報
){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        compaction_4_x( ptrs, ptrd, incs, h );      // 水平方向の処理
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}

(4-1)関数名

「compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!
「_4」は、4連結の処理を意味!

(4-2)仮引数

code:仮引数

void            Filter::compaction_4(
    TypeArray   *ps,                                // S画像Ptr
    TypeArray   *pd                                 // D画像情報
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!

(4-3)ローカル変数

code:ローカル変数

){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

「BYTE* ptrs;」は、元画像画素ポインタ変数です!
「BYTE* ptrd;」は、結果画像画素ポインタ変数です!
「int h;」は、水平幅
「int v;」は、垂直幅
「int incs;」は、元画像の垂直方向増加幅
「int incd;」は、結果画像の垂直方向増加幅

(4-4)アルゴリズム

code:アルゴリズム

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        compaction_4_x( ptrs, ptrd, incs, h );      // 水平方向の処理
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}

「h=ps->h;v=ps->v;」は、水平幅・垂直幅取り出し!
「incs=ps->inc;incd=pd->inc;」は、元画像・結果画像の
垂直方向増加幅取り出し!
「ptrs=(BYTE*)ps->adr;ptrd=(BYTE*)pd->adr;」は、
元画像・結果画像のポインタの値をローカル変数にセットと
高速化の為にローカル変数変数にセットする6行!
「while(--v>=0){・・ループ中身・・}」は、垂直方向に
垂直幅分繰り返し処理、そしてループ中身
は、「compaction_4_x(ptrs,ptrd,incs,h);」で
水平方向処理として画像1行分処理、
「ptrs+=incs;ptrd+=incd;」で元画像・結果画像のポイン
タの値をソレゾレの垂直幅分増加

(5)compaction_4_x(仮引数){アルゴリズム}

code:compaction_4_x(仮引数){

/************************************************************************/
/*****      収縮                            :実行部:4連結:x方向*****/
/*****      COMPACTION,s,d,4,r                    *****/
/************************************************************************/

void            Filter::compaction_4_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         h                                   // 水平幅
){
    BYTE        zero;                               // 0データ

    zero = 0;                                       // 0データセット
    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps ){                                  // 注視点有効時
            if( *( ps - inc ) == 0                  // 上か
                        || *( ps - 1 ) == 0         // 左か
                        || *( ps + 1 ) == 0         // 右か
                        || *( ps + inc ) == 0 ){    // 下が0ならば
                *pd = zero;                         // 0を書き込む
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}

(5-1)関数名

「compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!
「_4」は、4連結の処理を意味!
「_x」は、X座標方向(水平方向)の処理を意味!

(5-2)仮引数

code:仮引数

void            Filter::compaction_4_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         h                                   // 水平幅
){

「BYTE* ps,」は、元画像(S≒ソース画像)画素実行ポイ
ンタ「BYTE」型(1バイト単位)のポインタ変数です!
「BYTE* pd,」は、結果画像(D≒ディスティネーション
画像)画素実行ポインタ「BYTE」型(1バイト単位)の
ポインタ変数です!
「int inc,」は、元画像の垂直方向増加幅!
「int data)」は、結果書き込み画素の値です!
「int h」は、水平方向処理幅です!
(5-3)ローカル変数

code:ローカル変数

){
    BYTE        zero;                               // 0データ

「BYTE* zero;」は、高速化技法の為!

(5-4)アルゴリズム

code:アルゴリズム

    zero = 0;                                       // 0データセット
    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps ){                                  // 注視点有効時
            if( *( ps - inc ) == 0                  // 上か
                        || *( ps - 1 ) == 0         // 左か
                        || *( ps + 1 ) == 0         // 右か
                        || *( ps + inc ) == 0 ){    // 下が0ならば
                *pd = zero;                         // 0を書き込む
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}

「zero=0;」は、0書き込み画素データセット※高速化技法
「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の
「if(ps){・・分岐中身・・}」は、「if(ps){」で
元画像が画素が条件「ps」詰まり有効画素ならで
分岐中身を処理と「ps++;pd++;」で元画像・結果画像の
ポインタを水平方向に進める!
つまり、水平方向の処理として繰り返し、条件有効な場合で
分岐中身を処理します?!そして分岐中身は、
条件「(ps-inc)==0||(ps-1)==0||(ps+1)==0||
*(ps+inc)==0」で隣接する左・上・右・下の一つでも無効
なら、
「*pd=zero;」と結果画像画素に無効画素を書き込みセット
します!

(6)compaction_8(仮引数){アルゴリズム}

code:compaction_8(仮引数){

/************************************************************************/
/*****      収縮                                    :実行部:8連結*****/
/*****      COMPACTION,s,d,8,r                    *****/
/************************************************************************/

void            Filter::compaction_8(
    TypeArray   *ps,                                // S画像Ptr
    TypeArray   *pd                                 // D画像情報
){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        compaction_8_x( ptrs, ptrd, incs, h );      // 水平方向の処理
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}

(6-1)関数名

「compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!
「_8」は、8連結の処理を意味!

(6-2)仮引数

code:仮引数

void            Filter::compaction_8(
    TypeArray   *ps,                                // S画像Ptr
    TypeArray   *pd                                 // D画像情報
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!

(6-3)ローカル変数

code:ローカル変数

){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

「BYTE* ptrs;」は、元画像画素ポインタ変数です!
「BYTE* ptrd;」は、結果画像画素ポインタ変数です!
「int h;」は、水平幅
「int v;」は、垂直幅
「int incs;」は、元画像の垂直方向増加幅
「int incd;」は、結果画像の垂直方向増加幅

(6-4)アルゴリズム

code:アルゴリズム

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        compaction_8_x( ptrs, ptrd, incs, h );      // 水平方向の処理
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}

「h=ps->h;v=ps->v;」は、画像の水平幅・垂直幅を取り出
し!元画像・結果画像も同じ有効処理幅に補正されて居る
事が前提!
「incs=ps->inc;incd=pd->inc;」は、元画像・結果画像の
垂直方向増加幅を取り出し!
「ptrs=(BYTE*)ps->adr;ptrd=(BYTE*)pd->adr;」は、
元画像・結果画像のポインタの値をローカル変数にセットと
高速化の為にローカル変数変数にセットする6行!
「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の下請け
関数「compaction_8_x(ptrs,ptrd,incs,h);」で水平方向
処理として画像1行分処理、
「ptrs+=incs;ptrd+=incd;」で元画像・結果画像のポインタ
の値をソレゾレの垂直幅分増加

(7)compaction_8_x(仮引数){アルゴリズム}

code:compaction_8_x(仮引数){

/************************************************************************/
/*****      収縮                            :実行部:8連結:x方向*****/
/*****      COMPACTION,s,d,8,r                    *****/
/************************************************************************/

void            Filter::compaction_8_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         h                                   // 水平幅
){
    BYTE        *p;                                 // S画像Ptr
    BYTE        zero;                               // 0データ

    zero = 0;                                       // 0データセット
    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps ){                                  // 注視点有効時
            if( *( ps - 1 ) == 0                    // 左右に0が
                            || *( ps + 1 ) == 0 ){  // あれば
                *pd = zero;                         // 0を書き込む
            }else{                                  // 上記以外の場合
                p = ps - inc - 1;                   // 左上をセットし
                if( *p == 0 || *( p + 1 ) == 0      // 上側に0が
                            || *( p + 2 ) == 0 ){   // あれば
                    *pd = zero;                     // 0を書き込む
                }else{                              // 上記以外で
                    p = ps + inc - 1;               // 左下をセットし
                    if( *p == 0 || *( p + 1 ) == 0  // 下側に0が
                            || *( p + 2 ) == 0 ){   // あれば
                        *pd = zero;                 // 0を書き込む
                    }                               //
                }                                   //
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}

(7-1)関数名

「compaction」は、圧縮の意味ですが、ここでは、一回り
連結した図形を細くすると考えて下さい!
「_8」は、8連結の処理を意味!
「_x」は、X座標方向(水平方向)の処理を意味!

(7-2)仮引数

code:仮引数

void            Filter::compaction_8_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         h                                   // 水平幅
){

「BYTE* ps,」は、元画像(S≒ソース画像)画素実行ポイ
ンタ「BYTE」型(1バイト単位)のポインタ変数です!
「BYTE* pd,」は、結果画像(D≒ディスティネーション
画像)画素実行ポインタ「BYTE」型(1バイト単位)の
ポインタ変数です!
「int inc,」は、元画像の垂直方向増加幅!
「int h」は、水平方向処理幅です!

(7-3)ローカル変数

code:ローカル変数

){
    BYTE        *p;                                 // S画像Ptr
    BYTE        zero;                               // 0データ

「BYTE* p;」は、元画像画素への左上・左下等上下移動分の
ポインタ変数!
「BYTE zero;」は、高速化の為に「int型」で無く画素単位と
同じ「BYTE」を使用!多くのCPU&コンパイらでは大方、
高速化する筈!

(7-4)アルゴリズム

code:アルゴリズム

    zero = 0;                                       // 0データセット
    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps ){                                  // 注視点有効時
            if( *( ps - 1 ) == 0                    // 左右に0が
                            || *( ps + 1 ) == 0 ){  // あれば
                *pd = zero;                         // 0を書き込む
            }else{                                  // 上記以外の場合
                p = ps - inc - 1;                   // 左上をセットし
                if( *p == 0 || *( p + 1 ) == 0      // 上側に0が
                            || *( p + 2 ) == 0 ){   // あれば
                    *pd = zero;                     // 0を書き込む
                }else{                              // 上記以外で
                    p = ps + inc - 1;               // 左下をセットし
                    if( *p == 0 || *( p + 1 ) == 0  // 下側に0が
                            || *( p + 2 ) == 0 ){   // あれば
                        *pd = zero;                 // 0を書き込む
                    }                               //
                }                                   //
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}

「zero=0;」は、高速化の為に「0」の値をセット、初期化で
記述シナイのは、コンパイラに依って遅いコードが出る為!
「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の
「if(ps ==0){・・分岐中身・・}」は、「if(ps ==0){」
で元画像が画素が条件「(=0)」詰まり無効画素ならで
分岐中身を処理と「ps++;pd++;」で元画像・結果画像の
ポインタを水平方向に進める!
つまり、水平方向の処理として繰り返し、条件有効な場合で
分岐中身を処理します?!そして分岐中身は、
「if((ps-1)==0||(ps+1)==0){pd=zero;}」で更に
条件「(ps-1)==0||*(ps+1)==0」と左右隣接画素が一つでも
無効「(=0)」なら、「pd=zero;」で「0」を書き込む、
そして条件が非成立「else{・・非成立処理」として
「p=ps-inc-1;」で左上ポインタ変数セットし、
「if(p==0||(p+1)==0||(p+2)==0){pd=zero;」で更に
条件「p==0||(p+1)==0||(p+2)==0」と左上・右上隣接
画素が一つでも無効「(=0)」なら、「pd=zero;」で
「0」を書き込む、それでも条件が非成立
「else{・・非成立処理」として「p=ps+inc-1;」で
左下ポインタ変数セットし、
「if(p==0||(p+1)==0||(p+2)==0){pd=zero;}」で更に
条件「p==0||(p+1)==0||(p+2)==0」と左下・右下隣接
画素が一つでも無効「(=0)」なら、「*pd=zero;」で
「0」を書き込む!の値をソレゾレの垂直幅分増加セットします!

3.膨脹

4連結膨脹

注視点が(0)状態に隣接する点≪上・左・下≫が一つでも
有る(1)なれば、注視点が、存在(1)に成る!

8連結膨脹

注視点が(0)状態に隣接する点≪上・左・下・左上・右上
右下・左下・左・下上・左・下≫が一つでも有る(1)なれ
ば、注視点が、存在(1)に成る!

膨脹例題元画像

膨脹を行う前の2値化画像

膨脹例題結果画像


膨脹した結果を示す?!一回り太く成った事に注意!

3-1.膨脹ソースコード

code:膨脹ソースコード

/************************************************************************/
/*****      膨脹                            :実行部:4連結:x方向*****/
/*****      EXPANSION,s,d,4,r                      *****/
/************************************************************************/

void            Filter::expansion_4_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         data,                               // 描画データ
    int         h                                   // 水平幅
){
    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps == 0 ){                             // 注視点画素=0時
            if( *( ps - 1 ) || *( ps - inc )        // 左か上か
             || *( ps + 1 ) || *( ps + inc ) ){     // 右か下が有効なら
                *pd = data;                         // ば、書き込む
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}




//page
/************************************************************************/
/*****      膨脹                                    :実行部:4連結*****/
/*****      EXPANSION,s,d,4,r                      *****/
/************************************************************************/

void            Filter::expansion_4(
    TypeArray   *ps,                                // S画像Ptr
    TypeArray   *pd,                                // D画像情報
    int         data                                // 描画データ
){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        expansion_4_x( ptrs, ptrd, incs, data, h ); // 水平方向の処理
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}





//page
/************************************************************************/
/*****      膨脹                            :実行部:8連結:x方向*****/
/*****      EXPANSION,s,d,8,r                      *****/
/************************************************************************/

void            Filter::expansion_8_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         data,                               // 描画データ
    int         h                                   // 水平幅
){
    BYTE        *p;                                 // S画像Ptr

    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps == 0 ){                             // 注視点画素=0時
            if( *( ps - 1 ) || *( ps + 1 ) ){       // 左右が有効なら
                *pd = data;                         // 書き込む
            }else{                                  // 上記以外の場合
                p = ps - inc - 1;                   // 左上をセットし
                if( *p || *(p+1) || *(p+2) ){       // 上側が有効なら
                    *pd = data;                     // 書き込む
                }else{                              // 上記以外で
                    p = ps + inc - 1;               // 左下をセットし
                    if( *p || *(p+1) || *(p+2) ){   // 下側が有効なら
                        *pd = data;                 // 書き込む
                    }                               //
                }                                   //
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}





//page
/************************************************************************/
/*****      膨脹                                    :実行部:8連結*****/
/*****      EXPANSION,s,d,8,r                      *****/
/************************************************************************/

void            Filter::expansion_8(
    TypeArray   *ps,                                // S画像Ptr
    TypeArray   *pd,                                // D画像情報
    int         data                                // 描画データ
){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        expansion_8_x( ptrs, ptrd, incs, data, h ); // 水平方向の処理
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}





//page
/************************************************************************/
/*****      膨脹                :実行部:基本部:回数(r)=1専用*****/
/*****      EXPANSION,s,d,c,1                      *****/
/************************************************************************/

int             Filter::expansionSingle(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         c,                                  // 連結性
    int         data                                // 描画データ
){
    TypeArray   s;                                  // S画像情報:局所
    TypeArray   d;                                  // D画像情報:局所
    int         sti;                                // ステータス情報

    s   = *ps;                                      // 一旦、S画像情報
    ps  = &s;                                       // を局所化
    d   = *pd;                                      // 一旦、D画像情報
    pd  = &d;                                       // を局所化
    sti = PreProcessor3By3( ps, pd );               // 前処理
    if( sti != END_STI ){                           // エラーがある場合
        return( sti );                              // ステータスを返す
    }                                               //
    Copy( ps, pd );                                 // 予め、S→D実行
    if( c == 4 ){                                   // 4連結なら
        expansion_4( ps, pd, data );                // 左記で処理
    }else{                                          // 8連結なら
        expansion_8( ps, pd, data );                // 左記で処理
    }                                               //
    return( END_STI );                              // 正常終了
}





//page
/************************************************************************/
/*****      膨脹                    :実行部:基本部:複数回繰返    *****/
/*****      EXPANSION,s,d,c,r                      *****/
/************************************************************************/

int             Filter::expansion(
    TypeArray   *ps,                                    // S画像情報ptr
    TypeArray   *pd,                                    // D画像情報ptr
    int         c,                                      // 連結性
    int         r,                                      // 繰返回数(2以上)
    int         data                                    // 描画データ
){
    TypeArray   *pt;                                    // T画像情報ptr
    TypeArray   s;                                      // S画像情報:局所
    TypeArray   d;                                      // D画像情報:局所
    TypeArray   t;                                      // T画像情報:局所:ここでメモリ確保
    TypeArray   s1;                                     // T画像情報:局所:内側
    TypeArray   d1;                                     // T画像情報:局所:内側
    TypeArray   t1;                                     // T画像情報:局所:内側
    int         h;                                      // 水平幅
    int         v;                                      // 垂直幅
    int         i;                                      // カウンタ
    int         sti;                                    // ステータス情報

    h = ( ps->h <= pd->h ) ? ps->h : pd->h;             // 有効水平幅算出
    v = ( ps->v <= pd->v ) ? ps->v : pd->v;             // 有効垂直幅算出
    if( h < 3 ){                                        // 水平サイズ3未満
        return( STI_ARY_2 );                            // 左記を返す
    }                                                   //
    if( v < 3 ){                                        // 垂直サイズ3未満
        return( STI_ARY_3 );                            // 左記を返す
    }                                                   //
    s.subset( ps, 0, 0, h, v );                         // 有効画像情報セット
    d.subset( pd, 0, 0, h, v );                         // 有効画像情報セット
    sti = t.MallocByte( h, v );                         // 有効画像メモリ確保
    if( sti != END_STI ){                               // エラー時
        return( sti );                                  // ステータスを返す
    }                                                   // 
    pt = &t1;                                           // 一旦、ptrセット
    ps = &s1;                                           // 一旦、ptr付け替え
    pd = &d1;                                           // 一旦、ptr付け替え
    ps->subset( &s, 1, 1, h - 2, v - 2 );               // S画像情報ptr:内側
    pd->subset( &d, 1, 1, h - 2, v - 2 );               // D画像情報ptr:内側
    pt->subset( &t, 1, 1, h - 2, v - 2 );               // T画像情報ptr:内側
    Copy( &s, &d );                                     // 予め、S→D実行:全体
    Copy( &s, &t );                                     // 予め、S→T実行:全体
    if( ( r & 0x01 ) != 0 ){                            // 奇数回処理なら
        if( c == 4 ){                                   // 4連結なら
            expansion_4( pt, pd, data );                // 左記処理:T→D
        }else{                                          // 8連結なら
            expansion_8( pt, pd, data );                // 左記処理:T→D
        }                                               //
        Copy( pd, pt );                                 // 処理結果→T
        r--;                                            // 処理回数をダウン→偶数回
    }                                                   // 
    r /= 2;                                             // 2回を一組として組数算出
    for( i = 1; i <= r; i++ ){                          // 組数分以下繰返す
        if( c == 4 ){                                   // 4連結なら
            expansion_4( pd, pt, data );                // 左記処理:D→T
            Copy( pt, pd );                             // 処理結果→D
            expansion_4( pt, pd, data );                // 左記処理:T→D
        }else{                                          // 8連結なら
            expansion_8( pd, pt, data );                // 左記処理:D→T
            Copy( pt, pd );                             // 処理結果→D
            expansion_8( pt, pd, data );                // 左記処理:T→D
        }                                               //
        if( i < r ){                                    // 次の回も有る場合
            Copy( pd, pt );                             // 処理結果→T
        }                                               //
    }                                                   //
    t.freeMem();                                        // T画像メモリ解放
    return( END_STI );                                  // 正常終了
}





//page
/************************************************************************/
/*****      膨脹                                            :実行部*****/
/*****      EXPANSION,s,d,c,r                      *****/
/************************************************************************/

int             Filter::Expansion(
    TypeArray   *ps,                                    // S画像情報
    TypeArray   *pd,                                    // D画像情報
    int         c,                                      // 連結性
    int         r,                                      // 繰り返し回数(省略時1)
    int         data                                    // 描画データ(省略時255)
){
    if( ps->w != 1 || pd->w != 1 ){                     // 画素単位=1バイト
        return( STI_ARY_5 );                            // 以外→左記を返す
    }                                                   //
    if( c != 4 && c != 8 ){                             // 連結性間違い時
        return( STI_FLG );                              // 左記を返す
    }                                                   //
    if( r <= 0 ){                                       // 回数省略時は
        r = 1;                                          // 1をセット
    }                                                   //
    if( r == 1 ){                                       // 1回実行時は
        return( expansionSingle( ps, pd, c, data ) );   // 左記で実行
    }else{                                              // 複数回実行時は
        return( expansion( ps, pd, c, r, data ) );      // 左記で処理
    }                                                   //
}

(1)Expansion(仮引数){アルゴリズム}

code:Expansion(仮引数){

/************************************************************************/
/*****      膨脹                                            :実行部*****/
/*****      EXPANSION,s,d,c,r                      *****/
/************************************************************************/

int             Filter::Expansion(
    TypeArray   *ps,                                    // S画像情報
    TypeArray   *pd,                                    // D画像情報
    int         c,                                      // 連結性
    int         r,                                      // 繰り返し回数(省略時1)
    int         data                                    // 描画データ(省略時255)
){
    if( ps->w != 1 || pd->w != 1 ){                     // 画素単位=1バイト
        return( STI_ARY_5 );                            // 以外→左記を返す
    }                                                   //
    if( c != 4 && c != 8 ){                             // 連結性間違い時
        return( STI_FLG );                              // 左記を返す
    }                                                   //
    if( r <= 0 ){                                       // 回数省略時は
        r = 1;                                          // 1をセット
    }                                                   //
    if( r == 1 ){                                       // 1回実行時は
        return( expansionSingle( ps, pd, c, data ) );   // 左記で実行
    }else{                                              // 複数回実行時は
        return( expansion( ps, pd, c, r, data ) );      // 左記で処理
    }                                                   //
}

(1-1)関数名

「Expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!

(1-2)仮引数

code:仮引数

int             Filter::Expansion(
    TypeArray   *ps,                                    // S画像情報
    TypeArray   *pd,                                    // D画像情報
    int         c,                                      // 連結性
    int         r,                                      // 繰り返し回数(省略時1)
    int         data                                    // 描画データ(省略時255)
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int r)」は、処理を繰り返す回数です!
「int data」は、書き込む画素データ!

(1-3)アルゴリズム

code:アルゴリズム

){
    if( ps->w != 1 || pd->w != 1 ){                     // 画素単位=1バイト
        return( STI_ARY_5 );                            // 以外→左記を返す
    }                                                   //
    if( c != 4 && c != 8 ){                             // 連結性間違い時
        return( STI_FLG );                              // 左記を返す
    }                                                   //
    if( r <= 0 ){                                       // 回数省略時は
        r = 1;                                          // 1をセット
    }                                                   //
    if( r == 1 ){                                       // 1回実行時は
        return( expansionSingle( ps, pd, c, data ) );   // 左記で実行
    }else{                                              // 複数回実行時は
        return( expansion( ps, pd, c, r, data ) );      // 左記で処理
    }                                                   //
}

「if(ps->w!=1||pd->w!=1){return(STI_ARY_5);}」は、
元画像(S≒ソース)も結果画像(D≒ディスティネーショ
ン)も画素単位が1バイト以外ならエラー「STI_ARY_5」を
関数辺値とし返し終了!
「if(c!=4&&c!=8){return(STI_FLG);}」は、連結性が4でも
8でも無い場合はエラーとし「STI_FLG」を関数辺値とし返
し終了!
「if(r<=0){r=1;}」は、回数「r」が「0以下」ならば、
「1」にする!
「if(r==1){return(expansionSingle(ps,pd,c,data));}」は、
回数「r」が「1」ならば、下請け関数「
expansionSingle(ps,pd,c,data)」で処理し、その辺値を辺値と
し返す!
「else{return(expansion(ps,pd,c,r,data));}」は、回数「r」
が「1」を超える場合、下請け関数「
expansion(ps,pd,c,r,data)」で処理し、その辺値を辺値とし返
す!

(2)expansion(仮引数){アルゴリズム}

code:expansion(仮引数){

/************************************************************************/
/*****      膨脹                                            :実行部*****/
/*****      EXPANSION,s,d,c,r                      *****/
/************************************************************************/

int             Filter::Expansion(
    TypeArray   *ps,                                    // S画像情報
    TypeArray   *pd,                                    // D画像情報
    int         c,                                      // 連結性
    int         r,                                      // 繰り返し回数(省略時1)
    int         data                                    // 描画データ(省略時255)
){
    if( ps->w != 1 || pd->w != 1 ){                     // 画素単位=1バイト
        return( STI_ARY_5 );                            // 以外→左記を返す
    }                                                   //
    if( c != 4 && c != 8 ){                             // 連結性間違い時
        return( STI_FLG );                              // 左記を返す
    }                                                   //
    if( r <= 0 ){                                       // 回数省略時は
        r = 1;                                          // 1をセット
    }                                                   //
    if( r == 1 ){                                       // 1回実行時は
        return( expansionSingle( ps, pd, c, data ) );   // 左記で実行
    }else{                                              // 複数回実行時は
        return( expansion( ps, pd, c, r, data ) );      // 左記で処理
    }                                                   //
}

(2-1)関数名

「expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!
備考※「expansion」と「Expansion」で識別して居る事に
注意!

(2-2)仮引数

code:仮引数

int             Filter::Expansion(
    TypeArray   *ps,                                    // S画像情報
    TypeArray   *pd,                                    // D画像情報
    int         c,                                      // 連結性
    int         r,                                      // 繰り返し回数(省略時1)
    int         data                                    // 描画データ(省略時255)
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を
示す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティ
ネーション画像)情報を示す「TypeArray」型の情報への
ポインタ変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int r)」は、処理を繰り返す回数です!
「int data」は、書き込む画素データ!

(2-3)ローカル変数

code:ローカル変数

){
    TypeArray   *pt;                                    // T画像情報ptr
    TypeArray   s;                                      // S画像情報:局所
    TypeArray   d;                                      // D画像情報:局所
    TypeArray   t;                                      // T画像情報:局所:ここでメモリ確保
    TypeArray   s1;                                     // T画像情報:局所:内側
    TypeArray   d1;                                     // T画像情報:局所:内側
    TypeArray   t1;                                     // T画像情報:局所:内側
    int         h;                                      // 水平幅
    int         v;                                      // 垂直幅
    int         i;                                      // カウンタ
    int         sti;                                    // ステータス情報

「TypeArray* pt;」は、T画像≪テンポラリ画像と一時的
な使用領域≫情報へのポインタ
「TypeArray s;」は、S画像(元画像)の変更用局所変数
「TypeArray d;」は、D画像(結果画像)の変更用局所変数
「TypeArray t;」は、T画像(テンポラリ画像)を格納する
局所変数
「TypeArray s1;」は、S画像(元画像)の変更用局所変数
「TypeArray d1;」は、D画像(結果画像)の変更用局所変数
「TypeArray t1;」は、T画像(テンポラリ画像)を格納する
局所変数
「int h;」は、水平幅
「int v;」は、垂直幅
「int i;」は、ループ用のカウンター
「int sti;」は、ステータス(エラーコード)情報

(2-4)アルゴリズム

code:アルゴリズム

    h = ( ps->h <= pd->h ) ? ps->h : pd->h;             // 有効水平幅算出
    v = ( ps->v <= pd->v ) ? ps->v : pd->v;             // 有効垂直幅算出
    if( h < 3 ){                                        // 水平サイズ3未満
        return( STI_ARY_2 );                            // 左記を返す
    }                                                   //
    if( v < 3 ){                                        // 垂直サイズ3未満
        return( STI_ARY_3 );                            // 左記を返す
    }                                                   //
    s.subset( ps, 0, 0, h, v );                         // 有効画像情報セット
    d.subset( pd, 0, 0, h, v );                         // 有効画像情報セット
    sti = t.MallocByte( h, v );                         // 有効画像メモリ確保
    if( sti != END_STI ){                               // エラー時
        return( sti );                                  // ステータスを返す
    }                                                   // 
    pt = &t1;                                           // 一旦、ptrセット
    ps = &s1;                                           // 一旦、ptr付け替え
    pd = &d1;                                           // 一旦、ptr付け替え
    ps->subset( &s, 1, 1, h - 2, v - 2 );               // S画像情報ptr:内側
    pd->subset( &d, 1, 1, h - 2, v - 2 );               // D画像情報ptr:内側
    pt->subset( &t, 1, 1, h - 2, v - 2 );               // T画像情報ptr:内側
    Copy( &s, &d );                                     // 予め、S→D実行:全体
    Copy( &s, &t );                                     // 予め、S→T実行:全体
    if( ( r & 0x01 ) != 0 ){                            // 奇数回処理なら
        if( c == 4 ){                                   // 4連結なら
            expansion_4( pt, pd, data );                // 左記処理:T→D
        }else{                                          // 8連結なら
            expansion_8( pt, pd, data );                // 左記処理:T→D
        }                                               //
        Copy( pd, pt );                                 // 処理結果→T
        r--;                                            // 処理回数をダウン→偶数回
    }                                                   // 
    r /= 2;                                             // 2回を一組として組数算出
    for( i = 1; i <= r; i++ ){                          // 組数分以下繰返す
        if( c == 4 ){                                   // 4連結なら
            expansion_4( pd, pt, data );                // 左記処理:D→T
            Copy( pt, pd );                             // 処理結果→D
            expansion_4( pt, pd, data );                // 左記処理:T→D
        }else{                                          // 8連結なら
            expansion_8( pd, pt, data );                // 左記処理:D→T
            Copy( pt, pd );                             // 処理結果→D
            expansion_8( pt, pd, data );                // 左記処理:T→D
        }                                               //
        if( i < r ){                                    // 次の回も有る場合
            Copy( pd, pt );                             // 処理結果→T
        }                                               //
    }                                                   //
    t.freeMem();                                        // T画像メモリ解放
    return( END_STI );                                  // 正常終了
}

「h=(ps->h<=pd->h)?ps->h:pd->h;」は、水平幅の元画像・
結果画像の最小値を有効な処理幅とし産出!
「v=(ps->v<=pd->v)?ps->v:pd->v;」は、垂直幅の元画像・
結果画像の最小値を有効な処理幅とし産出!
「if(h<3){return(STI_ARY_2);}」は、水平幅が3未満なら
エラーコード「STI_ARY_2」を関数辺値とし返し終了!
「if(v<3){return(STI_ARY_3);}」は、垂直幅が3未満なら
エラーコード「STI_ARY_3」を関数辺値とし返し終了!
「s.subset(ps,0,0,h,v);d.subset(pd,0,0,h,v);」は、
ローカル変数として元画像・結果画像のサイズを調整!
「sti=t.MallocByte(h,v);」は、T画像をメモリ確保!
「if(sti!=END_STI){return(sti);}」は、メモリ確保が
失敗したらエラーコードを関数辺値とし返し終了!
「pt=&t1;ps=&s1;pd=&d1;」は、T画像・S画像・D画像の
ポインタをセット!
「ps->subset(&s,1,1,h-2,v-2);」は、部分画像とし一回り
内側を作成!
「pd->subset(&s,1,1,h-2,v-2);」は、部分画像とし一回り
内側を作成!
「pt->subset(&s,1,1,h-2,v-2);」は、部分画像とし一回り
内側を作成!
「Copy(&s,&d);Copy(&s,&t);」は、S(元)画像を
D(結果)画像とT画像にコピー
「if((r&0x01)!=0){・・条件成立・・}」は、
条件「(r&0x01)!=0」で回数「r」が奇数回の場合で成立が
「if(c==4){expansion_4(pt,pd,data);}」で4連結ならば
下請け関数「expansion_4(pt,pd,data);」で処理!
「}else{expansion_8(pt,pd,data);}」で84連結ならば
下請け関数「expansion_8(pt,pd,data);」で処理!
そして「Copy(pd,pt);」結果画像を一旦、T画像にコピー
「r--;」で回数「r」を1回処理したと減らす!
「ClearRoundImage(&d,0,1);」は、結果画像の外周一回り
クリア!
「r/=2;」は、回数「r」を半分にする≪処理一組として「
結果画像⇒T画像とT画像⇒結果画像」とするのでコノ回数
にする≫!
「for(i=1;i<=r;i++){・・ループ中身・・}」は、お馴染み
教科書的な繰り返しで回数「r」繰り返す!
そしてループ中身は、
「if(c==4){・4連結処理・}else{・8連結処理・}」で
4連結処理は、
「expansion_4(pd,pt,data);Copy(pt,pd);
expansion_4(pt,pd,data);」で「結果画像⇒T画像」し
T画像を結果画像にコピーし、「T画像⇒結果画像」を
実行!
8連結処理は、
「expansion_8(pd,pt,data);Copy(pt,pd);
expansion_8(pt,pd,data);」で「結果画像⇒T画像」し
T画像を結果画像にコピーし、「T画像⇒結果画像」を
実行!
「if(i<r){Copy(pd,pt);}」は、次の回も存在する場合は、
結果画像をT画像にコピーする!
「t.freeMem();」は、「t.MallocByte(h,v);」でメモリ
確保したメモリを後始末!
「return(END_STI);」は、正常終了を関数辺値とし返し終了

(3)expansionSingle(仮引数){アルゴリズム}

code:expansionSingle(仮引数){

/************************************************************************/
/*****      膨脹                :実行部:基本部:回数(r)=1専用*****/
/*****      EXPANSION,s,d,c,1                      *****/
/************************************************************************/

int             Filter::expansionSingle(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         c,                                  // 連結性
    int         data                                // 描画データ
){
    TypeArray   s;                                  // S画像情報:局所
    TypeArray   d;                                  // D画像情報:局所
    int         sti;                                // ステータス情報

    s   = *ps;                                      // 一旦、S画像情報
    ps  = &s;                                       // を局所化
    d   = *pd;                                      // 一旦、D画像情報
    pd  = &d;                                       // を局所化
    sti = PreProcessor3By3( ps, pd );               // 前処理
    if( sti != END_STI ){                           // エラーがある場合
        return( sti );                              // ステータスを返す
    }                                               //
    Copy( ps, pd );                                 // 予め、S→D実行
    if( c == 4 ){                                   // 4連結なら
        expansion_4( ps, pd, data );                // 左記で処理
    }else{                                          // 8連結なら
        expansion_8( ps, pd, data );                // 左記で処理
    }                                               //
    return( END_STI );                              // 正常終了
}

(3-1)関数名

「expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!
「Single」は、シングル、繰り返すで無くシンプルに1回
だけ処理!

(3-2)仮引数

code:仮引数

int             Filter::expansionSingle(
    TypeArray   *ps,                                // S画像情報
    TypeArray   *pd,                                // D画像情報
    int         c,                                  // 連結性
    int         data                                // 描画データ
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を
示す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティ
ネーション画像)情報を示す「TypeArray」型の情報への
ポインタ変数です!
「int c,」は、連結性を示す選択コードで「4」なら4連結
「8」なら8連結です!
「int data」は、書き込む画素データ!

(3-3)ローカル変数

code:ローカル変数

){
    TypeArray   s;                                  // S画像情報:局所
    TypeArray   d;                                  // D画像情報:局所
    int         sti;                                // ステータス情報

「TypeArray s;」は、S画像(元画像)の変更用局所
変数「TypeArray d;」は、D画像(結果画像)の変更用
局所変数
「int sti;」は、ステータス(エラーコード)

(3-4)アルゴリズム

code:アルゴリズム

    s   = *ps;                                      // 一旦、S画像情報
    ps  = &s;                                       // を局所化
    d   = *pd;                                      // 一旦、D画像情報
    pd  = &d;                                       // を局所化
    sti = PreProcessor3By3( ps, pd );               // 前処理
    if( sti != END_STI ){                           // エラーがある場合
        return( sti );                              // ステータスを返す
    }                                               //
    Copy( ps, pd );                                 // 予め、S→D実行
    if( c == 4 ){                                   // 4連結なら
        expansion_4( ps, pd, data );                // 左記で処理
    }else{                                          // 8連結なら
        expansion_8( ps, pd, data );                // 左記で処理
    }                                               //
    return( END_STI );                              // 正常終了
}

(4)expansion_4(仮引数){アルゴリズム}

code:expansion_4(仮引数){

/************************************************************************/
/*****      膨脹                                    :実行部:4連結*****/
/*****      EXPANSION,s,d,4,r                      *****/
/************************************************************************/

void            Filter::expansion_4(
    TypeArray   *ps,                                // S画像Ptr
    TypeArray   *pd,                                // D画像情報
    int         data                                // 描画データ
){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        expansion_4_x( ptrs, ptrd, incs, data, h ); // 水平方向の処理
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}

(4-1)関数名

「expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!
「_4」は、4連結の処理を意味!

(4-2)仮引数

code:仮引数

void            Filter::expansion_4(
    TypeArray   *ps,                                // S画像Ptr
    TypeArray   *pd,                                // D画像情報
    int         data                                // 描画データ
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!

(4-3)ローカル変数

code:ローカル変数

){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

「BYTE* ptrs;」は、元画像画素ポインタ変数です!
「BYTE* ptrd;」は、結果画像画素ポインタ変数です!
「int h;」は、水平幅
「int v;」は、垂直幅
「int incs;」は、元画像の垂直方向増加幅
「int incd;」は、結果画像の垂直方向増加幅

(4-4)アルゴリズム

code:アルゴリズム

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        expansion_4_x( ptrs, ptrd, incs, data, h ); // 水平方向の処理
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}

「h=ps->h;v=ps->v;」は、水平幅・垂直幅取り出し!
「incs=ps->inc;incd=pd->inc;」は、元画像・結果画像の
垂直方向増加幅取り出し!
「ptrs=(BYTE*)ps->adr;ptrd=(BYTE*)pd->adr;」は、
元画像・結果画像のポインタの値をローカル変数にセットと
高速化の為にローカル変数変数にセットする6行!
「while(--v>=0){・・ループ中身・・}」は、垂直方向に
垂直幅分繰り返し処理、そしてループ中身
は、「expansion_4_x(ptrs,ptrd,incs,data,h);」で
水平方向処理として画像1行分処理、
「ptrs+=incs;ptrd+=incd;」で元画像・結果画像のポイン
タの値をソレゾレの垂直幅分増加

(5)expansion_4_x(仮引数){アルゴリズム}

code:expansion_4_x(仮引数){

/************************************************************************/
/*****      膨脹                            :実行部:4連結:x方向*****/
/*****      EXPANSION,s,d,4,r                      *****/
/************************************************************************/

void            Filter::expansion_4_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         data,                               // 描画データ
    int         h                                   // 水平幅
){
    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps == 0 ){                             // 注視点画素=0時
            if( *( ps - 1 ) || *( ps - inc )        // 左か上か
             || *( ps + 1 ) || *( ps + inc ) ){     // 右か下が有効なら
                *pd = data;                         // ば、書き込む
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}

(5-1)関数名

「expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!
「_4」は、4連結の処理を意味!
「_x」は、X座標方向(水平方向)の処理を意味!

(5-2)仮引数

code:仮引数

void            Filter::expansion_4_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         data,                               // 描画データ
    int         h                                   // 水平幅
){

「BYTE* ps,」は、元画像(S≒ソース画像)画素実行ポイ
ンタ「BYTE」型(1バイト単位)のポインタ変数です!
「BYTE* pd,」は、結果画像(D≒ディスティネーション
画像)画素実行ポインタ「BYTE」型(1バイト単位)の
ポインタ変数です!
「int inc,」は、元画像の垂直方向増加幅!
「int data,」は、結果書き込み画素の値です!
「int h」は、水平方向処理幅です!

(5-3)アルゴリズム

code:アルゴリズム

){
    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps == 0 ){                             // 注視点画素=0時
            if( *( ps - 1 ) || *( ps - inc )        // 左か上か
             || *( ps + 1 ) || *( ps + inc ) ){     // 右か下が有効なら
                *pd = data;                         // ば、書き込む
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}

「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の
「if(ps ==0){・・分岐中身・・}」は、「if(ps ==0){」
で元画像が画素が条件「(=0)」詰まり無効画素ならで
分岐中身を処理と「ps++;pd++;」で元画像・結果画像の
ポインタを水平方向に進める!
つまり、水平方向の処理として繰り返し、条件有効な場合で
分岐中身を処理します?!そして分岐中身は、
条件「(ps-1)||(ps-inc)||(ps+1)||(ps+inc)」で隣接
する左・上・右・下の一つでも有効なら、
「*pd=data;」と結果画像画素に結果書き込み画素の値を
セットします!

(6)expansion_8(仮引数){アルゴリズム}

code:expansion_8(仮引数){

/************************************************************************/
/*****      膨脹                                    :実行部:8連結*****/
/*****      EXPANSION,s,d,8,r                      *****/
/************************************************************************/

void            Filter::expansion_8(
    TypeArray   *ps,                                // S画像Ptr
    TypeArray   *pd,                                // D画像情報
    int         data                                // 描画データ
){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        expansion_8_x( ptrs, ptrd, incs, data, h ); // 水平方向の処理
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}

(6-1)関数名

「expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!
「_8」は、8連結の処理を意味!

(6-2)仮引数

code:仮引数

void            Filter::expansion_8(
    TypeArray   *ps,                                // S画像Ptr
    TypeArray   *pd,                                // D画像情報
    int         data                                // 描画データ
){

「TypeArray* ps,」は、元画像(S≒ソース画像)情報を示
す「TypeArray」型の情報へのポインタ変数です!
「TypeArray* pd,」は、結果画像(D≒ディスティネーショ
ン画像)情報を示す「TypeArray」型の情報へのポインタ
変数です!
「int data)」は、結果書き込み画素の値です!

(6-3)ローカル変数

code:ローカル変数

){
    BYTE        *ptrs;                              // S画像Ptr
    BYTE        *ptrd;                              // D画像Ptr
    int         h;                                  // 水平幅
    int         v;                                  // 垂直幅
    int         incs;                               // S画像:増加幅
    int         incd;                               // D画像:増加幅

「BYTE* ptrs;」は、元画像画素ポインタ変数です!
「BYTE* ptrd;」は、結果画像画素ポインタ変数です!
「int h;」は、水平幅「int v;」は、垂直幅
「int incs;」は、元画像の垂直方向増加幅
「int incd;」は、結果画像の垂直方向増加幅

(6-4)アルゴリズム

code:アルゴリズム

    h    = ps->h;                                   // 画像のサイズを
    v    = ps->v;                                   // 取り出し
    incs = ps->inc;                                 // S画像増加幅取出
    incd = pd->inc;                                 // D画像増加幅取出
    ptrs = (BYTE*)ps->adr;                          // S画像Ptrを取出す
    ptrd = (BYTE*)pd->adr;                          // D画像Ptrを取出す
    while( --v >= 0 ){                              // 垂直方向に繰返
        expansion_4_x( ptrs, ptrd, incs, data, h ); // 水平方向の処理
        ptrs += incs;                               // S画像垂直増加
        ptrd += incd;                               // D画像垂直増加
    }                                               //
}

「h=ps->h;v=ps->v;」は、画像の水平幅・垂直幅を取り出
し!元画像・結果画像も同じ有効処理幅に補正されて居る
事が前提!
「incs=ps->inc;incd=pd->inc;」は、元画像・結果画像の
垂直方向増加幅を取り出し!
「ptrs=(BYTE*)ps->adr;ptrd=(BYTE*)pd->adr;」は、
元画像・結果画像のポインタの値をローカル変数にセットと
高速化の為にローカル変数変数にセットする6行!
「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の下請け
関数「expansion_8_x(ptrs,ptrd,incs,data,h);」で水平方向
処理として画像1行分処理、
「ptrs+=incs;ptrd+=incd;」で元画像・結果画像のポインタ
の値をソレゾレの垂直幅分増加

(7)expansion_8_x(仮引数){アルゴリズム}

code:expansion_8_x(仮引数){

/************************************************************************/
/*****      膨脹                            :実行部:8連結:x方向*****/
/*****      EXPANSION,s,d,8,r                      *****/
/************************************************************************/

void            Filter::expansion_8_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         data,                               // 描画データ
    int         h                                   // 水平幅
){
    BYTE        *p;                                 // S画像Ptr

    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps == 0 ){                             // 注視点画素=0時
            if( *( ps - 1 ) || *( ps + 1 ) ){       // 左右が有効なら
                *pd = data;                         // 書き込む
            }else{                                  // 上記以外の場合
                p = ps - inc - 1;                   // 左上をセットし
                if( *p || *(p+1) || *(p+2) ){       // 上側が有効なら
                    *pd = data;                     // 書き込む
                }else{                              // 上記以外で
                    p = ps + inc - 1;               // 左下をセットし
                    if( *p || *(p+1) || *(p+2) ){   // 下側が有効なら
                        *pd = data;                 // 書き込む
                    }                               //
                }                                   //
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}

(7-1)関数名

「expansion」は、膨脹の意味ですが、ここでは、一回り
連結した図形を太くすると考えて下さい!
「_8」は、8連結の処理を意味!
「_x」は、X座標方向(水平方向)の処理を意味!

(7-2)仮引数

code:仮引数

void            Filter::expansion_8_x(
    BYTE        *ps,                                // S画像Ptr
    BYTE        *pd,                                // D画像Ptr
    int         inc,                                // S画像:増加幅
    int         data,                               // 描画データ
    int         h                                   // 水平幅
){

「BYTE* ps,」は、元画像(S≒ソース画像)画素実行ポイ
ンタ「BYTE」型(1バイト単位)のポインタ変数です!
「BYTE* pd,」は、結果画像(D≒ディスティネーション
画像)画素実行ポインタ「BYTE」型(1バイト単位)の
ポインタ変数です!
「int inc,」は、元画像の垂直方向増加幅!
「int data)」は、結果書き込み画素の値です!
「int h」は、水平方向処理幅です!

(7-3)ローカル変数

code:ローカル変数

){
    BYTE        *p;                                 // S画像Ptr

「BYTE* p;」は、元画像画素への左上・左下等上下移動分の
ポインタ変数!

(7-4)アルゴリズム

code:アルゴリズム

    while( --h >= 0 ){                              // 水平方向に繰返し
        if( *ps == 0 ){                             // 注視点画素=0時
            if( *( ps - 1 ) || *( ps + 1 ) ){       // 左右が有効なら
                *pd = data;                         // 書き込む
            }else{                                  // 上記以外の場合
                p = ps - inc - 1;                   // 左上をセットし
                if( *p || *(p+1) || *(p+2) ){       // 上側が有効なら
                    *pd = data;                     // 書き込む
                }else{                              // 上記以外で
                    p = ps + inc - 1;               // 左下をセットし
                    if( *p || *(p+1) || *(p+2) ){   // 下側が有効なら
                        *pd = data;                 // 書き込む
                    }                               //
                }                                   //
            }                                       //
        }                                           //
        ps++;                                       // S画像進行
        pd++;                                       // D画像進行
    }                                               //
}

「while(--h>=0){」は、・・ループ中身・・}」は、水平
方向に水平幅分繰り返し処理、そしてループ中身の
「if(ps ==0){・・分岐中身・・}」は、「if(ps ==0){」
で元画像が画素が条件「(=0)」詰まり無効画素ならで
分岐中身を処理と「ps++;pd++;」で元画像・結果画像の
ポインタを水平方向に進める!
つまり、水平方向の処理として繰り返し、条件有効な場合で
分岐中身を処理します?!そして分岐中身は、
「if((ps-1)==0||(ps+1)==0){pd=zero;}」で更に
条件「(ps-1)==0||*(ps+1)==0」と左右隣接画素が一つでも
無効「(=0)」なら、「pd=zero;」で「0」を書き込む、
そして条件が非成立「else{・・非成立処理」として
「p=ps-inc-1;」で左上ポインタ変数セットし、
「if(p==0||(p+1)==0||(p+2)==0){pd=zero;」で更に
条件「p==0||(p+1)==0||(p+2)==0」と左上・右上隣接
画素が一つでも無効「(=0)」なら、「pd=zero;」で
「0」を書き込む、それでも条件が非成立
「else{・・非成立処理」として「p=ps+inc-1;」で
左下ポインタ変数セットし、
「if(p==0||(p+1)==0||(p+2)==0){pd=zero;}」で更に
条件「p==0||(p+1)==0||(p+2)==0」と左下・右下隣接
画素が一つでも無効「(=0)」なら、「*pd=zero;」で
「0」を書き込む!

4.追記

孤立点除去・収縮・膨脹が、基本的なよく使う画像図形変換
だが、画像処理アプリで役に立った画像図形変換処理とし、
骨格化(スケルトニング)処理が有りますが、前段として
距離変換と言う多値画像を生成する事を含む処理なので
別の解説エッセイ『距離変換・骨格化』を近々発表して解説
します?!

文末

いいなと思ったら応援しよう!