2017-11-27 12 views
0

私は現代のWindows環境で古いプログラムと古いプログラムを実行するためのサポートを提供しようとするDxWndツールの著者です。SetDIBitsToDeviceエミュレーション

非常に奇妙なゲームは、Win7-10システムでネイティブに実行できるにもかかわらず、グラフィック操作に深刻な問題をもたらします。

ゲームはddrawにリンクしますが、すべてのフレームをDIB_PAL_COLORS DIBとして構築し、SetDIBitsToDevice user32コールを使用してDIBを画面に表示します。 この操作は、ビデオの場合はOBJ_DC DCで32ビットの色深度ビデオモードでもサポートされますが、MEM_DCタイプのDCに適用すると色が悪くなります。私はこのような典型的なスキーマ使ってDIBを拡大しようとしている。この中に見つかった (変数宣言とエラーが簡潔にするために取り除かチェック):

hTempDc=CreateCompatibleDC(hdc); 
hbmPic=CreateCompatibleBitmap(hdc, OrigWidth, OrigHeight); 
SelectObject(hTempDc, hbmPic); 
SetDIBitsToDevice(hTempDc, 0, 0, OrigWidth, OrigHeight, XSrc, YSrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); 
StretchBlt(hdc, XDest, YDest, dwWidth, dwHeight, hTempDc, 0, 0, OrigWidth, OrigHeight, SRCCOPY); 

ピクセルがマップされているあなたをDIB_PAL_COLORS DIB出力MSDNによると、 「現在の」パレットを実現しましたが、もちろん32ビットのサーフェス上にあり、メモリ上にはDCクローンが全くありません。したがって、ピクセルの色がすべて間違っているのは不思議ではありません。

代替ソリューションは、StretchBltで自由にスケーリングする32ビットのメモリDCを構築SetDIBitsToDevice動作をエミュレートするかもしれないが、再び私が32bppのDIB_RGB_DIBまたはAのいずれかに8bppのDIB_PAL_COLORS DIBを変換することができるか、文書化されていません32bpp DC。

私はすでにいくつかの点で試してみましたが、すべての場合、ピクセルインデックスを変換するために使用する正しいパレットを特定できないようです。 誰かが8bpp DIB_PAL_COLORS DIB形式の解釈に役立つでしょうか?

+0

また、現在のパレットでSelectObjectを追加しようとしましたが、使用できません。GetCurrentObject(hdc、OBJ_PAL)はNULLを返します。 – gho

答えて

1

私が質問を正しく理解している場合は、カラーテーブルを持つDIBの形式のソースイメージがあり、そのイメージをSetDIBitsToDeviceを使用して非パレットDCに取り込みたいとします。

私は非常に長い時間パレットを扱っていませんが、正しくリコールすれば、宛先DCがパレットデバイスでない限り、DIB_PAL_COLORSを使用することはできません。それはあなたのメモリDCは、パレットデバイスであるとは考えにくいが、あなたがチェックすることができます。

GetDeviceCaps(hTempDc, RASTERCAPS) & RC_PALETTE 

それはパレットデバイスではないと仮定すると、私はあなたがfuColorUseためDIB_RGB_COLORSを使用することがあると思います。 SetDIBitsToDeviceは各ピクセルのインデックスを使用して、カラーテーブル内の対応するRGBQUAD値をルックアップします。 (カラーテーブルは、lpbmiが指すBITMAPINFO内のBITMAPINFOHEADERの後ろにあります。)RGBQUAD値は、宛先デバイスにピクセルごとに適用されます。

まだ問題がある場合は、ピクセルデータと対応するカラーテーブルの形式が正しく表示されているかどうかを確認するために、BITMAPINFOとカラーテーブルを詳しく見ていきたいと思います。

+0

残念ながら、私はその選択の自由を持っていません。 DxWndはGDI32、USER32、DDRAWなどのライブラリ呼び出しをインターセプトし、プログラムフローをフッカールーチンに再ルーティングするAPIフッカーです。G-Nome PCゲームでは、入力時にDIB_PAL_COLORS画像を持つSetDIBitToDevice呼び出しを呼び出すことによって、フレームをビデオにレンダリングすることが検出されました。だから、私は同じ入力を受け取り、カスタムサイズとデスクトップネイティブの色深度でウィンドウの表面にDIBをblitする必要がありますが、私はプログラムの実行可能ファイル(利用可能なCコードなし)の仕方を変更することはできませんフカールーチンを書くことができます。 – gho

+0

質問を誤解していない限り、ソースゲームを変更する必要はありません。正しいことをする必要があるのはあなたのフック機能です。 –

+0

私は混乱しています:MSIBによると、DIB_RGB_COLORS DIBはBITMAPINFOHEADERの後にRGBQUAD配列が続き、DIB_PAL_COLORS DIBの後にパレットにWORDインデックスの配列が続きます(私のメモリダンプはインデックス配列の直後であることが示されています)異なるColorUse値はランダムな色を導くはずです。 実際に、私はあなたが提案したことを行い、結果は私が今までに持っていた最高のものの1つでした。ほとんどの色は大丈夫ですが、スクリーンショットを見るとマゼンタピクセルの割合が大きくなります。終了しましたが、透明性の問題があります... – gho

0

ああ、私は犯人を持っていると思う:別のDxWndの娼婦がRC_PALETTEの能力をGetDeviceCaps()に偽っていた。この偽の機能を削除すると、ゲームはもはやDIB_PAL_COLORS形式を使用しようとせず、より管理しやすいDIB_RGB_COLORS DIBを構築します。問題は修正されました。間違ったトラックにご迷惑をおかけしました。ありがとうございます。

関連する問題