見出し画像

解説クラスCopyClear(16)

解説クラスCopyClear(16)


2025年1月20初講(初稿)

この講義は解説『解説クラスCopyClear(15)』
の続きです!

(4-14-38)関数「int MagnifyImage(TypeArray* ps,TypeArray* pd,double zh,double zv,int dataSize,int sw){・・・}」の説明

/************************************************************************/
/*****      正規に見える関数群                                      *****/
/************************************************************************/

int             CopyClear:: MagnifyImage(                   // 画像の拡大・縮小
    TypeArray*  ps,                                         // S配列
    TypeArray*  pd,                                         // D配列
    double      zh,                                         // 水平拡大率
    double      zv,                                         // 垂直拡大率
    int         dataSize,                                   // 画素サイズ(省略時=1)
                                                            // 1:主に濃淡画像
                                                            // 3:主にカラー(3原色)画像
    int         sw                                          // 補間SW(真:補間、省略時=偽)
){
    int         izh;                                        // 水平拡大率:整数値
    int         izv;                                        // 垂直拡大率:整数値

    if( sw ){                                               // 補間する場合は
        return( MagnifyZoomInterpolate(                     // 左記で補間付きの
                    ps, pd, zh, zv, 0.0, 0.0, dataSize ) ); // 拡大・縮小処理
    }                                                       // 
    if( zh >= 1.0 && zv >= 1.0 ){                           // 拡大時で
        izh = (int)zh;                                      // 整数の拡大率を
        izv = (int)zv;                                      // 求め
        if( (double)izh == zh && (double)izv == zv ){       // 整数倍で拡大の場合
            return( MagnifyZoomInt( ps, pd, izh, izv,       // 左記で拡大
                                            dataSize ) );   // 
        }                                                   // 
    }                                                       // 実数値での指定では
    return( MagnifyZoom( ps, pd, zh, zv, dataSize ) );      // 左記で拡大・縮小処理
}

☆備考☆この関数はファイル「CopyClear.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★備考★「C言語のコード部、関数本体の前のコメントに
【正規に見える関数群】」と有るのは、アルゴリズム解説で
説明する様にサブルーチン関数「MagnifyZoomInterpolate」
「MagnifyZoomint 」・「MagnifyZoom」と複数の良く似て細かく違う関数を大本の「正規」名称≪MagnifyImage≫の
名前でマトメタからです!

(A)関数「MagnifyImage()」の【関数名】説明

「Magnify」は、英単語「magnify」で拡大するとの意味です!
「Image」は、勿論、画像で、ココでは、拡大の一部としてと意味も拡大して「画像の拡大/縮小」を行う関数です!

(B)関数「int MagnifyImage()」の【返値】説明

基本的に内部で使用するサブルーチン関数の辺値をこの関数
の辺値とします!

(C)関数「MagnifyImage()」の【仮引数】説明

int             CopyClear:: MagnifyImage(                   // 画像の拡大・縮小
    TypeArray*  ps,                                         // S配列
    TypeArray*  pd,                                         // D配列
    double      zh,                                         // 水平拡大率
    double      zv,                                         // 垂直拡大率
    int         dataSize,                                   // 画素サイズ(省略時=1)
                                                            // 1:主に濃淡画像
                                                            // 3:主にカラー(3原色)画像
    int         sw                                          // 補間SW(真:補間、省略時=偽)
){

「TypeArray* ps,」は、S(元)画像情報
「TypeArray* pd,」は、D(結果)画像情報
「double zh,」は、水平方向(X座標方向)の拡大率です!
「double zv,」は、垂直方向(Y座標方向)の拡大率です!
「int dataSize=1,」は、引数省略時は1と1画素単位です
が、3画素をRGBとかのカラー画像に対応出来る様にして
います!
「int sw=FALSE);」は、画素間の補完を行うか否かです!
省略時は補完で無く高速化処理です

(D)関数「MagnifyImage()」の【アルゴリズム】説明

){
    int         izh;                                        // 水平拡大率:整数値
    int         izv;                                        // 垂直拡大率:整数値

    if( sw ){                                               // 補間する場合は
        return( MagnifyZoomInterpolate(                     // 左記で補間付きの
                    ps, pd, zh, zv, 0.0, 0.0, dataSize ) ); // 拡大・縮小処理
    }                                                       // 
    if( zh >= 1.0 && zv >= 1.0 ){                           // 拡大時で
        izh = (int)zh;                                      // 整数の拡大率を
        izv = (int)zv;                                      // 求め
        if( (double)izh == zh && (double)izv == zv ){       // 整数倍で拡大の場合
            return( MagnifyZoomInt( ps, pd, izh, izv,       // 左記で拡大
                                            dataSize ) );   // 
        }                                                   // 
    }                                                       // 実数値での指定では
    return( MagnifyZoom( ps, pd, zh, zv, dataSize ) );      // 左記で拡大・縮小処理
}

(D-1)ローカル変数

){
    int         izh;                                        // 水平拡大率:整数値
    int         izv;                                        // 垂直拡大率:整数値

「int izh;」は、水平方向の拡大率の整数化値
「int izv;」は、垂直方向の拡大率の整数化値

(D-2)アルゴリズムコード

    if( sw ){                                               // 補間する場合は
        return( MagnifyZoomInterpolate(                     // 左記で補間付きの
                    ps, pd, zh, zv, 0.0, 0.0, dataSize ) ); // 拡大・縮小処理
    }                                                       // 
    if( zh >= 1.0 && zv >= 1.0 ){                           // 拡大時で
        izh = (int)zh;                                      // 整数の拡大率を
        izv = (int)zv;                                      // 求め
        if( (double)izh == zh && (double)izv == zv ){       // 整数倍で拡大の場合
            return( MagnifyZoomInt( ps, pd, izh, izv,       // 左記で拡大
                                            dataSize ) );   // 
        }                                                   // 
    }                                                       // 実数値での指定では
    return( MagnifyZoom( ps, pd, zh, zv, dataSize ) );      // 左記で拡大・縮小処理
}

「if(sw){return(MagnifyZoomInterpolate(
ps,pd,zh,zv,0.0,0.0,dataSize));}」は、条件「sw」が真
なら「return(MagnifyZoomInterpolate(
ps,pd,zh,zv,0.0,0.0,dataSize));}」とサブルーチン
関数「MagnifyZoomInterpolate()」で処理し、この関数の
辺値を返し関数終了!
条件「zh>=1.0&&zv>=1.0」と水平・垂直方向の拡大率が、
両方とも1.0以上≪詰り、拡大する場合≫、一旦、
「izh=(int )zh;izv=(int )zv;」と整数化拡大率をセットし
条件「if((double)izh==zh&&(double)izv==zv)」と整数化
した値と拡大率が同じ≪詰り、整数倍拡大する場合≫なら
「return(MagnifyZoomInt(ps,pd,izh,izv,dataSize
));」とサブルーチン関数「MagnifyZoomInt()」で処理し、
この関数の辺値を返し関数終了!
これ等の条件の外ならば、
「return(MagnifyZoom(ps,pd,zh,zv,dataSize));」で
サブルーチン関数「MagnifyZoom()」で処理し、この関数の
辺値を返し関数終了!

(E)関数「MagnifyImage()」の【使用例】

★注意★
使用例は、別の解説エッセイ『画像幾何変換使用例』で
別途説明する事に方針変換しました!
使用例発表まで乞うご期待と記載して置きます!

(4-14-39)関数「int MoveImage(TypeArray* ps,TypeArray* pd,double x,double y,int dataSize,int sw){・・・}」の説明

/************************************************************************/
/*****  図形の平行移動:実行部:配列版                              *****/
/************************************************************************/

int             CopyClear::MoveImage(
    TypeArray   *ps,                                            // S配列
    TypeArray   *pd,                                            // D配列
    double      x,                                              // X座標
    double      y,                                              // Y座標
    int         dataSize,                                       // 画素サイズ(省略時=1)
                                                                // 1:主に濃淡画像
                                                                // 3:主にカラー(3原色)画像
    int         sw                                              // 補間SW(真:補間、省略時=偽)
){
    TypeArray   S;                                              // S画像情報
    TypeArray   S1;                                             // S画像情報
    TypeArray   D;                                              // D画像情報
    TypeArray   D1;                                             // D画像情報
    int         iX;                                             // X座標整数
    int         iY;                                             // Y座標整数
    double      offsetX;                                        // 微少X座標offset(0.0~1.0)
    double      offsetY;                                        // 微少Y座標offset(0.0~1.0)
    int         st1;                                            // ステータス情報
    int         st2;                                            // ステータス情報

    if( dataSize <= 0 ){                                        // 画素サイズ不正なら
        return( STI_FLG );                                      // 不正を返す
    }                                                           //
    if( sw ){                                                   // 補間がある場合
        iX      = (int)x;                                       // X座標を整数部と
        offsetX = x - (double)iX;                               // 微少部に分離
        if( offsetX < 0.0 ){                                    // 負なら
            offsetX += 1.0;                                     // 左記のように
            iX      -= 1;                                       // 補正
        }                                                       // 
        iY      = (int)y;                                       // Y座標を整数部と
        offsetY = y - (double)iY;                               // 微少部に分離
        if( offsetY < 0.0 ){                                    // 負なら
            offsetY += 1.0;                                     // 左記のように
            iY      -= 1;                                       // 補正
        }                                                       // 
    }else{                                                      // 補間がない場合
        iX      = (int)x;                                       // X座標を整数部と
        offsetX = 0.0;                                          // 微少部に分離
        iY      = (int)y;                                       // Y座標を整数部と
        offsetY = 0.0;                                          // 微少部に分離
    }                                                           //
    if( dataSize >= 2 ){                                        // 画素サイズ2以上なら
        iX *= dataSize;                                         // 論理座標を物理座標に変換
    }                                                           //
    if( iX >= 0 ){                                              // Xが正の場合
        st1 = S.subsetAdjust( ps, 0,  0, ps->h,      ps->v );   // Sは元のまま
        st2 = D.subsetAdjust( pd, iX, 0, pd->h - iX, pd->v );   // DをX座標ずらし
    }else{                                                      // Xが負の場合
        st1 = S.subsetAdjust( ps, -iX, 0, ps->h + iX, ps->v );  // SをX座標ずらし
        st2 = D.subsetAdjust( pd,   0, 0, pd->h,      pd->v );  // Dは元のまま
    }                                                           // 
    if( st1 != END_STI ){                                       // 不正があれば
        return( st1 );                                          // ステータスを返す
    }                                                           // 
    if( st2 != END_STI ){                                       // 不正があれば
        return( st2 );                                          // ステータスを返す
    }                                                           // 
    if( iY >= 0 ){                                              // Yが正の場合
        st1 = S1.subsetAdjust( &S, 0,  0, S.h, S.v );           // Sは元のまま
        st2 = D1.subsetAdjust( &D, 0, iY, D.h, D.v - iY );      // DをY座標ずらし
    }else{                                                      // Yが負の場合
        st1 = S1.subsetAdjust( &S, 0, -iY, S.h, S.v + iY );     // SをY座標ずらし
        st2 = D1.subsetAdjust( &D, 0,   0, D.h, D.v );          // Dは元のまま
    }                                                           // 
    if( st1 != END_STI ){                                       // 不正があれば
        return( st1 );                                          // ステータスを返す
    }                                                           // 
    if( st2 != END_STI ){                                       // 不正があれば
        return( st2 );                                          // ステータスを返す
    }                                                           // 
    if( !sw || offsetX == 0.0 && offsetY == 0.0 ){              // 整数分移動する場合
        return( Copy( &S1, &D1 ) );                             // 左記で画像コピー
    }else{                                                      // 実数で移動する場合
        if( ps->w == 1 ){                                       // 1Byte画素単位なら
            return( MoveImageByte(                              // 左記で平行移動
                    &S1, &D1, offsetX, offsetY, dataSize ) );   // (補間付き)
        }else if( ps->w == 2 ){                                 // 2Byte画素単位なら
            return( MoveImageShort(                             // 左記で平行移動
                    &S1, &D1, offsetX, offsetY, dataSize ) );   // (補間付き)
        }else if( ps->w == 4 ){                                 // 4Byte画素単位なら
            return( MoveImageLong(                              // 左記で平行移動
                    &S1, &D1, offsetX, offsetY, dataSize ) );   // (補間付き)
        }else if( ps->w == 101 ){                               // 単精度画素単位なら
            return( MoveImageFloat(                             // 左記で平行移動
                    &S1, &D1, offsetX, offsetY, dataSize ) );   // (補間付き)
        }else{                                                  // 上記以外なら
            return( STI_ARY_5 );                                // 不正を返す
        }                                                       // 
    }                                                           // 
}

