トップページ > 記事閲覧
GetDesktopScreenGraphMemImageの使い方
名前:ケーキ 日時: 2020/06/26 14:17

DXライブラリに存在するGetDesktopScreenGraphMemImageの使い方を教えてほしいです 調べてみましたが、使い方が見つからず、また、ヘッダ内のコメントの説明だけでは使いこなすことはできませんでした 私がやりたいことは、ディスプレイ2の画面を毎フレーム取得し、1フレーム前のものと比較して 特定の色かつ、変化のあった座標を取得したいです // 以下ヘッダの説明を見て書いてみたものです // 動作はしませんが、やろうとしているが伝わるかもしれないので一応載せておきます int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // ウインドウモードで起動 ChangeWindowMode(TRUE); // ウインドウのサイズは 1280x720 SetGraphMode(1280, 720, 32); // DXライブラリ初期化処理 if (DxLib_Init() == -1) { return -1; // エラーが起きたら直ちに終了 } SetDrawScreen(DX_SCREEN_BACK); const vec2 screen_size(1920, 1280); std::vector<vec2> pos; int *old = nullptr; // キャプチャ用の 1920x1080 のアルファチャンネル無しのグラフィックハンドルを作成 int CaptureGrHandle = MakeScreen(screen_size.x, screen_size.y, FALSE); // キーが押されるまでループします while (ProcessMessage() == 0) { ClearDrawScreen(); // デスクトップの画像を取得 GetDesktopScreenGraph(0, 0, screen_size.x, screen_size.y, CaptureGrHandle); // デスクトップ画面から指定領域の画像のメモリイメージの先頭アドレスとイメージの幅・高さ・ストライドを取得する( イメージのフォーマットは ColorBitDepth = 32( バイト順で B8G8R8X8 の 32bitカラー ) ColorBitDepth = 24( バイト順で B8G8R8 の 24bitカラー ) ) int width, height, *stride; GetDesktopScreenGraphMemImage(0, 0, screen_size.x, screen_size.y, &width, &height, stride, 24); if (old == nullptr) continue; for (int ix = 0; ix < width; ix++) { for (int iy = 0; iy < height; iy++) { stride[iy * width + ix] != old[iy * width + ix]; pos.push_back(vec2(ix, iy)); } } old = stride; // 1280x720 のウインドウに縮小して描画 DrawExtendGraph(0, 0, 1280, 720, CaptureGrHandle, FALSE); //DrawBox(0, 0, 300, 300, GetColor(255, 0, 0), TRUE); ScreenFlip(); } // DXライブラリ使用の終了処理 DxLib_End(); return 0; // ソフトの終了 }
メンテ

Page: 1 |

Re: GetDesktopScreenGraphMemImageの使い方 ( No.1 )
名前:管理人 日時:2020/06/28 01:02

