見出し画像

解説クラスCopyClear(12)

解説クラスCopyClear(12)


2024年3月28初講(初稿)

この講義は解説『解説クラスCopyClear(11)』
の続きです!
★注意★
ここでは、カラー画像に対する処理を行う関数の詳細を説明
します!カラー画像の概要に関しては、
解説『解説クラスCopyClear(2)』を参考にして
下さい!

(4-14-16)関数「int ConvertRgbToMono(
TypeArray* pr,TypeArray* pg,TypeArray* pb,
TypeArray* pd){・・・}」の説明

int             CopyClear::ConvertRgbToMono(
    TypeArray   *pr,                                    // S配列:赤
    TypeArray   *pg,                                    // S配列:緑
    TypeArray   *pb,                                    // S配列:青
    TypeArray   *pd                                     // D配列
){
    BYTE*       pry;                                    // Y方向ポインタ:赤
    BYTE*       pgy;                                    // Y方向ポインタ:緑
    BYTE*       pby;                                    // Y方向ポインタ:青
    BYTE*       pdy;                                    // Y方向ポインタ:結果
    int         h;                                      // 画像の水平サイズ
    int         v;                                      // 画像の垂直サイズ
    int         sti;                                    // エラーステータス

    sti = CheckImageByte( pr );                         // 赤配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 10 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pg );                         // 緑配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 20 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pb );                         // 青配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 30 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pd );                         // D配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 40 );                             // 左記を返す
    }                                                   // 
    CheckColorImageSize( pr, pg, pb, h, v );            // カラー最小サイズ算出
    h   = ( h <= pd->h ) ? h : pd->h;                   // Dとの最小を
    v   = ( v <= pd->v ) ? v : pd->v;                   // 算出
    pry = (BYTE*)pr->adr;                               // それぞれの
    pgy = (BYTE*)pg->adr;                               // Y座標方向ポインタ
    pby = (BYTE*)pb->adr;                               // セット
    pdy = (BYTE*)pd->adr;                               // 
    while( --v >= 0 ){                                  // 垂直方向に繰り返し
        ConvertRgbToMonoBase( pry, pgy, pby, pdy, h );  // 水平方向に処理
        pry += pr->inc;                                 // それぞれの
        pgy += pg->inc;                                 // Y座標方向ポインタ
        pby += pb->inc;                                 // Y方向に進行
        pdy += pd->inc;                                 // 
    }                                                   // 
    return( END_STI );                                  // 正常終了
}

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

(4-14-16-A)関数「ConvertRgbToMono()」の【関数名】説明

「Convert」は、英単語「Convert」として変換するの意味で
す!
「Rgb」は、RGB3原色カラー方式のカラー画像を意味
「To」は、「○○から××」と「から」の意味です!
「Mono」は、モノクロ画像≪白黒濃淡画像≫を意味

(4-14-16-B)関数「int ConvertRgbToMono()」の【返値】説明

int             CopyClear::ConvertRgbToMono(
    TypeArray   *pr,                                    // S配列:赤
    TypeArray   *pg,                                    // S配列:緑
    TypeArray   *pb,                                    // S配列:青
    TypeArray   *pd                                     // D配列
){

この関数内で明示的に検査しているのは、
仮引数「TypeArray* pr,TypeArray* pg,TypeArray* pb,
TypeArray* pd」が、1バイト単位で更に正常な画像情報で
無ければエラーコードを返します!
最後まで実行時は、正常終了「END_STI」を返します!

(4-14-16-C)関数「ConvertRgbToMono()」の【仮引数】説明

int             CopyClear::ConvertRgbToMono(
    TypeArray   *pr,                                    // S配列:赤
    TypeArray   *pg,                                    // S配列:緑
    TypeArray   *pb,                                    // S配列:青
    TypeArray   *pd                                     // D配列
){

「TypeArray* pr,」は、R(赤色)元画像情報
「TypeArray* pg,」は、G(緑色)元画像情報
「TypeArray* pb,」は、B(青色)元画像情報
「TypeArray* pd」は、D(モノクロ濃淡)結果画像情報

(4-14-16-D)関数「ConvertRgbToMono()」の【アルゴリズム】説明

){
    BYTE*       pry;                                    // Y方向ポインタ:赤
    BYTE*       pgy;                                    // Y方向ポインタ:緑
    BYTE*       pby;                                    // Y方向ポインタ:青
    BYTE*       pdy;                                    // Y方向ポインタ:結果
    int         h;                                      // 画像の水平サイズ
    int         v;                                      // 画像の垂直サイズ
    int         sti;                                    // エラーステータス

    sti = CheckImageByte( pr );                         // 赤配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 10 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pg );                         // 緑配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 20 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pb );                         // 青配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 30 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pd );                         // D配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 40 );                             // 左記を返す
    }                                                   // 
    CheckColorImageSize( pr, pg, pb, h, v );            // カラー最小サイズ算出
    h   = ( h <= pd->h ) ? h : pd->h;                   // Dとの最小を
    v   = ( v <= pd->v ) ? v : pd->v;                   // 算出
    pry = (BYTE*)pr->adr;                               // それぞれの
    pgy = (BYTE*)pg->adr;                               // Y座標方向ポインタ
    pby = (BYTE*)pb->adr;                               // セット
    pdy = (BYTE*)pd->adr;                               // 
    while( --v >= 0 ){                                  // 垂直方向に繰り返し
        ConvertRgbToMonoBase( pry, pgy, pby, pdy, h );  // 水平方向に処理
        pry += pr->inc;                                 // それぞれの
        pgy += pg->inc;                                 // Y座標方向ポインタ
        pby += pb->inc;                                 // Y方向に進行
        pdy += pd->inc;                                 // 
    }                                                   // 
    return( END_STI );                                  // 正常終了
}

ローカル変数

){
    BYTE*       pry;                                    // Y方向ポインタ:赤
    BYTE*       pgy;                                    // Y方向ポインタ:緑
    BYTE*       pby;                                    // Y方向ポインタ:青
    BYTE*       pdy;                                    // Y方向ポインタ:結果
    int         h;                                      // 画像の水平サイズ
    int         v;                                      // 画像の垂直サイズ
    int         sti;                                    // エラーステータス

「BYTE *pry;」は、R(赤)画像の実操作ポインタです!
「BYTE *pgy;」は、G(緑)画像の実操作ポインタです!
「BYTE *pby;」は、B(青)画像の実操作ポインタです!
「BYTE *pdy;」は、D(モノクロ濃淡)結果画像の実操作
ポインタです!
「int h;」は、有効(最小)水平幅
「int v;」は、有効(最小)垂直幅
「int sti;」は、ステータス情報

アルゴリズムコード

    sti = CheckImageByte( pr );                         // 赤配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 10 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pg );                         // 緑配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 20 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pb );                         // 青配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 30 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pd );                         // D配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 40 );                             // 左記を返す
    }                                                   // 
    CheckColorImageSize( pr, pg, pb, h, v );            // カラー最小サイズ算出
    h   = ( h <= pd->h ) ? h : pd->h;                   // Dとの最小を
    v   = ( v <= pd->v ) ? v : pd->v;                   // 算出
    pry = (BYTE*)pr->adr;                               // それぞれの
    pgy = (BYTE*)pg->adr;                               // Y座標方向ポインタ
    pby = (BYTE*)pb->adr;                               // セット
    pdy = (BYTE*)pd->adr;                               // 
    while( --v >= 0 ){                                  // 垂直方向に繰り返し
        ConvertRgbToMonoBase( pry, pgy, pby, pdy, h );  // 水平方向に処理
        pry += pr->inc;                                 // それぞれの
        pgy += pg->inc;                                 // Y座標方向ポインタ
        pby += pb->inc;                                 // Y方向に進行
        pdy += pd->inc;                                 // 
    }                                                   // 
    return( END_STI );                                  // 正常終了
}