☆備考☆この関数はファイル「CopyClear350.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「MoveImage()」の【関数名】説明

「Move」は、英単語「Move」でカタカナ語でムーブ、ココ
では、画像の位置の幾何的移動を行う処理です!

(B)関数「int MoveImage()」の【返値】説明

この関数内で明示的に検査しているのは、内部で使用する
部分画像生成が可能か否かで部分画像生成が出来なかった
時にソノ失敗時エラーコードを関数の辺値とし返し、
関数終了します!そしてサブルーチン関数で移動処理時に
発生したエラーコードを関数の値として返し関数終了!

(C)関数「MoveImage()」の【仮引数】説明

int             CopyClear::MoveImage(
    TypeArray   *ps,                                            // S配列
    TypeArray   *pd,                                            // D配列
    double      x,                                              // X座標
    double      y,                                              // Y座標
    int         dataSize,                                       // 画素サイズ(省略時=1)
                                                                // 1:主に濃淡画像
                                                                // 3:主にカラー(3原色)画像
    int         sw                                              // 補間SW(真:補間、省略時=偽)
){

「TypeArray* ps,」は、S(元)画像情報
「TypeArray* pd,」は、D(結果)画像情報
「double x,」は、移動先のX座標
「double y,」は、移動先のY座標
「int dataSize=1,」は、引数省略時は1と1画素単位です
が、3画素をRGBとかのカラー画像に対応出来る様にして
います!
「int sw=FALSE);」は、画素間の補完を行うか否かです!
省略時は補完で無く高速化処理です

(D)関数「MoveImage()」の【アルゴリズム】説明

){
    TypeArray   S;                                              // S画像情報
    TypeArray   S1;                                             // S画像情報
    TypeArray   D;                                              // D画像情報
    TypeArray   D1;                                             // D画像情報
    int         iX;                                             // X座標整数
    int         iY;                                             // Y座標整数
    double      offsetX;                                        // 微少X座標offset(0.0~1.0)
    double      offsetY;                                        // 微少Y座標offset(0.0~1.0)
    int         st1;                                            // ステータス情報
    int         st2;                                            // ステータス情報

    if( dataSize <= 0 ){                                        // 画素サイズ不正なら
        return( STI_FLG );                                      // 不正を返す
    }                                                           //
    if( sw ){                                                   // 補間がある場合
        iX      = (int)x;                                       // X座標を整数部と
        offsetX = x - (double)iX;                               // 微少部に分離
        if( offsetX < 0.0 ){                                    // 負なら
            offsetX += 1.0;                                     // 左記のように
            iX      -= 1;                                       // 補正
        }                                                       // 
        iY      = (int)y;                                       // Y座標を整数部と
        offsetY = y - (double)iY;                               // 微少部に分離
        if( offsetY < 0.0 ){                                    // 負なら
            offsetY += 1.0;                                     // 左記のように
            iY      -= 1;                                       // 補正
        }                                                       // 
    }else{                                                      // 補間がない場合
        iX      = (int)x;                                       // X座標を整数部と
        offsetX = 0.0;                                          // 微少部に分離
        iY      = (int)y;                                       // Y座標を整数部と
        offsetY = 0.0;                                          // 微少部に分離
    }                                                           //
    if( dataSize >= 2 ){                                        // 画素サイズ2以上なら
        iX *= dataSize;                                         // 論理座標を物理座標に変換
    }                                                           //
    if( iX >= 0 ){                                              // Xが正の場合
        st1 = S.subsetAdjust( ps, 0,  0, ps->h,      ps->v );   // Sは元のまま
        st2 = D.subsetAdjust( pd, iX, 0, pd->h - iX, pd->v );   // DをX座標ずらし
    }else{                                                      // Xが負の場合
        st1 = S.subsetAdjust( ps, -iX, 0, ps->h + iX, ps->v );  // SをX座標ずらし
        st2 = D.subsetAdjust( pd,   0, 0, pd->h,      pd->v );  // Dは元のまま
    }                                                           // 
    if( st1 != END_STI ){                                       // 不正があれば
        return( st1 );                                          // ステータスを返す
    }                                                           // 
    if( st2 != END_STI ){                                       // 不正があれば
        return( st2 );                                          // ステータスを返す
    }                                                           // 
    if( iY >= 0 ){                                              // Yが正の場合
        st1 = S1.subsetAdjust( &S, 0,  0, S.h, S.v );           // Sは元のまま
        st2 = D1.subsetAdjust( &D, 0, iY, D.h, D.v - iY );      // DをY座標ずらし
    }else{                                                      // Yが負の場合
        st1 = S1.subsetAdjust( &S, 0, -iY, S.h, S.v + iY );     // SをY座標ずらし
        st2 = D1.subsetAdjust( &D, 0,   0, D.h, D.v );          // Dは元のまま
    }                                                           // 
    if( st1 != END_STI ){                                       // 不正があれば
        return( st1 );                                          // ステータスを返す
    }                                                           // 
    if( st2 != END_STI ){                                       // 不正があれば
        return( st2 );                                          // ステータスを返す
    }                                                           // 
    if( !sw || offsetX == 0.0 && offsetY == 0.0 ){              // 整数分移動する場合
        return( Copy( &S1, &D1 ) );                             // 左記で画像コピー
    }else{                                                      // 実数で移動する場合
        if( ps->w == 1 ){                                       // 1Byte画素単位なら
            return( MoveImageByte(                              // 左記で平行移動
                    &S1, &D1, offsetX, offsetY, dataSize ) );   // (補間付き)
        }else if( ps->w == 2 ){                                 // 2Byte画素単位なら
            return( MoveImageShort(                             // 左記で平行移動
                    &S1, &D1, offsetX, offsetY, dataSize ) );   // (補間付き)
        }else if( ps->w == 4 ){                                 // 4Byte画素単位なら
            return( MoveImageLong(                              // 左記で平行移動
                    &S1, &D1, offsetX, offsetY, dataSize ) );   // (補間付き)
        }else if( ps->w == 101 ){                               // 単精度画素単位なら
            return( MoveImageFloat(                             // 左記で平行移動
                    &S1, &D1, offsetX, offsetY, dataSize ) );   // (補間付き)
        }else{                                                  // 上記以外なら
            return( STI_ARY_5 );                                // 不正を返す
        }                                                       // 
    }                                                           // 
}

