BMP画像を表示する(セキュリティ強化版)

BMP画像を表示します。
前回の記事との違いは fopen を fopen_s に、fread を fread_s にしています。
これらは C11 以降で標準ライブラリに導入された関数で、セキュリティが強化されたものです。
戻り値と引数が異なります。
fopen_s は戻り値が errno_t なので、errno マクロからエラーの原因を調べなくても良くなっています。
fopen_s は fopen とは違って排他的モードで開いてくれるらしいです。
尚、実装に関しては任意という事になっているらしく、最新の環境でもセキュリティ強化版が無い環境も
あります。

ファイル
main.cpp

sample.bmp

sample.bmp

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;
}

 

最終更新:2024年06月16日 22:55
添付ファイル