「sti=CheckImageBYTE (pr);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-10);}」は、ステータス
が正常で無ければ「sti-10」と【1番目】画像情報不具合
を返し関数終了!
「sti=CheckImageBYTE (pg);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-20);}」は、ステータス
が正常で無ければ「sti-20」と【2番目】画像情報不具合
を返し関数終了!
「sti=CheckImageBYTE (pb);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-30);}」は、ステータス
が正常で無ければ「sti-30」と【3番目】画像情報不具合
を返し関数終了!
「sti=CheckImageBYTE (pd);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-40);}」は、ステータス
が正常で無ければ「sti-30」と【4番目】画像情報不具合
を返し関数終了!
「CheckColorImageSize(pr,pg,pb,h,v);」は、3原色カラー
画像情報の水平幅・垂直幅の有効(最小値)幅を算出し、
ローカル変数「h,v」に算出した値をセット
★注意★検査関数「CheckColorImageSize()」の
仮引数「int &size_h,int &size_v」が「int &」とローカル
変数のポインタを検査関数に送って処理して居る事に留意
そして検査関数「CheckColorImageSize()」内部でエラー
チェックも行いますが、
既に検査関数「CheckImageBYTE ()」で検査しているので
コノ検査関数「CheckColorImageSize()」は、水平幅・
垂直幅の有効(最小値)幅算出のみ行いますので関数辺値
エラーコードは利用しません!
「h=(h<=pd->h)?h:pd->h;」は、D(結果)画像の水平幅と
の有効(最小値)幅を調整!
「v=(v<=pd->v)?v:pd->v;」は、D(結果)画像の垂直幅と
の有効(最小値)幅を調整!
「pry=(BYTE *)pr->adr;」は、R(赤)画像の実操作ポイン
タをセット
「pgy=(BYTE *)pg->adr;」は、G(緑)画像の実操作ポイン
タをセット
「pby=(BYTE *)pb->adr;」は、B(青)画像の実操作ポイン
タをセット
「pdy=(BYTE *)pd->adr;」は、D(モノクロ濃淡)結果
画像の実操作ポインタをセット
「while(--v>=0){・・ループ本体・・}」は、
ループ条件「--v>=0」で垂直幅の数分「ループ本体」を
ループ(繰り返す)処理です
★備考★「while(--v>=0」の様に「--v>=0」とデクリメント
演算子で変数値が変化しても影響が無い応用には、
経験上最適なCPU機械コードが生成出来るので、この
画像処理ライブラリは、この記法を多用して居ます!
学校の教科書的には余り教えて無い(恐らく変数の値が変わ
る事を説明する必要が有るので説明がヤヤコシク成る事を
嫌ったと推測)と思いますが、兎も角、高速に動かすには、
この記法がベストと考えて採用しています!
ループ本体「{ConvertRgbToMonoBase(pry,pgy,pby,pdy,h);
pry+=pr->inc;pgy+=pg->inc;pby+=pb->inc;pdy+=pd->inc;}
」、と水平方向の処理を担うサブルーチン関数「
ConvertRgbToMonoBase()」で1行水平方向を処理し、
「pry+=pr->inc;pgy+=pg->inc;pby+=pb->inc;
pdy+=pd->inc;」と
RGB元画像とD結果画像の実操作ポインタを次の行へ
垂直方向に1行進めます!
「return(END_STI);」は、正常終了を返し関数終了!

(4-14-16-E)関数「ConvertRgbToMono()」の【使用例】説明

グラフィック関数でパターン画像作成例紹介

グラフィック例文サンプル


#include"ImageFunc.h"           // 画像処理ライブラリ用
ImageFunc FUN;                  // ライブラリ関数使用定義

main()
{
・・・・・中身・・・
}
が、ライブラリ関数の使用方法で特にグラフィック
は、解説順序の都合で後回しにしますが、フライング気味に
先にクラス「class Graphic」で記述している関数を使用
します!
先ず、「SetGraphic()」と設定関数でグラフィックを描画
する画像・描画する画像が8ビットモノクロ画像が、
ウィンドウズ対応の表示画像を使用するかの選択肢・
描画する点とか線の大きさ(太さ)等を設定する関数を
グラフィックは、同じ画像に対して複数の処理を施すので
毎回、描画関数で設定で無く、事前に一括して設定する方法
を採用しました!関数「SetGraphic()」で設定します!
今回は、8ビット画像に線の太さ=画素1単位で白黒の描画
で行う事にします!
描画は、円を描く関数「DrawFillCircle()」を使用します!


{
    TypeArray   ImgRed;                    // 画像:赤色
    TypeArray   ImgGreen;                  // 画像:緑色
    TypeArray   ImgBlue;                   // 画像:青色
    TypeArray*  PtrImgRed=&ImgRed;         // 画像へのポインタ
    TypeArray*  PtrImgGreen=&ImgGreen;     // 画像へのポインタ
    TypeArray*  PtrImgBlue=&ImgBlue;       // 画像へのポインタ

    PtrImgRed->MallocBYTE( 640, 480 );      // サイズ640×480画像メモリ取得
    FUN.Clear( PtrImgRed, 0 );              // 画像メモリ「0クリア」
    PtrImgGreen->MallocBYTE( 640, 480 );    // サイズ640×480画像メモリ取得
    FUN.Clear( PtrImgGreen, 0 );            // 画像メモリ「0クリア」
    PtrImgBlue->MallocBYTE( 640, 480 );     // サイズ640×480画像メモリ取得
    FUN.Clear( PtrImgBlue, 0 );             // 画像メモリ「0クリア」

// 赤色画像パターン作成
    FUN.SetGraphic( PtrImgRed,              // グラフィックス対象セット:赤色画像
                8, 0, 1, 237, 0, 0, 0 );    // 8bit=1バイト画素で白黒画像で
                                            // 太さ1画素で描画値=237書き込み
    FUN.DrawFillCircle( 140, 294, 135 );    // 中心(140,294)で半径135で円描画
    FUN.WriteBitmap("testFile11.bmp",       // ファイル「testFile11.bmp」で
                        PtrImgRed );        // 8ビット輝度画素で赤色画像ファイル作成

// 緑色画像パターン作成
    FUN.SetGraphic( PtrImgGreen,            // グラフィックス対象セット:緑色画像
                8, 0, 1, 177, 0, 0, 0 );    // 8bit=1バイト画素で白黒画像で
                                            // 太さ1画素で描画値=177書き込み
    FUN.DrawFillCircle( 281, 294, 135 );    // 中心(281,294)で半径135で円描画
    FUN.WriteBitmap("testFile12.bmp",       // ファイル「testFile12.bmp」で
                        PtrImgGreen );      // 8ビット輝度画素で緑色画像ファイル作成

// 青色画像パターン作成
    FUN.SetGraphic( PtrImgBlue,				// グラフィックス対象セット:青色画像
    			8, 0, 1, 232, 0, 0, 0 );	// 8bit=1バイト画素で白黒画像で
    										// 太さ1画素で描画値=232書き込み
    FUN.DrawFillCircle( 225196, 135 );	// 中心(225,196)で半径135で円描画
    FUN.WriteBitmap("testFile13.bmp",		// ファイル「testFile13.bmp」で
    					PtrImgBlue );		// 8ビット輝度画素で青色画像ファイル作成
}

上記で作成した画像ファイル紹介

testFile11.bmp
testFile12.bmp
testFile13.bmp

RGB三原色のカラー表現が可能な状態での
イメージ(画像の意味では無い事に注意だが同じ様な物)

3画像を重ねた状態

今回の関数「ConvertRgbToMono()」使用例

{
    TypeArray   ImgRed;                    // 画像:赤色
    TypeArray   ImgGreen;                  // 画像:緑色
    TypeArray   ImgBlue;                   // 画像:青色
    TypeArray   ImgMono;                   // 画像:白黒
    TypeArray*  PtrImgRed=&ImgRed;         // 画像へのポインタ
    TypeArray*  PtrImgGreen=&ImgGreen;     // 画像へのポインタ
    TypeArray*  PtrImgBlue=&ImgBlue;       // 画像へのポインタ
    TypeArray*  PtrImgMono=&ImgMono;       // 画像へのポインタ

    PtrImgRed->MallocBYTE( 640, 480 );      // サイズ640×480画像メモリ取得
    FUN.Clear( PtrImgRed, 0 );              // 画像メモリ「0クリア」
    PtrImgGreen->MallocBYTE( 640, 480 );    // サイズ640×480画像メモリ取得
    FUN.Clear( PtrImgGreen, 0 );            // 画像メモリ「0クリア」
    PtrImgBlue->MallocBYTE( 640, 480 );     // サイズ640×480画像メモリ取得
    FUN.Clear( PtrImgBlue, 0 );             // 画像メモリ「0クリア」
    PtrImgMono->MallocBYTE( 640, 480 );     // サイズ640×480画像メモリ取得
    FUN.Clear( PtrImgMono, 0 );             // 画像メモリ「0クリア」

// 赤色画像パターン作成
    FUN.SetGraphic( PtrImgRed,              // グラフィックス対象セット:赤色画像
                8, 0, 1, 237, 0, 0, 0 );    // 8bit=1バイト画素で白黒画像で
                                            // 太さ1画素で描画値=237書き込み
    FUN.DrawFillCircle( 140, 294, 135 );    // 中心(140,294)で半径135で円描画
    FUN.WriteBitmap("testFile11.bmp",       // ファイル「testFile11.bmp」で
                        PtrImgRed );        // 8ビット輝度画素で赤色画像ファイル作成

// 緑色画像パターン作成
    FUN.SetGraphic( PtrImgGreen,            // グラフィックス対象セット:緑色画像
                8, 0, 1, 177, 0, 0, 0 );    // 8bit=1バイト画素で白黒画像で
                                            // 太さ1画素で描画値=177書き込み
    FUN.DrawFillCircle( 281, 294, 135 );    // 中心(281,294)で半径135で円描画
    FUN.WriteBitmap("testFile12.bmp",       // ファイル「testFile12.bmp」で
                        PtrImgGreen );      // 8ビット輝度画素で緑色画像ファイル作成

// 青色画像パターン作成
    FUN.SetGraphic( PtrImgBlue,             // グラフィックス対象セット:青色画像
                8, 0, 1, 232, 0, 0, 0 );    // 8bit=1バイト画素で白黒画像で
                                            // 太さ1画素で描画値=232書き込み
    FUN.DrawFillCircle( 225196, 135 );    // 中心(225,196)で半径135で円描画
    FUN.WriteBitmap("testFile13.bmp",       // ファイル「testFile13.bmp」で
                        PtrImgBlue );       // 8ビット輝度画素で青色画像ファイル作成
// 今回の「ConvertRgbToMono()」で3色画像からモノクロ画像作成
    FUN.ConvertRgbToMono( PtrImgRed,        // 
    PtrImgGreen, PtrImgBlue, PtrImgMono );  // 
    FUN.WriteBitmap("testFile14.bmp",       // ファイル「testFile14.bmp」で
                        PtrImgMono );       // 8ビット輝度画素で青色画像ファイル作成

// 後始末
    PtrImgRed->freeMem();                   // 画像メモリ解放
    PtrImgGreen->freeMem();                 // 画像メモリ解放
    PtrImgBlue->freeMem();                  // 画像メモリ解放
    PtrImgMono->freeMem();                  // 画像メモリ解放
}

上記で作成した画像ファイル「testFile14」紹介

testFile14

★注意★
上記例文で注意して欲しいのは、LUTは、用意して無い事
です!関数「ConvertRgbToMono()」の中でLUTも使用せず
演算式で変換を内部で行って居る事です!そして画像を
3枚(RGB)から1枚(モノクロ)に変換している例です

取り敢えず、本日(3月28)の講義は、ココまでにし
ます!何だか、疲れた!受講されている方も、新し項目「
画像データを三原色からモノクロ画像への変換」で理解に、
お疲れと思いますのでココまでとします!
まだ、Noteサーバーが快適に動く分量ですから、
引き続き、この文章に続きは、載せます!

2024年3月29続講

(4-14-17)関数「int ConvertRgbToDiff(TypeArray* pr,TypeArray* pg,TypeArray* pb,
TypeArray* pY,TypeArray* pRY,TypeArray* pBY);
{・・・}」の説明

int             CopyClear::ConvertRgbToDiff(
    TypeArray   *pr,                                    // S配列:赤
    TypeArray   *pg,                                    // S配列:緑
    TypeArray   *pb,                                    // S配列:青
    TypeArray   *pY,                                    // D配列:輝度
    TypeArray   *pRY,                                   // D配列:R-Y
    TypeArray   *pBY                                    // D配列:B-Y
){
    BYTE*       pry;                                    // Y方向ポインタ:赤
    BYTE*       pgy;                                    // Y方向ポインタ:緑
    BYTE*       pby;                                    // Y方向ポインタ:青
    BYTE*       pYy;                                    // Y方向ポインタ:輝度
    char*       pRYy;                                   // Y方向ポインタ:R-Y
    char*       pBYy;                                   // Y方向ポインタ:B-Y
    int         h;                                      // 画像の水平サイズ
    int         v;                                      // 画像の垂直サイズ
    int         h1;                                     // 画像の水平サイズ
    int         v1;                                     // 画像の垂直サイズ
    int         sti;                                    // エラーステータス

    sti = CheckImageByte( pr );                         // 赤配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 10 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pg );                         // 緑配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 20 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pb );                         // 青配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 30 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pY );                         // D配列:輝度検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 40 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pRY );                        // D配列:R-Y検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 50 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pBY );                        // D配列:B-Y検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 60 );                             // 左記を返す
    }                                                   // 
    CheckColorImageSize( pr, pg, pb, h, v );            // カラー最小サイズ算出:S
    CheckColorImageSize( pY, pRY, pBY, h1, v1 );        // カラー最小サイズ算出:D
    h    = ( h <= h1 ) ? h : h1;                        // 最小を値を
    v    = ( v <= v1 ) ? v : v1;                        // 算出
    pry  = (BYTE*)pr->adr;                              // それぞれの
    pgy  = (BYTE*)pg->adr;                              // Y座標方向ポインタ
    pby  = (BYTE*)pb->adr;                              // セット
    pYy  = (BYTE*)pY->adr;                              // 
    pRYy = (char*)pRY->adr;                             // 
    pBYy = (char*)pBY->adr;                             // 
    while( --v >= 0 ){                                  // 垂直方向に繰り返し
        ConvertRgbToDiffBase( pry, pgy, pby,            // 水平方向に処理
                                pYy, pRYy, pBYy, h );   // 
        pry  += pr->inc;                                // それぞれの
        pgy  += pg->inc;                                // Y座標方向ポインタ
        pby  += pb->inc;                                // Y方向に進行
        pYy  += pY->inc;                                // 
        pRYy += pRY->inc;                               // 
        pBYy += pBY->inc;                               // 
    }                                                   // 
    return( END_STI );                                  // 正常終了
}

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

(4-14-17-A)関数「ConvertRgbToDiff()」の【関数名】説明

「Convert」は、英単語「Convert」として変換するの意味で
す!
「Rgb」は、RGB3原色カラー方式のカラー画像を意味
「To」は、「○○から××」と「から」の意味です!
「Diff」は、英単語「difference」=「違い」の省略形で
ここでは、「差分」の意味から、色差方式のカラー表現方式
へを意味します!

(4-14-17-B)関数「int ConvertRgbToDiff()」の【返値】説明

int             CopyClear::ConvertRgbToDiff(
    TypeArray   *pr,                                    // S配列:赤
    TypeArray   *pg,                                    // S配列:緑
    TypeArray   *pb,                                    // S配列:青
    TypeArray   *pY,                                    // D配列:輝度
    TypeArray   *pRY,                                   // D配列:R-Y
    TypeArray   *pBY                                    // D配列:B-Y
){

この関数内で明示的に検査しているのは、
仮引数「TypeArray* pr,TypeArray* pg,TypeArray* pb,
TypeArray* pY,TypeArray* pRY,TypeArray* pBY」が、
1バイト単位で更に正常な画像情報で無ければエラー
コードを返します!
最後まで実行時は、正常終了「END_STI」を返します!

(4-14-17-C)関数「ConvertRgbToDiff()」の【仮引数】説明

int             CopyClear::ConvertRgbToDiff(
    TypeArray   *pr,                                    // S配列:赤
    TypeArray   *pg,                                    // S配列:緑
    TypeArray   *pb,                                    // S配列:青
    TypeArray   *pY,                                    // D配列:輝度
    TypeArray   *pRY,                                   // D配列:R-Y
    TypeArray   *pBY                                    // D配列:B-Y
){

「TypeArray* pr,」は、R(赤色)元画像情報
「TypeArray* pg,」は、G(緑色)元画像情報
「TypeArray* pb,」は、B(青色)元画像情報
「TypeArray* pY」は、Y(色差「Y」モノクロ濃淡)結果
画像情報
「TypeArray* pRY」は、RY(色差「R-Y」)結果画像
情報
「TypeArray* pBY」は、BY(色差「B-Y」)結果画像
情報

(4-14-17-D)関数「ConvertRgbToDiff()」の【アルゴリズム】説明

){
    BYTE*       pry;                                    // Y方向ポインタ:赤
    BYTE*       pgy;                                    // Y方向ポインタ:緑
    BYTE*       pby;                                    // Y方向ポインタ:青
    BYTE*       pYy;                                    // Y方向ポインタ:輝度
    char*       pRYy;                                   // Y方向ポインタ:R-Y
    char*       pBYy;                                   // Y方向ポインタ:B-Y
    int         h;                                      // 画像の水平サイズ
    int         v;                                      // 画像の垂直サイズ
    int         h1;                                     // 画像の水平サイズ
    int         v1;                                     // 画像の垂直サイズ
    int         sti;                                    // エラーステータス

    sti = CheckImageByte( pr );                         // 赤配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 10 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pg );                         // 緑配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 20 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pb );                         // 青配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 30 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pY );                         // D配列:輝度検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 40 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pRY );                        // D配列:R-Y検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 50 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pBY );                        // D配列:B-Y検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 60 );                             // 左記を返す
    }                                                   // 
    CheckColorImageSize( pr, pg, pb, h, v );            // カラー最小サイズ算出:S
    CheckColorImageSize( pY, pRY, pBY, h1, v1 );        // カラー最小サイズ算出:D
    h    = ( h <= h1 ) ? h : h1;                        // 最小を値を
    v    = ( v <= v1 ) ? v : v1;                        // 算出
    pry  = (BYTE*)pr->adr;                              // それぞれの
    pgy  = (BYTE*)pg->adr;                              // Y座標方向ポインタ
    pby  = (BYTE*)pb->adr;                              // セット
    pYy  = (BYTE*)pY->adr;                              // 
    pRYy = (char*)pRY->adr;                             // 
    pBYy = (char*)pBY->adr;                             // 
    while( --v >= 0 ){                                  // 垂直方向に繰り返し
        ConvertRgbToDiffBase( pry, pgy, pby,            // 水平方向に処理
                                pYy, pRYy, pBYy, h );   // 
        pry  += pr->inc;                                // それぞれの
        pgy  += pg->inc;                                // Y座標方向ポインタ
        pby  += pb->inc;                                // Y方向に進行
        pYy  += pY->inc;                                // 
        pRYy += pRY->inc;                               // 
        pBYy += pBY->inc;                               // 
    }                                                   // 
    return( END_STI );                                  // 正常終了
}