(D-1)ローカル変数

){
    TypeArray   S;                                              // S画像情報
    TypeArray   S1;                                             // S画像情報
    TypeArray   D;                                              // D画像情報
    TypeArray   D1;                                             // D画像情報
    int         iX;                                             // X座標整数
    int         iY;                                             // Y座標整数
    double      offsetX;                                        // 微少X座標offset(0.0~1.0)
    double      offsetY;                                        // 微少Y座標offset(0.0~1.0)
    int         st1;                                            // ステータス情報
    int         st2;                                            // ステータス情報

「TypeArrayS;」は、S(元)画像の部分画像:X座標変位
「TypeArrayS1;」は、S(元)画像の部分画像:Y座標変位
「TypeArrayD;」は、D(結果)画像の部分画像:X座標変位
「TypeArrayD1;」は、D(結果)画像の部分画像:Y座標変位、
「int iX;」は、整数化したX座標変位
「int iY;」は、整数化したY座標変位
「double offsetX;」は、X座標変位の小数点以下部分
「double offsetY;」は、Y座標変位の小数点以下部分
「int st1;」は、ステータス(エラー)情報
「int st2;」は、ステータス(エラー)情報

(D-2)アルゴリズムコード

    if( dataSize <= 0 ){                                        // 画素サイズ不正なら
        return( STI_FLG );                                      // 不正を返す
    }                                                           //
    if( sw ){                                                   // 補間がある場合
        iX      = (int)x;                                       // X座標を整数部と
        offsetX = x - (double)iX;                               // 微少部に分離
        if( offsetX < 0.0 ){                                    // 負なら
            offsetX += 1.0;                                     // 左記のように
            iX      -= 1;                                       // 補正
        }                                                       // 
        iY      = (int)y;                                       // Y座標を整数部と
        offsetY = y - (double)iY;                               // 微少部に分離
        if( offsetY < 0.0 ){                                    // 負なら
            offsetY += 1.0;                                     // 左記のように
            iY      -= 1;                                       // 補正
        }                                                       // 
    }else{                                                      // 補間がない場合
        iX      = (int)x;                                       // X座標を整数部と
        offsetX = 0.0;                                          // 微少部に分離
        iY      = (int)y;                                       // Y座標を整数部と
        offsetY = 0.0;                                          // 微少部に分離
    }                                                           //
    if( dataSize >= 2 ){                                        // 画素サイズ2以上なら
        iX *= dataSize;                                         // 論理座標を物理座標に変換
    }                                                           //
    if( iX >= 0 ){                                              // Xが正の場合
        st1 = S.subsetAdjust( ps, 0,  0, ps->h,      ps->v );   // Sは元のまま
        st2 = D.subsetAdjust( pd, iX, 0, pd->h - iX, pd->v );   // DをX座標ずらし
    }else{                                                      // Xが負の場合
        st1 = S.subsetAdjust( ps, -iX, 0, ps->h + iX, ps->v );  // SをX座標ずらし
        st2 = D.subsetAdjust( pd,   0, 0, pd->h,      pd->v );  // Dは元のまま
    }                                                           // 
    if( st1 != END_STI ){                                       // 不正があれば
        return( st1 );                                          // ステータスを返す
    }                                                           // 
    if( st2 != END_STI ){                                       // 不正があれば
        return( st2 );                                          // ステータスを返す
    }                                                           // 
    if( iY >= 0 ){                                              // Yが正の場合
        st1 = S1.subsetAdjust( &S, 0,  0, S.h, S.v );           // Sは元のまま
        st2 = D1.subsetAdjust( &D, 0, iY, D.h, D.v - iY );      // DをY座標ずらし
    }else{                                                      // Yが負の場合
        st1 = S1.subsetAdjust( &S, 0, -iY, S.h, S.v + iY );     // SをY座標ずらし
        st2 = D1.subsetAdjust( &D, 0,   0, D.h, D.v );          // Dは元のまま
    }                                                           // 
    if( st1 != END_STI ){                                       // 不正があれば
        return( st1 );                                          // ステータスを返す
    }                                                           // 
    if( st2 != END_STI ){                                       // 不正があれば
        return( st2 );                                          // ステータスを返す
    }                                                           // 
    if( !sw || offsetX == 0.0 && offsetY == 0.0 ){              // 整数分移動する場合
        return( Copy( &S1, &D1 ) );                             // 左記で画像コピー
    }else{                                                      // 実数で移動する場合
        if( ps->w == 1 ){                                       // 1Byte画素単位なら
            return( MoveImageByte(                              // 左記で平行移動
                    &S1, &D1, offsetX, offsetY, dataSize ) );   // (補間付き)
        }else if( ps->w == 2 ){                                 // 2Byte画素単位なら
            return( MoveImageShort(                             // 左記で平行移動
                    &S1, &D1, offsetX, offsetY, dataSize ) );   // (補間付き)
        }else if( ps->w == 4 ){                                 // 4Byte画素単位なら
            return( MoveImageLong(                              // 左記で平行移動
                    &S1, &D1, offsetX, offsetY, dataSize ) );   // (補間付き)
        }else if( ps->w == 101 ){                               // 単精度画素単位なら
            return( MoveImageFloat(                             // 左記で平行移動
                    &S1, &D1, offsetX, offsetY, dataSize ) );   // (補間付き)
        }else{                                                  // 上記以外なら
            return( STI_ARY_5 );                                // 不正を返す
        }                                                       // 
    }                                                           // 
}

