トップページ > 記事閲覧
GraphFilterのレベル補正
名前:休日プログラマー 日時: 2015/09/28 22:39

GraphFilter関数でDX_GRAPH_FILTER_LEVELを使用する際に、 リファレンスによりますと引数は順に int Min : 変換元の下限値( 0 〜 255 ) int Max : 変換元の上限値( 0 〜 255 ) int Gamma : ガンマ値( 100 で 1.0 を表し、ガンマ補正無し、1 より小さい値は不可 ) int AfterMin : 変換後の最低値( 0 〜 255 ) int AfterMax : 変換後の最大値( 0 〜 255 ) となっているかと思いますが、 MinとMaxに任意の数値を入れても特にフィルタ結果には反映が見られませんでした。 (常にMin=0、Max=255を指定したような絵になっている?) ※AfterMinとAfterMaxの方は、適切に数値が結果に反映されます。 これは当方の動作環境に依るものでしょうか? 以上、よろしくお願い致します。
メンテ

Page: 1 |

Re: GraphFilterのレベル補正 ( No.1 )
名前:休日プログラマー 日時:2015/09/28 22:42

バージョンの記入を失念しておりました、 当方で使用させて頂いているDXライブラリは 3.13d です。
メンテ
Re: GraphFilterのレベル補正 ( No.2 )
名前:管理人 日時:2015/09/30 02:20

以下のようなDX_GRAPH_FILTER_LEVELフィルターのパラメータを操作できるサンプルを組んでみました ( Src1.bmp はDXライブラリのパッケージの「サンプルプログラム実行用フォルダ」に入っています ) #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int SrcHandle ; int DestHandle ; int Min ; int Center ; int Max ; int AMin ; int AMax ; ChangeWindowMode( TRUE ) ; SetGraphMode( 480, 480, 32 ) ; if( DxLib_Init() < 0 ) return -1 ; // 画像の読み込み SrcHandle = LoadGraph( "Src1.bmp" ) ; // 出力先画像の作成 DestHandle = MakeScreen( 256, 256 ) ; // フィルターのパラメータを初期化 Min = 0 ; Max = 255 ; Center = 100 ; AMin = 0 ; AMax = 255 ; // 描画先を裏画面に変更 SetDrawScreen( DX_SCREEN_BACK ) ; // メインループ while( ProcessMessage() == 0 ) { // A.Z キーで Min の値を操作 if( CheckHitKey( KEY_INPUT_A ) && Min != 255 ) Min ++ ; if( CheckHitKey( KEY_INPUT_Z ) && Min != 0 ) Min -- ; // S.X キーで Max の値を操作 if( CheckHitKey( KEY_INPUT_S ) && Max != 255 ) Max ++ ; if( CheckHitKey( KEY_INPUT_X ) && Max != 0 ) Max -- ; // D.C キーで Center の値を操作 if( CheckHitKey( KEY_INPUT_D ) && Center != 255 ) Center ++ ; if( CheckHitKey( KEY_INPUT_C ) && Center != 0 ) Center -- ; // F.V キーで AMin の値を操作 if( CheckHitKey( KEY_INPUT_F ) && AMin != 255 ) AMin ++ ; if( CheckHitKey( KEY_INPUT_V ) && AMin != 0 ) AMin -- ; // G.B キーで AMax の値を操作 if( CheckHitKey( KEY_INPUT_G ) && AMax != 255 ) AMax ++ ; if( CheckHitKey( KEY_INPUT_B ) && AMax != 0 ) AMax -- ; // フィルターを掛ける GraphFilterBlt( SrcHandle, DestHandle, DX_GRAPH_FILTER_LEVEL, Min, Max, Center, AMin, AMax ) ; // 画面を初期化 ClearDrawScreen() ; // フィルターを掛けた結果を描画 DrawGraph( 0, 0, DestHandle, FALSE ) ; // パラメータを描画 DrawFormatString( 0, 0 + 256, GetColor( 0,255,0 ), "Min:%d Max:%d Center:%d AMin:%d AMax:%d", Min, Max, Center, AMin, AMax ) ; // 裏画面の内容を表画面に反映 ScreenFlip() ; } DxLib_End() ; return 0 ; } キーボードのキーで DX_GRAPH_FILTER_LEVEL のパラメータを変更できて、 その結果を常に画面に表示するというもので、 A,Zキーと S,Xキーで Min と Max の値が変更できます 手元で確認した限りでは Min と Max の値は反映されていましたので、 よろしければ休日プログラマーさんの環境でも上記サンプルプログラムが正常に動作するか お試しになってみてください m(_ _)m
メンテ
Re: GraphFilterのレベル補正 ( No.3 )
名前:休日プログラマー 日時:2015/09/30 19:59

