画像処理について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら

トピックに返信する


答えを正確にご入力ください。答えられるかどうかでスパムボットか否かを判定します。

BBCode: ON
[img]: ON
[flash]: OFF
[url]: ON
スマイリー: OFF

トピックのレビュー
   

展開ビュー トピックのレビュー: 画像処理について

Re: 画像処理について

#13

by スムージー » 3年前

あたっしゅ様、返信遅れてしまい申し訳ございません。
書き込んでいただいたプログラム確認しました。私の環境でも正常に動作しました。
あたっしゅ様のプログラムを参考に(というより丸写しなきがしますが…)描画したい内容を、60近いFPSで実現することが出来ました。

コード:

include "DxLib.h"
#include "c_select.h"
#include "battle.h"
#include "key_input.h"
#include "pad_input.h"
#include "effect.h"

static  int gcr = 0;//色成分
static  int gcg = 0;//色成分
static  int gcb = 0;//色成分
static  int gca = 0;//色成分




//シーン操作
static int scene = 1;

int handle = MakeScreen(320, 224, TRUE);//仮グラフィックハンドル
// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	
	SetGraphMode(960, 672, 32);
	
	ChangeWindowMode(TRUE);
	
	SetWindowSizeExtendRate(1);
	SetWindowSizeChangeEnableFlag(TRUE);
	




	if (DxLib_Init() == -1)		// DXライブラリ初期化処理
	{
		return -1;			// エラーが起きたら直ちに終了
	}

	C_S_Set();//キャラセレクト初期化
	effect_set();

while (ProcessMessage() == 0 ) {

	//裏画面の内容を初期化する
	SetDrawScreen(DX_SCREEN_BACK);
	ClearDrawScreen();




	key_update();
	pad_update();
	fade_update();

	switch (scene) {
	case 1:
		C_S__Update();
		C_S__Draw();
		break;
	case 2:
		chara_update();
		chara_draw();
		break;

	}
	//エフェクト
	fade_update();
	fade_draw();

	// 空のフルカラー画像を作成する
	int hSrc = MakeARGB8ColorSoftImage(320, 224);
	int hDst = MakeARGB8ColorSoftImage(960, 672);

	GetDrawScreenSoftImage(0, 0, 320, 224, hSrc);

	// 描画対象を裏画面にする
	SetDrawScreen(DX_SCREEN_BACK);
	

			for (int y = 0; y < 224; y++)
			{
				for (int x = 0; x < 320; x++)
				{
					//1ドットの色を取得
					GetPixelSoftImage(hSrc, x, y, &gcr, &gcg, &gcb, &gca);

					for (int L = 0; L < 3;L++){
						DrawPixelSoftImage_Unsafe_ARGB8(hDst, x * 3, y * 3 + L, gcr, 0, 0, 255);
					}

					for (int L = 0; L < 3; L++) {
						DrawPixelSoftImage_Unsafe_ARGB8(hDst, x * 3 + 1, y * 3 + L, 0, gcg, 0, 255);
					}

					for (int L = 0; L < 3; L++) {
						DrawPixelSoftImage_Unsafe_ARGB8(hDst, x * 3 + 2, y * 3 + L, 0, 0, gcb, 255);
					}
				}
			}


		

		// グラフィックハンドルを作成
		int grhandle = CreateGraphFromSoftImage(hDst);

		// グラフィックハンドルを描画
		DrawGraph(0, 0, grhandle, TRUE);

		// グラフィックハンドルの削除
		DeleteGraph(grhandle);

		// 使い終わったら解放
		DeleteSoftImage(hDst);
		DeleteSoftImage(hSrc);
	
	
	ScreenFlip();
}
	DxLib_End();				// DXライブラリ使用の終了処理

	return 0;				// ソフトの終了 
}

int g_m_get() {
	return gamemode;
}

void scene_set(int num) {
	scene = num;
}
CPUで扱うイメージ関係で後ろに"_Unsafe_ARGB8"がついてる関数は何だろうと思ったら、隠し関数なんですね。通常の物より(的確なコードが求められますが)高速に処理ができるようで、知ることが出来て良かったです。

