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
|
Re: GraphFilterのレベル補正 ( No.13 ) |
- 名前:休日プログラマー 日時:2015/10/11 17:47
> 管理人様
ご用意頂いた DX_GRAPH_FILTER_BRIGHT_SCALE を使うことで
実現したかった画面効果を実装することができました!
わがままな要望にも関わらずご対応いただき誠に恐縮です、
本当にありがとうございました!
|
|