頂いたサンプルプログラムを実行したところ、問題なく動作いたしました。 そのため当方のコードとの差分を調べ、問題が再現するコードを作成しました。 (最小構成では無いかもしれません、ご容赦下さい) 改変箇所はメインループのみで、 視認性のために行頭に「★」を付けています。 // メインループ while( ProcessMessage() == 0 ) { ★ SetDrawScreen(DestHandle); ★ DrawGraph(0, 0, SrcHandle, FALSE); ★ DrawBox(20, 20, 100, 100, GetColor(255, 255, 255), TRUE); ★ DrawBox(50, 50, 70, 70, GetColor(255, 0, 0), TRUE); ★ SetDrawScreen(DX_SCREEN_BACK); // A.Z キーで Min の値を操作 if( CheckHitKey( KEY_INPUT_A ) && Min != 255 ) Min ++ ; if( CheckHitKey( KEY_INPUT_Z ) && Min != 0 ) Min -- ; // S.X キーで Max の値を操作 if( CheckHitKey( KEY_INPUT_S ) && Max != 255 ) Max ++ ; if( CheckHitKey( KEY_INPUT_X ) && Max != 0 ) Max -- ; // D.C キーで Center の値を操作 if( CheckHitKey( KEY_INPUT_D ) && Center != 255 ) Center ++ ; if( CheckHitKey( KEY_INPUT_C ) && Center != 0 ) Center -- ; // F.V キーで AMin の値を操作 if( CheckHitKey( KEY_INPUT_F ) && AMin != 255 ) AMin ++ ; if( CheckHitKey( KEY_INPUT_V ) && AMin != 0 ) AMin -- ; // G.B キーで AMax の値を操作 if( CheckHitKey( KEY_INPUT_G ) && AMax != 255 ) AMax ++ ; if( CheckHitKey( KEY_INPUT_B ) && AMax != 0 ) AMax -- ; // フィルターを掛ける ★ //GraphFilterBlt( SrcHandle, DestHandle, DX_GRAPH_FILTER_LEVEL, Min, Max, Center, AMin, AMax ) ; ★ GraphFilter(DestHandle, DX_GRAPH_FILTER_LEVEL, Min, Max, Center, AMin, AMax); // 画面を初期化 ClearDrawScreen() ; // フィルターを掛けた結果を描画 DrawGraph( 0, 0, DestHandle, FALSE ) ; // パラメータを描画 DrawFormatString( 0, 0 + 256, GetColor( 0,255,0 ), "Min:%d Max:%d Center:%d AMin:%d AMax:%d", Min, Max, Center, AMin, AMax ) ; // 裏画面の内容を表画面に反映 ScreenFlip() ; } ビットマップ画像部分には Min, Max, Center, AMin, AMax のいずれも反映されるのですが、 DrawBoxで描画した部分は Min, Max, Center が反映されないようです。 (もしかして、そもそもプリミティブ描画はフィルターの対象外という仕様でしたらすみません…) 以上、よろしくお願い致します。
メンテ
Re: GraphFilterのレベル補正 ( No.4 )
名前:管理人 日時:2015/10/03 16:11

色の値が最大である真っ白、真っ赤については Min, Max の値が殆ど反映されないのは仕様です これはDXライブラリのレベル補正機能だからというわけではなく、Photoshop などのペイント ソフト等に実装されているレベル補正でも同じです Min はR.G.Bそれぞれに対して「どの値以下の部分を0にするか」の指定で Max はR.G.Bそれぞれに対して「どの値未満の部分を255にするか」の指定なので、 既にR.G.Bが255である真っ白の部分は Min を 255 にした場合のみ真っ黒になりますが、 それ以下の値の間はなんの影響も受けず、Max に至っては既に最大値である 255 なので、 値をどんなに弄っても変化はありません Rのみ255の真っ赤の部分も、同じく Min を 255 にした場合のみ真っ黒になり( G.B は 既に最低値の 0 なので Min を 255 にして R が影響を受けるまでは見た目に変化はありません ) Max については真っ白と同じく値をどんなに弄っても変化はありません( R は既に 255 で、 G.B については最低値の 0 なので、条件判定が「どの値『未満』だったら255にする」である ために Min と異なり Max を 0 にしても G.B 部分が 255 になることはありません( 0 は「0未満」ではないので ) ) DrawBox の GetColor( 255,255,255 ) の部分を GetColor( 180,180,180 ) などに変更すると 影響を受けるようになりますので、よろしければ試してみてください m(_ _)m
メンテ
Re: GraphFilterのレベル補正 ( No.5 )
名前:休日プログラマー 日時:2015/10/03 19:25