目的が達成できたため、とりあえず解決とはしますが、ISLe様のおっしゃっていたピクセルシェーダーというのはとても興味深いものなので、個人的に取り組んでみたいと思います。

最期に、コメントしてくださったあたっしゅ様、ISLe様、どうもありがとうございました。
また、この掲示板を利用する機会があると思いますが、その時もどうぞよろしくお願いします。

Re: 画像処理について

#12

by あたっしゅ » 3年前

東上☆海美☆「
眠れなかったので、作ってみたみみ

コード:

//
//
//
#include "DxLib.h"
//#include "c_select.h"
//#include "key_input.h"
//#include "pad_input.h"
//#include "effect.h"


static 	unsigned int sgc;//スポイト用

static  int gcr = 0;//色成分
static  int gcg = 0;//色成分
static  int gcb = 0;//色成分

// プログラムは WinMain から始まります
int
WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{

	SetGraphMode(960, 772, 16);

	ChangeWindowMode(TRUE);

	SetWindowSizeExtendRate(1);
	SetWindowSizeChangeEnableFlag(TRUE);

	int scene = 1;//シーン

	if (DxLib_Init() == -1)		// DXライブラリ初期化処理
	{
		return -1;			// エラーが起きたら直ちに終了
	}

#if 0
	// 透明かどうかわかるように画面を緑で塗りつぶす
	DrawBox(0, 0, 255, 255, GetColor(0, 255, 0), TRUE);
	{
		// 空のフルカラー画像を作成する
		int handle = MakeARGB8ColorSoftImage(256, 256);

		GetDrawScreenSoftImage( 0, 0, 255, 255, handle );
			// 描画対象の画面から指定領域をソフトウエアイメージハンドルに転送する

		// 縦方向に透明グラデーションした真っ赤な画像を作成する
		for (int i = 0; i < 256; i++)
		{
			for (int j = 0; j < 128; j++)
			{
				// 色をセット
				DrawPixelSoftImage(handle, j, i, 255, 0, 0, i);
			}
		}

		// グラフィックハンドルを作成
		int grhandle = CreateGraphFromSoftImage(handle);

		// グラフィックハンドルを描画
		DrawGraph(0, 0, grhandle, TRUE);

		// グラフィックハンドルの削除
		DeleteGraph(grhandle);

		// 使い終わったら解放
		DeleteSoftImage(handle);
	}

	// キー入力待ち
	WaitKey();
#endif

	//C_S_Set();
	//effect_set();

	int t = 0;

	while (ProcessMessage() == 0) {

		SetDrawScreen(DX_SCREEN_BACK);
		ClearDrawScreen();

		//key_update();
		//pad_update();
		//fade_update();

#if 0
		int handle;
		handle = MakeScreen(320, 224, TRUE);

		int handle2;
		handle2 = MakeScreen(960, 772, TRUE);

		SetDrawScreen(handle);


		switch (scene) {
		case 1:
			//C_S__Update();
			//C_S__Draw();
			break;

		}
		//エフェクト
		//fade_update();
		//fade_draw();
#endif
		{
			int Cr = GetColor(64, 255, 128);

			// 円を描画
			DrawCircle(32+t, 32, 32, Cr, FALSE);
			t++;
			if (t > 64) {
				t = 0;
			}
		}

#if 0
		//変換
		{
			//int i = 0;

			//if (i == 0) {
				for (int x = 0; x < 64; x++) {
					for (int y = 0; y < 64; y++) {
						//SetDrawScreen(handle);
						sgc = GetPixel(x, y);
						GetColor2(sgc, &gcr, &gcg, &gcb);
						//SetDrawScreen(handle2);

						DrawLine(x * 3, y * 3, x * 3, y * 3 + 2, GetColor(gcr, 0, 0));
						DrawLine(x * 3 + 1, y * 3, x * 3, y * 3 + 2, GetColor(0, gcg, 0));
						DrawLine(x * 3 + 2, y * 3, x * 3, y * 3 + 2, GetColor(0, 0, gcb));
					}
				}
			//}
		}
#else
		{
			// 空のフルカラー画像を作成する
			int hSrc = MakeARGB8ColorSoftImage(256, 256);
			int hDst = MakeARGB8ColorSoftImage(256, 256);

			GetDrawScreenSoftImage(0, 0, 255, 255, hSrc);
			// 描画対象の画面から指定領域をソフトウエアイメージハンドルに転送する

			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					int r, g, b, a;

					GetPixelSoftImage_Unsafe_ARGB8( hSrc, j, i, &r, &g, &b, &a );

					// 色をセット
					for (int k = 0; k < 3; k++) {
						DrawPixelSoftImage_Unsafe_ARGB8(hDst, j * 3, i * 3+k, r, 0, 0, a);
					}
					for (int k = 0; k < 3; k++) {
						DrawPixelSoftImage_Unsafe_ARGB8(hDst, j * 3 + 1, i * 3 + k, 0, g, 0, a);
					}
					for (int k = 0; k < 3; k++) {
						DrawPixelSoftImage_Unsafe_ARGB8(hDst, j * 3 + 2, i * 3 + k, 0, 0, b, a);
					}
				}
			}

			// グラフィックハンドルを作成
			int grhandle = CreateGraphFromSoftImage(hDst);

			// グラフィックハンドルを描画
			DrawGraph(0, 0, grhandle, TRUE);

			// グラフィックハンドルの削除
			DeleteGraph(grhandle);

			// 使い終わったら解放
			DeleteSoftImage(hDst);
			DeleteSoftImage(hSrc);
		}
