Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 191 lines (158 sloc) 5.494 kb
d5f7b48 @arvind Importing simplePhotos into git repo
authored
1 /*BMPLoader - loads Microsoft .bmp format
2 Copyright (C) 2006 Chris Backhouse
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18
19 cjbackhouse@hotmail.com www.backhouse.tk
20
21 I would appreciate it if anyone using this in something cool would tell me
22 so I can see where it ends up.
23
24 Takes a filename, returns an array of RGB pixel data
25 Loads:
26 24bit bitmaps
27 256 colour bitmaps
28 16 colour bitmaps
29 2 colour bitmaps (Thanks to Charles Rabier)
30
31 This code is designed for use in openGL programs, so bitmaps not correctly padded will not
32 load properly, I believe this only applies to:
33 256cols if width is not a multiple of 4
34 16cols if width is not a multiple of 8
35 2cols if width is not a multiple of 32
36
37 Sample code:
38
39 BMPClass bmp;
40 BMPLoad(fname,bmp);
41 glTexImage2D(GL_TEXTURE_2D,0,3,bmp.width,bmp.height,0,GL_RGB,GL_UNSIGNED_BYTE,bmp.bytes);
42 */
43
44
45 #include "bmp.h"
46
47 BMPClass::BMPClass(){bytes=0;}
48 BMPClass::~BMPClass(){delete[] bytes;}
49 BYTE& BMPClass::pixel(int x,int y,int c){return bytes[(y*width+x)*3+c];}
50 void BMPClass::allocateMem(){delete[] bytes;bytes=new BYTE[width*height*3];}
51
52 std::string TranslateBMPError(BMPError err)
53 {
54 switch(err)
55 {
56 case(BMPNOTABITMAP):
57 return "This file is not a bitmap, specifically it doesn't start 'BM'";
58 case(BMPNOOPEN):
59 return "Failed to open the file, suspect it doesn't exist";
60 case(BMPFILEERROR):
61 return "ferror said we had an error. This error seems to not always mean anything, try ignoring it";
62 case(BMPBADINT):
63 return "sizeof(int)!=4 quite a lot of rewriting probably needs to be done on the code";
64 case(BMPNOERROR):
65 return "No errors detected";
66 case(BMPUNKNOWNFORMAT):
67 return "Unknown bmp format, ie not 24bit, 256,16 or 2 colour";
68 default:
69 return "Not a valid error code";
70 }
71 }
72
73 BMPError BMPLoad(std::string fname,BMPClass& bmp)
74 {
75 if(sizeof(int)!=4) return BMPBADINT;
76
77 FILE* f=fopen(fname.c_str(),"rb"); //open for reading in binary mode
78 if(!f) return BMPNOOPEN;
79 char header[54];
80 fread(header,54,1,f); //read the 54bit main header
81
82 if(header[0]!='B' || header[1]!='M')
83 {
84 fclose(f);
85 return BMPNOTABITMAP; //all bitmaps should start "BM"
86 }
87
88 //it seems gimp sometimes makes its headers small, so we have to do this. hence all the fseeks
89 int offset=*(unsigned int*)(header+10);
90
91 bmp.width=*(int*)(header+18);
92 bmp.height=*(int*)(header+22);
93 //now the bitmap knows how big it is it can allocate its memory
94 bmp.allocateMem();
95
96 int bits=int(header[28]); //colourdepth
97
98 int x,y,c;
99 BYTE cols[256*4]; //colourtable
100 switch(bits)
101 {
102 case(24):
103 fseek(f,offset,SEEK_SET);
104 fread(bmp.bytes,bmp.width*bmp.height*3,1,f); //24bit is easy
105 for(x=0;x<bmp.width*bmp.height*3;x+=3) //except the format is BGR, grr
106 {
107 BYTE temp=bmp.bytes[x];
108 bmp.bytes[x]=bmp.bytes[x+2];
109 bmp.bytes[x+2]=temp;
110 }
111 break;
112
113 case(8):
114 fread(cols,256*4,1,f); //read colortable
115 fseek(f,offset,SEEK_SET);
116 for(y=0;y<bmp.height;++y) //(Notice 4bytes/col for some reason)
117 for(x=0;x<bmp.width;++x)
118 {
119 BYTE byte;
120 fread(&byte,1,1,f); //just read byte
121 for(int c=0;c<3;++c)
122 bmp.pixel(x,y,c)=cols[byte*4+2-c]; //and look up in the table
123 }
124 break;
125
126 case(4):
127 fread(cols,16*4,1,f);
128 fseek(f,offset,SEEK_SET);
129 for(y=0;y<256;++y)
130 for(x=0;x<256;x+=2)
131 {
132 BYTE byte;
133 fread(&byte,1,1,f); //as above, but need to exract two
134 for(c=0;c<3;++c) //pixels from each byte
135 bmp.pixel(x,y,c)=cols[byte/16*4+2-c];
136 for(c=0;c<3;++c)
137 bmp.pixel(x+1,y,c)=cols[byte%16*4+2-c];
138 }
139 break;
140
141 case(1):
142 fread(cols,8,1,f);
143 fseek(f,offset,SEEK_SET);
144 for(y=0;y<bmp.height;++y)
145 for(x=0;x<bmp.width;x+=8)
146 {
147 BYTE byte;
148 fread(&byte,1,1,f);
149 //Every byte is eight pixels
150 //so I'm shifting the byte to the relevant position, then masking out
151 //all but the lowest bit in order to get the index into the colourtable.
152 for(int x2=0;x2<8;++x2)
153 for(int c=0;c<3;++c)
154 bmp.pixel(x+x2,y,c)=cols[((byte>>(7-x2))&1)*4+2-c];
155 }
156 break;
157
158 default:
159 fclose(f);
160 return BMPUNKNOWNFORMAT;
161 }
162
163 if(ferror(f))
164 {
165 fclose(f);
166 return BMPFILEERROR;
167 }
168
169 fclose(f);
170
171 return BMPNOERROR;
172 }
173
174 BMPError BMPLoad(std::string fname){BMPClass bmp;return BMPLoad(fname,bmp);}
175
176 #ifdef __gl_h
177 BMPError BMPLoadGL(std::string fname)
178 {
179 BMPClass bmp;
180 BMPError e=BMPLoad(fname,bmp);
181 if(e!=BMPNOERROR) return e;
182
183 glEnable(GL_TEXTURE_2D);
184 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
185 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
186 glTexImage2D(GL_TEXTURE_2D,0,3,bmp.width,bmp.height,0,GL_RGB,GL_UNSIGNED_BYTE,bmp.bytes);
187
188 return BMPNOERROR;
189 }
190 #endif
Something went wrong with that request. Please try again.