「if(dataSize<=0){return(STI_FLG);}」は、画素単位が、
0以下をエラーとし「STI_FLG」を返し関数終了!
「if(sw){・・成立中身・・}else{・・不成立中身・・}」
は、成立条件「sw」詰り、補完する場合は、
成立中身「iX=(int )x;offsetX=x-(double)iX;
if(offsetX<0.0){offsetX+=1.0;iX-=1;}
iY=(int )y;offsetY=y-(double)iY;
if(offsetY<0.0){offsetY+=1.0;iY-=1;}」と
「iX=(int )x;offsetX=x-(double)iX;」で変数「ix」に
X座標の整数値部をセットし変数「offsetX」に小数点
以下の部分をセットします!そして
「if(offsetX<0.0){offsetX+=1.0;iX-=1;}」でX座標の
小数点以下部分が負の値なら、「offsetX+=1.0;iX-=1;」
と整数値部・小数点以下部分を正の数に成る様に補正!
「iY=(int )y;offsetY=y-(double)iY;」で変数「iy」に
Y座標の整数値部をセットし変数「offsetY」に小数点
以下の部分をセットします!そして
「if(offsetY<0.0){offsetY+=1.0;iY-=1;}」でY座標の
小数点以下部分が負の値なら、「offsetY+=1.0;iY-=1;」
と整数値部・小数点以下部分を正の数に成る様に補正!
不成立中身「iX=(int )x;offsetX=0.0;
iY=(int )y;offsetY=0.0;」は、勿論、座標補正しないので
「iX=(int )x;offsetX=0.0;」と整数部分は型変換だけ行い
小数点以下部分が0.0にセットがX座標方向でY座標方向
も「iY=(int )y;offsetY=0.0;」整数部分は型変換だけ行い
小数点以下部分が0.0にセット!
「if(dataSize>=2){iX*=dataSize;}」は、
条件「dataSize>=2」、詰り2画素単位以上なら
「iX*=dataSize;」でX座標方向の整数化部分を画素単位に
補正!
「if(iX>=0){・・成立中身・・}else{・・成立中身・・}」
は、条件「iX>=0」とX座標方向整数部が0以上で成立中身
「st1=S.subsetAdjust(ps,0,0,ps->h,ps->v);
st2=D.subsetAdjust(pd,iX,0,pd->h-iX,pd->v);」で
「S.subsetAdjust()」と「TypeArray」クラスのメンバー
関数「subsetAdjust()」で部分画像をローカル画像情報
「S」にセットし、
メンバー関数実行ステータス情報を変数「st1」
にセットします、
同じ様に部分画像をローカル画像情報「D」にセットし、
メンバー関数実行ステータス情報を変数「st2」にセット
します!★備考★【主にC言語だけに馴染んで来た
受講生の皆様へ、このC++言語から使える様に成ったクラ
スのメンバー関数を使用する方法をこのライブラリは多用し
ていますので慣れて下さい★注意★この様にクラスに限定し
た使用方法はオブジェクト指向の考えとして不用意に他で使
え無い事でソースコードの安全性を高める手法と理解して下
さい】
不成立中身「st1=S.subsetAdjust(
ps,-iX,0,ps->h+iX,ps->v);st2=D.subsetAdjust(
pd,0,0,pd->h,pd->v);」は、整数部が負数に成ったら、座標
始点を始終を逆にして部分画像を取得している事は字面から
理解して頂けると思いますが?!理解して頂いていますね!
「if(st1!=END_STI){return(st1);}」は、ステータス情報
「st1」にエラーが有れば、このコードの値を関数の値とし
返し関数終了!
「if(st2!=END_STI){return(st2);}」は、ステータス情報
「st1」にエラーが有れば、このコードの値を関数の値とし
返し関数終了!★注意★ここまででX座標方向の部分画像
を作成した事を理解して下さい!
「if(iY>=0){・・・・if(st2!=END_STI){return(st2);}」
は、今度は、Y座標方向の部分画像を作成した事を理解して
頂けますね!
「if(!sw||offsetX==0.0&&offsetY==0.0){・・成立中身・・
}else{・・不成立中身・・}」は、条件「
!sw||offsetX==0.0&&offsetY==0.0」、詰り、補正無し及び
XY座標の小数点以下移動部分が無い場合と例外条件と考え
て頂ければ良いかなで「return(Copy(&S1,&D1));」と
サブルーチン関数「Copy(&S1,&D1)」で処理し、その辺値を
関数の辺値として関数終了!★備考★幾何移動で画素単位の
場合は、画像処理の基本中の基本的なコピー関数で十分と言
う事です!そして「}else{・・不成立中身・・}」と細かい
小数点以下の移動も扱う処理では、
「if(ps->w==1){return(MoveImageBYTE (&S1,&D1,offsetX,
offsetY,dataSize));」と条件「ps->w==1」画素単位が、
1バイトの時、「return(MoveImageBYTE (&S1,&D1,
offsetX,offsetY,dataSize));」とサブルーチン関数「
MoveImageBYTE ()」で処理し、その辺値を関数の辺値として
関数終了!
「}else if(ps->w==2){return(MoveImageShort(&S1,&D1,
offsetX,offsetY,dataSize));」と条件「ps->w==2」画素
単位が2バイトの時、「return(MoveImageShort(
&S1,&D1,offsetX,offsetY,dataSize));」とサブルーチン
関数「MoveImageShort()」で処理し、その辺値を関数の
辺値として関数終了!
「}else if(ps->w==4){return(MoveImageLong(&S1,&D1,
offsetX,offsetY,dataSize));」と条件「ps->w==4」画素
単位が4バイトの時、「return(MoveImageLong(
&S1,&D1,offsetX,offsetY,dataSize));」とサブルーチン
関数「MoveImageLong()」で処理し、その辺値を関数の
辺値として関数終了!そして、「}else{」と全て非成立の
時は、「return(STI_ARY_5);」とエラーコードを辺値とし
関数終了!

(E)関数「MoveImage()」の【使用例】

★注意★
使用例は、別の解説エッセイ『画像幾何変換使用例』で
別途説明する事に方針変換しました!
使用例発表まで乞うご期待と記載して置きます!

(4-14-40)関数「int MirrorImage(TypeArray* ps,TypeArray* pd,int k,int dataSize){・・・}」

/************************************************************************/
/*****  配列の鏡像の作成(上下・左右等図形の変換)コマンド:実行部  *****/
/*****  MIRROR,s,d,k                                       *****/
/************************************************************************/

int             CopyClear::MirrorImage(
    TypeArray   *ps,                                    // S配列
    TypeArray   *pd,                                    // D配列
    int         k,                                      // 1:左右反転
                                                        // 2:上下反転
                                                        // 3:上下左右反転
    int         dataSize                                // 画素サイズ(省略時=1)
                                                        // 1:主に濃淡画像
                                                        // 3:主にカラー(3原色)画像
){
    TypeArray   D;                                      // D配列:局所
    BYTE        *psa;                                   // S配列実Adr
    BYTE        *pda;                                   // D配列実Adr
    int         h;                                      // 水平幅
    int         v;                                      // 垂直幅
    int         sl;                                     // Sの増加幅
    int         dl;                                     // Dの増加幅

    if( ps == 0 ){                                      // Sが空なら
        return( STI_ARY_0 - 10 );                       // 不正を返す
    }else if( ps->adr == 0 ){                           // Sの実ptrが空なら
        return( STI_ARY_1 - 10 );                       // 不正を返す
    }else if( pd == 0 ){                                // Dが空なら
        return( STI_ARY_0 - 20 );                       // 不正を返す
    }else if( pd->adr == 0 ){                           // Dの実ptrが空なら
        return( STI_ARY_1 - 20 );                       // 不正を返す
    }else if( ps->w != pd->w || ps->w < 0               // Bits幅が異なるか
                        || ps->w == 3 || ps->w > 4 ){   // 可能な幅以外は
        return( STI_ARY_5 - 20 );                       // 不正を返す
    }                                                   //
    if( k <= 0 || k > 3 || dataSize <= 0 ){             // 不正なら
        return( STI_FLG );                              // 不正を返す
    }                                                   //
    psa = (BYTE*)ps->adr;                               // S実Adr取出し
    pda = (BYTE*)pd->adr;                               // D実Adr取出し
    h   = (ps->h < pd->h) ? ps->h : pd->h;              // 水平幅を算出
    v   = (ps->v < pd->v) ? ps->v : pd->v;              // 垂直幅を算出
    sl  = ps->inc;                                      // Sの増加幅Set
    dl  = pd->inc;                                      // Dの増加幅Set
    if( h % dataSize != 0 ){                            // 水平幅が中途なら
        h = ( h / dataSize ) * dataSize;                // 左記で補正する
    }                                                   // 
    if( ps->w == 1 ){                                   // 1バイト版なら
        mirrorByte( psa, pda, h, v, sl, dl, k,          // 左記で実行
                                            dataSize ); //
    }else if( ps->w == 2 ){                             // 2バイト版なら
        mirrorShort( (short *)psa, (short *)pda,        // 左記で実行
                        h, v, sl, dl, k, dataSize );    //
    }else if( ps->w == 4 ){                             // 4バイト版なら
        mirrorLong( (long *)psa, (long *)pda,           // 左記で実行
                        h, v, sl, dl, k, dataSize );    //
    }                                                   //
    return( END_STI );                                  // 正常終了
}

☆備考☆この関数はファイル「CopyClear310」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「MirrorImage()」の【関数名】


「Mirror」は、英単語「Mirror」で鏡・鏡像、ココでは、
画像の左右を始め上下・上下左右の幾何的鏡像処理です!

(B)関数「int MirrorImage()」の【返値】

この関数内で明示的に検査しているのは、S(元)画像情報
とD(結果)画像情報が正常な画像か両方とも同じ画素単位
か処理可能なサイズか否かを判定し対象外ならばエラーコー
ドに画像エラーコードの意味を返し関数の辺値とし関数終了
及び、鏡像の種類選択肢が規定外(1から3以外)ならば、
エラーコード「STI_FLG」を返し関数の辺値とし関数終了!

(C)関数「MirrorImage()」の【仮引数】

int             CopyClear::MirrorImage(
    TypeArray   *ps,                                    // S配列
    TypeArray   *pd,                                    // D配列
    int         k,                                      // 1:左右反転
                                                        // 2:上下反転
                                                        // 3:上下左右反転
    int         dataSize                                // 画素サイズ(省略時=1)
                                                        // 1:主に濃淡画像
                                                        // 3:主にカラー(3原色)画像
){

「TypeArray* ps,」は、S(元)画像情報
「TypeArray* pd,」は、D(結果)画像情報
「int k,」は、鏡像種類≪1:左右、2:上下、
3:上下左右≫
「int dataSize=1,」は、引数省略時は1と1画素単位です
が、3画素をRGBとかのカラー画像に対応出来る様にして
います!

(D)関数「MirrorImage()」の【アルゴリズム】

){
    TypeArray   D;                                      // D配列:局所
    BYTE        *psa;                                   // S配列実Adr
    BYTE        *pda;                                   // D配列実Adr
    int         h;                                      // 水平幅
    int         v;                                      // 垂直幅
    int         sl;                                     // Sの増加幅
    int         dl;                                     // Dの増加幅

    if( ps == 0 ){                                      // Sが空なら
        return( STI_ARY_0 - 10 );                       // 不正を返す
    }else if( ps->adr == 0 ){                           // Sの実ptrが空なら
        return( STI_ARY_1 - 10 );                       // 不正を返す
    }else if( pd == 0 ){                                // Dが空なら
        return( STI_ARY_0 - 20 );                       // 不正を返す
    }else if( pd->adr == 0 ){                           // Dの実ptrが空なら
        return( STI_ARY_1 - 20 );                       // 不正を返す
    }else if( ps->w != pd->w || ps->w < 0               // Bits幅が異なるか
                        || ps->w == 3 || ps->w > 4 ){   // 可能な幅以外は
        return( STI_ARY_5 - 20 );                       // 不正を返す
    }                                                   //
    if( k <= 0 || k > 3 || dataSize <= 0 ){             // 不正なら
        return( STI_FLG );                              // 不正を返す
    }                                                   //
    psa = (BYTE*)ps->adr;                               // S実Adr取出し
    pda = (BYTE*)pd->adr;                               // D実Adr取出し
    h   = (ps->h < pd->h) ? ps->h : pd->h;              // 水平幅を算出
    v   = (ps->v < pd->v) ? ps->v : pd->v;              // 垂直幅を算出
    sl  = ps->inc;                                      // Sの増加幅Set
    dl  = pd->inc;                                      // Dの増加幅Set
    if( h % dataSize != 0 ){                            // 水平幅が中途なら
        h = ( h / dataSize ) * dataSize;                // 左記で補正する
    }                                                   // 
    if( ps->w == 1 ){                                   // 1バイト版なら
        mirrorByte( psa, pda, h, v, sl, dl, k,          // 左記で実行
                                            dataSize ); //
    }else if( ps->w == 2 ){                             // 2バイト版なら
        mirrorShort( (short *)psa, (short *)pda,        // 左記で実行
                        h, v, sl, dl, k, dataSize );    //
    }else if( ps->w == 4 ){                             // 4バイト版なら
        mirrorLong( (long *)psa, (long *)pda,           // 左記で実行
                        h, v, sl, dl, k, dataSize );    //
    }                                                   //
    return( END_STI );                                  // 正常終了
}

(D-1)ローカル変数

){
    TypeArray   D;                                      // D配列:局所
    BYTE        *psa;                                   // S配列実Adr
    BYTE        *pda;                                   // D配列実Adr
    int         h;                                      // 水平幅
    int         v;                                      // 垂直幅
    int         sl;                                     // Sの増加幅
    int         dl;                                     // Dの増加幅

「TypeArrayD;」は、不使用★注意★削除し忘れ
「BYTE *psa;」は、S画像実処理ポインタ
「BYTE *pda;」は、D画像実処理ポインタ
「int h;」は、水平幅
「int v;」は、垂直幅
「int sl;」は、S画像増加幅
「int dl;」は、D画像増加幅

(D-2)アルゴリズムコード

    if( ps == 0 ){                                      // Sが空なら
        return( STI_ARY_0 - 10 );                       // 不正を返す
    }else if( ps->adr == 0 ){                           // Sの実ptrが空なら
        return( STI_ARY_1 - 10 );                       // 不正を返す
    }else if( pd == 0 ){                                // Dが空なら
        return( STI_ARY_0 - 20 );                       // 不正を返す
    }else if( pd->adr == 0 ){                           // Dの実ptrが空なら
        return( STI_ARY_1 - 20 );                       // 不正を返す
    }else if( ps->w != pd->w || ps->w < 0               // Bits幅が異なるか
                        || ps->w == 3 || ps->w > 4 ){   // 可能な幅以外は
        return( STI_ARY_5 - 20 );                       // 不正を返す
    }                                                   //
    if( k <= 0 || k > 3 || dataSize <= 0 ){             // 不正なら
        return( STI_FLG );                              // 不正を返す
    }                                                   //
    psa = (BYTE*)ps->adr;                               // S実Adr取出し
    pda = (BYTE*)pd->adr;                               // D実Adr取出し
    h   = (ps->h < pd->h) ? ps->h : pd->h;              // 水平幅を算出
    v   = (ps->v < pd->v) ? ps->v : pd->v;              // 垂直幅を算出
    sl  = ps->inc;                                      // Sの増加幅Set
    dl  = pd->inc;                                      // Dの増加幅Set
    if( h % dataSize != 0 ){                            // 水平幅が中途なら
        h = ( h / dataSize ) * dataSize;                // 左記で補正する
    }                                                   // 
    if( ps->w == 1 ){                                   // 1バイト版なら
        mirrorByte( psa, pda, h, v, sl, dl, k,          // 左記で実行
                                            dataSize ); //
    }else if( ps->w == 2 ){                             // 2バイト版なら
        mirrorShort( (short *)psa, (short *)pda,        // 左記で実行
                        h, v, sl, dl, k, dataSize );    //
    }else if( ps->w == 4 ){                             // 4バイト版なら
        mirrorLong( (long *)psa, (long *)pda,           // 左記で実行
                        h, v, sl, dl, k, dataSize );    //
    }                                                   //
    return( END_STI );                                  // 正常終了
}