ご返信ありがとうございます、合点がいきました。 なるほど、RGB値の各成分に対してかかるので真っ赤や真っ青もダメだったのですね。 大変失礼いたしました… 当方で実現したかった処理としましては、あるグラフィックハンドル(仮にA)に対して まず GraphFilter の DX_GRAPH_FILTER_BRIGHT_CLIP で特定値以上の輝度成分を残し(仮に80)、 その後 DX_GRAPH_FILTER_LEVEL を使うことでグラフィックAの輝度クリップ済み画像 (輝度80〜255) の各画素を、輝度 0〜255 へと変換することを目論んでいました。 ご返信頂いてから別方法を思い立ち、 1.DX_GRAPH_FILTER_BRIGHT_CLIP でグラフィックAの輝度クリップ(80) 2.DX_GRAPH_FILTER_HSB でグラフィックAの輝度を相対で80下げる 3.DX_GRAPH_FILTER_LEVEL で min, max に 0, 255-80 を指定する というアプローチを試みたのですが、 [2]の時点で輝度のボーダーとした画素が真っ黒になるわけではないようで、断念しました… (仮に真っ黒になったところで、[3]で輝度≠色成分なので破綻しそうですね…) 輝度とレベル補正を混同してしまっていたのですが、 上記のような目的を実現することは可能でしょうか?
メンテ
Re: GraphFilterのレベル補正 ( No.6 )
名前:管理人 日時:2015/10/05 00:06

> 当方で実現したかった処理としましては、あるグラフィックハンドル(仮にA)に対して > まず GraphFilter の DX_GRAPH_FILTER_BRIGHT_CLIP で特定値以上の輝度成分を残し(仮に80)、 > その後 DX_GRAPH_FILTER_LEVEL を使うことでグラフィックAの輝度クリップ済み画像 > (輝度80〜255) の各画素を、輝度 0〜255 へと変換することを目論んでいました。 それでしたら DX_GRAPH_FILTER_BRIGHT_CLIP を使用する必要は無いような気がします DX_GRAPH_FILTER_LEVEL の Min を 80、Max を 255、Gamma を 167 ( 80 と 255 の真ん中 )、 AfterMin を 0、AfterMax を 255 とすることで輝度 80〜255 を輝度 0〜255 へと変換することができます
メンテ
Re: GraphFilterのレベル補正 ( No.7 )
名前:休日プログラマー 日時:2015/10/05 20:49

ご返信ありがとうございます。 > DX_GRAPH_FILTER_LEVEL の Min を 80、Max を 255、Gamma を 167 ( 80 と 255 の真ん中 )、 > AfterMin を 0、AfterMax を 255 とすることで輝度 80〜255 を輝度 0〜255 へと変換することができます 先の話題に戻ってしまい恐縮なのですが、この方法ですと RGB成分のいずれかが際立って高いケースで画素が色濃く残ってしまうのが悩ましい点です… (仮にRGB値が(255, 0, 0)である画素があった際に、  DX_GRAPH_FILTER_BRIGHT_CLIP であれば CmpParam = 77(以上)でクリップされるのですが  DX_GRAPH_FILTER_LEVEL ですと min, maxの値に関わらず(※255除く)真っ赤に残ってしまい…) どうも私の中で輝度とRGB値の概念がごっちゃになっていて状況を上手くお伝えできておらず 何度もお手数をお掛けして申し訳ございません。
メンテ
Re: GraphFilterのレベル補正 ( No.8 )
名前:管理人 日時:2015/10/07 02:29