#endif

		// 描画対象を裏画面にする
		SetDrawScreen(DX_SCREEN_BACK);


		//DrawGraph(0, 0, handle2, TRUE);

#if 0
		DeleteGraph(handle);
		DeleteGraph(handle2);
#endif
		ScreenFlip();
	}

	DxLib_End();				// DXライブラリ使用の終了処理

	return 0;				// ソフトの終了 
}


// end.
手提鞄あたっしゅ、「
かなり荒っぽいが、どうでしょうか ?

Re: 画像処理について

#11

by スムージー » 3年前

あたっしゅ さんが書きました:
3年前
WinG(ウィンジー)とか DirectDraw を使う物が、DxLib にも、あるはず。
C++Builder だと、ScanLIne に、当たる奴が。
GDI を使わないで、直接メモリを扱うんだが。
あたっしゅ様ご返信ありがとうございます。
「DirectDraw を使う物がDxLib にもある」とのことですが、
それは、DXLib内のグラフィックデータ制御関数のことを指しているのでしょうか。
それとも、上記とは別にDXライブラリにDirectXのDirectDrawに相当するようなものがあるのでしょうか。
私の認識だと、DXライブラリは"DirectXの機能を簡易的なものにしたもの"なので、前者の方しか想像できません。
私のDirectXの知識や国語力が乏しいためか、ご返信の内容がよく分かりませんでした。
差し支えなければ、もう少し詳しく、"DXLibのDirectDrawを使う物"について教えていただけないでしょうか。

Re: 画像処理について

#10

by あたっしゅ » 3年前

WinG(ウィンジー)とか DirectDraw を使う物が、DxLib にも、あるはず。
C++Builder だと、ScanLIne に、当たる奴が。
GDI を使わないで、直接メモリを扱うんだが。

Re: 画像処理について

#9

by スムージー » 3年前

あたっしゅ様コメントありがとうございます。
画面情報を読み込むイメージとは別に、描画用のイメージを作りDrawPixelSoftimage関数で線を書き込んでみたんですが、イメージの内容を描画するためにCreateGraphFromSoftImage()を使いイメージからハンドルを作ろうとしたところ、これもまた重くなってしまいました。(イメージを画面に描画するDrawSoftImage関数のリファレンスに負荷が非常に高いということなので、ハンドルにする際も同様に負荷がかかるのだと思います)