「if(ps==0){return(STI_ARY_0-10);}」は、条件「ps==0」
とS画像情報ポインタ自体が空ならエラーコード「
STI_ARY_0-10」と最初の画像情報にエラーが有る事も
含めたエラーコードを辺値とし返し関数終了!
「else if(ps->adr==0){return(STI_ARY_1-10);}」は、
条件「ps->adr==0」とS画像実処理ポインタが空なら、
エラーコード「STI_ARY_1-10」と最初の画像情報にエラー
が有る事も含めたエラーコードを辺値とし返し関数終了!
「else if(pd==0){return(STI_ARY_0-20);}」は、
条件「pd==0」とD画像情報ポインタ自体が空ならエラー
コード「STI_ARY_0-20」と2番の画像情報にエラーが有る
事も含めたエラーコードを辺値とし返し関数終了!
「else if(pd->adr==0){return(STI_ARY_1-20);}」は、
条件「pd->adr==0」とD画像実処理ポインタが空なら、
エラーコード「STI_ARY_1-20」と2番の画像情報にエラー
が有る事も含めたエラーコードを辺値とし返し関数終了!
「else if(ps->w!=pd->w||ps->w<0||ps->w==3||ps->w>4){
return(STI_ARY_5-20);}」は、条件「ps->w!=pd->w||
ps->w<0||ps->w==3||ps->w>4」と画素単位が異なるか、
ここで処理可能な画素単位で無い場合を判定し、成立時は
「STI_ARY_5-20」で2番の画像情報が「STI_ARY_5」を発生
させたと判定し、エラーコードを辺値とし返し関数終了!
「if(k<=0||k>3||dataSize<=0){return(STI_FLG);}」は、
鏡像の種類が1から3の範囲に入って居るか否かと処理する
画素数が0未満ならエラーコード「STI_FLG」を辺値とし
返し関数終了!
「psa=(BYTE *)ps->adr;pda=(BYTE *)pd->adr;」は、
SD両画像の実処理ポインタを使い易いローカル変数に
セット、
「h=(ps->h<pd->h)?ps->h:pd->h;
v=(ps->v<pd->v)?ps->v:pd->v;」は、水平垂直幅の有効幅
として処理する最小値を算出しローカル変数にセット、
「if(h%dataSize!=0){h=(h/dataSize)*dataSize;}」は、
水平幅が処理する画素数単位の倍数に成って無ければ、
倍数に成る様に一単位少ない幅で補正!
「if(ps->w==1){mirrorBYTE (psa,pda,h,v,sl,dl,k,
dataSize);}」は、条件「ps->w==1」で画素単位が1バイト
単位の場合、サブルーチン関数「mirrorBYTE ()」で処理
★注意★このサブルーチン関数ではエラーは発生しないとし
ステータス情報は取得しません!
「else if(ps->w==2){mirrorShort((short *)psa,
(short *)pda,h,v,sl,dl,k,dataSize);}」は、
条件「ps->w==2」で画素単位が2バイト
単位の場合、サブルーチン関数「mirrorShort()」で処理
★注意★このサブルーチン関数もラーは発生しないとし
ステータス情報は取得しません!
「else if(ps->w==4){mirrorLong((long *)psa,
(long *)pda,h,v,sl,dl,k,dataSize);}」は、
条件「ps->w==4」で画素単位が4バイト
単位の場合、サブルーチン関数「mirrorLong()」で処理
★注意★このサブルーチン関数もラーは発生しないとし
ステータス情報は取得しません!
「return(END_STI);」は、正常終了を返し関数終了!

(E)関数「MirrorImage()」の【使用例】

★注意★
使用例は、別の解説エッセイ『画像幾何変換使用例』で
別途説明する事に方針変換しました!
使用例発表まで乞うご期待と記載して置きます!

(4-14-41)関数「int MirrorImage(TypeArray* image,int k,int dataSiz){・・・}」

/************************************************************************/
/*****  配列の鏡像の作成(上下・左右等図形の変換)コマンド:実行部  *****/
/*****  ☆自分自身の鏡像作成☆                                      *****/
/************************************************************************/

int             CopyClear::MirrorImage(
    TypeArray*  image,                                      // 画像
    int         k,                                          // 1:左右反転
                                                            // 2:上下反転
                                                            // 3:上下左右反転
    int         dataSize                                    // 画素サイズ(省略時=1)
                                                            // 1:主に濃淡画像
                                                            // 3:主にカラー(3原色)画像
){
    TypeArray   s;                                          // S画像
    TypeArray   d;                                          // D画像
    TypeArray   t;                                          // T画像
    int         w;                                          // 単位
    int         h;                                          // 水平幅
    int         v;                                          // 垂直幅
    int         h2;                                         // 水平幅÷2
    int         v2;                                         // 垂直幅÷2
    int         sti;                                        // ステータス情報

    if( image == 0 ){                                       // 画像が空なら
        return( STI_ARY_0 );                                // 不正を返す
    }else if( image->adr == 0 ){                            // 画像の実ptrが空なら
        return( STI_ARY_1 );                                // 不正を返す
    }else if( ( h = image->h ) <= 0 ){                      // 画像の水平幅不正時
        return( STI_ARY_2 );                                // 不正を返す
    }else if( ( v = image->v ) <= 0 ){                      // 画像の水平幅不正時
        return( STI_ARY_3 );                                // 不正を返す
    }else if( ( w = image->w ) < 0 || w == 3 || w > 4 ){    // 可能な幅以外は
        return( STI_ARY_5 );                                // 不正を返す
    }                                                       //
    if( k <= 0 || k > 3 || dataSize <= 0 ){                 // 不正なら
        return( STI_FLG );                                  // 不正を返す
    }                                                       //
    if( k == 2 ){                                           // 上下反転時は
        v2 = v / 2;                                         // 垂直幅÷2算出
        s.subset( image, 0,  0, h, v2 );                    // 上半分画像作成
        d.subset( image, 0, v2, h, v2 );                    // 下半分画像作成
        sti = t.Malloc( w, h, v2 );                         // 左記でメモリ確保
    }else{                                                  // 左右反転時は
        h2 = h / 2;                                         // 水平幅÷2算出
        if( h2 % dataSize != 0 ){                           // 水平幅が中途なら
            h2 = ( h2 / dataSize ) * dataSize;              // 左記で補正する
        }                                                   // 
        s.subset( image, 0,  0, h2, v );                    // 左半分画像作成
        d.subset( image, h2, 0, h2, v );                    // 右半分画像作成
        sti = t.Malloc( w, h2, v );                         // 左記でメモリ確保
    }                                                       //
    if( sti == END_STI ){                                   // メモリ確保成功時
        Copy( &d, &t );                                     // D→T
        MirrorImage( &s, &d, k, dataSize );                 // S→D:鏡像処理
        MirrorImage( &t, &s, k, dataSize );                 // T→S:鏡像処理
        t.freeMem();                                        // T画像メモリ解放
        return( END_STI );                                  // 正常終了
    }                                                       // 
    return( sti );                                          // ステータスを返す
}

☆備考☆この関数はファイル「CopyClear310」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
★注意★この関数には、同名で仮引数が異なるオーバーロー
ド(多重定義)関数が存在します!

(A)関数「MirrorImage()」の【関数名】


「Mirror」は、英単語「Mirror」で鏡・鏡像、ココでは、
画像の左右を始め上下・上下左右の幾何的鏡像処理です!

(B)関数「int MirrorImage()」の【返値】


この関数内で明示的に検査しているのは、画像情報が正常な
画像か処理可能なサイズか否かを判定し対象外ならばエラー
コードに画像エラーコードの意味を返し関数の辺値とし
関数終了、及び、鏡像の種類選択肢が規定外(1から3以外
)ならば、エラーコード「STI_FLG」を返し関数の辺値とし
関数終了!

(C)関数「MirrorImage()」の【仮引数】

int             CopyClear::MirrorImage(
    TypeArray*  image,                                      // 画像
    int         k,                                          // 1:左右反転
                                                            // 2:上下反転
                                                            // 3:上下左右反転
    int         dataSize                                    // 画素サイズ(省略時=1)
                                                            // 1:主に濃淡画像
                                                            // 3:主にカラー(3原色)画像
){

「TypeArray* image,」は、処理対象の画像★注意★この
関数では、SD両者とも同じ画像です!この関数は、SD
両者を指定する関数に比べて画像と処理の性質から破壊(
内容が書き変わる)されるが、処理速度的に有利に成ります
「int k,」は、鏡像種類≪1:左右、2:上下、
3:上下左右≫
「int dataSize=1,」は、引数省略時は1と1画素単位です
が、3画素をRGBとかのカラー画像に対応出来る様にして
います!

(D)関数「MirrorImage()」の【アルゴリズム】

){
    TypeArray   s;                                          // S画像
    TypeArray   d;                                          // D画像
    TypeArray   t;                                          // T画像
    int         w;                                          // 単位
    int         h;                                          // 水平幅
    int         v;                                          // 垂直幅
    int         h2;                                         // 水平幅÷2
    int         v2;                                         // 垂直幅÷2
    int         sti;                                        // ステータス情報

    if( image == 0 ){                                       // 画像が空なら
        return( STI_ARY_0 );                                // 不正を返す
    }else if( image->adr == 0 ){                            // 画像の実ptrが空なら
        return( STI_ARY_1 );                                // 不正を返す
    }else if( ( h = image->h ) <= 0 ){                      // 画像の水平幅不正時
        return( STI_ARY_2 );                                // 不正を返す
    }else if( ( v = image->v ) <= 0 ){                      // 画像の水平幅不正時
        return( STI_ARY_3 );                                // 不正を返す
    }else if( ( w = image->w ) < 0 || w == 3 || w > 4 ){    // 可能な幅以外は
        return( STI_ARY_5 );                                // 不正を返す
    }                                                       //
    if( k <= 0 || k > 3 || dataSize <= 0 ){                 // 不正なら
        return( STI_FLG );                                  // 不正を返す
    }                                                       //
    if( k == 2 ){                                           // 上下反転時は
        v2 = v / 2;                                         // 垂直幅÷2算出
        s.subset( image, 0,  0, h, v2 );                    // 上半分画像作成
        d.subset( image, 0, v2, h, v2 );                    // 下半分画像作成
        sti = t.Malloc( w, h, v2 );                         // 左記でメモリ確保
    }else{                                                  // 左右反転時は
        h2 = h / 2;                                         // 水平幅÷2算出
        if( h2 % dataSize != 0 ){                           // 水平幅が中途なら
            h2 = ( h2 / dataSize ) * dataSize;              // 左記で補正する
        }                                                   // 
        s.subset( image, 0,  0, h2, v );                    // 左半分画像作成
        d.subset( image, h2, 0, h2, v );                    // 右半分画像作成
        sti = t.Malloc( w, h2, v );                         // 左記でメモリ確保
    }                                                       //
    if( sti == END_STI ){                                   // メモリ確保成功時
        Copy( &d, &t );                                     // D→T
        MirrorImage( &s, &d, k, dataSize );                 // S→D:鏡像処理
        MirrorImage( &t, &s, k, dataSize );                 // T→S:鏡像処理
        t.freeMem();                                        // T画像メモリ解放
        return( END_STI );                                  // 正常終了
    }                                                       // 
    return( sti );                                          // ステータスを返す
}