ローカル変数

){
    BYTE*       pry;                                    // Y方向ポインタ:赤
    BYTE*       pgy;                                    // Y方向ポインタ:緑
    BYTE*       pby;                                    // Y方向ポインタ:青
    BYTE*       pYy;                                    // Y方向ポインタ:輝度
    char*       pRYy;                                   // Y方向ポインタ:R-Y
    char*       pBYy;                                   // Y方向ポインタ:B-Y
    int         h;                                      // 画像の水平サイズ
    int         v;                                      // 画像の垂直サイズ
    int         h1;                                     // 画像の水平サイズ
    int         v1;                                     // 画像の垂直サイズ
    int         sti;                                    // エラーステータス

「BYTE* pry;」は、R(赤)画像の実操作ポインタです!
「BYTE* pgy;」は、G(緑)画像の実操作ポインタです!
「BYTE* pby;」は、B(青)画像の実操作ポインタです!
「BYTE* pYy;」は、Y(色差「輝度」)画像の実操作
ポインタです!
「char* pRYy;」は、RY(色差「R-Y」)画像の実操作
ポインタです!★注意★型が「char」と符号付きと
扱う事に留意!
「char* pBYy;」は、BY(色差「B-Y」)画像の実操作
ポインタです!★注意★型が「char」と符号付きと扱う
事に留意!
★備考★上記で英小文字「y」は、垂直方向へのポインタを
示す為に明示的に付けた物ですが、英大文字「Y」は、
色差式の「Y」成分と言う、アナログ電子回路での輝度を
示す単語の省略と記載して置きます!気に成る人はカラー
画像の専門書を探して確認して下さい!
「int h;」は、有効(最小)水平幅
「int v;」は、有効(最小)垂直幅
「int h1;」は、有効(最小)水平幅
「int v1;」は、有効(最小)垂直幅
「int sti;」は、ステータス情報

アルゴリズムコード

    sti = CheckImageByte( pr );                         // 赤配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 10 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pg );                         // 緑配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 20 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pb );                         // 青配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 30 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pY );                         // D配列:輝度検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 40 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pRY );                        // D配列:R-Y検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 50 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pBY );                        // D配列:B-Y検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 60 );                             // 左記を返す
    }                                                   // 
    CheckColorImageSize( pr, pg, pb, h, v );            // カラー最小サイズ算出:S
    CheckColorImageSize( pY, pRY, pBY, h1, v1 );        // カラー最小サイズ算出:D
    h    = ( h <= h1 ) ? h : h1;                        // 最小を値を
    v    = ( v <= v1 ) ? v : v1;                        // 算出
    pry  = (BYTE*)pr->adr;                              // それぞれの
    pgy  = (BYTE*)pg->adr;                              // Y座標方向ポインタ
    pby  = (BYTE*)pb->adr;                              // セット
    pYy  = (BYTE*)pY->adr;                              // 
    pRYy = (char*)pRY->adr;                             // 
    pBYy = (char*)pBY->adr;                             // 
    while( --v >= 0 ){                                  // 垂直方向に繰り返し
        ConvertRgbToDiffBase( pry, pgy, pby,            // 水平方向に処理
                                pYy, pRYy, pBYy, h );   // 
        pry  += pr->inc;                                // それぞれの
        pgy  += pg->inc;                                // Y座標方向ポインタ
        pby  += pb->inc;                                // Y方向に進行
        pYy  += pY->inc;                                // 
        pRYy += pRY->inc;                               // 
        pBYy += pBY->inc;                               // 
    }                                                   // 
    return( END_STI );                                  // 正常終了
}

「sti=CheckImageBYTE (pr);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-10);}」は、ステータスが
正常で無ければ「sti-10」と【1番目】画像情報不具合を
返し関数終了!
「sti=CheckImageBYTE (pg);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-20);}」は、ステータスが
正常で無ければ「sti-20」と【2番目】画像情報不具合を
返し関数終了!
「sti=CheckImageBYTE (pb);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-30);}」は、ステータスが
正常で無ければ「sti-30」と【3番目】画像情報不具合を
返し関数終了!
「sti=CheckImageBYTE (pY);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-40);}」は、ステータスが
正常で無ければ「sti-30」と【4番目】画像情報不具合を
返し関数終了!
「sti=CheckImageBYTE (pRY);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」
格納
「if(sti!=END_STI){return(sti-50);}」は、ステータスが
正常で無ければ「sti-30」と【5番目】画像情報不具合を
返し関数終了!
「sti=CheckImageBYTE (pBY);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-60);}」は、ステータスが
正常で無ければ「sti-30」と【6番目】画像情報不具合を
返し関数終了!
「CheckColorImageSize(pr,pg,pb,h,v);」は、RGB
3原色カラー画像情報の水平幅・垂直幅の有効(最小値)幅
を算出し、ローカル変数「h,v」に算出した値をセット!
「CheckColorImageSize(pY,pRY,pBY,h1,v1);」は、色差式
3色カラー画像情報の水平幅・垂直幅の有効(最小値)幅を
算出し、ローカル変数「h1,v1」に算出した値をセット!
★注意★検査関数「CheckColorImageSize()」の
仮引数「int &size_h,int &size_v」が「int &」とローカル
変数のポインタを検査関数に送って処理して居る事に留意
「h=(h<=h1)?h:h1;」は、水平幅の最小値(有効幅)算出
「v=(v<=v1)?v:v1;」は、垂直幅の最小値(有効幅)算出
「pry=(BYTE *)pr->adr;pgy=(BYTE *)pg->adr;
pby=(BYTE )pb->adr;」は、元画像のRGB3原色画像に
対して実画像メモリポインタを垂直方向処理実ポインタと
してセットした物です!
「pYy=(BYTE )pY->adr;pRYy=(char)pRY->adr;
pBYy=(char)pBY->adr;」は、結果画像の色差式(
Y・R-Y・B-Y)3画像に対して実画像メモリポインタを
垂直方向処理実ポインタとしてセットした物です!
「while(--v>=0){・・ループ本体・・}」は、
ループ条件「--v>=0」で垂直幅の数分「ループ本体」を
ループ(繰り返す)処理です★備考★「while(--v>=0」の
様に「--v>=0」とデクリメント演算子で変数値が変化して
も影響が無い応用には、経験上最適なCPU機械コードが
生成出来るので、この画像処理ライブラリは、この記法を
多用して居ます!学校の教科書的には余り教えて無い(
恐らく変数の値が変わる事を説明する必要が有るので説明が
ヤヤコシク成る事を嫌ったと推測)と思いますが、兎も角、
高速に動かすには、この記法がベストと考えて採用してい
ます!
ループ本体「{ConvertRgbToDiffBase(pry,pgy,pby,pYy,
pRYy,pBYy,h);pry+=pr->inc;pgy+=pg->inc;pby+=pb->inc;
pYy+=pY->inc;pRYy+=pRY->inc;pBYy+=pBY->inc;}」、と
水平方向の処理を担うサブルーチン関数「
ConvertRgbToDiffBase()」で1行水平方向を処理し、
「pry+=pr->inc;pgy+=pg->inc;pby+=pb->inc;
pYy+=pY->inc;pRYy+=pRY->inc;pBYy+=pBY->inc;」と
RGB元画像とY色差方式結果画像の実操作ポインタを
次の行へ垂直方向に1行進めます!「return(END_STI);」は、正常終了を返し関数終了!

(4-14-17-E)関数「ConvertRgbToDiff()」の【使用例】説明

☆備考☆
今回は、項目だけ示し、中身は後回し≪作者の私が、ライブ
ラリ関数を実行可能な環境が得られる≒十分に予算を得てか
ら使用可能なコンパイル&GOが出来るシステムとその解説
書・手引き書も購入し、例文とそれに依って作成した画像
ファイルサンプルが作成出来たら、作成し、ここに追加しま
す、その為に解説『投げ銭方式ライブラリのダウンロード』
での有料部分まで読んで私に「投げ銭」としての有料料金を
恵んで下さい!≫

★注意★
上記例文で注意して欲しいのは、LUTは、用意して無い事
です!関数「ConvertRgbToDiff()」の中でLUTも使用せず
演算式で変換を内部で行って居る事です!そして画像を
3枚(RGB形式)から3枚(色差方式)に変換している
例です!

取り敢えず、本日(3月29)の講義は、ココまでにし
ます!何だか、!受講されている方も、新し項目「
画像データを三原色から差分画像への変換」で理解に、
お疲れと思いますのでココまでとします!
まだ、Noteサーバーが快適に動く分量ですから、
引き続き、この文章に続きは、載せます!

2024年3月30続講

(4-14-18)関数「int ConvertDiffToRgb(
TypeArray* pY,TypeArray* pRY,TypeArray* pBY,
TypeArray* pr,TypeArray* pg,TypeArray* pb);
{・・・}」の説明

int             CopyClear::ConvertDiffToRgb(
    TypeArray   *pY,                                    // S配列:輝度
    TypeArray   *pRY,                                   // S配列:R-Y
    TypeArray   *pBY,                                   // S配列:B-Y
    TypeArray   *pr,                                    // D配列:赤
    TypeArray   *pg,                                    // D配列:緑
    TypeArray   *pb                                     // D配列:青
){
    BYTE*       pYy;                                    // Y方向ポインタ:輝度
    char*       pRYy;                                   // Y方向ポインタ:R-Y
    char*       pBYy;                                   // Y方向ポインタ:B-Y
    BYTE*       pry;                                    // Y方向ポインタ:赤
    BYTE*       pgy;                                    // Y方向ポインタ:緑
    BYTE*       pby;                                    // Y方向ポインタ:青
    int         h;                                      // 画像の水平サイズ
    int         v;                                      // 画像の垂直サイズ
    int         h1;                                     // 画像の水平サイズ
    int         v1;                                     // 画像の垂直サイズ
    int         sti;                                    // エラーステータス

    sti = CheckImageByte( pY );                         // S配列:輝度検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 10 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pRY );                        // S配列:R-Y検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 20 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pBY );                        // S配列:B-Y検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 30 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pr );                         // 赤配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 40 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pg );                         // 緑配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 50 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pb );                         // 青配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 60 );                             // 左記を返す
    }                                                   // 
    CheckColorImageSize( pY, pRY, pBY, h, v );          // カラー最小サイズ算出:S
    CheckColorImageSize( pr, pg, pb, h1, v1 );          // カラー最小サイズ算出:D
    h    = ( h <= h1 ) ? h : h1;                        // 最小を値を
    v    = ( v <= v1 ) ? v : v1;                        // 算出
    pYy  = (BYTE*)pY->adr;                              // 
    pRYy = (char*)pRY->adr;                             // 
    pBYy = (char*)pBY->adr;                             // 
    pry  = (BYTE*)pr->adr;                              // それぞれの
    pgy  = (BYTE*)pg->adr;                              // Y座標方向ポインタ
    pby  = (BYTE*)pb->adr;                              // セット
    while( --v >= 0 ){                                  // 垂直方向に繰り返し
        ConvertDiffToRgbBase( pYy, pRYy, pBYy,          // 水平方向に処理
                                    pry, pgy, pby, h ); // 
        pYy  += pY->inc;                                // それぞれの
        pRYy += pRY->inc;                               // Y座標方向ポインタ
        pBYy += pBY->inc;                               // Y方向に進行
        pry  += pr->inc;                                // 
        pgy  += pg->inc;                                // 
        pby  += pb->inc;                                // 
    }                                                   // 
    return( END_STI );                                  // 正常終了
}

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

(4-14-18-A)関数「ConvertDiffToRgb()」の【関数名】説明

「Convert」は、英単語「Convert」として変換するの意味で
す!
「Diff」は、英単語「difference」=「違い」の省略形で
ここでは、「差分」の意味から、色差方式のカラー表現方式
「Rgb」は、RGB3原色カラー方式のカラー画像を意味
「To」は、「○○から××」と「から」の意味です!
詰り、色差方式からRGB3原色カラー方式への変換を意味
します!

(4-14-18-B)関数「int ConvertDiffToRgb()」の【返値】説明

int             CopyClear::ConvertDiffToRgb(
    TypeArray   *pY,                                    // S配列:輝度
    TypeArray   *pRY,                                   // S配列:R-Y
    TypeArray   *pBY,                                   // S配列:B-Y
    TypeArray   *pr,                                    // D配列:赤
    TypeArray   *pg,                                    // D配列:緑
    TypeArray   *pb                                     // D配列:青
){

この関数内で明示的に検査しているのは、
仮引数「TypeArray* pY,TypeArray* pRY,TypeArray* pBY,
TypeArray* pr,TypeArray* pg,TypeArray* pb」が、
1バイト単位で更に正常な画像情報で無ければエラー
コードを返します!
最後まで実行時は、正常終了「END_STI」を返します!

(4-14-18-C)関数「ConvertDiffToRgb()」の【仮引数】説明

int             CopyClear::ConvertDiffToRgb(
    TypeArray   *pY,                                    // S配列:輝度
    TypeArray   *pRY,                                   // S配列:R-Y
    TypeArray   *pBY,                                   // S配列:B-Y
    TypeArray   *pr,                                    // D配列:赤
    TypeArray   *pg,                                    // D配列:緑
    TypeArray   *pb                                     // D配列:青
){

「TypeArray* pY」は、Y(色差「Y」モノクロ濃淡)
元画像情報
「TypeArray* pRY」は、RY(色差「R-Y」)元画像情報
「TypeArray* pBY」は、BY(色差「B-Y」)元画像情報
「TypeArray* pr,」は、R(赤色)結果画像情報
「TypeArray* pg,」は、G(緑色)結果画像情報
「TypeArray* pb,」は、B(青色)結果画像情報

(4-14-18-D)関数「ConvertDiffToRgb()」の【アルゴリズム】説明

){
    BYTE*       pYy;                                    // Y方向ポインタ:輝度
    char*       pRYy;                                   // Y方向ポインタ:R-Y
    char*       pBYy;                                   // Y方向ポインタ:B-Y
    BYTE*       pry;                                    // Y方向ポインタ:赤
    BYTE*       pgy;                                    // Y方向ポインタ:緑
    BYTE*       pby;                                    // Y方向ポインタ:青
    int         h;                                      // 画像の水平サイズ
    int         v;                                      // 画像の垂直サイズ
    int         h1;                                     // 画像の水平サイズ
    int         v1;                                     // 画像の垂直サイズ
    int         sti;                                    // エラーステータス

    sti = CheckImageByte( pY );                         // S配列:輝度検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 10 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pRY );                        // S配列:R-Y検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 20 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pBY );                        // S配列:B-Y検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 30 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pr );                         // 赤配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 40 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pg );                         // 緑配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 50 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pb );                         // 青配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 60 );                             // 左記を返す
    }                                                   // 
    CheckColorImageSize( pY, pRY, pBY, h, v );          // カラー最小サイズ算出:S
    CheckColorImageSize( pr, pg, pb, h1, v1 );          // カラー最小サイズ算出:D
    h    = ( h <= h1 ) ? h : h1;                        // 最小を値を
    v    = ( v <= v1 ) ? v : v1;                        // 算出
    pYy  = (BYTE*)pY->adr;                              // 
    pRYy = (char*)pRY->adr;                             // 
    pBYy = (char*)pBY->adr;                             // 
    pry  = (BYTE*)pr->adr;                              // それぞれの
    pgy  = (BYTE*)pg->adr;                              // Y座標方向ポインタ
    pby  = (BYTE*)pb->adr;                              // セット
    while( --v >= 0 ){                                  // 垂直方向に繰り返し
        ConvertDiffToRgbBase( pYy, pRYy, pBYy,          // 水平方向に処理
                                    pry, pgy, pby, h ); // 
        pYy  += pY->inc;                                // それぞれの
        pRYy += pRY->inc;                               // Y座標方向ポインタ
        pBYy += pBY->inc;                               // Y方向に進行
        pry  += pr->inc;                                // 
        pgy  += pg->inc;                                // 
        pby  += pb->inc;                                // 
    }                                                   // 
    return( END_STI );                                  // 正常終了
}

