管理人様、いつもDxLibでお世話になっております。
現在、「mp4形式の動画のグリーンバックまたはブルーバックを透過して描画する」といったことをしたいのですが、
GraphFilter関数のDX_GRAPH_FILTER_REPLACEMENTを用いて透過しようとした際に、1つの決まったRGB値しか透過できないため、
あまり期待した結果を得ることができませんでした。(指定した色と少し異なるところが一部が残ってしまう)
また、過去に以下のスレッドがあったため、こちらも参考にしてみたのですが、
「色成分を透過する」というものの影響により、少しでも指定した色成分が入っているところはその分透過され薄くなり透けてしまうため、
こちらも理想的な結果にはなりませんでした。
https://dxlib.xsrv.jp/cgi/patiobbs/patio.cgi?mode=view&no=5522
私の思いついた強引な解決方法として、
GraphFilter関数のDX_GRAPH_FILTER_LEVELを用いてコントラストを上げてからDX_GRAPH_FILTER_REPLACEMENTで透過するとある程度は透過できたのですが、
コントラストが少し上げただけでは透過の精度がイマイチなのと、かといってコントラストを上げすぎると元の動画と差が出てしまい少し微妙でした。
そこで相談したいことなのですが、
DX_GRAPH_FILTER_REPLACEMENTの拡張版(?)みたいなもので、「2つの指定したRGB値に入っているピクセルを透過する」といった機能を追加することは可能でしょうか?
例えば、以下のような形です。
GraphFilter(
int MovieHandle,
int DX_GRAPH_FILTER_REPLACEMENTの拡張版,
int r1, int g1, int b1, int a1, // 指定する1つ目のRGBA
int r2, int g2, int b2, int a2, // 指定する2つ目のRGBA
int R, int G, int B, int A, // 置換後のRGBA
);
もし似たような機能が既に存在していたら、私の調査不足になります。申し訳ございません。
難しい場合は先程の強引な解決方法にしようと思いますが、自分の中でどうにも諦めきれず、管理人様に助けを求めることにしました。
一応、以下に汚いですが私の試していたコードを載せておきます。
私が間違っていたり他に良い方法があればアドバイスを是非ご教授いただきたいです。m(_ _)m
どうぞよろしくお願いいたします。
```C++
#include "DxLib.h"
#include <fstream>
using namespace std;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// exe起動時にLog.txtを出力しない
SetOutApplicationLogValidFlag(FALSE);
SetUseCharCodeFormat(DX_CHARCODEFORMAT_UTF8);
// ウィンドウモードにする
ChangeWindowMode(TRUE);
// ウィンドウタイトルを設定
SetWindowText("動画透過");
// ウィンドウのサイズを設定
SetGraphMode(600, 450, 16);
// ウィンドウのサイズ変更を不可にする
SetWindowSizeChangeEnableFlag(FALSE);
SetDoubleStartValidFlag(FALSE);
// 非アクティブ時でも実行を継続する設定
SetAlwaysRunFlag(TRUE);
// 垂直同期(TRUEだとFPS固定、FALSEだとPCの最大FPS)
SetWaitVSyncFlag(TRUE);
// Dxライブラリ初期化処理
if (DxLib_Init() == -1)
{
return -1; // エラーが起きたら直ちに終了
}
// 描画先を裏画面にする
SetDrawScreen(DX_SCREEN_BACK);
// ライティングは行わない
SetUseLighting(FALSE);
int MHandle = LoadGraph("GB.mp4");
int W, H;
GetGraphSize(MHandle, &W, &H);
int Screen = MakeScreen(W, H, TRUE);
SetBackgroundColor(200, 200, 200);
PlayMovieToGraph(MHandle);
// メインループを追加
while (ProcessMessage() == 0 && ClearDrawScreen() == 0) {
ClearDrawScreen();
// ESCキーが押されたら終了
if (CheckHitKey(KEY_INPUT_ESCAPE)) break;
if (CheckHitKey(KEY_INPUT_SPACE)) {
PauseMovieToGraph(MHandle);
SeekMovieToGraph(MHandle, 0);
PlayMovieToGraph(MHandle);
}
/*
// これだと期待した結果を得られなかった
GraphBlendBlt(MHandle, MHandle, Screen, 0, DX_GRAPH_BLEND_RGBA_SELECT_MIX,
DX_RGBA_SELECT_SRC_R,
DX_RGBA_SELECT_SRC_G,
DX_RGBA_SELECT_SRC_B,
DX_RGBA_SELECT_SRC_INV_G // 緑成分を透過
);
*/
// コントラストを上げて、置換対象の色(今回は(0,255,0))に近い色をその色に近づける
GraphFilterBlt(MHandle, Screen, DX_GRAPH_FILTER_LEVEL, 30, 225, 120, 0, 255);
// 色の置換フィルタで特定の色を透明に
GraphFilter(Screen, DX_GRAPH_FILTER_REPLACEMENT,
0, 255, 0, 255, // 置換対象の色
0, 0, 0, 0 // 置換後の色 (透明)
);
// ここの/3はただサイズを調節してるだけ
DrawExtendGraph(0, 0, W/3, H/3, Screen, TRUE);
// ウィンドウの更新
ScreenFlip();
}
DxLib_End();
return 0; // ソフトの終了
}
```