BMP画像を表示します。
前回の記事との違いは fopen を fopen_s に、fread を fread_s にしています。
これらは C11 以降で標準ライブラリに導入された関数で、セキュリティが強化されたものです。
戻り値と引数が異なります。
fopen_s は戻り値が errno_t なので、errno マクロからエラーの原因を調べなくても良くなっています。
fopen_s は fopen とは違って排他的モードで開いてくれるらしいです。
尚、実装に関しては任意という事になっているらしく、最新の環境でもセキュリティ強化版が無い環境も
あります。
ファイル |
main.cpp |
|
main.cpp
#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#include <GL/freeglut/freeglut.h>
#include <stdio.h>
#define WIDTH 320
#define HEIGHT 240
class BMP
{
public:
unsigned long sizeX; //横
unsigned long sizeY; //縦
char* Data; //画像データ格納
bool Load(char* filename);
GLuint texture;
void TexSet();
BMP(char* FileName);
};
BMP::BMP(char* FileName) {
Load(FileName);
TexSet();
}
bool BMP::Load(char* FileName) {
FILE* File;
errno_t error;
unsigned long size;//
イメージのバイトサイズ
unsigned long i;// カウンタ
unsigned short int planes;
//デバイス面数
unsigned short int bpp; //
ピクセル数
char temp; //
カラー関係作業用
//ファイルオープン
error = fopen_s(&File, FileName,
"rb");
if (error){
printf("ファイルがありません");
return false;
}
//ビットマップの幅データ部分へ移動
fseek(File, 18, SEEK_CUR);
//横幅を読み込む
if ((i = fread_s(&sizeX, sizeof
sizeX, 4, 1, File)) != 1) {
printf("読み込みエラー");
return false;
}
//縦幅を読み込む
if ((i = fread_s(&sizeY, sizeof
sizeY, 4, 1, File)) != 1) {
printf("読み込みエラー");
return false;
}
//画像サイズの計算
size = sizeX * sizeY *
3;//プレーン数を読み込む
if ((fread_s(&planes, sizeof planes,
2, 1, File)) != 1) { //bmpは「1」になる
printf("プレーン数が読み込めません");
return false;
}
if (planes != 1) {
printf("プレーン数が1以外です");
return false;
}
//ピクセル値を読み込む
if ((i = fread_s(&bpp, sizeof bpp,
2, 1, File)) != 1) {
printf("ビット数が読めません");
return false;
}
if (bpp != 24)
{//24bppでなければエラー
printf("24ビット画像ではありません");
return false;
}
//24ビット飛ばして、カラーデータ(RGB)部分へ
fseek(File, 24, SEEK_CUR);
//データ読み込み
Data = (char*)malloc(size);
if (Data == NULL) {
printf("メモリが確保できません");
return false;
}
if ((i = fread_s(Data, size, size, 1,
File)) != 1) {
printf("データが読めません");
return false;
}
for (i = 0; i < size; i += 3) { //bgr
-> rgb
temp = Data[i];
Data[i] = Data[i + 2];
Data[i + 2] = temp;
}
return true;
}
void BMP::TexSet()
{
glEnable(GL_TEXTURE_2D);
glGenTextures(1,
&texture);
glBindTexture(GL_TEXTURE_2D,
texture);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, sizeX,
sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, Data);
glBindTexture(GL_TEXTURE_2D,
0);
}
BMP* bmp;
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho(0.0, WIDTH, HEIGHT, 0.0, -1.0,
1.0);
glEnable(GL_TEXTURE_2D);//テクスチャ有効
glBindTexture(GL_TEXTURE_2D,
bmp->texture);
glEnable(GL_ALPHA_TEST);//アルファテスト開始
glBegin(GL_POLYGON);
glTexCoord2f(0.0f, 0.0f); glVertex2d(10,
230);//左下
glTexCoord2f(0.0f, 1.0f); glVertex2d(10,
10);//左上
glTexCoord2f(1.0f, 1.0f);
glVertex2d(310, 10);//右上
glTexCoord2f(1.0f, 0.0f);
glVertex2d(310, 230);//右下
glEnd();
glDisable(GL_ALPHA_TEST);//アルファテスト終了
glDisable(GL_TEXTURE_2D);//テクスチャ無効
glutSwapBuffers();
}
void idle(void)
{
glutPostRedisplay();
}
void Init() {
glClearColor(0.0, 0.0, 0.0,
1.0);
glOrtho(0, WIDTH, HEIGHT, 0, -1.0,
1.0);
bmp = new
BMP((char*)"sample.bmp");
}
int main(int argc, char* argv[])
{
glutInitWindowPosition(100,
100);
glutInitWindowSize(WIDTH,
HEIGHT);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA |
GLUT_DOUBLE);
glutCreateWindow("BMP画像を読み込んで表示");
glutDisplayFunc(display);
glutIdleFunc(idle);
Init();
glutMainLoop();
return 0;
}
|