(D-1)ローカル変数

){
    TypeArray   s;                                          // S画像
    TypeArray   d;                                          // D画像
    TypeArray   t;                                          // T画像
    int         w;                                          // 単位
    int         h;                                          // 水平幅
    int         v;                                          // 垂直幅
    int         h2;                                         // 水平幅÷2
    int         v2;                                         // 垂直幅÷2
    int         sti;                                        // ステータス情報

「TypeArray s;」は、ローカルなS画像情報
「TypeArray d;」は、ローカルなD画像情報
「TypeArray t;」は、ローカルなT(テンポラリ)画像情報
「int w;」は、画素単位
「int h;」は、水平幅
「int v;」は、垂直幅
「int h2;」は、水平幅÷2
「int v2;」は、垂直幅÷2
「int sti;」は、ステータス情報

(D-2)アルゴリズムコード

    if( image == 0 ){                                       // 画像が空なら
        return( STI_ARY_0 );                                // 不正を返す
    }else if( image->adr == 0 ){                            // 画像の実ptrが空なら
        return( STI_ARY_1 );                                // 不正を返す
    }else if( ( h = image->h ) <= 0 ){                      // 画像の水平幅不正時
        return( STI_ARY_2 );                                // 不正を返す
    }else if( ( v = image->v ) <= 0 ){                      // 画像の水平幅不正時
        return( STI_ARY_3 );                                // 不正を返す
    }else if( ( w = image->w ) < 0 || w == 3 || w > 4 ){    // 可能な幅以外は
        return( STI_ARY_5 );                                // 不正を返す
    }                                                       //
    if( k <= 0 || k > 3 || dataSize <= 0 ){                 // 不正なら
        return( STI_FLG );                                  // 不正を返す
    }                                                       //
    if( k == 2 ){                                           // 上下反転時は
        v2 = v / 2;                                         // 垂直幅÷2算出
        s.subset( image, 0,  0, h, v2 );                    // 上半分画像作成
        d.subset( image, 0, v2, h, v2 );                    // 下半分画像作成
        sti = t.Malloc( w, h, v2 );                         // 左記でメモリ確保
    }else{                                                  // 左右反転時は
        h2 = h / 2;                                         // 水平幅÷2算出
        if( h2 % dataSize != 0 ){                           // 水平幅が中途なら
            h2 = ( h2 / dataSize ) * dataSize;              // 左記で補正する
        }                                                   // 
        s.subset( image, 0,  0, h2, v );                    // 左半分画像作成
        d.subset( image, h2, 0, h2, v );                    // 右半分画像作成
        sti = t.Malloc( w, h2, v );                         // 左記でメモリ確保
    }                                                       //
    if( sti == END_STI ){                                   // メモリ確保成功時
        Copy( &d, &t );                                     // D→T
        MirrorImage( &s, &d, k, dataSize );                 // S→D:鏡像処理
        MirrorImage( &t, &s, k, dataSize );                 // T→S:鏡像処理
        t.freeMem();                                        // T画像メモリ解放
        return( END_STI );                                  // 正常終了
    }                                                       // 
    return( sti );                                          // ステータスを返す
}

「if(image==0){return(STI_ARY_0);}」は、
仮引数「TypeArray* image,」のポインタ自体が空ならば
エラーコード「STI_ARY_0」を辺値とし返し関数終了!
「else if(image->adr==0){return(STI_ARY_1);}」は、
条件「image->adr==0」と実処理ポインタが空ならば
エラーコード「STI_ARY_1」を辺値とし返し関数終了!
「else if((h=image->h)<=0){return(STI_ARY_2);}」は、
条件「h=image->h」と水平幅が0以下ならばエラー
コード「STI_ARY_2」を辺値とし返し関数終了!
「else if((v=image->v)<=0){return(STI_ARY_3);}」は、
条件「v=image->v」と垂直幅が0以下ならばエラー
コード「STI_ARY_3」を辺値とし返し関数終了!
「else if((w=image->w)<0||w==3||w>4){
return(STI_ARY_5);}」は、
条件「(w=image->w)<0||w==3||w>4」と画素単位が、
1、2、4バイト単位以外ならばエラーコード
「STI_ARY_5」を辺値とし返し関数終了!
「if(k<=0||k>3||dataSize<=0){return(STI_FLG);}」は、
条件「k<=0||k>3||dataSize<=0」で鏡像の種類が、
1:左右、2:上下、3:上下左右と正規以外と処理する
画素サイズ「dataSize」が0以下の場合、エラーコード
「STI_FLG」を辺値とし返し関数終了!
「if(k==2){・・成立中身・・}」は、条件「k==2」詰り、
上下逆にする処理を成立中身で
「v2=v/2;s.subset(image,0,0,h,v2);
d.subset(image,0,v2,h,v2);sti=t.Malloc(w,h,v2);」と
「v2=v/2」で垂直幅÷2を「v2」にセットし、
「s.subset(image,0,0,h,v2);」で仮引数「
TypeArray* image,」で示される画像の上半分をローカル
変数「s」にセット、「d.subset(image,0,v2,h,v2);」で
画像の下上半分をローカル変数「d」にセット、更に
「sti=t.Malloc(w,h,v2);」でテンポラリー画像をSD両者
と同じく上下半分のサイズで画像メモリ取得!
「else{・・不成立中身・・}」は、条件「k!=2」詰り、
左右・上下左右逆にする処理で「h2=h/2;
if(h2%dataSize!=0){h2=(h2/dataSize)*dataSize;}
s.subset(image,0,0,h2,v);d.subset(image,h2,0,h2,v);
sti=t.Malloc(w,h2,v);}」と「h2=h/2;」で水平幅÷2を
「h2」にセットし、
「if(h2%dataSize!=0){h2=(h2/dataSize)*dataSize;}」で
ここの条件「h2%dataSize!=0」で処理する画素数単位で
水平幅が割り切れず余りが出る場合、
「h2=(h2/dataSize)dataSize;」水平幅÷2の値を補正、
そして「s.subset(image,0,0,h2,v);
d.subset(image,h2,0,h2,v);sti=t.Malloc(w,h2,v);}」と
仮引数「TypeArray image,」で示される画像の水平幅の
右半分の画像を「s.subset(image,0,0,h2,v);」でS画像
左半分の画像を「d.subset(image,h2,0,h2,v);」でD画像
更に「sti=t.Malloc(w,h,v2);」でテンポラリー画像を
SD両者と同じく上下半分のサイズで画像メモリ取得!
「if(sti==END_STI){・・分岐中身・・}」で
条件「sti==END_STI」と画像メモリ取得に成功した場合、
分岐中身「Copy(&d,&t);MirrorImage(&s,&d,k,dataSize);
MirrorImage(&t,&s,k,dataSize);
t.freeMem();return(END_STI);」で中身の処理ですが、
「Copy(&d,&t)」で一旦、テンポラリー画像へのコピー、
「MirrorImage(&s,&d,k,dataSize);」で二項演算のサブ
ルーチン関数「MirrorImage()」で「S⇒D方向」鏡像
処理し、「MirrorImage(&t,&s,k,dataSize);」で
「テンポラリー画像⇒S方向」鏡像処理する事で画像1枚
鏡像処理を行います!そして「t.freeMem();」でテンポラ
リー画像をメモリ解放し、「return(END_STI);」と
正常終了を辺値とし返し、関数終了!
最後に「return(sti);」でメモリ取得失敗時のエラー
コードを辺値とし返し、関数終了!

(E)関数「MirrorImage()」の【使用例】

★注意★
使用例は、別の解説エッセイ『画像幾何変換使用例』で
別途説明する事に方針変換しました!
使用例発表まで乞うご期待と記載して置きます!

(F)関数「MirrorImage()」の【注意】

仮引数「int k,」鏡像種類で「k=3」の時、上下左右鏡像
処理が、ソースコード解説で久し振りに読んで見て違和感を
感じてシマッタ!サブルーチン関数の中身を確認する必要が
有るが、取り敢えず、「k=1」左右鏡像・「k=2」上下
鏡像のみ使用して下さい!作成時は、動作確認している筈だ
が、何かオカシイ?!

(4-14-42)関数「int RotateImage(TypeArray* ps,TypeArray* pd,double a,double x1,double y1,double x2,double y2,int dataSize,int sw){・・・}」

/************************************************************************/
/*****  図形の回転を行うコマンド:実行部:配列版                    *****/
/*****  ROTATE,a,x1,y1,x2,y2,s,d                   *****/
/*****  ①D配列を基準に回転するため回転角の正負を反転します。      *****/
/*****  ②D(x,y)=S(base.x[x]+offset.x[y],base.y[x]+offset.y[y])と*****/
/*****   なるような配列 PTR TableとOffset-Tableを作成します。      *****/
/*****   makeRotateTable()関数                                     *****/
/*****  ③上記で作成したテーブルを使用してS→Dに転送:rotate()関数*****/
/************************************************************************/

