ビットマップ


ピクセルデータを描画する

これまでは、点や線、ポリゴンをウィンドウに表示してきました
しかし、これだけでは複雑な図を3次元の世界で描画するのは難しいでしょう
OpenGL では、これ以外にも画像データを描画する手段を提供しています
高度なグラフィックス処理や、華やかなプログラムの実現には欠かせないものですね

ピクセル単位の情報を格納した配列として、ビットマップを描画することができます
ビットマップとは OpenGL の用語で、描画するかしないかを表す情報を格納した配列のことです
形式的には、OS/2 や Windows の2色モノクロ DIB に等しいものです
0 であればピクセルは更新されず、1 であればピクセルを上書きすることを表します

OpenGL の座標系は、デフォルトで下から上へ Y 座標が加算される性質なので
配列は実際に描画される方形の下の列から順に格納されている必要があります
(DIB のボトムアップ形式の配列は OpenGL にとって都合の良いものです)

配列 16進数ピクセル
8A
5F
6A
DF
55
DF
55
5F
■□□□■□■□
□■□■■■■■
□■■□■□■□
■■□■■■■■
□■□■□■□■
■■□■■■■■
□■□■□■□■
□■□■■■■■

例えば、ビットマップを使うことによって、このようなフォントを作成することができるでしょう
ただし、実際にプログラムするときは 0x5F , 0x55 というように、下の列を先頭にします

ビットマップや画像が描画される地点は、現在のラスタ位置という属性に影響されます
ラスタ位置は glRasterPos() 関数から設定することができます
void glRasterPos2d(GLdouble x , GLdouble y);
void glRasterPos2f(GLfloat x , GLfloat y);
void glRasterPos2i(GLint x , GLint y);
void glRasterPos2s(GLshort x , GLshort y);

void glRasterPos3d(
	GLdouble x , GLdouble y , GLdouble z
);
void glRasterPos3f(
	GLfloat x , GLfloat y , GLfloat z
);
void glRasterPos3i(
	GLint x , GLint y , GLint z
);
void glRasterPos3s(
	GLshort x , GLshort y , GLshort z
);
void glRasterPos4d(
	GLdouble x , GLdouble y ,
	GLdouble z , GLdouble w
);
void glRasterPos4f(
	GLfloat x , GLfloat y ,
	GLfloat z , GLfloat w
);
void glRasterPos4i(
	GLint x , GLint y ,
	GLint z , GLint w
);
void glRasterPos4s(
	GLshort x , GLshort y ,
	GLshort z , GLshort w
);

void glRasterPos2dv(const GLdouble *v);
void glRasterPos2fv(const GLfloat *v);
void glRasterPos2iv(const GLint *v);
void glRasterPos2sv(const GLshort *v);
void glRasterPos3dv(const GLdouble *v);
void glRasterPos3fv(const GLfloat *v);
void glRasterPos3iv(const GLint *v);
void glRasterPos3sv(const GLshort *v);
void glRasterPos4dv(const GLdouble *v);
void glRasterPos4fv(const GLfloat *v);
void glRasterPos4iv(const GLint *v);
void glRasterPos4sv(const GLshort *v);
x、y、z、w には、ラスタ位置の新しい座標を指定します
座標の概念は glVertex() で指定した座標と同じで、行列変換の影響も受けます
ビットマップを描画するには glBitmap() 関数を使います
void glBitmap(
	GLsizei width , GLsizei height , 
	GLfloat xorig , GLfloat yorig ,
	GLfloat xmove , GLfloat ymove ,
	const GLubyte * bitmap   
);
width にはビットマップの幅、height には高さをピクセル単位で指定します
xorig と yorig には、ビットマップ画像の原点の位置を指定します
この座標は、ラスタ座標から相対的なものとなります
xmove と ymove は、ビットマップの描画後、ラスタ位置を移動させる場合に指定します
これも、現在のラスタ座標に加えられる相対的な値です
bitmap には、ビットマップ画像を現す配列へのポインタを指定します
#include <windows.h>
#include <GL/gl.h>
#include <GL/glut.h>

