summaryrefslogtreecommitdiff
path: root/utils/ibassoboot/jni/qdbmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/ibassoboot/jni/qdbmp.c')
-rw-r--r--utils/ibassoboot/jni/qdbmp.c798
1 files changed, 798 insertions, 0 deletions
diff --git a/utils/ibassoboot/jni/qdbmp.c b/utils/ibassoboot/jni/qdbmp.c
new file mode 100644
index 0000000000..fd1337277d
--- /dev/null
+++ b/utils/ibassoboot/jni/qdbmp.c
@@ -0,0 +1,798 @@
1#include "qdbmp.h"
2#include <stdlib.h>
3#include <string.h>
4
5
6/* Bitmap header */
7typedef struct _BMP_Header
8{
9 USHORT Magic; /* Magic identifier: "BM" */
10 UINT FileSize; /* Size of the BMP file in bytes */
11 USHORT Reserved1; /* Reserved */
12 USHORT Reserved2; /* Reserved */
13 UINT DataOffset; /* Offset of image data relative to the file's start */
14 UINT HeaderSize; /* Size of the header in bytes */
15 UINT Width; /* Bitmap's width */
16 UINT Height; /* Bitmap's height */
17 USHORT Planes; /* Number of color planes in the bitmap */
18 USHORT BitsPerPixel; /* Number of bits per pixel */
19 UINT CompressionType; /* Compression type */
20 UINT ImageDataSize; /* Size of uncompressed image's data */
21 UINT HPixelsPerMeter; /* Horizontal resolution (pixels per meter) */
22 UINT VPixelsPerMeter; /* Vertical resolution (pixels per meter) */
23 UINT ColorsUsed; /* Number of color indexes in the color table that are actually used by the bitmap */
24 UINT ColorsRequired; /* Number of color indexes that are required for displaying the bitmap */
25} BMP_Header;
26
27
28/* Private data structure */
29struct _BMP
30{
31 BMP_Header Header;
32 UCHAR* Palette;
33 UCHAR* Data;
34};
35
36
37/* Holds the last error code */
38static BMP_STATUS BMP_LAST_ERROR_CODE = 0;
39
40
41/* Error description strings */
42static const char* BMP_ERROR_STRING[] =
43{
44 "",
45 "General error",
46 "Could not allocate enough memory to complete the operation",
47 "File input/output error",
48 "File not found",
49 "File is not a supported BMP variant (must be uncompressed 8, 24 or 32 BPP)",
50 "File is not a valid BMP image",
51 "An argument is invalid or out of range",
52 "The requested action is not compatible with the BMP's type"
53};
54
55
56/* Size of the palette data for 8 BPP bitmaps */
57#define BMP_PALETTE_SIZE ( 256 * 4 )
58
59
60
61/*********************************** Forward declarations **********************************/
62int ReadHeader ( BMP* bmp, FILE* f );
63int WriteHeader ( BMP* bmp, FILE* f );
64
65int ReadUINT ( UINT* x, FILE* f );
66int ReadUSHORT ( USHORT *x, FILE* f );
67
68int WriteUINT ( UINT x, FILE* f );
69int WriteUSHORT ( USHORT x, FILE* f );
70
71
72
73
74
75
76/*********************************** Public methods **********************************/
77
78
79/**************************************************************
80 Creates a blank BMP image with the specified dimensions
81 and bit depth.
82**************************************************************/
83BMP* BMP_Create( UINT width, UINT height, USHORT depth )
84{
85 BMP* bmp;
86 int bytes_per_pixel = depth >> 3;
87 UINT bytes_per_row;
88
89 if ( height <= 0 || width <= 0 )
90 {
91 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
92 return NULL;
93 }
94
95 if ( depth != 8 && depth != 24 && depth != 32 )
96 {
97 BMP_LAST_ERROR_CODE = BMP_FILE_NOT_SUPPORTED;
98 return NULL;
99 }
100
101
102 /* Allocate the bitmap data structure */
103 bmp = calloc( 1, sizeof( BMP ) );
104 if ( bmp == NULL )
105 {
106 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
107 return NULL;
108 }
109
110
111 /* Set header' default values */
112 bmp->Header.Magic = 0x4D42;
113 bmp->Header.Reserved1 = 0;
114 bmp->Header.Reserved2 = 0;
115 bmp->Header.HeaderSize = 40;
116 bmp->Header.Planes = 1;
117 bmp->Header.CompressionType = 0;
118 bmp->Header.HPixelsPerMeter = 0;
119 bmp->Header.VPixelsPerMeter = 0;
120 bmp->Header.ColorsUsed = 0;
121 bmp->Header.ColorsRequired = 0;
122
123
124 /* Calculate the number of bytes used to store a single image row. This is always
125 rounded up to the next multiple of 4. */
126 bytes_per_row = width * bytes_per_pixel;
127 bytes_per_row += ( bytes_per_row % 4 ? 4 - bytes_per_row % 4 : 0 );
128
129
130 /* Set header's image specific values */
131 bmp->Header.Width = width;
132 bmp->Header.Height = height;
133 bmp->Header.BitsPerPixel = depth;
134 bmp->Header.ImageDataSize = bytes_per_row * height;
135 bmp->Header.FileSize = bmp->Header.ImageDataSize + 54 + ( depth == 8 ? BMP_PALETTE_SIZE : 0 );
136 bmp->Header.DataOffset = 54 + ( depth == 8 ? BMP_PALETTE_SIZE : 0 );
137
138
139 /* Allocate palette */
140 if ( bmp->Header.BitsPerPixel == 8 )
141 {
142 bmp->Palette = (UCHAR*) calloc( BMP_PALETTE_SIZE, sizeof( UCHAR ) );
143 if ( bmp->Palette == NULL )
144 {
145 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
146 free( bmp );
147 return NULL;
148 }
149 }
150 else
151 {
152 bmp->Palette = NULL;
153 }
154
155
156 /* Allocate pixels */
157 bmp->Data = (UCHAR*) calloc( bmp->Header.ImageDataSize, sizeof( UCHAR ) );
158 if ( bmp->Data == NULL )
159 {
160 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
161 free( bmp->Palette );
162 free( bmp );
163 return NULL;
164 }
165
166
167 BMP_LAST_ERROR_CODE = BMP_OK;
168
169 return bmp;
170}
171
172
173/**************************************************************
174 Frees all the memory used by the specified BMP image.
175**************************************************************/
176void BMP_Free( BMP* bmp )
177{
178 if ( bmp == NULL )
179 {
180 return;
181 }
182
183 if ( bmp->Palette != NULL )
184 {
185 free( bmp->Palette );
186 }
187
188 if ( bmp->Data != NULL )
189 {
190 free( bmp->Data );
191 }
192
193 free( bmp );
194
195 BMP_LAST_ERROR_CODE = BMP_OK;
196}
197
198
199/**************************************************************
200 Reads the specified BMP image file.
201**************************************************************/
202BMP* BMP_ReadFile( const char* filename )
203{
204 BMP* bmp;
205 FILE* f;
206
207 if ( filename == NULL )
208 {
209 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
210 return NULL;
211 }
212
213
214 /* Allocate */
215 bmp = calloc( 1, sizeof( BMP ) );
216 if ( bmp == NULL )
217 {
218 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
219 return NULL;
220 }
221
222
223 /* Open file */
224 f = fopen( filename, "rb" );
225 if ( f == NULL )
226 {
227 BMP_LAST_ERROR_CODE = BMP_FILE_NOT_FOUND;
228 free( bmp );
229 return NULL;
230 }
231
232
233 /* Read header */
234 if ( ReadHeader( bmp, f ) != BMP_OK || bmp->Header.Magic != 0x4D42 )
235 {
236 BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
237 fclose( f );
238 free( bmp );
239 return NULL;
240 }
241
242
243 /* Verify that the bitmap variant is supported */
244 if ( ( bmp->Header.BitsPerPixel != 32 && bmp->Header.BitsPerPixel != 24 && bmp->Header.BitsPerPixel != 8 )
245 || bmp->Header.CompressionType != 0 || bmp->Header.HeaderSize != 40 )
246 {
247 BMP_LAST_ERROR_CODE = BMP_FILE_NOT_SUPPORTED;
248 fclose( f );
249 free( bmp );
250 return NULL;
251 }
252
253
254 /* Allocate and read palette */
255 if ( bmp->Header.BitsPerPixel == 8 )
256 {
257 bmp->Palette = (UCHAR*) malloc( BMP_PALETTE_SIZE * sizeof( UCHAR ) );
258 if ( bmp->Palette == NULL )
259 {
260 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
261 fclose( f );
262 free( bmp );
263 return NULL;
264 }
265
266 if ( fread( bmp->Palette, sizeof( UCHAR ), BMP_PALETTE_SIZE, f ) != BMP_PALETTE_SIZE )
267 {
268 BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
269 fclose( f );
270 free( bmp->Palette );
271 free( bmp );
272 return NULL;
273 }
274 }
275 else /* Not an indexed image */
276 {
277 bmp->Palette = NULL;
278 }
279
280
281 /* Allocate memory for image data */
282 bmp->Data = (UCHAR*) malloc( bmp->Header.ImageDataSize );
283 if ( bmp->Data == NULL )
284 {
285 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
286 fclose( f );
287 free( bmp->Palette );
288 free( bmp );
289 return NULL;
290 }
291
292
293 /* Read image data */
294 if ( fread( bmp->Data, sizeof( UCHAR ), bmp->Header.ImageDataSize, f ) != bmp->Header.ImageDataSize )
295 {
296 BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
297 fclose( f );
298 free( bmp->Data );
299 free( bmp->Palette );
300 free( bmp );
301 return NULL;
302 }
303
304
305 fclose( f );
306
307 BMP_LAST_ERROR_CODE = BMP_OK;
308
309 return bmp;
310}
311
312
313/**************************************************************
314 Writes the BMP image to the specified file.
315**************************************************************/
316void BMP_WriteFile( BMP* bmp, const char* filename )
317{
318 FILE* f;
319
320 if ( filename == NULL )
321 {
322 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
323 return;
324 }
325
326
327 /* Open file */
328 f = fopen( filename, "wb" );
329 if ( f == NULL )
330 {
331 BMP_LAST_ERROR_CODE = BMP_FILE_NOT_FOUND;
332 return;
333 }
334
335
336 /* Write header */
337 if ( WriteHeader( bmp, f ) != BMP_OK )
338 {
339 BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
340 fclose( f );
341 return;
342 }
343
344
345 /* Write palette */
346 if ( bmp->Palette )
347 {
348 if ( fwrite( bmp->Palette, sizeof( UCHAR ), BMP_PALETTE_SIZE, f ) != BMP_PALETTE_SIZE )
349 {
350 BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
351 fclose( f );
352 return;
353 }
354 }
355
356
357 /* Write data */
358 if ( fwrite( bmp->Data, sizeof( UCHAR ), bmp->Header.ImageDataSize, f ) != bmp->Header.ImageDataSize )
359 {
360 BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
361 fclose( f );
362 return;
363 }
364
365
366 BMP_LAST_ERROR_CODE = BMP_OK;
367 fclose( f );
368}
369
370
371/**************************************************************
372 Returns the image's width.
373**************************************************************/
374UINT BMP_GetWidth( BMP* bmp )
375{
376 if ( bmp == NULL )
377 {
378 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
379 return -1;
380 }
381
382 BMP_LAST_ERROR_CODE = BMP_OK;
383
384 return ( bmp->Header.Width );
385}
386
387
388/**************************************************************
389 Returns the image's height.
390**************************************************************/
391UINT BMP_GetHeight( BMP* bmp )
392{
393 if ( bmp == NULL )
394 {
395 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
396 return -1;
397 }
398
399 BMP_LAST_ERROR_CODE = BMP_OK;
400
401 return ( bmp->Header.Height );
402}
403
404
405/**************************************************************
406 Returns the image's color depth (bits per pixel).
407**************************************************************/
408USHORT BMP_GetDepth( BMP* bmp )
409{
410 if ( bmp == NULL )
411 {
412 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
413 return -1;
414 }
415
416 BMP_LAST_ERROR_CODE = BMP_OK;
417
418 return ( bmp->Header.BitsPerPixel );
419}
420
421
422/**************************************************************
423 Populates the arguments with the specified pixel's RGB
424 values.
425**************************************************************/
426void BMP_GetPixelRGB( BMP* bmp, UINT x, UINT y, UCHAR* r, UCHAR* g, UCHAR* b )
427{
428 UCHAR* pixel;
429 UINT bytes_per_row;
430 UCHAR bytes_per_pixel;
431
432 if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
433 {
434 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
435 }
436 else
437 {
438 BMP_LAST_ERROR_CODE = BMP_OK;
439
440 bytes_per_pixel = bmp->Header.BitsPerPixel >> 3;
441
442 /* Row's size is rounded up to the next multiple of 4 bytes */
443 bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
444
445 /* Calculate the location of the relevant pixel (rows are flipped) */
446 pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x * bytes_per_pixel );
447
448
449 /* In indexed color mode the pixel's value is an index within the palette */
450 if ( bmp->Header.BitsPerPixel == 8 )
451 {
452 pixel = bmp->Palette + *pixel * 4;
453 }
454
455 /* Note: colors are stored in BGR order */
456 if ( r ) *r = *( pixel + 2 );
457 if ( g ) *g = *( pixel + 1 );
458 if ( b ) *b = *( pixel + 0 );
459 }
460}
461
462
463/**************************************************************
464 Sets the specified pixel's RGB values.
465**************************************************************/
466void BMP_SetPixelRGB( BMP* bmp, UINT x, UINT y, UCHAR r, UCHAR g, UCHAR b )
467{
468 UCHAR* pixel;
469 UINT bytes_per_row;
470 UCHAR bytes_per_pixel;
471
472 if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
473 {
474 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
475 }
476
477 else if ( bmp->Header.BitsPerPixel != 24 && bmp->Header.BitsPerPixel != 32 )
478 {
479 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
480 }
481
482 else
483 {
484 BMP_LAST_ERROR_CODE = BMP_OK;
485
486 bytes_per_pixel = bmp->Header.BitsPerPixel >> 3;
487
488 /* Row's size is rounded up to the next multiple of 4 bytes */
489 bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
490
491 /* Calculate the location of the relevant pixel (rows are flipped) */
492 pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x * bytes_per_pixel );
493
494 /* Note: colors are stored in BGR order */
495 *( pixel + 2 ) = r;
496 *( pixel + 1 ) = g;
497 *( pixel + 0 ) = b;
498 }
499}
500
501
502/**************************************************************
503 Gets the specified pixel's color index.
504**************************************************************/
505void BMP_GetPixelIndex( BMP* bmp, UINT x, UINT y, UCHAR* val )
506{
507 UCHAR* pixel;
508 UINT bytes_per_row;
509
510 if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
511 {
512 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
513 }
514
515 else if ( bmp->Header.BitsPerPixel != 8 )
516 {
517 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
518 }
519
520 else
521 {
522 BMP_LAST_ERROR_CODE = BMP_OK;
523
524 /* Row's size is rounded up to the next multiple of 4 bytes */
525 bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
526
527 /* Calculate the location of the relevant pixel */
528 pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x );
529
530
531 if ( val ) *val = *pixel;
532 }
533}
534
535
536/**************************************************************
537 Sets the specified pixel's color index.
538**************************************************************/
539void BMP_SetPixelIndex( BMP* bmp, UINT x, UINT y, UCHAR val )
540{
541 UCHAR* pixel;
542 UINT bytes_per_row;
543
544 if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
545 {
546 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
547 }
548
549 else if ( bmp->Header.BitsPerPixel != 8 )
550 {
551 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
552 }
553
554 else
555 {
556 BMP_LAST_ERROR_CODE = BMP_OK;
557
558 /* Row's size is rounded up to the next multiple of 4 bytes */
559 bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
560
561 /* Calculate the location of the relevant pixel */
562 pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x );
563
564 *pixel = val;
565 }
566}
567
568
569/**************************************************************
570 Gets the color value for the specified palette index.
571**************************************************************/
572void BMP_GetPaletteColor( BMP* bmp, UCHAR index, UCHAR* r, UCHAR* g, UCHAR* b )
573{
574 if ( bmp == NULL )
575 {
576 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
577 }
578
579 else if ( bmp->Header.BitsPerPixel != 8 )
580 {
581 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
582 }
583
584 else
585 {
586 if ( r ) *r = *( bmp->Palette + index * 4 + 2 );
587 if ( g ) *g = *( bmp->Palette + index * 4 + 1 );
588 if ( b ) *b = *( bmp->Palette + index * 4 + 0 );
589
590 BMP_LAST_ERROR_CODE = BMP_OK;
591 }
592}
593
594
595/**************************************************************
596 Sets the color value for the specified palette index.
597**************************************************************/
598void BMP_SetPaletteColor( BMP* bmp, UCHAR index, UCHAR r, UCHAR g, UCHAR b )
599{
600 if ( bmp == NULL )
601 {
602 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
603 }
604
605 else if ( bmp->Header.BitsPerPixel != 8 )
606 {
607 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
608 }
609
610 else
611 {
612 *( bmp->Palette + index * 4 + 2 ) = r;
613 *( bmp->Palette + index * 4 + 1 ) = g;
614 *( bmp->Palette + index * 4 + 0 ) = b;
615
616 BMP_LAST_ERROR_CODE = BMP_OK;
617 }
618}
619
620
621/**************************************************************
622 Returns the last error code.
623**************************************************************/
624BMP_STATUS BMP_GetError()
625{
626 return BMP_LAST_ERROR_CODE;
627}
628
629
630/**************************************************************
631 Returns a description of the last error code.
632**************************************************************/
633const char* BMP_GetErrorDescription()
634{
635 if ( BMP_LAST_ERROR_CODE > 0 && BMP_LAST_ERROR_CODE < BMP_ERROR_NUM )
636 {
637 return BMP_ERROR_STRING[ BMP_LAST_ERROR_CODE ];
638 }
639 else
640 {
641 return NULL;
642 }
643}
644
645
646
647
648
649/*********************************** Private methods **********************************/
650
651
652/**************************************************************
653 Reads the BMP file's header into the data structure.
654 Returns BMP_OK on success.
655**************************************************************/
656int ReadHeader( BMP* bmp, FILE* f )
657{
658 if ( bmp == NULL || f == NULL )
659 {
660 return BMP_INVALID_ARGUMENT;
661 }
662
663 /* The header's fields are read one by one, and converted from the format's
664 little endian to the system's native representation. */
665 if ( !ReadUSHORT( &( bmp->Header.Magic ), f ) ) return BMP_IO_ERROR;
666 if ( !ReadUINT( &( bmp->Header.FileSize ), f ) ) return BMP_IO_ERROR;
667 if ( !ReadUSHORT( &( bmp->Header.Reserved1 ), f ) ) return BMP_IO_ERROR;
668 if ( !ReadUSHORT( &( bmp->Header.Reserved2 ), f ) ) return BMP_IO_ERROR;
669 if ( !ReadUINT( &( bmp->Header.DataOffset ), f ) ) return BMP_IO_ERROR;
670 if ( !ReadUINT( &( bmp->Header.HeaderSize ), f ) ) return BMP_IO_ERROR;
671 if ( !ReadUINT( &( bmp->Header.Width ), f ) ) return BMP_IO_ERROR;
672 if ( !ReadUINT( &( bmp->Header.Height ), f ) ) return BMP_IO_ERROR;
673 if ( !ReadUSHORT( &( bmp->Header.Planes ), f ) ) return BMP_IO_ERROR;
674 if ( !ReadUSHORT( &( bmp->Header.BitsPerPixel ), f ) ) return BMP_IO_ERROR;
675 if ( !ReadUINT( &( bmp->Header.CompressionType ), f ) ) return BMP_IO_ERROR;
676 if ( !ReadUINT( &( bmp->Header.ImageDataSize ), f ) ) return BMP_IO_ERROR;
677 if ( !ReadUINT( &( bmp->Header.HPixelsPerMeter ), f ) ) return BMP_IO_ERROR;
678 if ( !ReadUINT( &( bmp->Header.VPixelsPerMeter ), f ) ) return BMP_IO_ERROR;
679 if ( !ReadUINT( &( bmp->Header.ColorsUsed ), f ) ) return BMP_IO_ERROR;
680 if ( !ReadUINT( &( bmp->Header.ColorsRequired ), f ) ) return BMP_IO_ERROR;
681
682 return BMP_OK;
683}
684
685
686/**************************************************************
687 Writes the BMP file's header into the data structure.
688 Returns BMP_OK on success.
689**************************************************************/
690int WriteHeader( BMP* bmp, FILE* f )
691{
692 if ( bmp == NULL || f == NULL )
693 {
694 return BMP_INVALID_ARGUMENT;
695 }
696
697 /* The header's fields are written one by one, and converted to the format's
698 little endian representation. */
699 if ( !WriteUSHORT( bmp->Header.Magic, f ) ) return BMP_IO_ERROR;
700 if ( !WriteUINT( bmp->Header.FileSize, f ) ) return BMP_IO_ERROR;
701 if ( !WriteUSHORT( bmp->Header.Reserved1, f ) ) return BMP_IO_ERROR;
702 if ( !WriteUSHORT( bmp->Header.Reserved2, f ) ) return BMP_IO_ERROR;
703 if ( !WriteUINT( bmp->Header.DataOffset, f ) ) return BMP_IO_ERROR;
704 if ( !WriteUINT( bmp->Header.HeaderSize, f ) ) return BMP_IO_ERROR;
705 if ( !WriteUINT( bmp->Header.Width, f ) ) return BMP_IO_ERROR;
706 if ( !WriteUINT( bmp->Header.Height, f ) ) return BMP_IO_ERROR;
707 if ( !WriteUSHORT( bmp->Header.Planes, f ) ) return BMP_IO_ERROR;
708 if ( !WriteUSHORT( bmp->Header.BitsPerPixel, f ) ) return BMP_IO_ERROR;
709 if ( !WriteUINT( bmp->Header.CompressionType, f ) ) return BMP_IO_ERROR;
710 if ( !WriteUINT( bmp->Header.ImageDataSize, f ) ) return BMP_IO_ERROR;
711 if ( !WriteUINT( bmp->Header.HPixelsPerMeter, f ) ) return BMP_IO_ERROR;
712 if ( !WriteUINT( bmp->Header.VPixelsPerMeter, f ) ) return BMP_IO_ERROR;
713 if ( !WriteUINT( bmp->Header.ColorsUsed, f ) ) return BMP_IO_ERROR;
714 if ( !WriteUINT( bmp->Header.ColorsRequired, f ) ) return BMP_IO_ERROR;
715
716 return BMP_OK;
717}
718
719
720/**************************************************************
721 Reads a little-endian unsigned int from the file.
722 Returns non-zero on success.
723**************************************************************/
724int ReadUINT( UINT* x, FILE* f )
725{
726 UCHAR little[ 4 ]; /* BMPs use 32 bit ints */
727
728 if ( x == NULL || f == NULL )
729 {
730 return 0;
731 }
732
733 if ( fread( little, 4, 1, f ) != 1 )
734 {
735 return 0;
736 }
737
738 *x = ( little[ 3 ] << 24 | little[ 2 ] << 16 | little[ 1 ] << 8 | little[ 0 ] );
739
740 return 1;
741}
742
743
744/**************************************************************
745 Reads a little-endian unsigned short int from the file.
746 Returns non-zero on success.
747**************************************************************/
748int ReadUSHORT( USHORT *x, FILE* f )
749{
750 UCHAR little[ 2 ]; /* BMPs use 16 bit shorts */
751
752 if ( x == NULL || f == NULL )
753 {
754 return 0;
755 }
756
757 if ( fread( little, 2, 1, f ) != 1 )
758 {
759 return 0;
760 }
761
762 *x = ( little[ 1 ] << 8 | little[ 0 ] );
763
764 return 1;
765}
766
767
768/**************************************************************
769 Writes a little-endian unsigned int to the file.
770 Returns non-zero on success.
771**************************************************************/
772int WriteUINT( UINT x, FILE* f )
773{
774 UCHAR little[ 4 ]; /* BMPs use 32 bit ints */
775
776 little[ 3 ] = (UCHAR)( ( x & 0xff000000 ) >> 24 );
777 little[ 2 ] = (UCHAR)( ( x & 0x00ff0000 ) >> 16 );
778 little[ 1 ] = (UCHAR)( ( x & 0x0000ff00 ) >> 8 );
779 little[ 0 ] = (UCHAR)( ( x & 0x000000ff ) >> 0 );
780
781 return ( f && fwrite( little, 4, 1, f ) == 1 );
782}
783
784
785/**************************************************************
786 Writes a little-endian unsigned short int to the file.
787 Returns non-zero on success.
788**************************************************************/
789int WriteUSHORT( USHORT x, FILE* f )
790{
791 UCHAR little[ 2 ]; /* BMPs use 16 bit shorts */
792
793 little[ 1 ] = (UCHAR)( ( x & 0xff00 ) >> 8 );
794 little[ 0 ] = (UCHAR)( ( x & 0x00ff ) >> 0 );
795
796 return ( f && fwrite( little, 2, 1, f ) == 1 );
797}
798