解説クラスCopyClear(13)
解説クラスCopyClear(13)
2024年4月28続講(初稿)
この講義は解説『解説クラスCopyClear(12)』
の続きです!
(4-14-25)関数「int Make0Lut(BYTE lut[],int m,int n,int d){・・・}」の説明
int CopyClear::Make0Lut(
BYTE lut[], // 作成するLUT
int m, // Pattern書込始点IX
int n, // Pattern書込終点IX
int d // パターン書込データ
){
BYTE *p; // 始点ポインタ
BYTE *pend; // 終点ポインタ
int cmp_255; // 比較用255の定数値
if( m < 0 || m > n || d < 0 || d >= 256 ){ // 終始点とデータが範囲
return( STI_FLG ); // 外なら、引数検査違反
} //
cmp_255 = 255; // 定数255をセット
p = &lut[ m ]; // 始点作成
pend = &lut[ n ]; // 終点作成
if( d + ( n - m ) <= cmp_255 ){ // 最終Dataが255以下なら
while( p <= pend ){ // 終始点の範囲で
*p++ = d; // 増加パターンを
d++; // 書き込む
} //
}else{ // 最終Data255超えるなら
while( d < cmp_255 ){ // Data255までの範囲で
*p++ = d; // 増加パターンを
d++; // 書き込む
} //
while( p <= pend ){ // 残りの範囲を
*p++ = d; // 255で書き込む
} //
} //
return( END_STI ); // 正常終了
}
☆備考☆この関数はファイル「CopyClear040.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
(4-14-25-A)関数「Make0Lut()」の【関数名】説明
「Make」は、作成するで
「Lut」は、勿論、LUT変換用のLUTです!
ココでは、「Make○○Lut」と枝番号○○で機能分けした内の
一つのLUTパターン作成の意味です!
ここの○○=0は、インクリメントパターン作成です!
このイメージです!
(4-14-25-B)関数「int Make0Lut()」の【返値】説明
int CopyClear::Make0Lut(
BYTE lut[], // 作成するLUT
int m, // Pattern書込始点IX
int n, // Pattern書込終点IX
int d // パターン書込データ
){
この関数内で明示的に検査しているのは、
仮引数「int m,int n,int d」が、所定の値に成って
居るか如何かを判定し仕様外ならエラー「STI_FLG」を
返します!
最後まで実行時は、正常終了「END_STI」を返します!
(4-14-25-C)関数「Make0Lut()」の【仮引数】説明
int CopyClear::Make0Lut(
BYTE lut[], // 作成するLUT
int m, // Pattern書込始点IX
int n, // Pattern書込終点IX
int d // パターン書込データ
){
「BYTE lut[],」はLUTを一次元配列として使用!
「int m,」は、「lut[]」内の始点
「int n,」は、「lut[]」内の終点
「int d」は、書き込むデータ初期値
(4-14-25-D)関数「Make0Lut()」の【アルゴリズム】説明
){
BYTE *p; // 始点ポインタ
BYTE *pend; // 終点ポインタ
int cmp_255; // 比較用255の定数値
if( m < 0 || m > n || d < 0 || d >= 256 ){ // 終始点とデータが範囲
return( STI_FLG ); // 外なら、引数検査違反
} //
cmp_255 = 255; // 定数255をセット
p = &lut[ m ]; // 始点作成
pend = &lut[ n ]; // 終点作成
if( d + ( n - m ) <= cmp_255 ){ // 最終Dataが255以下なら
while( p <= pend ){ // 終始点の範囲で
*p++ = d; // 増加パターンを
d++; // 書き込む
} //
}else{ // 最終Data255超えるなら
while( d < cmp_255 ){ // Data255までの範囲で
*p++ = d; // 増加パターンを
d++; // 書き込む
} //
while( p <= pend ){ // 残りの範囲を
*p++ = d; // 255で書き込む
} //
} //
return( END_STI ); // 正常終了
}
ローカル変数
){
BYTE *p; // 始点ポインタ
BYTE *pend; // 終点ポインタ
int cmp_255; // 比較用255の定数値
「BYTE *p;」は、パターン書き込み始点ポインタ
「BYTE *pend;」は、パターン書き込み終点ポインタ
「int cmp_255;」は、定数「255」
★注意★何故、初期値込み記法「int cmp_255=255;」と
シナカッタかは、恐らく、この記法ではコンパイラに依って
最速に成る変数に成ら無かったからと覚えて居る!
アルゴリズムコード
if( m < 0 || m > n || d < 0 || d >= 256 ){ // 終始点とデータが範囲
return( STI_FLG ); // 外なら、引数検査違反
} //
cmp_255 = 255; // 定数255をセット
p = &lut[ m ]; // 始点作成
pend = &lut[ n ]; // 終点作成
if( d + ( n - m ) <= cmp_255 ){ // 最終Dataが255以下なら
while( p <= pend ){ // 終始点の範囲で
*p++ = d; // 増加パターンを
d++; // 書き込む
} //
}else{ // 最終Data255超えるなら
while( d < cmp_255 ){ // Data255までの範囲で
*p++ = d; // 増加パターンを
d++; // 書き込む
} //
while( p <= pend ){ // 残りの範囲を
*p++ = d; // 255で書き込む
} //
} //
return( END_STI ); // 正常終了
}
「if(m<0||m>n||d<0||d>=256){return(STI_FLG);}」は、
条件「m<0||m>n||d<0||d>=256」で仮引数「int m,」が
0未満か仮引数「int m,」を越える、或いは、
仮引数「int d」が0未満か255を越える場合、エラーと
判断し「return(STI_FLG);」でエラーコード「STI_FLG」を
返し関数終了!
「cmp_255=255;」は、ローカル変数「cmp_255」に
値「255」をセットし!定数「255」直記載より早く成る
コードを記載した心算
★注意★処理系に依り扱いは異なるので気に成る人は、
コンパイラが出力するアセンブラリストを確認して下さい!
「p=&lut[m];」は、LUT内始点ポインタセット
「pend=&lut[n];」は、LUT内終点ポインタセット
「if(d+(n-m)<=cmp_255){・・条件成立・・}else{
・・条件不成立・・}」は、条件「d+(n-m)<=cmp_255」で
インクリメントパターンで最終データも255以内なら
条件成立「while(p<=pend){*p++=d;d++;}」で、While
ループで始点から終点まで「*p++=d;d++;」とインクリメン
トパターンを書き込み!
条件不成立時「while(d<cmp_255){*p++=d;d++;}
while(p<=pend){*p++=d;}」は、先ず、最初の
「while(d<cmp_255){*p++=d;d++;}」とWhileループで
始点から条件「d<cmp_255」と書き込みデータ「int d」が
255以下の間繰り返し「*p++=d;d++;」を繰り返しインク
リメントパターンを書き込み!Whileループ条件不成立
に成ったら、「while(p<=pend){*p++=d;}」でWhile
ループで残りの終点まで最大値「int d」データをパターン
に書き込み!
「return(END_STI);」は、正常終了!
(4-14-25-E)関数「Make0Lut()」の【使用例】
{
//:LUT配列用
BYTE lut[256]; // LUT実体
int i; // ループカウンタ
int sti; // ステータス情報
// ここで説明する関数「Make0Lut()」使用例
sti = FUN.Make0Lut( lut, 0, 255, 0 );
// 作成したLUTパターンを数値表示
for( i = 0; i <= 255; i++ ){
printf( "%d,", lut[i] );
}
printf( "\n" );
}
★注意★
上記例文で注意して欲しいのは、LUT一次元配列「tbl」
と直接、C言語表現での実テーブルを使用して居る事です!
☆お詫び☆
暫く、講座が途切れたのは、ここの例文解説に迷ったからで
す下手に画像処理でLUT変換すると現状≪貧乏に成り、
開発環境としてコンパイル&GO出来る環境が整わ無いと
画像を主導でペイント等のアプリ作成で作成する事が困難で
予算が十分【解説『投げ銭方式ライブラリのダウンロード』
での「投げ銭」で予算が溜まるまで無理なので受講者の皆様
寄付お願いします!】≫なので手動で画像作成する事を諦め
数値的に如何に動くかに方針を変えた為に時間が掛かった事
と理解して下さい!コノLUT変換パターン作成関数は、
本質的に数値表現だけの方が反って分かり易い筈と考えまし
た!
(4-14-26)関数「int Make1Lut(BYTE lut[],int m,int n,int d){・・・}」の説明
int CopyClear::Make1Lut(
BYTE lut[], // 作成するLUT
int m, // Pattern書込始点Ix
int n, // Pattern書込終点Ix
int d // パターン書込データ
){
BYTE *p; // 始点ポインタ
BYTE *pend; // 終点ポインタ
if( m < 0 || m > n || d < 0 || d >= 256 ){ // 終始点とデータが範囲
return( STI_FLG ); // 外なら、引数検査違反
} //
p = &lut[ m ]; // 始点作成
pend = &lut[ n ]; // 終点作成
if( d - ( n - m ) >= 0 ){ // 最終Dataが0以上なら
while( p <= pend ){ // 終始点の範囲で
*p++ = d; // 減少パターンを
d--; // 書き込む
} //
}else{ // 最終Dataが0未満なら
while( 0 < d ){ // Data0までの範囲で
*p++ = d; // 減少パターンを
d--; // 書き込む
} //
while( p <= pend ){ // 残りの範囲を
*p++ = d; // 0で書き込む
} //
} //
return( END_STI ); // 正常終了
}
☆備考☆この関数はファイル「CopyClear040.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
(4-14-26-A)関数「Make1Lut()」の【関数名】説明
「Make」は、作成するで
「Lut」は、勿論、LUT変換用のLUTです!
ココでは、「Make○○Lut」と枝番号○○で機能分けした内の
一つのLUTパターン作成の意味です!
ここの○○=1は、デクリメントパターン作成です!
このイメージです!
(4-14-26-B)関数「int Make1Lut()」の【返値】説明
int CopyClear::Make1Lut(
BYTE lut[], // 作成するLUT
int m, // Pattern書込始点Ix
int n, // Pattern書込終点Ix
int d // パターン書込データ
){
この関数内で明示的に検査しているのは、
仮引数「int m,int n,int d」が、所定の値に成って
居るか如何かを判定し仕様外ならエラー「STI_FLG」を
返します!
最後まで実行時は、正常終了「END_STI」を返します!
(4-14-26-C)関数「Make1Lut()」の【仮引数】説明
int CopyClear::Make1Lut(
BYTE lut[], // 作成するLUT
int m, // Pattern書込始点Ix
int n, // Pattern書込終点Ix
int d // パターン書込データ
){
「BYTE lut[],」はLUTを一次元配列として使用!
「int m,」は、「lut[]」内の始点
「int n,」は、「lut[]」内の終点
「int d」は、書き込むデータ初期値
(4-14-26-D)関数「Make1Lut()」の【アルゴリズム】説明
){
BYTE *p; // 始点ポインタ
BYTE *pend; // 終点ポインタ
if( m < 0 || m > n || d < 0 || d >= 256 ){ // 終始点とデータが範囲
return( STI_FLG ); // 外なら、引数検査違反
} //
p = &lut[ m ]; // 始点作成
pend = &lut[ n ]; // 終点作成
if( d - ( n - m ) >= 0 ){ // 最終Dataが0以上なら
while( p <= pend ){ // 終始点の範囲で
*p++ = d; // 減少パターンを
d--; // 書き込む
} //
}else{ // 最終Dataが0未満なら
while( 0 < d ){ // Data0までの範囲で
*p++ = d; // 減少パターンを
d--; // 書き込む
} //
while( p <= pend ){ // 残りの範囲を
*p++ = d; // 0で書き込む
} //
} //
return( END_STI ); // 正常終了
}
ローカル変数
){
BYTE *p; // 始点ポインタ
BYTE *pend; // 終点ポインタ
「BYTE *p;」は、パターン書き込み始点ポインタ
「BYTE *pend;」は、パターン書き込み終点ポインタ
アルゴリズムコード
if( m < 0 || m > n || d < 0 || d >= 256 ){ // 終始点とデータが範囲
return( STI_FLG ); // 外なら、引数検査違反
} //
p = &lut[ m ]; // 始点作成
pend = &lut[ n ]; // 終点作成
if( d - ( n - m ) >= 0 ){ // 最終Dataが0以上なら
while( p <= pend ){ // 終始点の範囲で
*p++ = d; // 減少パターンを
d--; // 書き込む
} //
}else{ // 最終Dataが0未満なら
while( 0 < d ){ // Data0までの範囲で
*p++ = d; // 減少パターンを
d--; // 書き込む
} //
while( p <= pend ){ // 残りの範囲を
*p++ = d; // 0で書き込む
} //
} //
return( END_STI ); // 正常終了
}
「if(m<0||m>n||d<0||d>=256){return(STI_FLG);}」は、
条件「m<0||m>n||d<0||d>=256」で仮引数「int m,」が
0未満か仮引数「int m,」を越える、或いは、
仮引数「int d」が0未満か255を越える場合、エラーと
判断し「return(STI_FLG);」でエラーコード「STI_FLG」を
返し関数終了!
「p=&lut[m];」は、LUT内始点ポインタセット
「pend=&lut[n];」は、LUT内終点ポインタセット
「if(d-(n-m)>=0){・・条件成立・・}else{
・・条件不成立・・}」は、条件「d-(n-m)>=0」で
デクリメントパターンで最終データも0以上なら
条件成立「while(p<=pend){*p++=d;d--;}」で、While
ループで始点から終点まで「*p++=d;d--;」とデクリメント
パターンを書き込み!
条件不成立時「while(0<d){*p++=d;d--;}
while(p<=pend){*p++=d;}」は、先ず、最初の
「while(0<d){*p++=d;d--;}」とWhileループで
始点から条件「0<d」と書き込みデータ「int d」が
0以上の間繰り返し「*p++=d;d--;」を繰り返しデクリ
メントパターンを書き込み!Whileループ条件不成立
に成ったら、「while(p<=pend){*p++=d;}」でWhile
ループで残りの終点まで最小値「int d」データをパターン
に書き込み!
「return(END_STI);」は、正常終了!
(4-14-26-E)関数「Make1Lut()」の【使用例】
{
//:LUT配列用
BYTE lut[256]; // LUT実体
int i; // ループカウンタ
int sti; // ステータス情報
// ここで説明する関数「Make1Lut()」使用例
sti = FUN.Make1Lut( lut, 0, 255, 0 );
// 作成したLUTパターンを数値表示
for( i = 0; i <= 255; i++ ){
printf( "%d,", lut[i] );
}
printf( "\n" );
}
★注意★
上記例文で注意して欲しいのは、LUT一次元配列「tbl」
と直接、C言語表現での実テーブルを使用して居る事です!
場合に依っては、関数「int Convert()」を使用した場合
より効率的に成る為にコノ関数が用意された事が分かる
でしょう!今回の例文実行は、数値表現だけの方が分かり
易いと考えてこの方式にしました!
(4-14-27)関数「int Make2Lut(BYTE lut[],int m,int n,int d){・・・}」の説明
int CopyClear::Make2Lut(
BYTE lut[], // 作成するLUT
int m, // Pattern書込始点Ix
int n, // Pattern書込終点Ix
int d // パターン書込データ
){
if( m < 0 || m > n || d < 0 || d >= 256 ){ // 終始点とデータが範囲
return( STI_FLG ); // 外なら、引数検査違反
} //
up_fill_void( d, &lut[ m ], n - m + 1 ); // lut[m..n]=d
return( END_STI ); // 正常終了
}
☆備考☆この関数はファイル「CopyClear040.cpp」に存在!
★注意★この関数は「public:」属性ですのでライブラリの
外から使用可能です!
(4-14-27-A)関数「Make2Lut()」の【関数名】説明
「Make」は、作成するで
「Lut」は、勿論、LUT変換用のLUTです!
ココでは、「Make○○Lut」と枝番号○○で機能分けした内の
一つのLUTパターン作成の意味です!
ここの○○=2は、同一レベルパターン作成です!
このイメージです!
(4-14-27-B)関数「int Make2Lut()」の【返値】説明
int CopyClear::Make2Lut(
BYTE lut[], // 作成するLUT
int m, // Pattern書込始点Ix
int n, // Pattern書込終点Ix
int d // パターン書込データ
){
この関数内で明示的に検査しているのは、
仮引数「int m,int n,int d」が、所定の値に成って
居るか如何かを判定し仕様外ならエラー「STI_FLG」を
返します!
最後まで実行時は、正常終了「END_STI」を返します!
(4-14-27-C)関数「Make2Lut()」の【仮引数】説明
int CopyClear::Make2Lut(
BYTE lut[], // 作成するLUT
int m, // Pattern書込始点Ix
int n, // Pattern書込終点Ix
int d // パターン書込データ
){
「BYTE lut[],」はLUTを一次元配列として使用!
「int m,」は、「lut[]」内の始点
「int n,」は、「lut[]」内の終点
「int d」は、書き込むデータ
(4-14-27-D)関数「Make2Lut()」の【アルゴリズム】説明
){
if( m < 0 || m > n || d < 0 || d >= 256 ){ // 終始点とデータが範囲
return( STI_FLG ); // 外なら、引数検査違反
} //
up_fill_void( d, &lut[ m ], n - m + 1 ); // lut[m..n]=d
return( END_STI ); // 正常終了
}
アルゴリズムコード
「if(m<0||m>n||d<0||d>=256){return(STI_FLG);}」は、
条件「m<0||m>n||d<0||d>=256」で仮引数「int m,」が
0未満か仮引数「int m,」を越える、或いは、
仮引数「int d」が0未満か255を越える場合、エラーと
判断し「return(STI_FLG);」でエラーコード「STI_FLG」を
返し関数終了!
「up_fill_void (d,&lut[m],n-m+1);」は、サブルーチン
関数「up_fill_void ()」で始点「&lut[m]」と書き込む
サイズ「n-m+1」と実引数を算出して値を渡す事で
データ「d」を始点「&lut[m]」からサイズ「n-m+1」分、
書き込みます!
「return(END_STI);」は、正常終了!
(4-14-27-E)関数「Make2Lut()」の【使用例】
{
TypeArray PatImg; // 画像型変数
// :変換前のパターン画像
TypeArray* pPatImg=&PatImg; // 上記へのポインタ
TypeArray Wimg; // 画像型変数
//:フィル書き込み用
TypeArray* pWimg=&Wimg; // 上記へのポインタ
//:部分画像用
TypeArray* pimgA=&PatImg; // 部分画像用
TypeArray* pimgB=&PatImg; // 部分画像用
BYTE lut[256]; // LUT実体
long hgm[256]; // ヒストグラム算出データ配列
BYTE* p; // 画像画素へのポインタ
int i; // ループカウンタ
int j; // ループカウンタ
int x; // X座標
int y; // Y座標
int d; // 画素データ
int t; // 2値化しきい値
int sti; // ステータス情報
pPatImg->MallocBYTE( 640, 480 ); // サイズ640×480画像メモリ取得
FUN.Clear( pPatImg, 0 ); // 画像メモリ「0クリア」
p = pPatImg->getPtrByte( 0, 0 ); //
for( x = 0; x < 640; x++ ){ //
d = x & 0x0ff; // 0..255の値にする
*p++ = d; // 画素として書き込む
} // 1行分パターン画像作成
pimgA->subset( pPatImg, 0, 0, 640, 1 ); // 先頭行の部分画像
for( y = 1; y < 480; y++ ){ //
pimgB->subset( pPatImg, 0, y, 640, // 2行以降の任意場所の
1 ); // 部分画像
FUN.Copy( pimgA, pimgB ); // 先頭行のパターン画像を2行目以降にコピー
} // これで横方向インクリメントパターン画像作成
//作成した画像をBMP形式ファイルとして作成
FUN.WriteBitmap( "testFile5.bmp", pPatImg );
//LUT変換サンプル:2値化を今回説明する
//関数「Make2Lut()」使用例
sti = FUN.Make2Lut( lut, 0, 127, 0 );
sti = FUN.Make2Lut( lut, 128, 255, 255 );
// 作成したLUTパターンを数値表示
for( i = 0; i <= 255; i++ ){
printf( "%d,", lut[i] );
}
printf( "\n" );
pWimg->MallocBYTE( 640, 480 ); // サイズ640×480画像メモリ取得
FUN.Clear( pWimg, 0 ); // 画像メモリ「0クリア」
FUN.ConvertByte( pPatImg, pWimg, lut ); // 今回紹介する関数「ConvertByte()」でLUT変換
//作成した画像をBMP形式ファイルとして作成
FUN.WriteBitmap("testFile15.bmp", pWimg );
// 後始末
pPatImg->freeMem(); // 画像メモリ解放
pWimg->freeMem(); // 画像メモリ解放
}
★注意★
上記例文で注意して欲しいのは、LUT一次元配列「tbl」
と直接、C言語表現での実テーブルを使用して居る事です!
場合に依っては、関数「int Convert()」を使用した場合
より効率的に成る為にコノ関数が用意された事が分かる
でしょう!と「int ConvertByte()」で使用した例文を改造
しました!LUT変換は、「int ConvertByte()」関数で行
います!
作成した画像ファイル
★備考★解説『解説クラスTypeArray』でも記載したが、私が、テキストエディタ編集作業ミス≪文字列置き換え作業の範囲設定し忘れで余計な別の文字列まで置き換え等≫とかnoteエディタの変な特性でコピペした文章の半角「*」が消されたり、空白「 」が消される事が多々あります!注意して手作業で修正している筈ですが、必ず、code機能で表示して居る物を正しいとして確認して下さい
本日(4月28)の講義はココまでとします!
LUTパターン作成の話に本日から変ったので学習の消化を
促す為にココまでとします!
十分にNoteサーバーが動く分量なので続きは、
この文章に引き続き掲載しますので御贔屓をお願いします!