トップページ > 記事閲覧
α付き画像複数から新しいα付き画像一枚を作りたい
名前:鈴見咲 君高 日時: 2013/07/12 18:52

まず、下記のソースコード(約150行)を実行してください。 そして、実行結果が次を満たしているかを確認してください。 1) 上の二つは完全に一致している。 2) 上の二つと一致するものは下の三つにはない。 これらが成り立っている前提で、次の要望は受け付けてもらえますでしょうか。 『GraphBlend 系 ではなく SetDrawBlendMode を使って中央上を実現させたい』 あるいは、ほかに簡単に実現する方法はありますでしょうか。 要望の理由: α付き画像複数から新しいα付き画像一枚を作りたい。 GraphBlend 系 には DrawTurn/Rota/ModiGraph に相当するものがなくて不便。 DX_BLENDMODE_ALPHA (左下) や DX_BLENDMODE_HALF_ADD(中央下) が役に立たない。 よろしくお願いいたします。 #include "DxLib.h" const int numOfSrcs = 4; int sources[ numOfSrcs ]; int backGround; int tempScreen; // // 貼り付けたい大元のαチャンネル付き画像を作ります。 // void makeSources() { for ( int c = 0; c < numOfSrcs; ++c ) { sources[ c ] = MakeScreen( 100, 100, TRUE ); FillGraph( sources[ c ], 0, 0, 0, 0 ); SetDrawScreen( sources[ c ] ); for ( int i = 0; i < 50; ++i ) { int v = ( 25 - i ) * 255 / 25; if ( v < 0 ) { v = -v; } int vs = v / 4; int cc = 0; switch ( c ) { case 0: cc = GetColor( v, vs, v ); break; case 1: cc = GetColor( vs, v, vs ); break; case 2: cc = GetColor( v, vs, vs ); break; case 3: cc = GetColor( v, v, vs ); break; } DrawCircle( 50, 50, 50 - i, cc, TRUE ); } } } // // 背景用の画像を作ります。 // void makeBackground() { backGround = MakeScreen( 200, 480, TRUE ); SetDrawScreen( backGround ); for ( int i = 0 ; i < 12 ; ++i ) { for ( int j = 0 ; j < 4 ; ++j ) { const int c = GetColor( 192, i % 2 == j % 2 ? 192 : 255, 192 ); DrawBox( j*50, i*40, j*50+50, i*40+40, c, TRUE ); } } } // // αチャンネル付き画像を別のαチャンネル付き画像に貼り付けます。 // 描画先は SetDrawScreen() で指定したものを自動的に取得します。 // 貼り付ける寸法は srcHandle の大きさそのものになります。 // void copyByGraphBlendRect( int dstX, int dstY, int srcHandle, int ratio, int dummy ) { int width, height; GetGraphSize( srcHandle, &width, &height ); GraphBlendRectBlt( tempScreen, srcHandle, tempScreen, dstX, dstY, dstX + width, dstY + height, 0, 0, dstX, dstY, ratio, DX_GRAPH_BLEND_NORMAL_ALPHACH ); } // // copyByGraphBlendRect と同じ結果を求めようとしています。 // が、現在ある合成方法では成功するものがありません。 // void copyByBlendMode( int dstX, int dstY, int srcHandle, int ratio, int blendMode ) { SetDrawBlendMode( blendMode, ratio ); DrawGraph( dstX, dstY, srcHandle, TRUE ); } typedef void (funcType)( int, int, int, int, int ); void drawGraphs( int startAlpha, funcType* ptr, int param ) { int alpha = startAlpha; const int e = numOfSrcs - 1; for ( int c = 0; c < numOfSrcs; ++c, alpha = ( alpha + 64 ) % 256 ) { (*ptr)( ( e - c ) * 30, ( e - c ) * 40, sources[ c ], alpha, param ); } } void drawGraphsWithTempScreen( int x, int y, int startAlpha, funcType* ptr, int param ) { SetDrawScreen( tempScreen ); FillGraph( tempScreen, 0, 0, 0, 0 ); drawGraphs( startAlpha, ptr, param ); SetDrawScreen( DX_SCREEN_BACK ); SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 255 ); DrawGraph( x, y, tempScreen, TRUE ); } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ChangeWindowMode( TRUE ); SetGraphMode( 640, 480, 32, 60 ); DxLib_Init(); makeSources(); makeBackground(); tempScreen = MakeScreen( 320, 240, TRUE ); int offset = 0; while ( -1 != ProcessMessage() && 0 == CheckHitKeyAll() ) { SetDrawScreen( DX_SCREEN_BACK ); SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 255 ); DrawGraph( 0, 0, backGround, FALSE ); DrawGraph( 200, 0, backGround, FALSE ); DrawGraph( 400, 0, backGround, FALSE ); const int startAlpha = 255 - GetNowCount() / 25 % 255; // 左上 ( 目標画像 ) SetDrawScreen( DX_SCREEN_BACK ); drawGraphs( startAlpha, &copyByBlendMode, DX_BLENDMODE_ALPHA ); // 左中 ( 合成に成功 ) drawGraphsWithTempScreen( 200, 0, startAlpha, &copyByGraphBlendRect, 0 ); // 左下・中下・右下 ( すべて合成に失敗 ) const int bm[ 3 ] = { DX_BLENDMODE_ALPHA, DX_BLENDMODE_HALF_ADD, DX_BLENDMODE_SRCCOLOR }; for ( int t = 0; t < 3; ++t ) { drawGraphsWithTempScreen( t * 200, 240, startAlpha, &copyByBlendMode, bm[ t ] ); } ScreenFlip(); } DxLib_End(); }
メンテ

