-
Notifications
You must be signed in to change notification settings - Fork 0
/
loadtexbmp.c
100 lines (94 loc) · 3.22 KB
/
loadtexbmp.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*
* Load texture from BMP file
*/
#include "CSCIx229.h"
/*
* Reverse n bytes
*/
static void Reverse(void* x,const int n)
{
int k;
char* ch = (char*)x;
for (k=0;k<n/2;k++)
{
char tmp = ch[k];
ch[k] = ch[n-1-k];
ch[n-1-k] = tmp;
}
}
/*
* Load texture from BMP file
*/
unsigned int LoadTexBMP(const char* file)
{
unsigned int texture; // Texture name
FILE* f; // File pointer
unsigned short magic; // Image magic
unsigned int dx,dy,size; // Image dimensions
unsigned short nbp,bpp; // Planes and bits per pixel
unsigned char* image; // Image data
unsigned int k; // Counter
int max; // Maximum texture dimensions
// Open file
f = fopen(file,"rb");
if (!f) Fatal("Cannot open file %s\n",file);
// Check image magic
if (fread(&magic,2,1,f)!=1) Fatal("Cannot read magic from %s\n",file);
if (magic!=0x4D42 && magic!=0x424D) Fatal("Image magic not BMP in %s\n",file);
// Seek to and read header
if (fseek(f,16,SEEK_CUR) || fread(&dx ,4,1,f)!=1 || fread(&dy ,4,1,f)!=1 ||
fread(&nbp,2,1,f)!=1 || fread(&bpp,2,1,f)!=1 || fread(&k,4,1,f)!=1)
Fatal("Cannot read header from %s\n",file);
// Reverse bytes on big endian hardware (detected by backwards magic)
if (magic==0x424D)
{
Reverse(&dx,4);
Reverse(&dy,4);
Reverse(&nbp,2);
Reverse(&bpp,2);
Reverse(&k,4);
}
// Check image parameters
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max);
if (dx<1 || dx>max) Fatal("%s image width %d out of range 1-%d\n",file,dx,max);
if (dy<1 || dy>max) Fatal("%s image height %d out of range 1-%d\n",file,dy,max);
if (nbp!=1) Fatal("%s bit planes is not 1: %d\n",file,nbp);
if (bpp!=24) Fatal("%s bits per pixel is not 24: %d\n",file,bpp);
if (k!=0) Fatal("%s compressed files not supported\n",file);
#ifndef GL_VERSION_2_0
// OpenGL 2.0 lifts the restriction that texture size must be a power of two
for (k=1;k<dx;k*=2);
if (k!=dx) Fatal("%s image width not a power of two: %d\n",file,dx);
for (k=1;k<dy;k*=2);
if (k!=dy) Fatal("%s image height not a power of two: %d\n",file,dy);
#endif
// Allocate image memory
size = 3*dx*dy;
image = (unsigned char*) malloc(size);
if (!image) Fatal("Cannot allocate %d bytes of memory for image %s\n",size,file);
// Seek to and read image
if (fseek(f,20,SEEK_CUR) || fread(image,size,1,f)!=1) Fatal("Error reading data from image %s\n",file);
fclose(f);
// Reverse colors (BGR -> RGB)
for (k=0;k<size;k+=3)
{
unsigned char temp = image[k];
image[k] = image[k+2];
image[k+2] = temp;
}
// Sanity check
ErrCheck("LoadTexBMP");
// Generate 2D texture
glGenTextures(1,&texture);
glBindTexture(GL_TEXTURE_2D,texture);
// Copy image
glTexImage2D(GL_TEXTURE_2D,0,3,dx,dy,0,GL_RGB,GL_UNSIGNED_BYTE,image);
if (glGetError()) Fatal("Error in glTexImage2D %s %dx%d\n",file,dx,dy);
// Scale linearly when image size doesn't match
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
// Free image memory
free(image);
// Return texture name
return texture;
}