コード:

#include "DxLib.h"
#include "c_select.h"
#include "battle.h"
#include "key_input.h"
#include "pad_input.h"
#include "effect.h"

static  int gcr = 0;//色成分
static  int gcg = 0;//色成分
static  int gcb = 0;//色成分
static  int gca = 0;//色成分

//シーン操作
static int scene = 1;

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	
	SetGraphMode(960, 672, 32);
	
	//ChangeWindowMode(TRUE);


	SetWindowSizeExtendRate(1);
	SetWindowSizeChangeEnableFlag(TRUE);
	

	if (DxLib_Init() == -1)		// DXライブラリ初期化処理
	{
		return -1;			// エラーが起きたら直ちに終了
	}

	C_S_Set();
	effect_set();
int SoftImage = MakeXRGB8ColorSoftImage(320, 224);
int SoftImage2 = MakeXRGB8ColorSoftImage(960, 672);
int handle;//仮グラフィックハンドル
handle = MakeScreen(320, 224, TRUE);

while (ProcessMessage() == 0 ) {

	//裏画面の内容を初期化する
	SetDrawScreen(DX_SCREEN_BACK);
	ClearDrawScreen();
	
	// 作成した画像を描画対象にする
	SetDrawScreen(handle);

	key_update();
	pad_update();
	fade_update();

	switch (scene) {
	case 1:
		C_S__Update();
		C_S__Draw();
		break;
	case 2:
		chara_update();
		chara_draw();
		break;

	}
	//エフェクト
	fade_update();
	fade_draw();



	// 描画先の画像情報を「CPUで扱うイメージ」に取り込み
	GetDrawScreenSoftImage(0, 0, 320, 224, SoftImage);

	// 描画対象を裏画面にする
	SetDrawScreen(DX_SCREEN_BACK);
	
	
	for (int y = 0; y < 224; y++)
		{
			for (int x = 0; x < 320; x++)
			{
				// 1ドットの色を取得
				GetPixelSoftImage(SoftImage, x, y, &gcr, &gcg, &gcb, &gca);

				DrawPixelSoftImage(SoftImage2,x*3,y*3,gcr,0,0,gca);
				DrawPixelSoftImage(SoftImage2, x*3, y*3+1, gcr, 0, 0, gca);
				DrawPixelSoftImage(SoftImage2, x*3, y*3+2, gcr, 0, 0, gca);

				DrawPixelSoftImage(SoftImage2,x*3+1,y*3,0,gcg,0,gca);
				DrawPixelSoftImage(SoftImage2, x*3+1, y*3+1, 0, gcg, 0, gca);
				DrawPixelSoftImage(SoftImage2, x*3+1, y*3+2, 0, gcg, 0, gca);

				DrawPixelSoftImage(SoftImage2,x*3+2,y*3,0,gcg,0,gca);
				DrawPixelSoftImage(SoftImage2, x*3+2, y*3+1, 0, gcg, 0, gca);
				DrawPixelSoftImage(SoftImage2, x*3+2, y*3+2, 0, gcg, 0, gca);
			}
		}
	Softhg = CreateGraphFromSoftImage(SoftImage2);

	//DrawGraph(0, 0, Softhg, TRUE);

		

	

	
	


	ScreenFlip();
}
//グラフィックハンドルの削除
	DeleteGraph(handle);
	DeleteSoftImage(SoftImage);
	DeleteSoftImage(SoftImage2);

	DxLib_End();				// DXライブラリ使用の終了処理

	return 0;				// ソフトの終了 
}

Re: 画像処理について

#8

by スムージー » 3年前

ISLe様ありがとうございます。
ピクセルシェーダーというのがあるのですね。調べてみます。

Re: 画像処理について

#7

by あたっしゅ » 3年前

GetPixelSoftImage関数と対になる関数として

int DrawPixelSoftImage( int SIHandle, int x, int y, int r, int g, int b, int a ) ;