ローカル変数

){
    BYTE*       pYy;                                    // Y方向ポインタ:輝度
    char*       pRYy;                                   // Y方向ポインタ:R-Y
    char*       pBYy;                                   // Y方向ポインタ:B-Y
    BYTE*       pry;                                    // Y方向ポインタ:赤
    BYTE*       pgy;                                    // Y方向ポインタ:緑
    BYTE*       pby;                                    // Y方向ポインタ:青
    int         h;                                      // 画像の水平サイズ
    int         v;                                      // 画像の垂直サイズ
    int         h1;                                     // 画像の水平サイズ
    int         v1;                                     // 画像の垂直サイズ
    int         sti;                                    // エラーステータス

「BYTE* pYy;」は、Y(色差「輝度」)画像の実操作
ポインタです!
「char* pRYy;」は、RY(色差「R-Y」)画像の実操作
ポインタです!★注意★型が「char*」と符号付きと
扱う事に留意!
「char* pBYy;」は、BY(色差「B-Y」)画像の実操作
ポインタです!★注意★型が「char」と符号付きと扱う
事に留意!
「BYTE *pry;」は、R(赤)画像の実操作ポインタです!
「BYTE *pgy;」は、G(緑)画像の実操作ポインタです!
「BYTE pby;」は、B(青)画像の実操作ポインタです!
★備考★上記で英小文字「y」は、垂直方向へのポインタを
示す為に明示的に付けた物ですが、英大文字「Y」は、
色差式の「Y」成分と言う、アナログ電子回路での輝度を
示す単語の省略と記載して置きます!気に成る人はカラー
画像の専門書を探して確認して下さい!
「int h;」は、有効(最小)水平幅
「int v;」は、有効(最小)垂直幅
「int h1;」は、有効(最小)水平幅
「int v1;」は、有効(最小)垂直幅
「int sti;」は、ステータス情報

アルゴリズムコード

    sti = CheckImageByte( pY );                         // S配列:輝度検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 10 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pRY );                        // S配列:R-Y検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 20 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pBY );                        // S配列:B-Y検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 30 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pr );                         // 赤配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 40 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pg );                         // 緑配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 50 );                             // 左記を返す
    }                                                   // 
    sti = CheckImageByte( pb );                         // 青配列検査
    if( sti != END_STI ){                               // 引数違反なら
        return( sti - 60 );                             // 左記を返す
    }                                                   // 
    CheckColorImageSize( pY, pRY, pBY, h, v );          // カラー最小サイズ算出:S
    CheckColorImageSize( pr, pg, pb, h1, v1 );          // カラー最小サイズ算出:D
    h    = ( h <= h1 ) ? h : h1;                        // 最小を値を
    v    = ( v <= v1 ) ? v : v1;                        // 算出
    pYy  = (BYTE*)pY->adr;                              // 
    pRYy = (char*)pRY->adr;                             // 
    pBYy = (char*)pBY->adr;                             // 
    pry  = (BYTE*)pr->adr;                              // それぞれの
    pgy  = (BYTE*)pg->adr;                              // Y座標方向ポインタ
    pby  = (BYTE*)pb->adr;                              // セット
    while( --v >= 0 ){                                  // 垂直方向に繰り返し
        ConvertDiffToRgbBase( pYy, pRYy, pBYy,          // 水平方向に処理
                                    pry, pgy, pby, h ); // 
        pYy  += pY->inc;                                // それぞれの
        pRYy += pRY->inc;                               // Y座標方向ポインタ
        pBYy += pBY->inc;                               // Y方向に進行
        pry  += pr->inc;                                // 
        pgy  += pg->inc;                                // 
        pby  += pb->inc;                                // 
    }                                                   // 
    return( END_STI );                                  // 正常終了
}