int             CopyClear::RotateImage(
    TypeArray   *ps,                                        // S配列
    TypeArray   *pd,                                        // D配列
    double      a,                                          // 回転角:ラジアン
    double      x1,                                         // S配列回転中心x
    double      y1,                                         // S配列回転中心y
    double      x2,                                         // D配列回転中心x
    double      y2,                                         // D配列回転中心y
    int         dataSize,                                   // 画素サイズ(省略時=1)
                                                            // 1:主に濃淡画像
                                                            // 3:主にカラー(3原色)画像
    int         sw                                          // 補間SW(真:補間、省略時=偽)
){
    TypeXYI*    base;                                       // S配列Base-xytbl
    TypeXYI*    offset;                                     // S配列Offsetxytbl
    int         adrS;                                       // アドレス:S
    int         adrD;                                       // アドレス:D
    int         hS;                                         // 水平幅:S
    int         hD;                                         // 水平幅:D
    int         vS;                                         // 垂直幅:S
    int         vD;                                         // 垂直幅:D
    int         incS;                                       // 増加幅:S
    int         incD;                                       // 増加幅:D

    if( ps->w != pd->w ){                                   // 画素処理単位が
        return( STI_FLG );                                  // 異なれば不正を返す
    }                                                       //
    if( dataSize <= 0 ){                                    // 画素サイズ不正なら
        return( STI_FLG );                                  // 不正を返す
    }                                                       //
    if( a == 0.0 ){                                         // 回転角=0の場合
        return( MoveImage( ps, pd, x2 - x1, y2 - y1,        // 左記で画像移動
                                        dataSize, sw ) );   //
    }                                                       //
    if( sw ){                                               // 補間する場合は
        return( RotateImageInterpolate(                     // 左記で補間付きの
                ps, pd, a, x1, y1, x2, y2, dataSize ) );    // 回転
    }                                                       // 
    adrS = ps->adr;                                         // S・Dの実処理
    adrD = pd->adr;                                         // ADR を取り出し
    hS   = ps->h;                                           // S・Dの
    hD   = pd->h;                                           // 水平幅取り出し
    vS   = ps->v;                                           // S・Dの
    vD   = pd->v;                                           // 垂直幅取り出し
    incS = ps->inc;                                         // S・Dの増加幅
    incD = pd->inc;                                         // を取り出し
    base = (TypeXYI*)malloc(                                // BaseTableを確保
                        sizeof(TypeXYI) * ( hD + 10 ) );    // (水平幅+α)
    if( base == 0 ){                                        // 確保失敗時は
        return( STI_MEM );                                  // 左記を返す
    }                                                       //
    offset = (TypeXYI*)malloc(                              // OffsetTableを確保
                        sizeof(TypeXYI) * ( vD + 10 ) );    // (垂直幅+α)
    if( offset == 0 ){                                      // 確保失敗時は
        free( base );                                       // メモリ解放:BaseTable
        return( STI_MEM );                                  // 左記を返す
    }                                                       //
    makeRotateTable( -a, x1, y1, x2, y2, base, offset,      // 回転座標のTableを
                                        hD, vD, dataSize ); // 作成する
    if( ps->w == 1 ){                                       // 8ビット版なら
        rotateByte( base, offset,                           // 左記で回転実行
                        (BYTE*)adrS, hS, vS,                //
                        (BYTE*)adrD, hD, vD, incS, incD,    //
                        dataSize );                         // 
    }else if( ps->w == 2 ){                                 // 16ビット版なら
        rotateShort( base, offset,                          // 左記で回転実行
                        (short*)adrS, hS, vS,               //
                        (short*)adrD, hD, vD, incS, incD,   //
                        dataSize );                         // 
    }else if( ps->w == 4 || ps->w == 101 ){                 // 32ビット版なら
        rotateLong( base, offset,                           // 左記で回転実行
                        (long*)adrS, hS, vS,                //
                        (long*)adrD, hD, vD, incS, incD,    //
                        dataSize );                         // 
    }                                                       //
    free( base );                                           // メモリ解放:BaseTable
    free( offset );                                         // メモリ解放:OffsetTable
    return( END_STI );                                      // 正常終了
}

☆備考☆この関数はファイル「CopyClear320」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!

(A)関数「RotateImage()」の【関数名】

「Rotate」は、英単語「Rotate」で回転、ココでは、
画像の二次元表面的な幾何的回転処理です!

(B)関数「int RotateImage()」の【返値】

この関数内で明示的に検査しているのは、画像情報が、
SD両者画素単位が同じか否かで否かを判定し対象外ならば
エラーコードに画像エラーコードの意味を返し関数の辺値と
し関数終了、角度指定が「0.0」の場合は、サブルーチン
関数「MoveImage()」の辺値を関数の辺値とし返し関数終了
そして仮引数「int sw」が真(詰り補完処理を行う)場合は
サブルーチン関数「RotateImageInterpolate()」の辺値を
関数の辺値とし返し関数終了!
そして、内部でメモリ取得して居るので取得に失敗時、
エラーコード「STI_MEM」を返し終了!
それ以外は、「return(END_STI);」と正常終了を返しま
す★注意★何故、細かい引数チェックを行わないかは、
処理不能なパラメータの時は、単にサブルーチン関数で処理
シナイだけで終了するからです!

(C)関数「RotateImage()」の【仮引数】

int             CopyClear::RotateImage(
    TypeArray   *ps,                                        // S配列
    TypeArray   *pd,                                        // D配列
    double      a,                                          // 回転角:ラジアン
    double      x1,                                         // S配列回転中心x
    double      y1,                                         // S配列回転中心y
    double      x2,                                         // D配列回転中心x
    double      y2,                                         // D配列回転中心y
    int         dataSize,                                   // 画素サイズ(省略時=1)
                                                            // 1:主に濃淡画像
                                                            // 3:主にカラー(3原色)画像
    int         sw                                          // 補間SW(真:補間、省略時=偽)
){

「TypeArray* ps,」は、S(元)画像情報
「TypeArray* pd,」は、D(結果)画像情報
「double a,」は、回転角度指定★注意★単位は、ラディアン
「double x1,」は、S(元)画像の回転中心X座標
「double y1,」は、S(元)画像の回転中心Y座標
「double x2,」は、D(結果)画像の回転中心X座標
「double y2,」は、D(結果)画像の回転中心Y座標
「int dataSize=1,」は、引数省略時は1と1画素単位です
が、3画素をRGBとかのカラー画像に対応出来る様にして
います!
「int sw=FALSE);」は、画素間の補完を行うか否かです!
省略時は補完で無く高速化処理です

(D)関数「RotateImage()」の【アルゴリズム】

){
    TypeXYI*    base;                                       // S配列Base-xytbl
    TypeXYI*    offset;                                     // S配列Offsetxytbl
    int         adrS;                                       // アドレス:S
    int         adrD;                                       // アドレス:D
    int         hS;                                         // 水平幅:S
    int         hD;                                         // 水平幅:D
    int         vS;                                         // 垂直幅:S
    int         vD;                                         // 垂直幅:D
    int         incS;                                       // 増加幅:S
    int         incD;                                       // 増加幅:D

    if( ps->w != pd->w ){                                   // 画素処理単位が
        return( STI_FLG );                                  // 異なれば不正を返す
    }                                                       //
    if( dataSize <= 0 ){                                    // 画素サイズ不正なら
        return( STI_FLG );                                  // 不正を返す
    }                                                       //
    if( a == 0.0 ){                                         // 回転角=0の場合
        return( MoveImage( ps, pd, x2 - x1, y2 - y1,        // 左記で画像移動
                                        dataSize, sw ) );   //
    }                                                       //
    if( sw ){                                               // 補間する場合は
        return( RotateImageInterpolate(                     // 左記で補間付きの
                ps, pd, a, x1, y1, x2, y2, dataSize ) );    // 回転
    }                                                       // 
    adrS = ps->adr;                                         // S・Dの実処理
    adrD = pd->adr;                                         // ADR を取り出し
    hS   = ps->h;                                           // S・Dの
    hD   = pd->h;                                           // 水平幅取り出し
    vS   = ps->v;                                           // S・Dの
    vD   = pd->v;                                           // 垂直幅取り出し
    incS = ps->inc;                                         // S・Dの増加幅
    incD = pd->inc;                                         // を取り出し
    base = (TypeXYI*)malloc(                                // BaseTableを確保
                        sizeof(TypeXYI) * ( hD + 10 ) );    // (水平幅+α)
    if( base == 0 ){                                        // 確保失敗時は
        return( STI_MEM );                                  // 左記を返す
    }                                                       //
    offset = (TypeXYI*)malloc(                              // OffsetTableを確保
                        sizeof(TypeXYI) * ( vD + 10 ) );    // (垂直幅+α)
    if( offset == 0 ){                                      // 確保失敗時は
        free( base );                                       // メモリ解放:BaseTable
        return( STI_MEM );                                  // 左記を返す
    }                                                       //
    makeRotateTable( -a, x1, y1, x2, y2, base, offset,      // 回転座標のTableを
                                        hD, vD, dataSize ); // 作成する
    if( ps->w == 1 ){                                       // 8ビット版なら
        rotateByte( base, offset,                           // 左記で回転実行
                        (BYTE*)adrS, hS, vS,                //
                        (BYTE*)adrD, hD, vD, incS, incD,    //
                        dataSize );                         // 
    }else if( ps->w == 2 ){                                 // 16ビット版なら
        rotateShort( base, offset,                          // 左記で回転実行
                        (short*)adrS, hS, vS,               //
                        (short*)adrD, hD, vD, incS, incD,   //
                        dataSize );                         // 
    }else if( ps->w == 4 || ps->w == 101 ){                 // 32ビット版なら
        rotateLong( base, offset,                           // 左記で回転実行
                        (long*)adrS, hS, vS,                //
                        (long*)adrD, hD, vD, incS, incD,    //
                        dataSize );                         // 
    }                                                       //
    free( base );                                           // メモリ解放:BaseTable
    free( offset );                                         // メモリ解放:OffsetTable
    return( END_STI );                                      // 正常終了
}

