Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 286 lines (242 sloc) 7.098 kB
50431dc @philogb Added a load function to load js files. Clean up.
authored
1 /* Permission is hereby granted, free of charge, to any person obtaining a copy
2 * of this software and associated documentation files (the "Software"), to deal
3 * in the Software without restriction, including without limitation the rights
4 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5 * copies of the Software, and to permit persons to whom the Software is
6 * furnished to do so, subject to the following conditions:
7 *
8 * The above notice and this permission notice shall be included in all copies
9 * or substantial portions of the Software.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19 /* File for "Putting It All Together" lesson of the OpenGL tutorial on
20 * www.videotutorialsrock.com
21 */
22
23
24
25 #include <assert.h>
26 #include <fstream>
27
28 #include "imageloader.h"
29
30 using namespace std;
31
32 Image::Image(char* ps, int w, int h) : pixels(ps), width(w), height(h) {
33
34 }
35
36 Image::~Image() {
37 delete[] pixels;
38 }
39
40 namespace {
41 //Converts a four-character array to an integer, using big-endian form
42 int toInt(const char* bytes) {
43 return (int)(((unsigned char)bytes[0] << 24) |
44 ((unsigned char)bytes[1] << 16) |
45 ((unsigned char)bytes[2] << 8) |
46 (unsigned char)bytes[3]);
47 }
48
49 //Converts a two-character array to a short, using little-endian form
50 short toShort(const char* bytes) {
51 return (short)(((unsigned char)bytes[1] << 8) |
52 (unsigned char)bytes[0]);
53 }
54
55 //Reads the next four bytes as an integer, using big-endian form
56 int readInt(ifstream &input) {
57 char buffer[4];
58 input.read(buffer, 4);
59 return toInt(buffer);
60 }
61
62 //Reads the next two bytes as a short, using little-endian form
63 short readShort(ifstream &input) {
64 char buffer[2];
65 input.read(buffer, 2);
66 return toShort(buffer);
67 }
68
69 //Just like auto_ptr, but for arrays
70 template<class T>
71 class auto_array {
72 private:
73 T* array;
74 mutable bool isReleased;
75 public:
76 explicit auto_array(T* array_ = NULL) :
77 array(array_), isReleased(false) {
78 }
79
80 auto_array(const auto_array<T> &aarray) {
81 array = aarray.array;
82 isReleased = aarray.isReleased;
83 aarray.isReleased = true;
84 }
85
86 ~auto_array() {
87 if (!isReleased && array != NULL) {
88 delete[] array;
89 }
90 }
91
92 T* get() const {
93 return array;
94 }
95
96 T &operator*() const {
97 return *array;
98 }
99
100 void operator=(const auto_array<T> &aarray) {
101 if (!isReleased && array != NULL) {
102 delete[] array;
103 }
104 array = aarray.array;
105 isReleased = aarray.isReleased;
106 aarray.isReleased = true;
107 }
108
109 T* operator->() const {
110 return array;
111 }
112
113 T* release() {
114 isReleased = true;
115 return array;
116 }
117
118 void reset(T* array_ = NULL) {
119 if (!isReleased && array != NULL) {
120 delete[] array;
121 }
122 array = array_;
123 }
124
125 T* operator+(int i) {
126 return array + i;
127 }
128
129 T &operator[](int i) {
130 return array[i];
131 }
132 };
133
134
135 }
136
137 Image* loadBMP(const char* filename) {
138 ifstream input;
139 input.open(filename, ifstream::binary);
140 assert(!input.fail() || !"Could not find file");
141 char buffer[2];
142 input.read(buffer, 2);
1e83b94 @cscott Quiet some compiler warnings about &&/|| precedence.
cscott authored
143 assert((buffer[0] == 'B' && buffer[1] == 'M') || !"Not a bitmap file");
50431dc @philogb Added a load function to load js files. Clean up.
authored
144 input.ignore(8);
145 int dataOffset = readInt(input);
146
147 //Read the header
148 int headerSize = readInt(input);
149 int width;
150 int height;
151 switch(headerSize) {
152 case 40:
153 //V3
154 width = readInt(input);
155 height = readInt(input);
156 input.ignore(2);
157 assert(readShort(input) == 24 || !"Image is not 24 bits per pixel");
158 assert(readShort(input) == 0 || !"Image is compressed");
159 break;
160 case 12:
161 //OS/2 V1
162 width = readShort(input);
163 height = readShort(input);
164 input.ignore(2);
165 assert(readShort(input) == 24 || !"Image is not 24 bits per pixel");
166 break;
167 case 64:
168 //OS/2 V2
169 assert(!"Can't load OS/2 V2 bitmaps");
170 break;
171 case 108:
172 //Windows V4
173 assert(!"Can't load Windows V4 bitmaps");
174 break;
175 case 124:
176 //Windows V5
177 assert(!"Can't load Windows V5 bitmaps");
178 break;
179 default:
180 assert(!"Unknown bitmap format");
181 }
182
183 //Read the data
184 int bytesPerRow = ((width * 3 + 3) / 4) * 4 - (width * 3 % 4);
185 int size = bytesPerRow * height;
186 auto_array<char> pixels(new char[size]);
187 input.seekg(dataOffset, ios_base::beg);
188 input.read(pixels.get(), size);
189
190 //Get the data into the right format
191 auto_array<char> pixels2(new char[width * height * 3]);
192 for(int y = 0; y < height; y++) {
193 for(int x = 0; x < width; x++) {
194 for(int c = 0; c < 3; c++) {
195 pixels2[3 * (width * y + x) + c] =
196 pixels[bytesPerRow * y + 3 * x + (2 - c)];
197 }
198 }
199 }
200
201 input.close();
202 return new Image(pixels2.release(), width, height);
203 }
204
205 Image* loadPNG(const char* filename) {
206 ifstream input;
207 input.open(filename, ifstream::binary);
208 assert(!input.fail() || !"Could not find file");
209 //check if png file
210 char buffer[8];
211 input.read(buffer, 8);
1e83b94 @cscott Quiet some compiler warnings about &&/|| precedence.
cscott authored
212 assert((buffer[1] == 'P' && buffer[2] == 'N' && buffer[3] == 'G')
50431dc @philogb Added a load function to load js files. Clean up.
authored
213 || !"Not a png file");
214
215 char* data;
216 int width, height;
217
218 //read header
219 char type_buffer[4];
220 //read header length
221 int len = readInt(input);
222 printf("%d - len\n", len);
223 input.read(type_buffer, 4);
224 if(type_buffer[0] == 'I' && type_buffer[1] == 'H'
225 && type_buffer[2] == 'D' && type_buffer[3] == 'R') {
226 //grab width and height
227 width = readInt(input);
228 height = readInt(input);
229
230 printf("\n\nheader - width: %d, height: %d\n\n", width, height);
231 //read other header options like color type, bit depths
232 char buff[5];
233 input.read(buff, 5);
234 //check for RGB pixel data
235 if((buff[0] == 8 || buff[0] == 16)
236 && buff[1] == 2) {
237 input.ignore(4); //CRC
238 //store data.
239 data = new char[width * height * 3];
240 int len_accum = 0;
241 int len = 0;
242 //read all data chunks
243 len = readInt(input);
244 input.read(type_buffer, 4);
245 while(!(type_buffer[0] == 'I' && type_buffer[1] == 'E'
246 && type_buffer[2] == 'N' && type_buffer[3] == 'D')) {
247 printf("%c-%c-%c-%c ", type_buffer[0], type_buffer[1], type_buffer[2], type_buffer[3]);
248 if(type_buffer[0] == 'I' && type_buffer[1] == 'D'
249 && type_buffer[2] == 'A' && type_buffer[3] == 'T') {
250 printf("data\n\n");
251 // char* d = new char[len];
252 // input.read(d, len);
253 // for(int i=0; i < len; i++) {
254 // data[len_accum + (len - i - 1)] = d[i];
255 // }
256 // delete[] d;
257 input.read(data + len_accum, len);
258 len_accum += len;
259 } else {
260 printf("not data\n\n");
261 input.ignore(len);
262 }
263
264 input.ignore(4); //CRC
265 len = readInt(input);
266 input.read(type_buffer, 4);
267 }
268 } else {
269 //TODO(nico) take care of other png formats also
270 return NULL;
271 }
272 } else {
273 return NULL;
274 }
275
276 input.close();
277 return new Image(data, width, height);
278 }
279
280
281
282
283
284
285
Something went wrong with that request. Please try again.