「sti=CheckImageBYTE (pY);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-10);}」は、ステータス
が正常で無ければ「sti-10」と【1番目】画像情報不具合
を返し関数終了!
「sti=CheckImageBYTE (pRY);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-20);}」は、ステータス
が正常で無ければ「sti-20」と【2番目】画像情報不具合
を返し関数終了!
「sti=CheckImageBYTE (pBY);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-30);}」は、ステータス
が正常で無ければ「sti-30」と【3番目】画像情報不具合
を返し関数終了!
「sti=CheckImageBYTE (pr);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-40);}」は、ステータス
が正常で無ければ「sti-40」と【4番目】画像情報不具合
を返し関数終了!
「sti=CheckImageBYTE (pg);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-50);}」は、ステータス
が正常で無ければ「sti-50」と【5番目】画像情報不具合
を返し関数終了!
「sti=CheckImageBYTE (pb);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-60);}」は、ステータス
が正常で無ければ「sti-60」と【6番目】画像情報不具合
を返し関数終了!
「CheckColorImageSize(pY,pRY,pBY,h,v);」は、色差式
3色カラー画像情報の水平幅・垂直幅の有効(最小値)幅
を算出し、ローカル変数「h1,v1」に算出した値をセット!
「CheckColorImageSize(pr,pg,pb,h1,v1);」は、RGB
3原色カラー画像情報の水平幅・垂直幅の有効(最小値)幅
を算出し、ローカル変数「h,v」に算出した値をセット!
★注意★
検査関数「CheckColorImageSize()」の
仮引数「int &size_h,int &size_v」が「int &」とローカル
変数のポインタを検査関数に送って処理して居る事に留意
「h=(h<=h1)?h:h1;」は、水平幅の最小値(有効幅)算出
「v=(v<=v1)?v:v1;」は、垂直幅の最小値(有効幅)算出
「pYy=(BYTE )pY->adr;pRYy=(char)pRY->adr;
pBYy=(char)pBY->adr;」は、元画像の色差式(Y・
R-Y・B-Y)3画像に対して実画像メモリポインタを
垂直方向処理実ポインタとしてセットした物です!
「pry=(BYTE *)pr->adr;pgy=(BYTE *)pg->adr;
pby=(BYTE *)pb->adr;」は、結果画像のRGB3原色画像に
対して実画像メモリポインタを垂直方向処理実ポインタとし
てセットした物です!
「while(--v>=0){・・ループ本体・・}」は、
ループ条件「--v>=0」で垂直幅の数分「ループ本体」を
ループ(繰り返す)処理です
★備考★「while(--v>=0」の様に「--v>=0」と
デクリメント演算子で変数値が変化しても影響が無い応用
には、経験上最適なCPU機械コードが生成出来るので、
この画像処理ライブラリは、この記法を多用して居ます!
学校の教科書的には余り教えて無い(恐らく変数の値が変
わる事を説明する必要が有るので説明がヤヤコシク成る事を
嫌ったと推測)と思いますが、兎も角、高速に動かすには、
この記法がベストと考えて採用しています!
ループ本体「{ConvertDiffToRgbBase(pry,pgy,pby,
pYy,pRYy,pBYy,h);
pry+=pr->inc;pgy+=pg->inc;pby+=pb->inc;
pYy+=pY->inc;pRYy+=pRY->inc;pBYy+=pBY->inc;
}」、と水平方向の処理を担うサブルーチン関数「
ConvertDiffToRgbBase()」で1行水平方向を処理し、
「pYy+=pY->inc;pRYy+=pRY->inc;pBYy+=pBY->inc;
pry+=pr->inc;pgy+=pg->inc;pby+=pb->inc;」と
Y色差方式元画像とRGB結果画像との実操作ポインタを
次の行へ垂直方向に1行進めます!
「return(END_STI);」は、正常終了を返し関数終了!

(4-14-18-E)関数「ConvertDiffToRgb()」の【使用例】説明

☆備考☆
今回は、項目だけ示し、中身は後回し≪作者の私が、ライブ
ラリ関数を実行可能な環境が得られる≒十分に予算を得てか
ら使用可能なコンパイル&GOが出来るシステムとその解説
書・手引き書も購入し、例文とそれに依って作成した画像
ファイルサンプルが作成出来たら、作成し、ここに追加しま
す、その為に解説『投げ銭方式ライブラリのダウンロード』
での有料部分まで読んで私に「投げ銭」としての有料料金を
恵んで下さい!≫

★注意★
上記例文で注意して欲しいのは、LUTは、用意して無い事
です!関数「ConvertDiffToRgb()」の中でLUTも使用せず
演算式で変換を内部で行って居る事です!そして画像を
3枚(色差方式)から3枚(RGB形式)に変換している
例です!

本日(3月30)の講義はココまでとします!
流石に新しくカラー画像変換の話に変えたので受講者の
皆様が消化出来る為にココまでとします!十分に
Noteサーバーが動く分量なので続きは、この文章に
引き続き掲載しますので御贔屓をお願いします!

2024年3月31続講

(4-14-19)関数「int ConvertBmpToMono(
TypeArray* pbgr,TypeArray* pd,int rev=TRUE){・・・}」の説明

int             CopyClear::ConvertBmpToMono(
    TypeArray   *pbgr,                                      // S配列:青緑赤
    TypeArray   *pd,                                        // D配列
    int         rev                                         // 真(省略時)→上下反転、偽→そのまま
){
    BYTE*       pbgry;                                      // Y方向ポインタ:青緑赤
    BYTE*       pdy;                                        // Y方向ポインタ:結果
    int         h;                                          // 画像の水平サイズ
    int         v;                                          // 画像の垂直サイズ
    int         inc;                                        // 増加幅:青緑赤
    int         sti;                                        // エラーステータス

    sti = CheckImageByte( pbgr );                           // BMP配列検査
    if( sti != END_STI ){                                   // 引数違反なら
        return( sti - 10 );                                 // 左記を返す
    }                                                       // 
    sti = CheckImageByte( pd );                             // D配列検査
    if( sti != END_STI ){                                   // 引数違反なら
        return( sti - 20 );                                 // 左記を返す
    }                                                       // 
    h   = pbgr->h / 3;                                      // カラー単位水平幅
    h   = ( h       <= pd->h ) ? h       : pd->h;           // Dとの最小を
    v   = ( pbgr->v <= pd->v ) ? pbgr->v : pd->v;           // 水平/垂直それぞれ算出
    pdy = (BYTE*)pd->adr;                                   // 結果ptrセット
    if( rev ){                                              // 上下反転時
        inc   = - pbgr->inc;                                // 増加幅を減少方向セット:青緑赤
        pbgry = (BYTE*)pbgr->getPtrByte( 0, pbgr->maxY() ); // 先頭ポインタ算出:青緑赤
    }else{                                                  // そのままなら
        inc   = pbgr->inc;                                  // 増加幅セット:青緑赤
        pbgry = (BYTE*)pbgr->adr;                           // 先頭ポインタセット:青緑赤
    }                                                       // 
    while( --v >= 0 ){                                      // 垂直方向に繰り返し
        ConvertBmpToMonoBase( pbgry, pdy, h );              // 水平方向に処理
        pbgry += inc;                                       // それぞれのY座標方向ポインタ
        pdy   += pd->inc;                                   // Y方向に進行
    }                                                       // 
    return( END_STI );                                      // 正常終了
}

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

(4-14-19-A)関数「ConvertBmpToMono()」の【関数名】説明

「Convert」は、英単語「Convert」として変換するの意味で
す!

解説書

「Bmp」は、「bitmap」の省略形です!「bitmap」ビット
マップは、広義≪コンピュータグラフィックスにおける画像
の表現形式で、ピクセル(画素)を用いたもの≫と有ります
が、ココでは、狭義的「Windows」でグラフィック表示に
使用して居る都合の良い形式として「BGR(青緑赤)と
独特なカラー画素が順番に並んだ形式でカラー画像が表示さ
れる事を上記に示した解説書から学んでWindows上でアプリ
を開発した時に使用した画像メモリの形式です!」を意味!
※備考※
上記解説書に記載して有る方法でアプリを作成した物は、
「Windows95の解説書とヴィジュアルスタジオ6.0の入門
書ですが、【XP】で開発したアプリが前に持っていた台湾
エーサー製ノートPCの【Windows8】でアプリの動作は、
確認出来ました⇒但し、台湾製PCが壊れて修理時に新品と
交換との形でデータが失われた時に元のアプリも行方不明に
成りどうやって台湾製PCにインストールしたかも覚えて無
いと今は、何も使えない状態ですが、【Windows8】で動い
たので恐らく、最新の【Windows】でも動作するデータ構造
」と思います
★注意★私としては保証はできません!ナンセマイクロソフ
トの都合ですからと記載して置きます!※
「To」は、「○○から××」と「から」の意味です!
「Mono」は、モノクロ画像≪白黒濃淡画像≫を意味
詰り、この「Windows」表示用の「bitmap」画像から白黒
濃淡画像への変換を行う関数です!

(4-14-19-B)関数「int ConvertBmpToMono()」の【返値】説明

int             CopyClear::ConvertBmpToMono(
    TypeArray   *pbgr,                                      // S配列:青緑赤
    TypeArray   *pd,                                        // D配列
    int         rev                                         // 真(省略時)→上下反転、偽→そのまま
){

この関数内で明示的に検査しているのは、
仮引数「TypeArray* pbgr,TypeArray* pd,」が、
1バイト単位で更に正常な画像情報で無ければエラー
コードを返します!
最後まで実行時は、正常終了「END_STI」を返します!

(4-14-19-C)関数「ConvertBmpToMono()」の【仮引数】説明

int             CopyClear::ConvertBmpToMono(
    TypeArray   *pbgr,                                      // S配列:青緑赤
    TypeArray   *pd,                                        // D配列
    int         rev                                         // 真(省略時)→上下反転、偽→そのまま
){

「TypeArray* pbgr,」は、BGR(ビットマップ)元画像
情報
「TypeArray* pd」は、D(モノクロ濃淡)結果画像情報
「int rev」は、省略時(真「TRUE」)と私の画像処理
ライブラリが元々≪ADS社と言う今は消滅させられた画像
処理装置メーカーの技術者として開発したデータ構造で構成
した「解説書文章『画像メモリ概要』で説明した第四象限に
表示するハードウェアに合わせて作成されたデータ構造と
「Windows」表示用の構造との変換の為に上下逆さまにする
事が必要」との事で省略時=デフォルト時は上下逆さまにし
画像を組み合わせて表現する場合に不都合が無い為に
偽「FALSE」で上下逆さまにシナイ設定が出来る様にしてい
ます≫

(4-14-19-D)関数「ConvertBmpToMono()」の【アルゴリズム】説明

){
    BYTE*       pbgry;                                      // Y方向ポインタ:青緑赤
    BYTE*       pdy;                                        // Y方向ポインタ:結果
    int         h;                                          // 画像の水平サイズ
    int         v;                                          // 画像の垂直サイズ
    int         inc;                                        // 増加幅:青緑赤
    int         sti;                                        // エラーステータス

    sti = CheckImageByte( pbgr );                           // BMP配列検査
    if( sti != END_STI ){                                   // 引数違反なら
        return( sti - 10 );                                 // 左記を返す
    }                                                       // 
    sti = CheckImageByte( pd );                             // D配列検査
    if( sti != END_STI ){                                   // 引数違反なら
        return( sti - 20 );                                 // 左記を返す
    }                                                       // 
    h   = pbgr->h / 3;                                      // カラー単位水平幅
    h   = ( h       <= pd->h ) ? h       : pd->h;           // Dとの最小を
    v   = ( pbgr->v <= pd->v ) ? pbgr->v : pd->v;           // 水平/垂直それぞれ算出
    pdy = (BYTE*)pd->adr;                                   // 結果ptrセット
    if( rev ){                                              // 上下反転時
        inc   = - pbgr->inc;                                // 増加幅を減少方向セット:青緑赤
        pbgry = (BYTE*)pbgr->getPtrByte( 0, pbgr->maxY() ); // 先頭ポインタ算出:青緑赤
    }else{                                                  // そのままなら
        inc   = pbgr->inc;                                  // 増加幅セット:青緑赤
        pbgry = (BYTE*)pbgr->adr;                           // 先頭ポインタセット:青緑赤
    }                                                       // 
    while( --v >= 0 ){                                      // 垂直方向に繰り返し
        ConvertBmpToMonoBase( pbgry, pdy, h );              // 水平方向に処理
        pbgry += inc;                                       // それぞれのY座標方向ポインタ
        pdy   += pd->inc;                                   // Y方向に進行
    }                                                       // 
    return( END_STI );                                      // 正常終了
}

ローカル変数

){
    BYTE*       pbgry;                                      // Y方向ポインタ:青緑赤
    BYTE*       pdy;                                        // Y方向ポインタ:結果
    int         h;                                          // 画像の水平サイズ
    int         v;                                          // 画像の垂直サイズ
    int         inc;                                        // 増加幅:青緑赤
    int         sti;                                        // エラーステータス

「BYTE *pbgry;」は、BGR(ビットマップ)画像の実操作
ポインタです!
「BYTE *pby;」は、D(結果白黒濃淡)画像の実操作
ポインタです!
「int h;」は、有効(最小)水平幅
「int v;」は、有効(最小)垂直幅
「int inc;」は、BGR(ビットマップ)画像の増加幅
★注意★D画像の増加幅は用意して居ません!
「int sti;」は、ステータス情報

アルゴリズムコード

    sti = CheckImageByte( pbgr );                           // BMP配列検査
    if( sti != END_STI ){                                   // 引数違反なら
        return( sti - 10 );                                 // 左記を返す
    }                                                       // 
    sti = CheckImageByte( pd );                             // D配列検査
    if( sti != END_STI ){                                   // 引数違反なら
        return( sti - 20 );                                 // 左記を返す
    }                                                       // 
    h   = pbgr->h / 3;                                      // カラー単位水平幅
    h   = ( h       <= pd->h ) ? h       : pd->h;           // Dとの最小を
    v   = ( pbgr->v <= pd->v ) ? pbgr->v : pd->v;           // 水平/垂直それぞれ算出
    pdy = (BYTE*)pd->adr;                                   // 結果ptrセット
    if( rev ){                                              // 上下反転時
        inc   = - pbgr->inc;                                // 増加幅を減少方向セット:青緑赤
        pbgry = (BYTE*)pbgr->getPtrByte( 0, pbgr->maxY() ); // 先頭ポインタ算出:青緑赤
    }else{                                                  // そのままなら
        inc   = pbgr->inc;                                  // 増加幅セット:青緑赤
        pbgry = (BYTE*)pbgr->adr;                           // 先頭ポインタセット:青緑赤
    }                                                       // 
    while( --v >= 0 ){                                      // 垂直方向に繰り返し
        ConvertBmpToMonoBase( pbgry, pdy, h );              // 水平方向に処理
        pbgry += inc;                                       // それぞれのY座標方向ポインタ
        pdy   += pd->inc;                                   // Y方向に進行
    }                                                       // 
    return( END_STI );                                      // 正常終了
}

「sti=CheckImageBYTE (pbgr);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-10);}」は、ステータス
が正常で無ければ「sti-10」と【1番目】画像情報不具合
を返し関数終了!
「sti=CheckImageBYTE (pd);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-20);}」は、ステータス
が正常で無ければ「sti-20」と【2番目】画像情報不具合
を返し関数終了!
「h=pbgr->h/3;」は、水平幅の算出です!
仮引数「TypeArray* pbgr,」からの水平幅情報「pbgr->h」
を「h/3」と3で除算して居るのは、BGRと3画素を
1単位の画素としてバイト数から画素単位の水平幅を算出し
た事に留意して下さい!
「h=(h<=pd->h)?h:pd->h;」は、結果画像の水平幅との有効
幅(最小値)の算出用!
「v=(pbgr->v<=pd->v)?pbgr->v:pd->v;」は、BGR画像
との垂直幅の有効幅(最小値)の算出用!
★注意★垂直方向は除算シナイ事は理解してますね!
「pdy=(BYTE *)pd->adr;」は、D(結果)画像の実ポインタ
を取り出して変数「pdy」にセット!
「if(rev){・・条件成立中身・・}else{・・条件不成立中身
・・}」は、条件「rev」の真偽≪仮引数「int rev」≫で
縦(垂直)方向の上下の向きを逆転(省略時)するか如何か
を逆転(省略時=条件成立)時を
「inc=-pbgr->inc;」で増加幅を「-pbgr->inc」と「-」演算
で逆方向への増加する様にします!そして条件成立中身が
「pbgry=(BYTE *)pbgr->getPtrBYTE (0,pbgr->maxY());」で
BGR画像の最終行≪「0,」と水平方向【X座標】の値が
0で「pbgr->maxY()」と垂直方向【Y座標】最大値≫の実行
ポインタ算出!ところで条件不成立中身が
「inc=pbgr->inc;」で増加幅を「pbgr->inc」とソノママの
方向で増加する様にします!そして
「pbgry=(BYTE *)pbgr->adr;」で素直に画像先頭を実行ポイ
ンタとしてセット!
「while(--v>=0){・・ループ本体・・}」は、
ループ条件「--v>=0」で垂直幅の数分「ループ本体」を
ループ(繰り返す)処理です
★備考★「while(--v>=0」の様に「--v>=0」とデクリメント
演算子で変数値が変化しても影響が無い応用には、
経験上最適なCPU機械コードが生成出来るので、
この画像処理ライブラリは、この記法を多用して居ます!
学校の教科書的には余り教えて無い(恐らく変数の値が変わ
る事を説明する必要が有るので説明がヤヤコシク成る事を
嫌ったと推測)と思いますが、兎も角、高速に動かすには、
この記法がベストと考えて採用しています!
ループ本体「{ConvertBmpToMonoBase(pbgry,pdy,h);
pbgry+=inc;pdy+=pd->inc;}」、と水平方向の処理を担う
サブルーチン関数「ConvertBmpToMonoBase();」で
1行水平方向を処理し、「pbgry+=inc;pdy+=pd->inc;」と
BGR元画像と結果画像との実操作ポインタを次の行へ
垂直方向に1行進めます!
「return(END_STI);」は、正常終了を返し関数終了!
※補足※結果画像の実ポインタ「pdy」を増加させる増加幅
「pd->inc」とローカル変数にして無いのは、ローカル変数
にセットしてループ内で使うと確かに若干高速化しますが、
顕著に高速化出来るとは思え無いとの理由でコノ方式にして
います!理解して頂いていると思いますが、BGR元画像の
実ポインタ「pbgry」を増加させる増加幅「inc」とローカル
変数にしているのは、正逆方向の算出とかループ内ではヤヤ
コシク処理時間も無駄に掛かるのでローカル変数にしていま
す!

(4-14-19-E)関数「ConvertBmpToMono()」の【備考】

この関数は、BGR画像と言う「Windows」の表示用の為の
ビットマップ画像を扱いますので例文は、提示しません!
尚、「Windows」表示用関連の表示方法は、XPのビジュアルCで開発したアプリの紹介を行って居る資料を鋭意探索中ですので「Windows」表示が必要な読者様はお待ちください!

(4-14-20)関数「int ConvertBmpToSingle(
TypeArray* pbgr,TypeArray* pd,
int sel,int rev=TRUE){・・・}」の説明

int             CopyClear::ConvertBmpToSingle(
    TypeArray   *pbgr,                                      // S配列:青緑赤
    TypeArray   *pd,                                        // D配列:単独の赤,緑,青
    int         sel,                                        // 0:赤,1:緑,2:青
    int         rev                                         // 真(省略時)→上下反転、偽→そのまま
){
    BYTE*       pbgry;                                      // Y方向ポインタ:青緑赤
    BYTE*       pdy;                                        // Y方向ポインタ:結果
    int         h;                                          // 画像の水平サイズ
    int         v;                                          // 画像の垂直サイズ
    int         inc;                                        // 増加幅:青緑赤
    int         sti;                                        // エラーステータス

    sti = CheckImageByte( pbgr );                           // BMP配列検査
    if( sti != END_STI ){                                   // 引数違反なら
        return( sti - 10 );                                 // 左記を返す
    }                                                       // 
    sti = CheckImageByte( pd );                             // D配列検査
    if( sti != END_STI ){                                   // 引数違反なら
        return( sti - 20 );                                 // 左記を返す
    }                                                       // 
    h   = pbgr->h / 3;                                      // カラー単位水平幅
    h   = ( h       <= pd->h ) ? h       : pd->h;           // Dとの最小を
    v   = ( pbgr->v <= pd->v ) ? pbgr->v : pd->v;           // 水平/垂直それぞれ算出
    pdy = (BYTE*)pd->adr;                                   // 結果ptrセット
    if( rev ){                                              // 上下反転時
        inc   = - pbgr->inc;                                // 増加幅を減少方向セット:青緑赤
        pbgry = (BYTE*)pbgr->getPtrByte( 0, pbgr->maxY() ); // 先頭ポインタ算出:青緑赤
    }else{                                                  // そのままなら
        inc   = pbgr->inc;                                  // 増加幅セット:青緑赤
        pbgry = (BYTE*)pbgr->adr;                           // 先頭ポインタセット:青緑赤
    }                                                       // 
    while( --v >= 0 ){                                      // 垂直方向に繰り返し
        ConvertBmpToSingleBase( pbgry, pdy, sel, h );       // 水平方向に処理
        pbgry += inc;                                       // それぞれのY座標方向ポインタ
        pdy   += pd->inc;                                   // Y方向に進行
    }                                                       // 
    return( END_STI );                                      // 正常終了
}

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

(4-14-20-A)関数「ConvertBmpToSingle()」の【関数名】説明

「Convert」は、英単語「Convert」として変換するの意味で
す!
「Bmp」は、「bitmap」の省略形です!「bitmap」ビット
マップは、広義≪コンピュータグラフィックスにおける画像
の表現形式で、ピクセル(画素)を用いたもの≫と有ります
が、ココでは、狭義的「Windows」でグラフィック表示に
使用して居る都合の良い形式として「BGR(青緑赤)と
独特なカラー画素が順番に並んだ形式でカラー画像が表示さ
れる事の画像メモリの形式です!」を意味!
「To」は、「○○から××」と「から」の意味です!
「Single」は、英単語「single」ただ一つのを意味し、
ここでは、BGR画像の中からR(赤)・G(緑)・
B(青)とRGB3原色の内の一つに変換する関数です!

(4-14-20-B)関数「int ConvertBmpToSingle()」の【返値】説明

int             CopyClear::ConvertBmpToSingle(
    TypeArray   *pbgr,                                      // S配列:青緑赤
    TypeArray   *pd,                                        // D配列:単独の赤,緑,青
    int         sel,                                        // 0:赤,1:緑,2:青
    int         rev                                         // 真(省略時)→上下反転、偽→そのまま
){

この関数内で明示的に検査しているのは、
仮引数「TypeArray* pbgr,TypeArray* pd,」が、
1バイト単位で更に正常な画像情報で無ければエラー
コードを返します!
最後まで実行時は、正常終了「END_STI」を返します!

(4-14-20-C)関数「ConvertBmpToSingle()」の【仮引数】説明

int             CopyClear::ConvertBmpToSingle(
    TypeArray   *pbgr,                                      // S配列:青緑赤
    TypeArray   *pd,                                        // D配列:単独の赤,緑,青
    int         sel,                                        // 0:赤,1:緑,2:青
    int         rev                                         // 真(省略時)→上下反転、偽→そのまま
){

「TypeArray* pbgr,」は、BGR(ビットマップ)元画像
情報
「TypeArray* pd」は、D(モノクロ濃淡)結果画像情報
「int sel,」は、BGR画像の内の一色を選択≪0:赤、
1:緑、2:青≫する選択肢です!
「int rev」は、省略時(真「TRUE」)と私の画像処理
ライブラリが元々≪ADS社と言う今は消滅させられた画像
処理装置メーカーの技術者として開発したデータ構造で構成
した「解説書文章『画像メモリ概要』で説明した第四象限に
表示するハードウェアに合わせて作成されたデータ構造と
「Windows」表示用の構造との変換の為に上下逆さまにする
事が必要」との事で省略時=デフォルト時は上下逆さまにし
画像を組み合わせて表現する場合に不都合が無い為に
偽「FALSE」で上下逆さまにシナイ設定が出来る様にしてい
ます≫

(4-14-20-D)関数「ConvertBmpToSingle()」の【アルゴリズム】説明

){
    BYTE*       pbgry;                                      // Y方向ポインタ:青緑赤
    BYTE*       pdy;                                        // Y方向ポインタ:結果
    int         h;                                          // 画像の水平サイズ
    int         v;                                          // 画像の垂直サイズ
    int         inc;                                        // 増加幅:青緑赤
    int         sti;                                        // エラーステータス

    sti = CheckImageByte( pbgr );                           // BMP配列検査
    if( sti != END_STI ){                                   // 引数違反なら
        return( sti - 10 );                                 // 左記を返す
    }                                                       // 
    sti = CheckImageByte( pd );                             // D配列検査
    if( sti != END_STI ){                                   // 引数違反なら
        return( sti - 20 );                                 // 左記を返す
    }                                                       // 
    h   = pbgr->h / 3;                                      // カラー単位水平幅
    h   = ( h       <= pd->h ) ? h       : pd->h;           // Dとの最小を
    v   = ( pbgr->v <= pd->v ) ? pbgr->v : pd->v;           // 水平/垂直それぞれ算出
    pdy = (BYTE*)pd->adr;                                   // 結果ptrセット
    if( rev ){                                              // 上下反転時
        inc   = - pbgr->inc;                                // 増加幅を減少方向セット:青緑赤
        pbgry = (BYTE*)pbgr->getPtrByte( 0, pbgr->maxY() ); // 先頭ポインタ算出:青緑赤
    }else{                                                  // そのままなら
        inc   = pbgr->inc;                                  // 増加幅セット:青緑赤
        pbgry = (BYTE*)pbgr->adr;                           // 先頭ポインタセット:青緑赤
    }                                                       // 
    while( --v >= 0 ){                                      // 垂直方向に繰り返し
        ConvertBmpToSingleBase( pbgry, pdy, sel, h );       // 水平方向に処理
        pbgry += inc;                                       // それぞれのY座標方向ポインタ
        pdy   += pd->inc;                                   // Y方向に進行
    }                                                       // 
    return( END_STI );                                      // 正常終了
}

ローカル変数

){
    BYTE*       pbgry;                                      // Y方向ポインタ:青緑赤
    BYTE*       pdy;                                        // Y方向ポインタ:結果
    int         h;                                          // 画像の水平サイズ
    int         v;                                          // 画像の垂直サイズ
    int         inc;                                        // 増加幅:青緑赤
    int         sti;                                        // エラーステータス

「BYTE *pbgry;」は、BGR(ビットマップ)画像の実操作
ポインタです!
「BYTE pby;」は、D(結果白黒濃淡)画像の実操作
ポインタです!
「int h;」は、有効(最小)水平幅
「int v;」は、有効(最小)垂直幅
「int inc;」は、BGR(ビットマップ)画像の増加幅
★注意★D画像の増加幅は用意して居ません!
「int sti;」は、ステータス情報

アルゴリズムコード

    sti = CheckImageByte( pbgr );                           // BMP配列検査
    if( sti != END_STI ){                                   // 引数違反なら
        return( sti - 10 );                                 // 左記を返す
    }                                                       // 
    sti = CheckImageByte( pd );                             // D配列検査
    if( sti != END_STI ){                                   // 引数違反なら
        return( sti - 20 );                                 // 左記を返す
    }                                                       // 
    h   = pbgr->h / 3;                                      // カラー単位水平幅
    h   = ( h       <= pd->h ) ? h       : pd->h;           // Dとの最小を
    v   = ( pbgr->v <= pd->v ) ? pbgr->v : pd->v;           // 水平/垂直それぞれ算出
    pdy = (BYTE*)pd->adr;                                   // 結果ptrセット
    if( rev ){                                              // 上下反転時
        inc   = - pbgr->inc;                                // 増加幅を減少方向セット:青緑赤
        pbgry = (BYTE*)pbgr->getPtrByte( 0, pbgr->maxY() ); // 先頭ポインタ算出:青緑赤
    }else{                                                  // そのままなら
        inc   = pbgr->inc;                                  // 増加幅セット:青緑赤
        pbgry = (BYTE*)pbgr->adr;                           // 先頭ポインタセット:青緑赤
    }                                                       // 
    while( --v >= 0 ){                                      // 垂直方向に繰り返し
        ConvertBmpToSingleBase( pbgry, pdy, sel, h );       // 水平方向に処理
        pbgry += inc;                                       // それぞれのY座標方向ポインタ
        pdy   += pd->inc;                                   // Y方向に進行
    }                                                       // 
    return( END_STI );                                      // 正常終了
}

「sti=CheckImageBYTE (pbgr);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-10);}」は、ステータス
が正常で無ければ「sti-10」と【1番目】画像情報不具合
を返し関数終了!
「sti=CheckImageBYTE (pd);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti-20);}」は、ステータス
が正常で無ければ「sti-20」と【2番目】画像情報不具合
を返し関数終了!
「h=pbgr->h/3;」は、水平幅の算出です!仮引数「
TypeArray pbgr,」からの水平幅情報「pbgr->h」を
「h/3」と3で除算して居るのは、BGRと3画素を1単位
の画素としてバイト数から画素単位の水平幅を算出した事に
留意して下さい!
「h=(h<=pd->h)?h:pd->h;」は、結果画像の水平幅との有効
幅(最小値)の算出用!
「v=(pbgr->v<=pd->v)?pbgr->v:pd->v;」は、BGR画像
との垂直幅の有効幅(最小値)の算出用!
★注意★垂直方向は除算シナイ事は理解してますね!
「pdy=(BYTE *)pd->adr;」は、D(結果)画像の実ポインタ
を取り出して変数「pdy」にセット!
「if(rev){・・条件成立中身・・}else{・・条件不成立中身
・・}」は、条件「rev」の真偽≪仮引数「int rev」≫で
縦(垂直)方向の上下の向きを逆転(省略時)するか如何か
を逆転(省略時=条件成立)時を
「inc=-pbgr->inc;」で増加幅を「-pbgr->inc」と「-」演算
で逆方向への増加する様にします!そして条件成立中身が
「pbgry=(BYTE *)pbgr->getPtrBYTE (0,pbgr->maxY());」で
BGR画像の最終行≪「0,」と水平方向【X座標】の値が
0で「pbgr->maxY()」と垂直方向【Y座標】最大値≫の実行
ポインタ算出!ところで条件不成立中身が
「inc=pbgr->inc;」で増加幅を「pbgr->inc」とソノママの
方向で増加する様にします!そして
「pbgry=(BYTE *)pbgr->adr;」で素直に画像先頭を実行ポイ
ンタとしてセット!
「while(--v>=0){・・ループ本体・・}」は、
ループ条件「--v>=0」で垂直幅の数分「ループ本体」を
ループ(繰り返す)処理です
★備考★「while(--v>=0」の様に「--v>=0」とデクリメント演算子で変数値が変化しても影響が無い応用には、経験上
最適なCPU機械コードが生成出来るので、
この画像処理ライブラリは、この記法を多用して居ます!
学校の教科書的には余り教えて無い(恐らく変数の値が変
わる事を説明する必要が有るので説明がヤヤコシク成る事を嫌ったと推測)と思いますが、兎も角、高速に動かす
には、この記法がベストと考えて採用しています!
ループ本体「{ConvertBmpToSingleBase(pbgry,pdy,sel,h);
pbgry+=inc;pdy+=pd->inc;}」、と水平方向の処理を担う
サブルーチン関数「ConvertBmpToSingleBase();」で
1行水平方向を処理し、「pbgry+=inc;pdy+=pd->inc;」と
BGR元画像と結果画像との実操作ポインタを次の行へ
垂直方向に1行進めます!
「return(END_STI);」は、正常終了を返し関数終了!
※補足※結果画像の実ポインタ「pdy」を増加させる増加幅
「pd->inc」とローカル変数にして無いのは、ローカル変数
にセットしてループ内で使うと確かに若干高速化しますが、
顕著に高速化出来るとは思え無いとの理由でコノ方式にして
います!理解して頂いていると思いますが、BGR元画像の
実ポインタ「pbgry」を増加させる増加幅「inc」とローカル
変数にしているのは、正逆方向の算出とかループ内ではヤヤ
コシク処理時間も無駄に掛かるのでローカル変数にしていま
す!

(4-14-20-E)関数「ConvertBmpToSingle()」の【備考】

この関数は、BGR画像と言う「Windows」の表示用の為の
ビットマップ画像を扱いますので例文は、提示しません!
尚、「Windows」表示用関連の表示方法は、XPのビジュアルCで開発したアプリの紹介を行って居る資料を鋭意探索中ですので「Windows」表示が必要な読者様はお待ちください!

(4-14-21)関数「int CalculateRgbToMono(int r,int g,int b){・・・}」の説明

int             CopyClear::CalculateRgbToMono(
    int         r,                                      // 値:赤
    int         g,                                      // 値:緑
    int         b                                       // 値:青
){
    int         d;                                      // 値:結果

    d = r * 30 + g * 59 + b * 11 + 50;                  // 結果×100の値算出
    if( d <= 25500 ){                                   // 範囲内なら
        return( d / 100 );                              // 結果を算出して書き込む
    }else{                                              // Over時は
        return( 255 );                                  // 255をセット
    }                                                   // 
}

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

(4-14-21-A)関数「CalculateRgbToMono()」の【関数名】説明

「Calculate」は、英単語「Calculate」として計算するの
意味です!
「Rgb」は、RGB3原色カラー方式のカラー画像を意味
「To」は、「○○から××」と「から」の意味です!
「Mono」は、モノクロ画像画素≪白黒濃淡画像≫を意味!
詰り、この画像処理ライブラリでRGB三原色の値から
モノクロ濃淡の値へを算出する関数です!

(4-14-21-B)関数「int CalculateRgbToMono()」の【返値】説明

int             CopyClear::CalculateRgbToMono(
    int         r,                                      // 値:赤
    int         g,                                      // 値:緑
    int         b                                       // 値:青
){

この関数は、数値計算関数です!詳細はアルゴリズムで説明
します!計算した数値を辺値として返します!

(4-14-21-C)関数「CalculateRgbToMono()」の【仮引数】説明

int             CopyClear::CalculateRgbToMono(
    int         r,                                      // 値:赤
    int         g,                                      // 値:緑
    int         b                                       // 値:青
){

「int r,」は、R(赤)成分の値です!
「int g,」は、G(緑)成分の値です!
「int b」は、B(青)成分の値です!

(4-14-21-D)関数「CalculateRgbToMono()」の【アルゴリズム】説明

){
    int         d;                                      // 値:結果

    d = r * 30 + g * 59 + b * 11 + 50;                  // 結果×100の値算出
    if( d <= 25500 ){                                   // 範囲内なら
        return( d / 100 );                              // 結果を算出して書き込む
    }else{                                              // Over時は
        return( 255 );                                  // 255をセット
    }                                                   // 
}

ローカル変数

){
    int         d;                                      // 値:結果

「int d;」は、結果の途中データです!

アルゴリズムコード

    d = r * 30 + g * 59 + b * 11 + 50;                  // 結果×100の値算出
    if( d <= 25500 ){                                   // 範囲内なら
        return( d / 100 );                              // 結果を算出して書き込む
    }else{                                              // Over時は
        return( 255 );                                  // 255をセット
    }                                                   // 
}

「d=r*30+g*59+b*11+50;」は、整数型で100倍した値としてRGB⇒モノクロ画素結果を算出!
「if(d<=25500){return(d/100);}else{return(255);}」は、
「if(d<=25500)」で条件「d<=25500」で100倍して居るの
で実際は実数値「255.0」以下の場合、条件成立で
「return(d/100);」と計算値を100で除算した値を関数の
値として辺値で返し終了します!
条件不成立「d>25500」詰り、実数値「255.0」を越え
た場合、「return(255);」と符号無し8ビット最大値を
関数の値として辺値で返し終了します!

(4-14-21-E)関数「CalculateRgbToMono()」の【備考】

★注意★
散々、最近のコンピューターシステムの高速化は、
「CPUと半導体メモリー間の転送時間の問題で最新の
CPU内部で演算する速度は無視出来る」との事を述べて
来ましたが、無視できないCPU内部での処理時間が掛かる
処理は、「整数⇔実数」の変換時の処理です!極最近の高速
CPUでもコノ「整数⇔実数」は出来るだけ避けた方が良い
ので基本整数型で「RGB⇒モノクロ」は行います!
※備考※古いCPUでは整数型演算しか出来ない物や、有っ
ても浮動小数点演算が遅い物も有りますので整数型で記載!
その為に所謂、下駄ばき「ココでは100を掛けた値として
小数点以下を算出し、結果が必要な時に100で割る」を
行って居る事に留意して下さい!

(4-14-22)関数「void CalculateRgbToDiff(int r,int g,int b,int &Y,int &RY,int &BY){・・・}」の説明

void            CopyClear::CalculateRgbToDiff(
    int         r,                                      // 値:赤
    int         g,                                      // 値:緑
    int         b,                                      // 値:青
    int&        Y,                                      // 結果:輝度
    int&        RY,                                     // 結果:R-Y
    int&        BY                                      // 結果:B-Y
){
    int         d;                                      // 値:結果

    d = r * 30 + g * 59 + b * 11 + 50;                  // 結果×100の値算出
    if( d <= 25500 ){                                   // 範囲内なら
        Y = d / 100;                                    // 結果を算出して書き込む
    }else{                                              // Over時は
        Y = 255;                                        // 255をセット
    }                                                   // 
    d = r * 70 - g * 59 - b * 11 + 50;                  // R-Y結果×100の値算出
    if( d < -12800 ){                                   // -128×100未満なら
        RY = -128;                                      // -128をセット
    }else if( d <= 12700 ){                             // 範囲内なら
        RY = d / 100;                                   // 結果を算出して書き込む
    }else{                                              // Over時は
        RY = 127;                                       // 127をセット
    }                                                   // 
    d = -r * 30 - g * 59 + b * 89 + 50;                 // B-Y結果×100の値算出
    if( d < -12800 ){                                   // -128×100未満なら
        BY = -128;                                      // -128をセット
    }else if( d <= 12700 ){                             // 範囲内なら
        BY = d / 100;                                   // 結果を算出して書き込む
    }else{                                              // Over時は
        BY = 127;                                       // 127をセット
    }                                                   // 
}

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

(4-14-22-A)関数「CalculateRgbToDiff()」の【関数名】説明

「Calculate」は、英単語「Calculate」として計算するの
意味です!
「Rgb」は、RGB3原色カラー方式のカラー画像を意味
「To」は、「○○から××」と「から」の意味です!
「Diff」は、英単語「difference」=「違い」の省略形で
ここでは、「差分」の意味から、色差方式のカラー表現方式
詰り、RGB3原色カラー方式から色差方式への変換を意味
します!

(4-14-22-B)関数「void CalculateRgbToDiff()」の【返値】説明

void            CopyClear::CalculateRgbToDiff(
    int         r,                                      // 値:赤
    int         g,                                      // 値:緑
    int         b,                                      // 値:青
    int&        Y,                                      // 結果:輝度
    int&        RY,                                     // 結果:R-Y
    int&        BY                                      // 結果:B-Y
){

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(4-14-22-C)関数「CalculateRgbToDiff()」の【仮引数】説明

void            CopyClear::CalculateRgbToDiff(
    int         r,                                      // 値:赤
    int         g,                                      // 値:緑
    int         b,                                      // 値:青
    int&        Y,                                      // 結果:輝度
    int&        RY,                                     // 結果:R-Y
    int&        BY                                      // 結果:B-Y
){

「int r,」は、R(赤)成分の値です!
「int g,」は、G(緑)成分の値です!
「int b」は、B(青)成分の値です!
「int &Y,」は、Y(色差「Y」モノクロ濃淡)結果
「int &RY,」は、RY(色差「R-Y」)結果
「int &BY」は、BY(色差「B-Y」)結果
★注意★
仮引数「int &Y,int &RY,int &BY」が「int &」とローカル
変数のポインタを呼び出した関数に送って処理して居る事に
留意

(4-14-22-D)関数「CalculateRgbToDiff()」の【アルゴリズム】説明

){
    int         d;                                      // 値:結果

    d = r * 30 + g * 59 + b * 11 + 50;                  // 結果×100の値算出
    if( d <= 25500 ){                                   // 範囲内なら
        Y = d / 100;                                    // 結果を算出して書き込む
    }else{                                              // Over時は
        Y = 255;                                        // 255をセット
    }                                                   // 
    d = r * 70 - g * 59 - b * 11 + 50;                  // R-Y結果×100の値算出
    if( d < -12800 ){                                   // -128×100未満なら
        RY = -128;                                      // -128をセット
    }else if( d <= 12700 ){                             // 範囲内なら
        RY = d / 100;                                   // 結果を算出して書き込む
    }else{                                              // Over時は
        RY = 127;                                       // 127をセット
    }                                                   // 
    d = -r * 30 - g * 59 + b * 89 + 50;                 // B-Y結果×100の値算出
    if( d < -12800 ){                                   // -128×100未満なら
        BY = -128;                                      // -128をセット
    }else if( d <= 12700 ){                             // 範囲内なら
        BY = d / 100;                                   // 結果を算出して書き込む
    }else{                                              // Over時は
        BY = 127;                                       // 127をセット
    }                                                   // 
}

ローカル変数

){
    int         d;                                      // 値:結果

「int d;」は、結果の途中データです!

アルゴリズムコード

    d = r * 30 + g * 59 + b * 11 + 50;                  // 結果×100の値算出
    if( d <= 25500 ){                                   // 範囲内なら
        Y = d / 100;                                    // 結果を算出して書き込む
    }else{                                              // Over時は
        Y = 255;                                        // 255をセット
    }                                                   // 
    d = r * 70 - g * 59 - b * 11 + 50;                  // R-Y結果×100の値算出
    if( d < -12800 ){                                   // -128×100未満なら
        RY = -128;                                      // -128をセット
    }else if( d <= 12700 ){                             // 範囲内なら
        RY = d / 100;                                   // 結果を算出して書き込む
    }else{                                              // Over時は
        RY = 127;                                       // 127をセット
    }                                                   // 
    d = -r * 30 - g * 59 + b * 89 + 50;                 // B-Y結果×100の値算出
    if( d < -12800 ){                                   // -128×100未満なら
        BY = -128;                                      // -128をセット
    }else if( d <= 12700 ){                             // 範囲内なら
        BY = d / 100;                                   // 結果を算出して書き込む
    }else{                                              // Over時は
        BY = 127;                                       // 127をセット
    }                                                   // 
}

「d=r*30+g*59+b*11+50;」は、整数型で100倍した値と
してRGB⇒モノクロ画素結果を算出!
「if(d<=25500){Y=d/100;}else{Y=255;}」は、
「if(d<=25500)」で条件「d<=25500」で100倍して居るの
で実際は実数値「255.0」以下の場合、条件成立で
「Y=d/100;」と計算値を100で除算した値を実引数の
値として返します!
条件不成立「d>25500」詰り、実数値「255.0」を越え
た場合、「Y=255;」と符号無し8ビット最大値を
関数の値として辺値で返します!
「d=r70-g59-b11+50;」は、整数型で100倍した値とし
てRGB⇒色差「R-Y」画素結果を算出!
「if(d<-12800){RY=-128;}else if(d<=12700){RY=d/100;
}else{RY=127;}」は、
「if(d<-12800)」で条件「d<-12800」で100倍して居るの
で実際は実数値「128.0」以下の場合、条件成立で
「RY=d/100;」と計算値を100で除算した値を実引数の
値として返します!
条件不成立「d>=-12800」詰り、実数値「128.0」以下
のた場合、「RY=-128;」と符号有り8ビット負最大値を
関数の値として辺値で返します!
「else if(d<=12700){RY=d/100;}else{RY=127;}」は、
「if(d<=12700)」で条件「d<=12700」で100倍して
居るので実際は実数値「127.0」以下の場合、条件成立
で「RY=d/100;」と計算値を100で除算した値を実引数の
値として返します!
条件不成立「d>12800」詰り、実数値「127.0」を越え
たた場合、「RY=127;」と符号有り8ビット正最大値を
関数の値として辺値で返します!
「if(d<-12800){RY=-128;}else if(d<=12700){RY=d/100;
}else{RY=127;}」は、
「if(d<-12800)」で条件「d<-12800」で100倍して居るの
で実際は実数値「128.0」以下の場合、条件成立で
「RY=d/100;」と計算値を100で除算した値を実引数の
値として返します!
条件不成立「d>=-12800」詰り、実数値「128.0」以下
のた場合、「RY=-128;」と符号有り8ビット負最大値を
関数の値として辺値で返します!
「else if(d<=12700){RY=d/100;}else{RY=127;}」は、
「if(d<=12700)」で条件「d<=12700」で100倍して
居るので実際は実数値「127.0」以下の場合、条件成立
で「RY=d/100;」と計算値を100で除算した値を実引数の
値として返します!
条件不成立「d>12800」詰り、実数値「127.0」を越え
たた場合、「RY=127;」と符号有り8ビット正最大値を
関数の値として辺値で返します!
「d=-r30-g59+b*89+50;」は、整数型で100倍した値とし
てRGB⇒色差「B-Y」画素結果を算出!
「if(d<-12800){BY=-128;}else if(d<=12700){BY=d/100;
}else{BY=127;}」は、
「if(d<-12800)」で条件「d<-12800」で100倍して居るの
で実際は実数値「128.0」以下の場合、条件成立で
「BY=d/100;」と計算値を100で除算した値を実引数の
値として返します!
条件不成立「d>=-12800」詰り、実数値「128.0」以下
のた場合、「BY=-128;」と符号有り8ビット負最大値を
関数の値として辺値で返します!
「else if(d<=12700){BY=d/100;}else{BY=127;}」は、
「if(d<=12700)」で条件「d<=12700」で100倍して
居るので実際は実数値「127.0」以下の場合、条件成立
で「BY=d/100;」と計算値を100で除算した値を実引数の
値として返します!
条件不成立「d>12800」詰り、実数値「127.0」を越え
たた場合、「BY=127;」と符号有り8ビット正最大値を
関数の値として辺値で返します!
「if(d<-12800){BY=-128;}else if(d<=12700){BY=d/100;
}else{BY=127;}」は、
「if(d<-12800)」で条件「d<-12800」で100倍して居るの
で実際は実数値「128.0」以下の場合、条件成立で
「BY=d/100;」と計算値を100で除算した値を実引数の
値として返します!
条件不成立「d>=-12800」詰り、実数値「128.0」以下
のた場合、「BY=-128;」と符号有り8ビット負最大値を
関数の値として辺値で返します!
「else if(d<=12700){BY=d/100;}else{BY=127;}」は、
「if(d<=12700)」で条件「d<=12700」で100倍して
居るので実際は実数値「127.0」以下の場合、条件成立
で「BY=d/100;」と計算値を100で除算した値を実引数の
値として返します!
条件不成立「d>12800」詰り、実数値「127.0」を越え
たた場合、「BY=127;」と符号有り8ビット正最大値を
関数の値として辺値で返します!

(4-14-22-E)関数「CalculateRgbToDiff()」の【備考】

★注意★
散々、最近のコンピューターシステムの高速化は、
「CPUと半導体メモリー間の転送時間の問題で最新の
CPU内部で演算する速度は無視出来る」との事を述べて
来ましたが、無視できないCPU内部での処理時間が掛かる
処理は、「整数⇔実数」の変換時の処理です!極最近の高速
CPUでもコノ「整数⇔実数」は出来るだけ避けた方が良い
ので基本整数型で「RGB⇒モノクロ」は行います!
※備考※古いCPUでは整数型演算しか出来ない物や、有っ
ても浮動小数点演算が遅い物も有りますので整数型で記載!
その為に所謂、下駄ばき「ココでは100を掛けた値として
小数点以下を算出し、結果が必要な時に100で割る」を
行って居る事に留意して下さい!

(4-14-23)関数「void CalculateDiffToRgb(int Y,int RY,int BY,int &r,int &g,int &b){・・・}」の説明

void            CopyClear::CalculateDiffToRgb(
    int         Y,                                      // 値:輝度
    int         RY,                                     // 値:R-Y
    int         BY,                                     // 値:B-Y
    int&        r,                                      // 結果:赤
    int&        g,                                      // 結果:緑
    int&        b                                       // 結果:青
){
    int         d;                                      // 値:結果

    d = Y + RY;                                         // 赤結果の値算出
    if( d < 0 ){                                        // 0未満なら
        r = 0;                                          // 0をセット
    }else if( d <= 255 ){                               // 範囲内なら
        r = d;                                          // 結果を書き込む
    }else{                                              // Over時は
        r = 255;                                        // 255をセット
    }                                                   // 
    d = Y + BY;                                         // 青結果の値算出
    if( d < 0 ){                                        // 0未満なら
        b = 0;                                          // 0をセット
    }else if( d <= 255 ){                               // 範囲内なら
        b = d;                                          // 結果を書き込む
    }else{                                              // Over時は
        b = 255;                                        // 255をセット
    }                                                   // 
    d = (int)( (double)Y                                // 緑結果算出
              -(double)RY * 0.3  / 0.59                 // 
              -(double)BY * 0.11 / 0.59                 // 
              + 0.5 );                                  // 
    if( d < 0 ){                                        // 0未満なら
        g = 0;                                          // 0をセット
    }else if( d <= 255 ){                               // 範囲内なら
        g = d;                                          // 結果を書き込む
    }else{                                              // Over時は
        g = 255;                                        // 255をセット
    }                                                   // 
}

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

(4-14-23-A)関数「CalculateDiffToRgb()」の【関数名】説明

「Calculate」は、英単語「Calculate」として計算するの
意味です!
「Diff」は、英単語「difference」=「違い」の省略形で
ここでは、「差分」の意味から、色差方式のカラー表現方式
「To」は、「○○から××」と「から」の意味です!
「Rgb」は、RGB3原色カラー方式のカラー画像を意味
詰り、色差方式からRGB3原色カラー方式への変換を意味
します!

(4-14-23-B)関数「void CalculateDiffToRgb()」の【返値】説明

void            CopyClear::CalculateDiffToRgb(
    int         Y,                                      // 値:輝度
    int         RY,                                     // 値:R-Y
    int         BY,                                     // 値:B-Y
    int&        r,                                      // 結果:赤
    int&        g,                                      // 結果:緑
    int&        b                                       // 結果:青
){

返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!

(4-14-23-C)関数「CalculateDiffToRgb()」の【仮引数】説明

void            CopyClear::CalculateDiffToRgb(
    int         Y,                                      // 値:輝度
    int         RY,                                     // 値:R-Y
    int         BY,                                     // 値:B-Y
    int&        r,                                      // 結果:赤
    int&        g,                                      // 結果:緑
    int&        b                                       // 結果:青
){

「int Y,」は、Y(色差「Y」モノクロ濃淡)結果
「int RY,」は、RY(色差「R-Y」)結果
「int BY」は、BY(色差「B-Y」)結果
「int &r,」は、R(赤)成分の値です!
「int &g,」は、G(緑)成分の値です!
「int &b」は、B(青)成分の値です!
★注意★
仮引数「int &r,int &g,int &b」が「int &」とローカル
変数のポインタを呼び出した関数に送って処理して居る事に
留意

(4-14-23-D)関数「CalculateDiffToRgb()」の【アルゴリズム】説明

){
    int         d;                                      // 値:結果

    d = Y + RY;                                         // 赤結果の値算出
    if( d < 0 ){                                        // 0未満なら
        r = 0;                                          // 0をセット
    }else if( d <= 255 ){                               // 範囲内なら
        r = d;                                          // 結果を書き込む
    }else{                                              // Over時は
        r = 255;                                        // 255をセット
    }                                                   // 
    d = Y + BY;                                         // 青結果の値算出
    if( d < 0 ){                                        // 0未満なら
        b = 0;                                          // 0をセット
    }else if( d <= 255 ){                               // 範囲内なら
        b = d;                                          // 結果を書き込む
    }else{                                              // Over時は
        b = 255;                                        // 255をセット
    }                                                   // 
    d = (int)( (double)Y                                // 緑結果算出
              -(double)RY * 0.3  / 0.59                 // 
              -(double)BY * 0.11 / 0.59                 // 
              + 0.5 );                                  // 
    if( d < 0 ){                                        // 0未満なら
        g = 0;                                          // 0をセット
    }else if( d <= 255 ){                               // 範囲内なら
        g = d;                                          // 結果を書き込む
    }else{                                              // Over時は
        g = 255;                                        // 255をセット
    }                                                   // 
}

ローカル変数

){
    int         d;                                      // 値:結果

「int d;」は、結果の途中データです!

アルゴリズムコード

    d = Y + RY;                                         // 赤結果の値算出
    if( d < 0 ){                                        // 0未満なら
        r = 0;                                          // 0をセット
    }else if( d <= 255 ){                               // 範囲内なら
        r = d;                                          // 結果を書き込む
    }else{                                              // Over時は
        r = 255;                                        // 255をセット
    }                                                   // 
    d = Y + BY;                                         // 青結果の値算出
    if( d < 0 ){                                        // 0未満なら
        b = 0;                                          // 0をセット
    }else if( d <= 255 ){                               // 範囲内なら
        b = d;                                          // 結果を書き込む
    }else{                                              // Over時は
        b = 255;                                        // 255をセット
    }                                                   // 
    d = (int)( (double)Y                                // 緑結果算出
              -(double)RY * 0.3  / 0.59                 // 
              -(double)BY * 0.11 / 0.59                 // 
              + 0.5 );                                  // 
    if( d < 0 ){                                        // 0未満なら
        g = 0;                                          // 0をセット
    }else if( d <= 255 ){                               // 範囲内なら
        g = d;                                          // 結果を書き込む
    }else{                                              // Over時は
        g = 255;                                        // 255をセット
    }                                                   // 
}

「d=Y+RY;」は、素朴に輝度「Y」+色差「RY⇒R-Y」で
意味的に「Y+RY」で赤色成分の数値を算出!
「if(d<0){r=0;}else if(d<=255){r=d;}else{r=255;}」は
算出した値が0未満なら0、0以上255以下なら、
ソノママ255を越える場合255で仮引数「int &r,」
で実引数に値を返す!
「d=Y+BY;」は、素朴に輝度「Y」+色差「BY⇒B-Y」で
意味的に「Y+BY」で青色成分の数値を算出!
「if(d<0){b=0;}else if(d<=255){b=d;}else{b=255;}」は
算出した値が0未満なら0、0以上255以下なら、
ソノママ255を越える場合255で仮引数「int &b,」
で実引数に値を返す!
「d=(int )((double)Y-(double)RY*0.3/0.59
-(double)BY*0.11/0.59+0.5);」は、緑成分の算出式
です!
「if(d<0){g=0;}else if(d<=255){g=d;}else{g=255;}」は
算出した値が0未満なら0、0以上255以下なら、
ソノママ255を越える場合255で仮引数「int &g」
で実引数に値を返す!

(4-14-23-E)関数「CalculateDiffToRgb()」の【備考】

★注意★散々、【高速化には「整数⇔実数」変換は出来る
だけ避けた方が良い】と記載して来たが、ココで緑成分の
算出に多用している「言い訳」として下駄を履かせると、
後でヤヤコシ過ぎて理解出来無く成る(作者の自分自身が)
と考えた筈と推測します!更に後に、モット高速化の為に
下駄ばき方式で作成途中だったが、余り高速化メリット≪
XPでアプリ≪画面上で操作する人手作業≫を作成中に
PC速度が十分だと感じた為≫が無いので後回しにしたと思
える!

(4-14-24)関数「int EraseMinusImage(TypeArray* img){・・・}」の説明

int             CopyClear::EraseMinusImage(
    TypeArray   *img                                        // 画像
){
    char*       p;                                          // 画像ポインタ
    int         h;                                          // 水平幅
    int         v;                                          // 垂直幅
    int         inc;                                        // 増加幅
    int         y;                                          // Y座標
    int         sti;                                        // エラーステータス

    sti = CheckImageByte( img );                            // 元画像検査
    if( sti != END_STI ){                                   // 不正が有れば
        return( sti );                                      // エラーステータスを返す
    }                                                       // 
    p   = (char*)img->adr;                                  // 画像ポインタ取り出し
    h   = img->h;                                           // 水平幅取り出し
    v   = img->v;                                           // 垂直幅取り出し
    inc = img->inc;                                         // 増加幅取り出し
    for( y = 0; y < v; y++, p += inc ){                     // Y座標方向繰り返し
        EraseMinusImageBase( p, h );                        // 水平方向の処理
    }                                                       // 
    return( END_STI );                                      // 正常終了
}

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

(4-14-24-A)関数「EraseMinusImage()」の【関数名】説明

「Erase」は、英単語「Erase」と「消すとか削除する消去」
の意味です!
「Minus」は、マイナス⇒ここでは、数値がマイナス(負の
値)を意味し、
「Image」は、勿論、画像で「MinusImage」で画像画素が
負の値を意味し、ココでは、マイナス(負の値)画素を
消去≪画素の値を0にする≫を行います!

(4-14-24-B)関数「int EraseMinusImage()」の【返値】説明

int             CopyClear::EraseMinusImage(
    TypeArray   *img                                        // 画像
){

この関数内で明示的に検査しているのは、
仮引数「TypeArray* img」が、1バイト単位で更に正常な
画像情報で無ければエラーコードを返します!
最後まで実行時は、正常終了「END_STI」を返します!

(4-14-24-C)関数「EraseMinusImage()」の【仮引数】説明

int             CopyClear::EraseMinusImage(
    TypeArray   *img                                        // 画像
){

「TypeArray* img」は、消去画素処理対象画像情報です!

(4-14-24-D)関数「EraseMinusImage()」の【アルゴリズム】説明

){
    char*       p;                                          // 画像ポインタ
    int         h;                                          // 水平幅
    int         v;                                          // 垂直幅
    int         inc;                                        // 増加幅
    int         y;                                          // Y座標
    int         sti;                                        // エラーステータス

    sti = CheckImageByte( img );                            // 元画像検査
    if( sti != END_STI ){                                   // 不正が有れば
        return( sti );                                      // エラーステータスを返す
    }                                                       // 
    p   = (char*)img->adr;                                  // 画像ポインタ取り出し
    h   = img->h;                                           // 水平幅取り出し
    v   = img->v;                                           // 垂直幅取り出し
    inc = img->inc;                                         // 増加幅取り出し
    for( y = 0; y < v; y++, p += inc ){                     // Y座標方向繰り返し
        EraseMinusImageBase( p, h );                        // 水平方向の処理
    }                                                       // 
    return( END_STI );                                      // 正常終了
}

ローカル変数

){
    char*       p;                                          // 画像ポインタ
    int         h;                                          // 水平幅
    int         v;                                          // 垂直幅
    int         inc;                                        // 増加幅
    int         y;                                          // Y座標
    int         sti;                                        // エラーステータス

「charp;」は、操作用実画像ポインタ
「int h;」は、水平幅
「int v;」は、垂直幅
「int inc;」は、増加幅
「int y;」は、Y座標
「int sti;」は、ステータス情報

アルゴリズムコード

    sti = CheckImageByte( img );                            // 元画像検査
    if( sti != END_STI ){                                   // 不正が有れば
        return( sti );                                      // エラーステータスを返す
    }                                                       // 
    p   = (char*)img->adr;                                  // 画像ポインタ取り出し
    h   = img->h;                                           // 水平幅取り出し
    v   = img->v;                                           // 垂直幅取り出し
    inc = img->inc;                                         // 増加幅取り出し
    for( y = 0; y < v; y++, p += inc ){                     // Y座標方向繰り返し
        EraseMinusImageBase( p, h );                        // 水平方向の処理
    }                                                       // 
    return( END_STI );                                      // 正常終了
}

「sti=CheckImageBYTE (pd);」は、1バイト単位画像情報
検査関数で検査しステータスを変数「sti」格納
「if(sti!=END_STI){return(sti);}」は、エラー発生なら
「return(sti);」でエラーコードを辺値とし返し関数終了!
「p=(char)img->adr;」は、実操作ポインタセット!
「h=img->h;」は、水平幅をローカル変数にセット
「v=img->v;」は、垂直幅をローカル変数にセット
「inc=img->inc;」は、増加幅をローカル変数にセット
「for(y=0;y<v;y++,p+=inc){EraseMinusImageBase(p,h);}」
は、教科書的な
forループ構文「for(y=0;y<v;y++,p+=inc){・・・}」で
サブルーチン関数「EraseMinusImageBase(p,h);」をループ
させます!
「p+=inc」は、垂直方向(Y座標方向)へのポインタ進行
です!そしてサブルーチン関数「EraseMinusImageBase()」
は、水平方向の処理です!
「return(END_STI);」は、正常終了です!

(4-14-24-E)関数「EraseMinusImage()」の【備考】

★注意★散々、別の関数のアルゴリズム説明で
【「while(--v>=0){・・ループ本体・・}」は、
ループ条件「--v>=0」で垂直幅の数分「ループ本体」を
ループ(繰り返す)処理です★備考★「while(--v>=0」の
様に「--v>=0」とデクリメント演算子で変数値が変化して
も影響が無い応用には、経験上最適なCPU機械コードが
生成出来るので、この画像処理ライブラリは、この記法を
多用して居ます!学校の教科書的には余り教えて無い(恐ら
く変数の値が変わる事を説明する必要が有るので説明がヤヤ
コシク成る事を嫌ったと推測)】と高速化の為に【
「while(--v>=0)】とwhileループ使用していますが、
ここでforループを使用して居るのは、勿論、分かり易い
からです!この関数自体は使用頻度が少ないと考えて高速化
より分かり易い方を優先しました!

★備考★
解説『解説クラスTypeArray』でも記載したが、
私が、テキストエディタ編集作業ミス≪文字列置き換え作業
の範囲設定し忘れで余計な別の文字列まで置き換え等≫とか
noteエディタの変な特性でコピペした文章の半角「*」
が消されたり、空白「 」が消される事が多々あります!
注意して手作業で修正している筈ですが、必ず、code
機能で表示して居る物を正しいとして確認して下さい

本日(31月31)の講義はココまでとします!
流石に新しくと言うか「Windows」表示の話を扱ったので
受講者の皆様が消化出来る為にココまでとします!
流石に新しくと言うか「色成分」算出数値式の話を扱ったの
で受講者の皆様が消化出来る為にココまでとします!
十分にNoteサーバーが動く分量なので続きは、
この文章に引き続き掲載しますので御贔屓をお願いします!
続きは、「解説クラスCopyClear(13)」
成ります!引き続き御贔屓して受講して下さい!

文末

この記事が気に入ったらサポートをしてみませんか?