(D-1)ローカル変数

){
    TypeXYI*    base;                                       // S配列Base-xytbl
    TypeXYI*    offset;                                     // S配列Offsetxytbl
    int         adrS;                                       // アドレス:S
    int         adrD;                                       // アドレス:D
    int         hS;                                         // 水平幅:S
    int         hD;                                         // 水平幅:D
    int         vS;                                         // 垂直幅:S
    int         vD;                                         // 垂直幅:D
    int         incS;                                       // 増加幅:S
    int         incD;                                       // 増加幅:D

「TypeXYI* base;」は、S画像基底XY座標テーブル
「TypeXYI* offset;」は、S画像変位XY座標テーブル
「int adrS;」は、S(元)実画像機械アドレス
「int adrD;」は、D(結果)実画像機械アドレス★注意★
SD両者共にポインタで無く整数型の「int 」で扱う!
「int hS;」は、水平幅:S画像
「int hD;」は、水平幅:D画像
「int vS;」は、垂直幅:S画像
「int vD;」は、垂直幅:D画像
「int incS;」は、増加幅:S画像
「int incD;」は、増加幅:D画像

(D-2)アルゴリズムコード

    if( ps->w != pd->w ){                                   // 画素処理単位が
        return( STI_FLG );                                  // 異なれば不正を返す
    }                                                       //
    if( dataSize <= 0 ){                                    // 画素サイズ不正なら
        return( STI_FLG );                                  // 不正を返す
    }                                                       //
    if( a == 0.0 ){                                         // 回転角=0の場合
        return( MoveImage( ps, pd, x2 - x1, y2 - y1,        // 左記で画像移動
                                        dataSize, sw ) );   //
    }                                                       //
    if( sw ){                                               // 補間する場合は
        return( RotateImageInterpolate(                     // 左記で補間付きの
                ps, pd, a, x1, y1, x2, y2, dataSize ) );    // 回転
    }                                                       // 
    adrS = ps->adr;                                         // S・Dの実処理
    adrD = pd->adr;                                         // ADR を取り出し
    hS   = ps->h;                                           // S・Dの
    hD   = pd->h;                                           // 水平幅取り出し
    vS   = ps->v;                                           // S・Dの
    vD   = pd->v;                                           // 垂直幅取り出し
    incS = ps->inc;                                         // S・Dの増加幅
    incD = pd->inc;                                         // を取り出し
    base = (TypeXYI*)malloc(                                // BaseTableを確保
                        sizeof(TypeXYI) * ( hD + 10 ) );    // (水平幅+α)
    if( base == 0 ){                                        // 確保失敗時は
        return( STI_MEM );                                  // 左記を返す
    }                                                       //
    offset = (TypeXYI*)malloc(                              // OffsetTableを確保
                        sizeof(TypeXYI) * ( vD + 10 ) );    // (垂直幅+α)
    if( offset == 0 ){                                      // 確保失敗時は
        free( base );                                       // メモリ解放:BaseTable
        return( STI_MEM );                                  // 左記を返す
    }                                                       //
    makeRotateTable( -a, x1, y1, x2, y2, base, offset,      // 回転座標のTableを
                                        hD, vD, dataSize ); // 作成する
    if( ps->w == 1 ){                                       // 8ビット版なら
        rotateByte( base, offset,                           // 左記で回転実行
                        (BYTE*)adrS, hS, vS,                //
                        (BYTE*)adrD, hD, vD, incS, incD,    //
                        dataSize );                         // 
    }else if( ps->w == 2 ){                                 // 16ビット版なら
        rotateShort( base, offset,                          // 左記で回転実行
                        (short*)adrS, hS, vS,               //
                        (short*)adrD, hD, vD, incS, incD,   //
                        dataSize );                         // 
    }else if( ps->w == 4 || ps->w == 101 ){                 // 32ビット版なら
        rotateLong( base, offset,                           // 左記で回転実行
                        (long*)adrS, hS, vS,                //
                        (long*)adrD, hD, vD, incS, incD,    //
                        dataSize );                         // 
    }                                                       //
    free( base );                                           // メモリ解放:BaseTable
    free( offset );                                         // メモリ解放:OffsetTable
    return( END_STI );                                      // 正常終了
}

「if(ps->w!=pd->w){return(STI_FLG);}」は、SD画像の
画素単位が異なればエラーコード「STI_FLG」を辺値とし
返し関数終了!
「if(dataSize<=0){return(STI_FLG);}」は、画素サイ
ズ「dataSize」が0以下の場合、エラーコード「STI_FLG」
を辺値とし返し関数終了!
「if(a==0.0){return(MoveImage(ps,pd,x2-x1,y2-y1,
dataSize,sw));}」は、角度指定≪仮引数「double a,」≫
が、「0.0」の場合、回転では無く幾何移動サブルーチン
関数「MoveImage(ps,pd,x2-x1,y2-y1,dataSize,sw)」で
処理し、その関数の辺値をコノ関数辺値とし関数終了!
「if(sw){return(RotateImageInterpolate(ps,pd,a,
x1,y1,x2,y2,dataSize));}」は、仮引数「int sw」が
真「≠0」≪詰り補正を行う場合≫は、サブルーチン関数
「RotateImageInterpolate(ps,pd,a,x1,y1,x2,y2,
dataSize)」とサブルーチン関数で処理しその関数の辺値を
コノ関数辺値とし関数終了!
「adrS=ps->adr;adrD=pd->adr;」は、実処理ポインタの
値をローカル変数に格納して高速化★注意★整数型の変数
にしているのは、最初に作成したターゲットCPUが、
MC68Kでポインタ変数を数少ないCPUレジスタに割
り当てる時に都合が良く、この変数を各サブルーチン関数
で処理する時に、ソレゾレ((BYTE )adrS)とかと型変換を
明示的に使用して速度ロスを抑えた為です!本当に極僅か
ですが高速化(nsナノ秒の単位)したのだ!
「hS=ps->h;hD=pd->h;」は、SD両者の水平幅を変数に
格納する事で高速化!
「vS=ps->v;vD=pd->v;」は、SD両者の垂直幅を変数に
格納する事で高速化!
「incS=ps->inc;incD=pd->inc;」は、SD両者の増加幅を
変数に格納する事で高速化!
「base=(TypeXYI)malloc(sizeof(TypeXYI)*(hD+10));」は、
座標変換作業用のテーブル配列をメモリ取得≪
型「TypeXYI」は、解説『解説クラスSupport』
解説しているXY座標とインデックスの複合です≫、
C言語システム標準のメモリ取得関数「malloc()」の取得
サイズ「sizeof(TypeXYI)(hD+10)」は、
「sizeof(TypeXYI)」と型「TypeXYI」自体のバイト数と
「(hD+10)」水平幅+α≪ギリギリで無く少し多めに取得
するのは★注意★細かい座標範囲特定の手間を少しでも減
らせる為です!≫
「if(base==0){return(STI_MEM);}」は、メモリ取得に
失敗時にエラーコード「STI_MEM」を辺値で返し関数終了!
「offset=(TypeXYI)malloc(sizeof(TypeXYI)*(vD+10));」は、
座標変換作業用のテーブル配列をメモリ取得≪
型「TypeXYI」は、解説『解説クラスSupport』で解説しているXY座標とインデックスの複合です≫、
C言語システム標準のメモリ取得関数「malloc()」の取得
サイズ「sizeof(TypeXYI)*(vD+10)」は、
「sizeof(TypeXYI)」と型「TypeXYI」自体のバイト数と
「(vD+10)」垂直幅+α≪ギリギリで無く少し多めに取得
するのは★注意★細かい座標範囲特定の手間を少しでも減
らせる為です!≫
「if(offset==0){return(STI_MEM);}」は、メモリ取得に
失敗時にエラーコード「STI_MEM」を辺値で返し関数終了!
「makeRotateTable(-a,x1,y1,x2,y2,base,offset,
hD,vD,dataSize);」は、先ほどメモリ取得した「base」・
「offset」に対してサブルーチン
関数「makeRotateTable()」で幾何変換する座標情報を
算出します!
「if(ps->w==1){rotateBYTE (base,offset,
(BYTE *)adrS,hS,vS,(BYTE *)adrD,hD,vD,incS,incD,
dataSize);}」は、選択条件「ps->w==1」で1バイト画素
画像ならば、サブルーチン関数「rotateBYTE (base,offset,(BYTE *)adrS,hS,vS,(BYTE *)adrD,hD,vD,incS,incD,dataSize);」とサブルーチン関数「rotateBYTE ()」で処理します!
「else if(ps->w==2){rotateShort(base,offset,
(short *)adrS,hS,vS,(short *)adrD,hD,vD,incS,incD,dataSize);}」は、選択条件「ps->w==2」で2バイト画素画像ならば、
サブルーチン関数「rotateShort(base,offset,(short*)adrS,
hS,vS,(short *)adrD,hD,vD,incS,incD,dataSize);」と
サブルーチン関数「rotateShort()」で処理します!
「else if(ps->w==4||ps->w==101){rotateLong(base,offset,(long *)adrS,hS,vS,(long *)adrD,hD,vD,incS,incD,dataSize);}」は、選択条件「ps->w==4」で4バイト画素画像ならば、
サブルーチン関数「rotateLong(base,offset,(long *)adrS,hS,
vS,(long *)adrD,hD,vD,incS,incD,dataSize);」と
サブルーチン関数「rotateLong()」で処理します!
★備考★画素単位の選択肢「ps->w==102」と8バイト
倍精度浮動小数点型は用意しませんでした!ライブラリ作成
当時、需要が無いと判断したのですが!ソースコードで公開
していますので必要な方は、このソースコードを参考にして
追加して下さい!私(作者)は、新規に作成したコード動作
保証はできませんので悪しからず!
「free(base);free(offset);」は、メモリ取得した後始末!
「return(END_STI);」は、正常終了を返し関数終了!

(E)関数「RotateImage()」の【使用例】

★注意★
使用例は、別の解説エッセイ『画像幾何変換使用例』で
別途説明する事に方針変換しました!
使用例発表まで乞うご期待と記載して置きます!

本日(1月20)の講義はココまでとします!
流石に新しくと言うか「画像幾何変換」の話に遷ったの
で受講者の皆様が消化出来る為にココまでとします!
次から幾何的回転処理詳細を扱いますので別の解説
解説『解説クラスCopyClear(17)』に続きます

文末

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