質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

3898閲覧

C++ openGL BMP描画について

nia_1001

総合スコア13

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/07/18 05:07

編集2019/07/18 05:15

前提・実現したいこと

24BitのBMP描画はできました...

しかしRGBの配置が変なので変更したのですが色が白黒になってしまいます

配列を変える前はこの画像は青のキャラではなくオレンジで描画されてました

これを下の画像のように正しい色で描画したいです

あと画像が反転してるのでそれも直したいです

イメージ説明

発生している問題・エラーメッセージ

エラーメッセージ

該当のソースコード

C++

1#include <stdio.h> 2#include <Windows.h> 3#include "glut.h" 4#include "Tex.h" 5 6 7int TexFromBMP(const char * _fileName) 8{ 9 FILE *pFile; 10 fopen_s(&pFile, _fileName, "rb");//ファイルの読み込み 11 12 if (pFile == nullptr) 13 { 14 printf("%s open failed\n", _fileName); 15 return 1; 16 } 17 printf("%s open\n", _fileName); 18 19 BITMAPFILEHEADER bf;//ヘッダーのデータを格納する 20 21 fread(&bf, sizeof BITMAPFILEHEADER, 1, pFile); 22 printf("bf size:%d\n", bf.bfSize);//ファイルサイズ 23 24 BITMAPINFOHEADER bi; 25 fread(&bi, sizeof BITMAPINFOHEADER, 1, pFile); 26 27 printf("biWidth:%d biHHeight:%d\n", bi.biWidth, bi.biHeight); 28 printf("biBitCount:%d\n",bi.biBitCount); 29 30 typedef struct { 31 unsigned char r, g, b;//24Bitなので 32 }RGB; 33 RGB *bits = (RGB*)malloc(sizeof RGB * bi.biWidth * bi.biHeight);//ピクセルデータを確保する 34 fread(bits, sizeof RGB, bi.biWidth * bi.biHeight, pFile);//ピクセルデータを読み込んだ 35 36 37 //RGBのRとBを入れ替えた 38 for(int y=0; y<bi.biHeight; y++) 39 for (int x = 0; x < bi.biWidth; x++) 40 { 41 RGB *pBit = &bits[y * bi.biWidth + x]; 42 unsigned char temp = pBit->r; 43 pBit->r = pBit->b; 44 pBit->b = temp; 45 46 } 47 /*for (int y = 0; y < bi.biHeight; y++) 48 for (int x = 0; x < bi.biWidth; x++) 49 { 50 RGB *pBit0 = &bits[y*bi.biWidth+x]; 51 RGB *pBit1 = &bits[(bi.biHeight - 1 - y)*bi.biWidth + x]; 52 RGB temp = *pBit0; 53 *pBit0 = *pBit1; 54 *pBit1 = temp; 55 }*/ 56 57 //2次元テクスチャを描画 58 glTexImage2D( 59 GL_TEXTURE_2D, //GLenum target, 60 0,//GLint level, 61 GL_RGB, //GLint internalformat, 62 bi.biWidth, //GLsizei width, 63 bi.biHeight, //GLsizei height, 64 0,//GLint border, 65 GL_RGB,//GLenum format, 66 GL_UNSIGNED_BYTE,//GLenum type, 67 bits);//const GLvoid *pixels 68 69 //フィルタリング 70 glTexParameteri( 71 GL_TEXTURE_2D,//GLenum target, 72 GL_TEXTURE_MAG_FILTER,//GLenum pname, 73 GL_NEAREST//GLint param 74 ); 75 glTexParameteri( 76 GL_TEXTURE_2D,//GLenum target, 77 GL_TEXTURE_MIN_FILTER,//GLenum pname, 78 GL_NEAREST//GLint param 79 ); 80 free(bits); 81 fclose(pFile); 82 83 return 0; 84} 85```C++ main 86```C++ 四角を描画 87#include <stdio.h> 88#include <time.h> 89#include "Font.h" 90#include "glm/glm.hpp" 91#include "glut.h" 92#include "Rect.h" 93#include "Ball.h" 94#include "Tex.h" 95 96using namespace glm; 97 98#define BALL_MAX 256 99 100ivec2 WindowSize = { 600,420 }; //Windowのサイズ 縦,横 101 102bool Keys[256];//押されているかのフラグ 103 104Ball balls[BALL_MAX]; 105 106Rect rect1 = Rect(vec2(100, 100), vec2(100, 200)); 107Rect rect2 = Rect(vec2(WindowSize.x/2, WindowSize.y/2), vec2(200, 100)); 108 109 110void display(void) 111{ 112 glClear(GL_COLOR_BUFFER_BIT); //GLbitfield mask 画面の情報をリセット 113 114 //2D 115 glMatrixMode(GL_PROJECTION);//GLenum mode 116 117 glLoadIdentity(); 118 gluOrtho2D( 119 0,//GLdouble left, 120 WindowSize.x,//GLdouble right, 121 WindowSize.y,//GLdouble bottom, 122 0//GLdouble top 123 124 ); 125 glMatrixMode(GL_MODELVIEW); //GLenum mode モード設定 126 glLoadIdentity();//リセットしている 127 128 /*if (rect1.Intersect(rect2)) 129 glColor3ub(0xff, 0x00, 0x00); 130 else 131 glColor3ub(0x00, 0x00, 0xff); 132 rect1.Draw(); 133 134 glColor3ub(0x00, 0xff, 0x00); 135 rect2.Draw();*/ 136 137 //unsigned char pixels[] = { 138 // 0xff,0x00,0x00,//赤 139 // 0x00,0xff,0x00,//緑 140 // 0x00,0x00,0xff,//青 141 // 0xff,0xff,0x00//黄 142 //}; 143 //glPixelStorei( 144 // GL_UNPACK_ALIGNMENT,//GLenum pname 145 // 1//GLint param 146 //); 147 148 glEnable(GL_TEXTURE_2D);//2次元テクスチャを有効 149 150 Rect(vec2(0,0),vec2(150,150)).Draw(); 151 152 //*for (int i = 0; i < BALL_MAX; i++) 153 //{ 154 // balls[1].Draw(); 155 //} 156 //float y=0;*/ 157 FontBegin(); 158 /*FontSetPosition(0, y);*/ 159 //FontDraw("min:%f max:%f", FontGetWeightMin(), FontGetWeightMax()); 160 161 162 FontEnd(); 163 164 glutSwapBuffers();//命令 165 166} 167 168void Idle(void) 169{ 170 float f = 0.5; 171 if (Keys['w'])rect1.m_position.y -= f; 172 if (Keys['s'])rect1.m_position.y += f; 173 if (Keys['a'])rect1.m_position.x -= f; 174 if (Keys['d'])rect1.m_position.x += f; 175 for (int i = 0; i < BALL_MAX; i++) 176 { 177 178 balls[i].Update(); 179 //跳ね返り 180 if (balls[i].m_position.x >= WindowSize.x)//右壁 181 { 182 balls[i].m_position = balls[i].m_LastPosition; 183 balls[i].m_speed.x = -fabs(balls[i].m_speed.x); 184 } 185 if (balls[i].m_position.x < 0)//左壁 186 { 187 balls[i].m_position = balls[i].m_LastPosition; 188 balls[i].m_speed.x = fabs(balls[i].m_speed.x); 189 } 190 if (balls[i].m_position.y < 0)//上壁 191 { 192 balls[i].m_position = balls[i].m_LastPosition; 193 balls[i].m_speed.y = fabs(balls[i].m_speed.y); 194 } 195 if (balls[i].m_position.y >= WindowSize.y)//下壁 196 { 197 balls[i].m_position = balls[i].m_LastPosition; 198 balls[i].m_speed.y = -fabs(balls[i].m_speed.y); 199 } 200 } 201 202 glutPostRedisplay(); 203} 204 205//再描画命令 206void Timer(int value) 207{ 208 glutPostRedisplay();//再度描画命令 209 glutTimerFunc( 210 1000/60,//unsigned int millis 〇秒後に開始 60FPSにしてる 211 Timer,//void (GLUTCALLBACK *func)(int value) 関数起動 212 0); //int value 渡す数値 必要ないので0 213 214} 215void Reshape(int width, int height) 216{ 217 printf("reshape: width:%d height:%d\n", width, height);//確認のため 218 //更新するのでwindowサイズが変わっても大丈夫 219 glViewport( 220 0, 0,//(GLint x,y, 座標 221 width, height//GLsizei width,height) 幅高さ 222 ); 223 //windowサイズ更新 224 WindowSize = ivec2(width, height); 225} 226void (Keyboard)(unsigned char key, int x, int y)//intはマウス 227{ 228 if (key == 0x1b) 229 { 230 exit(0); 231 } 232 printf("Keyboard:\'%c\'(%#x)\n",key,key); 233 Keys[key] = true; 234} 235void (KeyboardUp)(unsigned char key, int x, int y) 236{ 237 printf("KeyboardUp:\'%c\'(%#x)\n", key, key); 238 Keys[key] = false; 239} 240 241int main(int argc, char *argv[]) 242{ 243 srand(time(NULL)); 244 for (int i = 0; i < BALL_MAX; i++) 245 { 246 balls[i].m_speed = normalize( vec2((float)rand()/RAND_MAX, (float)rand()/RAND_MAX)); 247 248 } 249 250 glutInit( 251 &argc, //int *argcp, 252 argv); //char **argv); 253 glutInitDisplayMode(GL_DOUBLE);//unsigned int mode ダブルバッファを使うようにする 254 glutInitWindowSize(WindowSize.x, WindowSize.y); //int width, int height 255 glutCreateWindow("title");//const char *title 256 257 TexFromBMP("Megaman01.bmp"); 258 259 glutDisplayFunc(display);//void (GLUTCALLBACK *func)(void) 260 glutIdleFunc(Idle);//void (GLUTCALLBACK *func)(void) Idle状態のときに呼ばれる 261 //垂直同期がとれないためTimerでやる 262 glutTimerFunc( 263 0,//unsigned int millis 〇秒後に開始 264 Timer,//void (GLUTCALLBACK *func)(int value) 関数起動 265 0); //int value 渡す数値 必要ないので0 266 267 //windowのサイズが変わったときのコールバック関数定義 268 glutReshapeFunc(Reshape);//void (GLUTCALLBACK *func)(int width, int height) 269 //Keyboardを取得 270 glutKeyboardFunc(Keyboard);//void (GLUTCALLBACK *func)(unsigned char key, int x, int y) 271 //keyrepeatを無効にする 272 glutIgnoreKeyRepeat(GL_TRUE);//int ignore 273 //keyboardが離されたときの処理 274 glutKeyboardUpFunc(KeyboardUp);//void (GLUTCALLBACK *func)(unsigned char key, int x, int y) 275 glutMainLoop();//MainLoop 276 277}
### 試したこと 配列を変えた感じです ### 補足情報(FW/ツールのバージョンなど) ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

