Panda3D
bmp.h
1 /* Filename: bmp.h
2  * Created by:
3  *
4  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
5  *
6  * PANDA 3D SOFTWARE
7  * Copyright (c) Carnegie Mellon University. All rights reserved.
8  *
9  * All use of this software is subject to the terms of the revised BSD
10  * license. You should have received a copy of this license along
11  * with this source code in a file named "LICENSE."
12  *
13  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
14 
15 #ifndef _BMP_H_
16 #define _BMP_H_
17 
18 #include "pandabase.h"
19 #include "pnmimage_base.h"
20 
21 /* prototypes */
22 static unsigned long BMPlenfileheader(int classv);
23 static unsigned long BMPleninfoheader(int classv);
24 static unsigned long BMPlenrgbtable(int classv, unsigned long bitcount);
25 static unsigned long BMPlenline(int classv, unsigned long bitcount, unsigned long x);
26 static unsigned long BMPlenbits(int classv, unsigned long bitcount, unsigned long x, unsigned long y);
27 static unsigned long BMPlenfile(int classv, unsigned long bitcount, unsigned long x, unsigned long y);
28 static unsigned long BMPoffbits(int classv, unsigned long bitcount);
29 /*
30  * Classves of BMP files
31  */
32 
33 #define C_WIN 1
34 #define C_OS2 2
35 #define C_WINV2 3
36 #define C_WINV3 4
37 #define C_WINV4 5
38 #define C_WINV5 6
39 
40 static char er_internal[] = "%s: internal error!";
41 
42 static unsigned long
43 BMPlenfileheader(int classv)
44 {
45  switch (classv)
46  {
47  case C_WIN:
48  case C_OS2:
49  case C_WINV2:
50  case C_WINV3:
51  case C_WINV4:
52  case C_WINV5:
53  return 14;
54  return 14;
55  default:
56  pm_error(er_internal, "BMPlenfileheader");
57  return 0;
58  }
59 }
60 
61 static unsigned long
62 BMPleninfoheader(int classv)
63 {
64  switch (classv)
65  {
66  case C_WIN:
67  return 40;
68  case C_OS2:
69  return 12;
70  case C_WINV2:
71  return 52;
72  case C_WINV3:
73  return 56;
74  case C_WINV4:
75  return 108;
76  case C_WINV5:
77  return 124;
78  default:
79  pm_error(er_internal, "BMPleninfoheader");
80  return 0;
81  }
82 }
83 
84 static unsigned long
85 BMPlenrgbtable(int classv, unsigned long bitcount)
86 {
87  unsigned long lenrgb;
88 
89  if (bitcount > 8) {
90  return 0;
91  }
92 
93  if (bitcount < 1)
94  {
95  pm_error(er_internal, "BMPlenrgbtable");
96  return 0;
97  }
98  switch (classv)
99  {
100  case C_WIN:
101  lenrgb = 4;
102  break;
103  case C_OS2:
104  lenrgb = 3;
105  break;
106  default:
107  pm_error(er_internal, "BMPlenrgbtable");
108  return 0;
109  }
110 
111  return (1 << bitcount) * lenrgb;
112 }
113 
114 /*
115  * length, in bytes, of a line of the image
116  *
117  * Evidently each row is padded on the right as needed to make it a
118  * multiple of 4 bytes long. This appears to be true of both
119  * OS/2 and Windows BMP files.
120  */
121 static unsigned long
122 BMPlenline(int classv, unsigned long bitcount, unsigned long x)
123 {
124  unsigned long bitsperline;
125 
126  bitsperline = x * bitcount;
127 
128  /*
129  * if bitsperline is not a multiple of 32, then round
130  * bitsperline up to the next multiple of 32.
131  */
132  if ((bitsperline % 32) != 0)
133  {
134  bitsperline += (32 - (bitsperline % 32));
135  }
136 
137  if ((bitsperline % 32) != 0)
138  {
139  pm_error(er_internal, "BMPlenline");
140  return 0;
141  }
142 
143  /* number of bytes per line == bitsperline/8 */
144  return bitsperline >> 3;
145 }
146 
147 /* return the number of bytes used to store the image bits */
148 static unsigned long
149 BMPlenbits(
150  int classv,
151  unsigned long bitcount,
152  unsigned long x,
153  unsigned long y)
154 {
155  return y * BMPlenline(classv, bitcount, x);
156 }
157 
158 /* return the offset to the BMP image bits */
159 static unsigned long
160 BMPoffbits(
161  int classv,
162  unsigned long bitcount)
163 {
164  return BMPlenfileheader(classv)
165  + BMPleninfoheader(classv)
166  + BMPlenrgbtable(classv, bitcount);
167 }
168 
169 /* return the size of the BMP file in bytes */
170 static unsigned long
171 BMPlenfile(
172  int classv,
173  unsigned long bitcount,
174  unsigned long x,
175  unsigned long y)
176 {
177  return BMPoffbits(classv, bitcount)
178  + BMPlenbits(classv, bitcount, x, y);
179 }
180 
181 #endif /* _BMP_H_ */
182