輝度の操作が休日プログラマーさんの意図通りにならないのは DX_GRAPH_FILTER_LEVEL と DX_GRAPH_FILTER_BRIGHT_CLIP と DX_GRAPH_FILTER_HSB で 「輝度」としているものの値の求め方が異なるからです DX_GRAPH_FILTER_BRIGHT_CLIP で求めるタイプの「輝度」の場合、「輝度」を0にしても 真っ黒にはなりませんので、仮に DX_GRAPH_FILTER_BRIGHT_CLIP で求めるタイプの「輝度」 の 80 〜 255 を 0 〜 255 に変換するフィルターを使っても輝度が 77 である真っ赤の 部分は真っ黒になりませんが( 暗い赤になる )、それでもよろしいでしょうか? 若しくは、DX_GRAPH_FILTER_HSB タイプの「輝度」でしたら 0 なら必ず真っ黒、255 なら 必ず真っ白になるので、こちらのタイプの「輝度」を使ったフィルターを追加する、でも良いでしょうか? ( 因みに DX_GRAPH_FILTER_HSB タイプの「輝度」では真っ赤・真緑・真っ青がそれぞれ輝度128となります )
メンテ
Re: GraphFilterのレベル補正 ( No.9 )
名前:休日プログラマー 日時:2015/10/07 20:26

ご返信ありがとうございます。 > 若しくは、DX_GRAPH_FILTER_HSB タイプの「輝度」でしたら 0 なら必ず真っ黒、255 なら > 必ず真っ白になるので、こちらのタイプの「輝度」を使ったフィルターを追加する、でも良いでしょうか? 直観的な分かりやすさで、こちらの方を希望いたします。 お忙しい中たいへん恐縮です、よろしくお願い致します。
メンテ
Re: GraphFilterのレベル補正 ( No.10 )
名前:管理人 日時:2015/10/08 01:34

分かりました、では DX_GRAPH_FILTER_HSB タイプの輝度のレベル補正風のフィルタを作ります ただ、今週の平日は時間が確保できそうに無いので、申し訳ありませんが週末までお待ちください m(_ _;m
メンテ
Re: GraphFilterのレベル補正 ( No.11 )
名前:割り込みで申し訳ない 日時:2015/10/09 22:19

応用性を考えるとブレンド処理として、DX_GRAPH_BLEND_RGBA_SELECT_MIXのHSB版を作った方がいいのではないでしょうか? 例えばこの場合ですと、別のスクリーンにグレースケールで出力、それをレベル補正してから元画像の色相と彩度として出力、のような使い方になると思います ライブラリ独特の機能を増やし過ぎないほうがユーザーにやさしいと思います
メンテ
Re: GraphFilterのレベル補正 ( No.12 )
名前:管理人 日時:2015/10/11 02:09

DX_GRAPH_FILTER_HSB タイプのレベル補正風のフィルタ DX_GRAPH_FILTER_BRIGHT_SCALE を追加しました よろしければこちらをダウンロードしてください https://dxlib.xsrv.jp/temp/DxLibVCTest.exe // VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.exe // BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibGCC_DevCppTest.exe // Dev-C++ 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.exe // MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // .NET用 https://dxlib.xsrv.jp/temp/DxLibMakeTest.exe // ソース (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』を、VCをお使いの場合は『リビルド』を、 Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい) DX_GRAPH_FILTER_BRIGHT_SCALE の引数は BrightMin と BrightMax で以下のようになります int GraphFilter( int GrHandle, int FilterType = DX_GRAPH_FILTER_BRIGHT_SCALE, int MinBright = 変換後に真っ暗になる明るさ( 0 〜 255 ), int MaxBright = 変換後に真っ白になる明るさ( 0 〜 255 ) ) ; よろしければお試しください m(_ _)m > 割り込みで申し訳ないさん フィルター処理はまだまだ重い処理なので、個人的には限定的な用途しかないフィルターも 要望があればどんどん追加していきたいと思っています ( DX_GRAPH_BLEND_RGBA_SELECT_MIX の HSB版も追加してみたいと思います )
メンテ
Re: GraphFilterのレベル補正 ( No.13 )
名前:休日プログラマー 日時:2015/10/11 17:47

> 管理人様 ご用意頂いた DX_GRAPH_FILTER_BRIGHT_SCALE を使うことで 実現したかった画面効果を実装することができました! わがままな要望にも関わらずご対応いただき誠に恐縮です、 本当にありがとうございました!
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存