(no commit message)
[atyndall/cits2231.git] / bitmap.c
1 /*
2  * Windows BMP file functions for OpenGL.
3  *
4  * Written by Michael Sweet.
5  */
6
7 #include "bitmap.h"
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <errno.h>
11
12 /*
13  * Functions for reading and writing 16- and 32-bit little-endian integers.
14  */
15
16 static unsigned short read_word(FILE *fp);
17 static unsigned int   read_dword(FILE *fp);
18 static int            read_long(FILE *fp);
19
20 /*
21  * 'LoadDIBitmap()' - Load a DIB/BMP file from disk.
22  *
23  * Returns a pointer to the bitmap if successful, NULL otherwise...
24  */
25
26 GLubyte *                          /* O - Bitmap data */
27 LoadDIBitmap(const char *filename, /* I - File to load */
28              BITMAPINFO **info)    /* O - Bitmap information */
29     {
30     FILE             *fp;          /* Open file pointer */
31     GLubyte          *bits;        /* Bitmap pixel bits */
32     GLubyte          *ptr;         /* Pointer into bitmap */
33     GLubyte          temp;         /* Temporary variable to swap red and blue */
34     int              x, y;         /* X and Y position in image */
35     int              length;       /* Line length */
36     int              bitsize;      /* Size of bitmap */
37     int              infosize;     /* Size of header information */
38     BITMAPFILEHEADER header;       /* File header */
39
40
41     /* Try opening the file; use "rb" mode to read this *binary* file. */
42     if ((fp = fopen(filename, "rb")) == NULL)
43         return (NULL);
44
45     /* Read the file header and any following bitmap information... */
46     header.bfType      = read_word(fp);
47     header.bfSize      = read_dword(fp);
48     header.bfReserved1 = read_word(fp);
49     header.bfReserved2 = read_word(fp);
50     header.bfOffBits   = read_dword(fp);
51
52     if (header.bfType != 0x4D42) /* Check for BM reversed... */
53         {
54         /* Not a bitmap file - return NULL... */
55         fclose(fp);
56         return (NULL);
57         }
58
59     infosize = header.bfOffBits - 18;
60     if ((*info = (BITMAPINFO *)malloc(sizeof(BITMAPINFO))) == NULL)
61         {
62         /* Couldn't allocate memory for bitmap info - return NULL... */
63         fclose(fp);
64         return (NULL);
65         }
66
67     (*info)->bmiHeader.biSize          = read_dword(fp);
68     (*info)->bmiHeader.biWidth         = read_long(fp);
69     (*info)->bmiHeader.biHeight        = read_long(fp);
70     (*info)->bmiHeader.biPlanes        = read_word(fp);
71     (*info)->bmiHeader.biBitCount      = read_word(fp);
72     (*info)->bmiHeader.biCompression   = read_dword(fp);
73     (*info)->bmiHeader.biSizeImage     = read_dword(fp);
74     (*info)->bmiHeader.biXPelsPerMeter = read_long(fp);
75     (*info)->bmiHeader.biYPelsPerMeter = read_long(fp);
76     (*info)->bmiHeader.biClrUsed       = read_dword(fp);
77     (*info)->bmiHeader.biClrImportant  = read_dword(fp);
78
79     if (infosize > 40)
80         if (fread((*info)->bmiColors, infosize - 40, 1, fp) < 1)
81             {
82             /* Couldn't read the bitmap header - return NULL... */
83             free(*info);
84             fclose(fp);
85             return (NULL);
86             }
87
88     /* Now that we have all the header info read in, allocate memory for *
89      * the bitmap and read *it* in...                                    */
90     if ((bitsize = (*info)->bmiHeader.biSizeImage) == 0)
91         bitsize = ((*info)->bmiHeader.biWidth *
92                    (*info)->bmiHeader.biBitCount + 7) / 8 *
93                    abs((*info)->bmiHeader.biHeight);
94
95     if ((bits = malloc(bitsize)) == NULL)
96         {
97         /* Couldn't allocate memory - return NULL! */
98         free(*info);
99         fclose(fp);
100         return (NULL);
101         }
102
103     if (fread(bits, 1, bitsize, fp) < bitsize)
104         {
105         /* Couldn't read bitmap - free memory and return NULL! */
106         free(*info);
107         free(bits);
108         fclose(fp);
109         return (NULL);
110         }
111
112     /* Swap red and blue */
113     length = ((*info)->bmiHeader.biWidth * 3 + 3) & ~3;
114     for (y = 0; y < (*info)->bmiHeader.biHeight; y ++)
115         for (ptr = bits + y * length, x = (*info)->bmiHeader.biWidth;
116              x > 0;
117              x --, ptr += 3)
118             {
119             temp   = ptr[0];
120             ptr[0] = ptr[2];
121             ptr[2] = temp;
122             }
123
124     /* OK, everything went fine - return the allocated bitmap... */
125     fclose(fp);
126     return (bits);
127     }
128
129 /*
130  * 'read_word()' - Read a 16-bit unsigned integer.
131  */
132
133 static unsigned short     /* O - 16-bit unsigned integer */
134 read_word(FILE *fp)       /* I - File to read from */
135     {
136     unsigned char b0, b1; /* Bytes from file */
137
138     b0 = getc(fp);
139     b1 = getc(fp);
140
141     return ((b1 << 8) | b0);
142     }
143
144
145 /*
146  * 'read_dword()' - Read a 32-bit unsigned integer.
147  */
148
149 static unsigned int               /* O - 32-bit unsigned integer */
150 read_dword(FILE *fp)              /* I - File to read from */
151     {
152     unsigned char b0, b1, b2, b3; /* Bytes from file */
153
154     b0 = getc(fp);
155     b1 = getc(fp);
156     b2 = getc(fp);
157     b3 = getc(fp);
158
159     return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
160     }
161
162
163 /*
164  * 'read_long()' - Read a 32-bit signed integer.
165  */
166
167 static int                        /* O - 32-bit signed integer */
168 read_long(FILE *fp)               /* I - File to read from */
169     {
170     unsigned char b0, b1, b2, b3; /* Bytes from file */
171
172     b0 = getc(fp);
173     b1 = getc(fp);
174     b2 = getc(fp);
175     b3 = getc(fp);
176
177     return ((int)(((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
178     }

UCC git Repository :: git.ucc.asn.au