GetDesktopScreenGraphMemImage はポインタについて熟知していないと扱うのは難しいです 引数や戻り値の解説は以下の通りです // デスクトップ画面から指定領域の画像のメモリイメージの先頭アドレスとイメージの幅・高さ・ストライドを取得する // ( イメージのフォーマットは ColorBitDepth = 32( バイト順で B8G8R8X8 の 32bitカラー ) ColorBitDepth = 24( バイト順で B8G8R8 の 24bitカラー ) ) // // <引数> // x1, y1 : イメージを取得したいデスクトップ上の領域の左上座標 // x2, y2 : イメージを取得したいデスクトップ上の領域の右下座標 // Width : 取り込んだ領域の幅を格納するint型変数のアドレス // Height : 取り込んだ領域の高さを格納するint型変数のアドレス // Stride : 取り込んだ画像の1ライン辺りのバイト数を格納するint型変数のアドレス // ColorBitDepth : 32( バイト順で B8G8R8X8 の 32bitカラー ) 24( バイト順で B8G8R8 の 24bitカラー ) // // <戻り値> // 取り込んだ画像のイメージが格納されているメモリ領域の先頭アドレス void *GetDesktopScreenGraphMemImage( int x1, int y1, int x2, int y2, int *Width, int *Height, int *Stride, int ColorBitDepth ) ; 載せていただいたコードを拝見する限りではケーキさんはポインタについて、この関数が使用できるほどには理解をされていないとお見受けします とりあえずデスクトップ画面の左上の 640x480 の領域の『1フレーム前と色の変化が発生した部分のみ赤色に、それ以外は水色に表示される』プログラムを 組んでみましたので、よろしければご覧ください #include "DxLib.h" #include <memory.h> #define CAPTURE_W 640 #define CAPTURE_H 480 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { void *Image ; int Width ; int Height ; int Stride ; int TempSoftImage ; void *TempSoftImageAddr ; int BackupSoftImage ; void *BackupSoftImageAddr ; int i, j ; // ウインドウモードで起動 ChangeWindowMode( TRUE ) ; // キャプチャするサイズと同じ画面のサイズに設定 SetGraphMode( CAPTURE_W, CAPTURE_H, 32 ) ; // ウィンドウが非アクティブな状態でも動作するようにする SetAlwaysRunFlag( TRUE ) ; // DXライブラリの初期化 if( DxLib_Init() < 0 ) return -1 ; // 描画先を裏画面にする SetDrawScreen( DX_SCREEN_BACK ) ; // 描画用ソフトイメージを作成 TempSoftImage = MakeXRGB8ColorSoftImage( CAPTURE_W, CAPTURE_H ) ; // 描画用ソフトイメージの実イメージが格納されているメモリアドレスを取得 TempSoftImageAddr = GetImageAddressSoftImage( TempSoftImage ) ; // 1フレーム前の画像保存用ソフトイメージを作成 BackupSoftImage = MakeXRGB8ColorSoftImage( CAPTURE_W, CAPTURE_H ) ; // 1フレーム前の画像保存用ソフトイメージの実イメージが格納されているメモリアドレスを取得 BackupSoftImageAddr = GetImageAddressSoftImage( BackupSoftImage ) ; // 1フレーム前の画像保存用ソフトイメージをクリア memset( BackupSoftImageAddr, 0, CAPTURE_W * 4 * CAPTURE_H ) ; // メインループ while( ProcessMessage() == 0 ) { // 画面のクリア ClearDrawScreen() ; // デスクトップ画面左上のイメージを取得 Image = GetDesktopScreenGraphMemImage( 0, 0, CAPTURE_W, CAPTURE_H, &Width, &Height, &Stride, 32 ) ; // 描画用ソフトイメージに1フレーム前の画像保存用ソフトイメージと色の違う所のみを赤色を格納、それ以外は水色 for( i = 0; i < CAPTURE_H ; i++ ) { for( j = 0; j < CAPTURE_W; j++ ) { if( *( ( DWORD * )( ( BYTE * )Image + j * 4 + i * Stride ) ) != *( ( DWORD * )( ( BYTE * )BackupSoftImageAddr + j * 4 + i * CAPTURE_W * 4 ) ) ) { *( ( DWORD * )( ( BYTE * )TempSoftImageAddr + j * 4 + i * CAPTURE_W * 4 ) ) = 0x00ff0000 ; } else { *( ( DWORD * )( ( BYTE * )TempSoftImageAddr + j * 4 + i * CAPTURE_W * 4 ) ) = 0x0000ffff ; } } } // 1フレーム前の画像保存用ソフトイメージに現在のフレームのイメージを保存 for( i = 0; i < CAPTURE_H ; i++ ) { for( j = 0; j < CAPTURE_W; j++ ) { *( ( DWORD * )( ( BYTE * )BackupSoftImageAddr + j * 4 + i * CAPTURE_W * 4 ) ) = *( ( DWORD * )( ( BYTE * )Image + j * 4 + i * Stride ) ) ; } } // 現在のフレームと1フレーム前の画像の差異の結果を画面に描画する DrawSoftImage( 0, 0, TempSoftImage ) ; // 裏画面の内容を表画面に反映 ScreenFlip() ; } // DXライブラリの後始末 DxLib_End() ; // ソフトの終了 return 0 ; }
メンテ
Re: GetDesktopScreenGraphMemImageの使い方 ( No.2 )
名前:ケーキ (解決) 日時:2020/07/01 14:22

