Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1789 yogev_ezra 1
//
2
//	bmp.cpp - source file / freeware
3
//
4
//	David Henry - tfc_duke@hotmail.com
5
//
6
 
7
 
8
#include	"bmp.h"
9
#include    
10
 
11
#include    
12
 
13
extern "C"{
14
long filelength(int fhandle);
15
}
16
 
17
// --------------------------------------------------
18
// LoadFileBMP() - load a Windows/OS2 BITMAP image
19
//				   [.bmp].
20
//
21
// parameters :
22
//    - filename [in]  : image source file
23
//    - pixels	 [out] : 32 bits rgb image data
24
//    - width    [out] : image width in pixels
25
//    - height   [out] : image height in pixels
26
//    - flipvert [in]  : flip vertically
27
//
28
// return value :
29
//    - -1 : no image data
30
//    -  0 : failure
31
//    -  1 : success
32
//
33
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
34
// accepted image formats :
35
//     # RGB 1-4-8-24-32 bits	WINDOWS - OS/2
36
//     # RLE 4-8 bits			WINDOWS
37
// --------------------------------------------------
38
 
39
int LoadFileBMP( const char *filename, unsigned char **pixels, int *width, int *height, bool flipvert )
40
{
41
	FILE		*file;			// file stream
42
	BITMAPFILEHEADER	*bmfh;			// bitmap file header
43
	BITMAPINFOHEADER	*bmih;			// bitmap info header (windows)
44
	BITMAPCOREHEADER	*bmch;			// bitmap core header (os/2)
45
	RGBTRIPLE			*os2_palette;	// pointer to the color palette os/2
46
	RGBQUAD				*win_palette;	// pointer to the color palette windows
47
	char				*buffer;		// buffer storing the entire file
48
	unsigned char		*ptr;			// pointer to pixels data
49
	int					bitCount;		// number of bits per pixel
50
	int					compression;	// compression type (rgb/rle)
51
	int					row, col, i;	// temporary variables
52
	int					w, h;			// width, height
53
 
54
 
55
 
56
	/////////////////////////////////////////////////////
57
	// read the entire file in the buffer
58
 
59
	file = fopen(filename,"rb");
60
 
61
	if( !file)
62
		return 0;
63
 
64
	long flen = filelength(fileno(file));
65
 
66
	buffer = new char[ flen + 1 ];
67
	int rd = fread(buffer, flen, 1, file);
68
	char *pBuff = buffer;
69
 
70
	fclose(file);
71
 
72
	/////////////////////////////////////////////////////
73
 
74
 
75
	// read the header
76
	bmfh = (BITMAPFILEHEADER *)pBuff;
77
	pBuff += sizeof( BITMAPFILEHEADER );
78
 
79
	// verify that it's a BITMAP file
80
	if( bmfh->bfType != BITMAP_ID )
81
	{
82
		delete [] buffer;
83
		return 0;
84
	}
85
 
86
 
87
	bmch = (BITMAPCOREHEADER *)pBuff;
88
	bmih = (BITMAPINFOHEADER *)pBuff;
89
 
90
 
91
	if( (bmih->biCompression < 0) || (bmih->biCompression > 3) )
92
	{
93
		// OS/2 style
94
		pBuff += sizeof( BITMAPCOREHEADER );
95
 
96
		bitCount	= bmch->bcBitCount;
97
		compression	= BI_OS2;
98
 
99
		w = bmch->bcWidth;
100
		h = bmch->bcHeight;
101
	}
102
	else
103
	{
104
		// WINDOWS style
105
		pBuff += sizeof( BITMAPINFOHEADER );
106
 
107
		bitCount	= bmih->biBitCount;
108
		compression	= bmih->biCompression;
109
 
110
		w = bmih->biWidth;
111
		h = bmih->biHeight;
112
	}
113
 
114
 
115
	if( width )
116
		*width	= w;
117
 
118
	if( height )
119
		*height	= h;
120
 
121
 
122
	if( !pixels )
123
	{
124
		delete [] buffer;
125
		return (-1);
126
	}
127
 
128
 
129
	/////////////////////////////////////////////////////
130
	// read the palette
131
 
132
	if( bitCount <= 8 )
133
	{
134
		// 24 and 32 bits images are not paletted
135
 
136
		// ajust the palette pointer to the memory in the buffer
137
		os2_palette = (RGBTRIPLE *)pBuff;
138
		win_palette = (RGBQUAD *)pBuff;
139
 
140
		//	[number of colors in the palette] * [size of one pixel]
141
		pBuff += (1 << bitCount) * (bitCount >> 3) * sizeof( unsigned char );
142
	}
143
 
144
	/////////////////////////////////////////////////////
145
 
146
 
147
	// allocate memory to store pixel data
148
	*pixels = new unsigned char[ w * h * 3 ];
149
	ptr		= &(*pixels)[0];
150
 
151
 
152
	// move the pixel data pointer to the begening of bitmap data
153
	pBuff = buffer + (bmfh->bfOffBits * sizeof( char ));
154
 
155
 
156
	/////////////////////////////////////////////////////
157
	// read pixel data following the image compression
158
	// type and the number of bits per pixels
159
	/////////////////////////////////////////////////////
160
 
161
	switch( compression )
162
	{
163
		case BI_OS2:
164
		case BI_RGB:
165
		{
166
			for( row = h - 1; row >= 0; row-- )
167
			{
168
				if( flipvert )
169
					ptr = &(*pixels)[ row * w * 3 ];
170
 
171
				switch( bitCount )
172
				{
173
					case 1:
174
					{
175
// RGB 1 BITS
176
						for( col = 0; col < (int)(w / 8); col++ )
177
						{
178
							// read the current pixel
179
							unsigned char color = *((unsigned char *)(pBuff++));
180
 
181
							for( i = 7; i >= 0; i--, ptr += 3 )
182
							{
183
								// convert indexed pixel (1 bit) into rgb (32 bits) pixel
184
								int clrIdx = ((color & (1< 0);
185
 
186
								if( compression == BI_OS2 )
187
								{
188
									ptr[2] = os2_palette[ clrIdx ].rgbtRed;
189
									ptr[1] = os2_palette[ clrIdx ].rgbtGreen;
190
									ptr[0] = os2_palette[ clrIdx ].rgbtBlue;
191
								}
192
								else
193
								{
194
									ptr[2] = win_palette[ clrIdx ].rgbRed;
195
									ptr[1] = win_palette[ clrIdx ].rgbGreen;
196
									ptr[0] = win_palette[ clrIdx ].rgbBlue;
197
								}
198
							}
199
						}
200
 
201
						break;
202
					}
203
 
204
					case 4:
205
					{
206
// RGB 4 BITS
207
						for( col = 0; col < (int)(w / 2); col++, ptr += 6 )
208
						{
209
							// read the current pixel
210
							unsigned char color = *((unsigned char *)(pBuff++));
211
 
212
							// convert indexed pixel (4 bits) into rgb (32 bits) pixel
213
							int clrIdx;
214
 
215
							if( compression == BI_OS2 )
216
							{
217
								clrIdx = (color >> 4);
218
								ptr[2] = os2_palette[ clrIdx ].rgbtRed;
219
								ptr[1] = os2_palette[ clrIdx ].rgbtGreen;
220
								ptr[0] = os2_palette[ clrIdx ].rgbtBlue;
221
 
222
								clrIdx = (color & 0x0F);
223
								ptr[6] = os2_palette[ clrIdx ].rgbtRed;
224
								ptr[5] = os2_palette[ clrIdx ].rgbtGreen;
225
								ptr[4] = os2_palette[ clrIdx ].rgbtBlue;
226
 
227
							}
228
							else
229
							{
230
								clrIdx = (color >> 4);
231
								ptr[2] = win_palette[ clrIdx ].rgbRed;
232
								ptr[1] = win_palette[ clrIdx ].rgbGreen;
233
								ptr[0] = win_palette[ clrIdx ].rgbBlue;
234
 
235
								clrIdx = (color & 0x0F);
236
								ptr[6] = win_palette[ clrIdx ].rgbRed;
237
								ptr[5] = win_palette[ clrIdx ].rgbGreen;
238
								ptr[4] = win_palette[ clrIdx ].rgbBlue;
239
							}
240
						}
241
 
242
						break;
243
					}
244
 
245
					case 8:
246
					{
247
// RGB 8 BITS
248
						for( col = 0; col < w; col++, ptr += 3 )
249
						{
250
							// read the current pixel
251
							unsigned char color = *((unsigned char *)(pBuff++));
252
 
253
							// convert indexed pixel (8 bits) into rgb (32 bits) pixel
254
							if( compression == BI_OS2 )
255
							{
256
								ptr[2] = os2_palette[ color ].rgbtRed;
257
								ptr[1] = os2_palette[ color ].rgbtGreen;
258
								ptr[0] = os2_palette[ color ].rgbtBlue;
259
							}
260
							else
261
							{
262
								ptr[2] = win_palette[ color ].rgbRed;
263
								ptr[1] = win_palette[ color ].rgbGreen;
264
								ptr[0] = win_palette[ color ].rgbBlue;
265
							}
266
						}
267
 
268
						break;
269
					}
270
 
271
					case 24:
272
					{
273
// RGB 24 BITS
274
						for( col = 0; col < w; col++, ptr += 3 )
275
						{
276
							// convert bgr pixel (24 bits) into rgb (32 bits) pixel
277
							RGBTRIPLE *pix = (RGBTRIPLE *)pBuff;
278
							pBuff += sizeof( RGBTRIPLE );
279
 
280
							ptr[2] = pix->rgbtRed;
281
							ptr[1] = pix->rgbtGreen;
282
							ptr[0] = pix->rgbtBlue;
283
						}
284
 
285
  						break;
286
					}
287
 
288
					case 32:
289
					{
290
// RGB 32 BITS
291
						for( col = 0; col < w; col++, ptr += 3 )
292
						{
293
							// // convert bgr pixel (32 bits) into rgb (32 bits) pixel
294
							RGBQUAD *pix = (RGBQUAD *)pBuff;
295
							pBuff += sizeof( RGBQUAD );
296
 
297
							ptr[2] = pix->rgbRed;
298
							ptr[1] = pix->rgbGreen;
299
							ptr[0] = pix->rgbBlue;
300
 
301
						}
302
 
303
						break;
304
					}
305
				}
306
			}
307
 
308
			break;
309
		}
310
 
311
		case BI_RLE8:
312
		{
313
// RLE 8 BITS
314
			for( row = h - 1; row >= 0; row-- )
315
			{
316
				if( flipvert )
317
					ptr = &(*pixels)[ row * w * 3 ];
318
 
319
				for( col = 0; col < w; /* nothing */ )
320
				{
321
					// get one packet (2 bytes)
322
					unsigned char byte1 = *((unsigned char *)(pBuff++));
323
					unsigned char byte2 = *((unsigned char *)(pBuff++));
324
 
325
 
326
					if( byte1 == RLE_COMMAND )
327
					{
328
						// absolute encoding
329
						for( i = 0; i < byte2; i++, ptr += 3, col++ )
330
						{
331
							// read the current pixel
332
							unsigned char color = *((unsigned char *)(pBuff++));
333
 
334
							// convert indexed pixel (8 bits) into rgb (32 bits) pixel
335
							ptr[2] = win_palette[ color ].rgbRed;
336
							ptr[1] = win_palette[ color ].rgbGreen;
337
							ptr[0] = win_palette[ color ].rgbBlue;
338
						}
339
 
340
						if( (byte2 % 2) == 1 )
341
							pBuff++;
342
					}
343
					else
344
					{
345
						// read next pixels
346
						for( i = 0; i < byte1; i++, ptr += 3, col++ )
347
						{
348
							// convert indexed pixel (8 bits) into rgb (32 bits) pixel
349
							ptr[2] = win_palette[ byte2 ].rgbRed;
350
							ptr[1] = win_palette[ byte2 ].rgbGreen;
351
							ptr[0] = win_palette[ byte2 ].rgbBlue;
352
						}
353
					}
354
				}
355
			}
356
 
357
			break;
358
		}
359
 
360
		case BI_RLE4:
361
		{
362
// RLE 4 BITS
363
			unsigned char color;
364
			int	bytesRead = 0;		// number of bytes read
365
 
366
			for( row = h - 1; row >= 0; row-- )
367
			{
368
				if( flipvert )
369
					ptr = &(*pixels)[ row * w * 3 ];
370
 
371
				for( col = 0; col < w; /* nothing */ )
372
				{
373
					// get one packet (2 bytes)
374
					unsigned char byte1 = *((unsigned char *)(pBuff++));
375
					unsigned char byte2 = *((unsigned char *)(pBuff++));
376
 
377
					bytesRead += 2;
378
 
379
 
380
					if( byte1 == RLE_COMMAND )
381
					{
382
						// absolute encoding
383
						unsigned char databyte;
384
 
385
						for( i = 0; i < byte2; i++, ptr += 3, col++ )
386
						{
387
							if( (i % 2) == 0 )
388
							{
389
								// read the current pixel
390
								databyte = *((unsigned char *)(pBuff++));
391
								bytesRead++;
392
 
393
								color = (databyte >> 4);	// 4 first bits
394
							}
395
							else
396
							{
397
								color = (databyte & 0x0F);	// 4 last bits
398
							}
399
 
400
							// convert indexed pixel (4 bits) into rgb (32 bits) pixel
401
							ptr[2] = win_palette[ color ].rgbRed;
402
							ptr[1] = win_palette[ color ].rgbGreen;
403
							ptr[0] = win_palette[ color ].rgbBlue;
404
						}
405
 
406
						while( (bytesRead % 2) != 0 )
407
						{
408
							pBuff++;
409
							bytesRead++;
410
						}
411
					}
412
					else
413
					{
414
						// read next pixels
415
						for( i = 0; i < byte1; i++, ptr += 3, col++ )
416
						{
417
							if( (i % 2) == 0 )
418
								color = (byte2 >> 4);	// 4 first bits
419
							else
420
								color = (byte2 & 0x0F);	// 4 last bits
421
 
422
							// convert indexed pixel (4 bits) into rgb (32 bits) pixel
423
							ptr[2] = win_palette[ color ].rgbRed;
424
							ptr[1] = win_palette[ color ].rgbGreen;
425
							ptr[0] = win_palette[ color ].rgbBlue;
426
						}
427
					}
428
				}
429
			}
430
 
431
			break;
432
		}
433
	}
434
 
435
 
436
	// free buffer memory
437
	delete [] buffer;
438
 
439
 
440
	// return success
441
	return 1;
442
}