Page: 1 |

Re: α付き画像複数から新しいα付き画像一枚を作りたい ( No.1 )
名前:鈴見咲 君高 日時:2013/07/12 20:37

なお、このスレッドは下記の話題から派生したものです。 h ttp://hpcgi2.nifty.com/natupaji/bbs/patio.cgi?mode=view&no=3073
メンテ
Re: α付き画像複数から新しいα付き画像一枚を作りたい ( No.2 )
名前:いっち 日時:2013/07/13 00:27

ご存知かもしれませんが、以下のスレッドに正確なアルファブレンドに関する管理人さんのコメントがあります。 > ttp://hpcgi2.nifty.com/natupaji/bbs/patio.cgi?mode=view&no=2438
メンテ
Re: α付き画像複数から新しいα付き画像一枚を作りたい ( No.3 )
名前:鈴見咲 君高 日時:2013/07/13 13:04

> いっちさん 教えていただいたスレッドを読んでみました。 もともと3Dレンダリングのためにある機能を応用しているため 今回の要望は実は特殊な部類に入ることとか、仮に要望が実現 したとしても、プログラミングが楽になるだけで処理速度の 優位性には疑問符がつくことなどが理解できました。 現状でも一応できることはできますし、急を要する話でもないので 管理人さんの忙しさと実装難度・手間対効果の兼ね合いで実装の 可否を決めてもらってもいいかなと(私個人として)思いました。 お知らせありがとうございました。
メンテ
Re: α付き画像複数から新しいα付き画像一枚を作りたい ( No.4 )
名前:管理人 日時:2013/07/15 15:45

実装はできるような気はしますが、かなり規模の大きい変更になるのと、シェーダーが必須になるので タイミングが難しいです( あと、モデル描画でも対応させようとするとシェーダーコードバイナリ容量が 増えるのも悩ましいところ・・・ ) ピクセルシェーダーで決定した色の値と書き込み先バッファの色の値をどのようにブレンドするかを プログラミングできるシェーダーがあれば一発で解決するのですが・・・ ジオメトリシェーダーやテッセレータよりそっちの方が欲しい・・・
メンテ
Re: α付き画像複数から新しいα付き画像一枚を作りたい ( No.5 )
名前:管理人 日時:2013/07/27 23:30

すみません、「乗算済みアルファ」という機能を使えば 「α付き画像複数から新しいα付き画像一枚を作る」ことが可能だということが分かりました orz 早速その機能を実装してみましたので、よろしければこちらのバージョンをダウンロードしてください http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_DevCppTest.exe // Dev-C++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_MinGWTest.exe // MinGW 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibDotNet.zip // .NET用 http://homepage2.nifty.com/natupaji/DxLib/DxLibMakeTest.exe // ソース (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』を、VCをお使いの場合は『リビルド』を、 Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい) DXライブラリで「乗算済みアルファ」を使用するための機能については解説ページを 用意しましたので、よろしければご覧になってみてください m(_ _)m http://homepage2.nifty.com/natupaji/DxLib/lecture/PremulAlpha/PremulAlpha.html
メンテ
Re: α付き画像複数から新しいα付き画像一枚を作りたい ( No.6 )
名前:鈴見咲 君高(解決) 日時:2013/07/28 21:27

すばらしい… 説明くださったとおりに動作することを確認できました。 このスレッドの最初に書いた約 150 行のコードについて 皆さんの参考用にどう入れ替えたらよいかも記しておきます。 ありがとうございました! // // 次の関数を差し換え // 引数が一つ増え、SetDrawBlendMode の第一引数に充てられる // void drawGraphsWithTempScreen( int x, int y, int startAlpha, funcType* ptr, int param, int param2 ) { SetDrawScreen( tempScreen ); FillGraph( tempScreen, 0, 0, 0, 0 ); drawGraphs( startAlpha, ptr, param ); SetDrawScreen( DX_SCREEN_BACK ); SetDrawBlendMode( param2, 255 ); DrawGraph( x, y, tempScreen, TRUE ); } … // // WinMain の中の左上以外の描画処理を次のように差し替え // // 残り五つ( 上三つが同一画像になります ) const int bx[ 5 ] = { 200, 400, 0, 200, 400 }; const int by[ 5 ] = { 0, 0, 240, 240, 240 }; const int bf[ 5 ] = { DX_BLENDMODE_ALPHA, DX_BLENDMODE_PMA_ALPHA, DX_BLENDMODE_PMA_ADD, DX_BLENDMODE_PMA_SUB, DX_BLENDMODE_PMA_INVSRC }; funcType*const bp[ 5 ] = { &copyByGraphBlendRect, &copyByBlendMode, &copyByBlendMode, &copyByBlendMode, &copyByBlendMode }; for ( int t = 0; t < 5; ++t ) { drawGraphsWithTempScreen( bx[ t ], by[ t ], startAlpha, bp[ t ], DX_BLENDMODE_PMA_ALPHA, bf[ t ] ); }
メンテ

Page: 1 |

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

   クッキー保存