というのを見つけた。

Re: 画像処理について

#6

by ISLe » 3年前

高速かつ自由度が高いのは、ピクセルシェーダーを使う方法です。
ブラウン管風の表現とか通信ノイズの表現とかシェーダープログラム次第でいろいろできます。

Re: 画像処理について

#5

by スムージー » 3年前

あたっしゅ さんが書きました:
3年前
ちょっと忙しいので、とりあえず。

viewtopic.php?t=14569
WindowsAPI GetPixelについて - ミクプラ(ja)

確・定・申・告 !
あたっしゅ様ありがとうございます。
そちらのURLを参考に再び考えてみます。

Re: 画像処理について

#4

by スムージー » 3年前

GetPixel2関数を用いずに、一度描画先をCPUで扱うイメージに取り込んだ後GetPixelSoftImage関数を用いることで、より高速に色を取得することが出来ました。
ソースコードはこちらです。

コード:

#include "DxLib.h"
#include "c_select.h"
#include "battle.h"
#include "key_input.h"
#include "pad_input.h"
#include "effect.h"


static  int gcr = 0;//色成分
static  int gcg = 0;//色成分
static  int gcb = 0;//色成分
static  int gca = 0;//色成分

sta
//シーン操作
static int scene = 1;
// 「CPUで扱うイメージ」を作成
//static int SoftImage = MakeXRGB8ColorSoftImage(320, 224);
//static int SoftImage2 = MakeXRGB8ColorSoftImage(960, 672);

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{

	SetGraphMode(960, 672, 32);
	
	ChangeWindowMode(TRUE);
	SetWindowSizeExtendRate(1);
	SetWindowSizeChangeEnableFlag(TRUE);

	if (DxLib_Init() == -1)		// DXライブラリ初期化処理
	{
		return -1;			// エラーが起きたら直ちに終了
	}

	C_S_Set();
	effect_set();

	int SoftImage = MakeXRGB8ColorSoftImage(320, 224);
	int handle;//仮グラフィックハンドル
	handle = MakeScreen(320, 224, TRUE);

while (ProcessMessage() == 0 ) {

	//裏画面の内容を初期化する
	SetDrawScreen(DX_SCREEN_BACK);
	ClearDrawScreen();


	// 作成した画像を描画対象にする
	SetDrawScreen(handle);

	key_update();
	pad_update();
	fade_update();

	switch (scene) {
	case 1:
		C_S__Update();
		C_S__Draw();
		break;
	case 2:
		chara_update();
		chara_draw();
		break;

	}
	//エフェクト
	fade_update();
	fade_draw();



	// 描画先の画像情報を「CPUで扱うイメージ」に取り込み
	GetDrawScreenSoftImage(0, 0, 320, 224, SoftImage);

	// 描画対象を裏画面にする
	SetDrawScreen(DX_SCREEN_BACK);
	
		

		
		if (stype == 1) {
			for (int y = 0; y < 224; y++)
			{
				for (int x = 0; x < 320; x++)
				{
					// 1ドットの色を取得
					GetPixelSoftImage(SoftImage, x, y, &gcr, &gcg, &gcb, &gca);

					DrawLine(x * 3, y * 3, x * 3, y * 3 + 3, GetColor(gcr, 0, 0), TRUE);
					DrawLine(x * 3 + 1, y * 3, x * 3 + 1, y * 3 + 3, GetColor(0, gcg, 0), TRUE);
					DrawLine(x * 3 + 2, y * 3, x * 3 + 2, y * 3 + 3, GetColor(0, 0, gcb), TRUE);

				}
			}

		}

	
		

	}
	ScreenFlip();
}
//グラフィックハンドルの削除
	DeleteGraph(handle);
	DeleteSoftImage(SoftImage);

	DxLib_End();				// DXライブラリ使用の終了処理

	return 0;				// ソフトの終了 
}