const GLubyte bits[] = {
	0xFF , 0xFF , 0xFF , 0xFF , 0 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0xFF , 0xFF , 0xFF , 0xFF ,
	0xFF , 0xFF , 0xFF , 0xFF , 0 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0xFF , 0xFF , 0xFF , 0xFF ,
	0xFF , 0xFF , 0xFF , 0xFF , 0 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0xFF , 0xFF , 0xFF , 0xFF ,
	0xFF , 0xFF , 0xFF , 0xFF , 0 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0xFF , 0xFF , 0xFF , 0xFF ,
	0xFF , 0xFF , 0xFF , 0xFF , 0 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0xFF , 0xFF , 0xFF , 0xFF ,
	0xFF , 0xFF , 0xFF , 0xFF , 0 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0xFF , 0xFF , 0xFF , 0xFF ,
	0xFF , 0xFF , 0xFF , 0xFF , 0 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0xFF , 0xFF , 0xFF , 0xFF ,
	0xFF , 0xFF , 0xFF , 0xFF , 0 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0xFF , 0xFF , 0xFF , 0xFF ,
};

void disp( void ) {
	glClear(GL_COLOR_BUFFER_BIT);
	glRasterPos2i(-1 , -1);
	glBitmap(64 , 16 , 0 , 0 , 0 , 0 , bits);
	glFlush();
}

int main(int argc , char ** argv) {
	glutInit(&argc , argv);
	glutInitWindowSize(400 , 300);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);

	glutCreateWindow("Kitty on your lap");
	glutDisplayFunc(disp);

	glClearColor(1 , 1 , 1 , 0);
	glColor3f(0 , 0 , 0);

	glutMainLoop();
	return 0;
}


このプログラムでは、glRasterPos2i() 関数を使って、ウィンドウ左下を原点としています
ピクセルの原点が左下となるため、glBitmap() では、ビットマップを左下に描画しています
図のウィンドウの左下に表示されている横線が、表示されたビットマップです

通常、ビットマップが表せる情報は限られているため、マスク処理などに使われます
色情報が必要ない、フォントなどの描画マスクに利用することができるでしょう
このプログラムでは glColor3f() で黒、glClearColor() で白を選択していますが
例えば、前景色を赤にすればビットマップは赤で描画されます

OpenGL のビットマップ機能は、いわゆるイメージを描画する能力はありません
しかし、写真は無理でも2色の DIB ファイルなどであれば描画することは可能です
#include <windows.h>
#include <stdio.h>
#include <GL/gl.h>
#include <GL/glut.h>

GLubyte * bits;
GLuint width , height;

void disp( void ) {
	glClear(GL_COLOR_BUFFER_BIT);
	glRasterPos2i(-1 , -1);
	glBitmap(width , height , 0 , 0 , 0 , 0 , bits);
	glFlush();
}

int main(int argc , char ** argv) {
	FILE *stream;

	if (argc < 2) {
		printf("exeFileName bitmap\n");
		return 0;
	}

	stream = fopen(argv[1] , "rb");
	if (stream == NULL) {
		printf("stream did not open.\n");
		return 0;
	}

	fseek(stream , 0x12 , SEEK_SET);
	fread(&width , 4 , 1 , stream);
	fread(&height , 4 , 1 , stream);
	bits = malloc(width * height);
	fseek(stream , 0x3E , SEEK_SET);
	fread(bits , 1 , width * height , stream);
	fclose(stream);

	glutInit(&argc , argv);
	glutInitWindowSize(width , height);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);

	glutCreateWindow("Kitty on your lap");
	glutDisplayFunc(disp);

	glClearColor(1 , 1 , 1 , 0);
	glColor3f(0 , 0 , 0);

	glutMainLoop();

	free(bits);
	return 0;
}


このプログラムは、コマンドライン引数で指定した 2 色 DIB ファイルを表示します
DIB ファイルは、Windows 専用のヘッダを持つ正しい 2 色のビットマップでなければなりません
このプログラムではヘッダの分析を行っていないため、セキュリティは貧弱です
誤ったファイルを渡しても、ビットマップであると仮定して処理しようとしてしまいます
DIB ファイルの使用については、Win32 API 入門を参照してください



前のページへ戻る次のページへ