ご回答ありがとうございました サンプルコードで関数の使い方がわかりました とりあえずスクリーン全体の変化地点だけを赤くして、それ以外を縮小表示するウィンドウを作れました 座標も保存することができたので、想像通りのものが作れそうです 動作しないコードで申し訳ないのですが、変更後のコードを貼っておきます const vec2 SCREEN_SIZE(1920, 1080); const vec2 WINDOW_SIZE(SCREEN_SIZE.x / 2, SCREEN_SIZE.y / 2); // デスクトップ画面から指定領域の画像のメモリイメージの先頭アドレスとイメージの幅・高さ・ストライドを取得する // ( イメージのフォーマットは ColorBitDepth = 32( バイト順で B8G8R8X8 の 32bitカラー ) ColorBitDepth = 24( バイト順で B8G8R8 の 24bitカラー ) ) // // <引数> // x1, y1 : イメージを取得したいデスクトップ上の領域の左上座標 // x2, y2 : イメージを取得したいデスクトップ上の領域の右下座標 // Width : 取り込んだ領域の幅を格納するint型変数のアドレス // Height : 取り込んだ領域の高さを格納するint型変数のアドレス // Stride : 取り込んだ画像の1ライン辺りのバイト数を格納するint型変数のアドレス // ColorBitDepth : 32( バイト順で B8G8R8X8 の 32bitカラー ) 24( バイト順で B8G8R8 の 24bitカラー ) // // <戻り値> // 取り込んだ画像のイメージが格納されているメモリ領域の先頭アドレス int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { void* Image; int Width; int Height; int Stride; int TempSoftImage; void* TempSoftImageAddr; int BackupSoftImage; void* BackupSoftImageAddr; int i, j; // ウインドウモードで起動 ChangeWindowMode(TRUE); // キャプチャするサイズと同じ画面のサイズに設定 SetGraphMode(WINDOW_SIZE.x, WINDOW_SIZE.y, 32); // ウィンドウが非アクティブな状態でも動作するようにする SetAlwaysRunFlag(TRUE); // DXライブラリの初期化 if (DxLib_Init() < 0) return -1; // 描画先を裏画面にする SetDrawScreen(DX_SCREEN_BACK); // 描画用ソフトイメージを作成 TempSoftImage = MakeXRGB8ColorSoftImage(CAPTURE_W, CAPTURE_H); // 描画用ソフトイメージの実イメージが格納されているメモリアドレスを取得 TempSoftImageAddr = GetImageAddressSoftImage(TempSoftImage); // 1フレーム前の画像保存用ソフトイメージを作成 BackupSoftImage = MakeXRGB8ColorSoftImage(CAPTURE_W, CAPTURE_H); // 1フレーム前の画像保存用ソフトイメージの実イメージが格納されているメモリアドレスを取得 BackupSoftImageAddr = GetImageAddressSoftImage(BackupSoftImage); // 1フレーム前の画像保存用ソフトイメージをクリア memset(BackupSoftImageAddr, 0, CAPTURE_W * 4 * CAPTURE_H); // メインループ while (ProcessMessage() == 0) { // 画面のクリア ClearDrawScreen(); std::vector<vec2> pos; // デスクトップ画面左上のイメージを取得 Image = GetDesktopScreenGraphMemImage(0, 0, CAPTURE_W, CAPTURE_H, &Width, &Height, &Stride, 32); // 描画用ソフトイメージに1フレーム前の画像保存用ソフトイメージと色の違う所のみを赤色を格納、それ以外は水色 for (i = 0; i < CAPTURE_H; i++) { for (j = 0; j < CAPTURE_W; j++) { if (*((DWORD*)((BYTE*)Image + j * 4 + i * Stride)) != *((DWORD*)((BYTE*)BackupSoftImageAddr + j * 4 + i * CAPTURE_W * 4))) { *((DWORD*)((BYTE*)TempSoftImageAddr + j * 4 + i * CAPTURE_W * 4)) = 0x00ff0000; pos.push_back(vec2(i, j)); } else { *((DWORD*)((BYTE*)TempSoftImageAddr + j * 4 + i * CAPTURE_W * 4)) = *((DWORD*)((BYTE*)Image + j * 4 + i * Stride)); } } } // 1フレーム前の画像保存用ソフトイメージに現在のフレームのイメージを保存 for (i = 0; i < CAPTURE_H; i++) { for (j = 0; j < CAPTURE_W; j++) { *((DWORD*)((BYTE*)BackupSoftImageAddr + j * 4 + i * CAPTURE_W * 4)) = *((DWORD*)((BYTE*)Image + j * 4 + i * Stride)); } } int screen_handle = MakeScreen(CAPTURE_W, CAPTURE_H); SetDrawScreen(screen_handle); // 現在のフレームと1フレーム前の画像の差異の結果を画面に描画する DrawSoftImage(0, 0, TempSoftImage); SetDrawScreen(DX_SCREEN_BACK); DrawExtendGraph(0, 0, WINDOW_SIZE.x, WINDOW_SIZE.y, screen_handle, TRUE); // 裏画面の内容を表画面に反映 ScreenFlip(); } // DXライブラリの後始末 DxLib_End(); // ソフトの終了 return 0; }
メンテ

Page: 1 |

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

   クッキー保存