2乗のpixselサイズじゃないと読み込みませんでした
ただそれだけです

openGLのverは1.1です

2,4,8,16,32,64,128,256じゃないと読み込まない感じでした

投稿2019/07/19 01:21

nia_1001

総合スコア13

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

BMPファイルはRGBではなく、BGRの順で格納されています。
BRの並び順を入れ替えるのではなく、glTexImage2Dの引数でGL_RGBの代わりにGL_BGRを指定すればよいのでは?
glTexImage2D

あと画像が反転してるのでそれも直したいです

BITMAPINFOHEADERbiHeightが正の場合は下から上に向かって格納されています。
BITMAPINFOHEADER

biHeight The height of the bitmap, in pixels. If biHeight is positive, the bitmap is a bottom-up DIB and its origin is the lower-left corner. If biHeight is negative, the bitmap is a top-down DIB and its origin is the upper-left corner. If biHeight is negative, indicating a top-down DIB, biCompression must be either BI_RGB or BI_BITFIELDS. Top-down DIBs cannot be compressed. If biCompression is BI_JPEG or BI_PNG, the biHeight member specifies the height of the decompressed JPEG or PNG image file, respectively.

各ライン毎のバイト数が4の倍数に満たない場合は0パディングされます。
このコードで24bitBMPファイルを読むとRGBが3バイトなので、画像の幅が4の倍数でない場合はずれますね。

C++

1 typedef struct { 2 unsigned char r, g, b;//24Bitなので 3 }RGB; 4 RGB *bits = (RGB*)malloc(sizeof RGB * bi.biWidth * bi.biHeight);//ピクセルデータを確保する 5 fread(bits, sizeof RGB, bi.biWidth * bi.biHeight, pFile);//ピクセルデータを読み込んだ

投稿2019/07/18 11:41

編集2019/07/18 12:02
SHOMI

総合スコア4079

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nia_1001

2019/07/19 01:46 編集

glTexImage2Dの引数でGL_RGBの代わりにGL_BGRですか すみませんopenGLのver.は1.1なのでGL_BGRという引数はなかったですが解決できました ありがとうございます お聞きしたいことがあるのですがOpenGLのverって上げたほうがいいですか? 関数や定義が変わるらしいので今から上げるとなると不安です もし上げる際に利点とかがあれば教えてくれませんか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問