画面の色の高速な取得はできるようになったのですが、DrawLineの処理が重く60fpsを維持することが出来ませんでした。
for文中のDrawLine関数の回数別にFPSを測ったところ、
1回(Rのみ)...58.1~59.1
2回(RとG)...47.5~48.8
3回(R,G,B)...36.5~38.6
というような結果になり、DrawLineを用いる回数が多くなるほどfpsが低くなるようになりました。

3回用いた場合でも60FPS近くを維持するにはどのようにすればよいでしょうか。

Re: 画像処理について

#3

by あたっしゅ » 3年前

ちょっと忙しいので、とりあえず。

viewtopic.php?t=14569
WindowsAPI GetPixelについて - ミクプラ(ja)

確・定・申・告 !

Re: 画像処理について

#2

by スムージー » 3年前

すいません。「変換」の所のif分の閉じかっこが抜けているのはミスです。

画像処理について

#1

by スムージー » 3年前

現在Visual Studio 2019とDXライブラリでゲーム制作を行ってるものです。
ゲーム画面をブラウン管風の画面にしたいと思い、MakeScreenで作ったグラフィックに描画したものからGetPixel2でRGBを取得し、各色成分ごとに縦に並べるというプログラムを組みました。
下記のようなものです。

コード:

#include "DxLib.h"
#include "c_select.h"
#include "key_input.h"
#include "pad_input.h"
#include "effect.h"


static 	unsigned int sgc;//スポイト用

static  int gcr = 0;//色成分
static  int gcg = 0;//色成分
static  int gcb = 0;//色成分

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{

	SetGraphMode(960, 772, 16);

	ChangeWindowMode(TRUE);

	SetWindowSizeExtendRate(1);
	SetWindowSizeChangeEnableFlag(TRUE);
	


	int scene = 1;//シーン

	if (DxLib_Init() == -1)		// DXライブラリ初期化処理
	{
		return -1;			// エラーが起きたら直ちに終了
	}

	C_S_Set();
	effect_set();

while (ProcessMessage() == 0 ) {

	SetDrawScreen(DX_SCREEN_BACK);
	ClearDrawScreen();


	key_update();
	pad_update();
	fade_update();

	int handle;
	handle = MakeScreen(320, 224, TRUE);

	int handle2;
	handle2 = MakeScreen(960, 772, TRUE);

	SetDrawScreen(handle);


	switch (scene) {
	case 1:
		C_S__Update();
		C_S__Draw();
		break;

	}
	//エフェクト
	fade_update();
	fade_draw();

	//変換
	if (int i = 0 == 0 {
		for (int x = 0; x < 64; x++) {
			for (int y = 0; y < 64; y++) {
				SetDrawScreen(handle);
				sgc = GetPixel(x, y);
				GetColor2(sgc, &gcr, &gcg, &gcb);
				SetDrawScreen(handle2);
				DrawLine(x * 3, y * 3, x * 3, y * 3 + 2, GetColor(gcr, 0, 0));
				DrawLine(x * 3 + 1, y * 3, x * 3, y * 3 + 2, GetColor(0, gcg, 0));
				DrawLine(x * 3 + 2, y * 3, x * 3, y * 3 + 2, GetColor(0, 0, gcb));
			}
		}
	}
	// 描画対象を裏画面にする
	SetDrawScreen(DX_SCREEN_BACK);


	//DrawGraph(0, 0, handle2, TRUE);


	DeleteGraph(handle);
	DeleteGraph(handle2);

	ScreenFlip();
}

	DxLib_End();				// DXライブラリ使用の終了処理

	return 0;				// ソフトの終了 
}
しかし、リファレンスにもある通りGetPixel2関数は非常に処理が重く、とても低いフレームレートで動作するようになってしまいました。
ここで皆さんにお聞きしたいのは、
①GetPixelよりも動作が軽い色を取得する方法
②ブラウン管風の画面を描画する他の方法
です。
私も考えているところですが、皆さまからの助言を頂ければと考えています。
わかりにくい文章でしたら、申し訳ございません。何卒、よろしくお願いします。

ページトップ