1 //-----------------------------------------------------------------------------
2 //
3 // ImageLib Sources
4 // Copyright (C) 2001-2002 by Denton Woods
5 // Last modified: 05/25/2001 <--Y2K Compliant! =]
6 //
7 // Filename: src-IL/include/il_manip.h
8 //
9 // Description: Image manipulation
10 //
11 //-----------------------------------------------------------------------------
12
13 #ifndef MANIP_H
14 #define MANIP_H
15
16 #ifdef _cplusplus
17 extern "C" {
18 #endif
19
20 ILboolean ilFlipImage(void);
21 ILboolean ilMirrorImage(void); //@JASON New routine created 03/28/2001
22
23 //-----------------------------------------------
24 // Overflow handler for float-to-half conversion;
25 // generates a hardware floating-point overflow,
26 // which may be trapped by the operating system.
27 //-----------------------------------------------
28 #ifndef NOINLINE
29
30 #if defined(_MSC_VER)
31 #pragma warning(push)
32 #pragma warning(disable : 4756) // Disables 'named type definition in parentheses' warning
33 #endif
ilFloatToHalfOverflow()34 INLINE ILfloat /*ILAPIENTRY*/ ilFloatToHalfOverflow() {
35 ILfloat f = 1e10;
36 ILint j;
37 for (j = 0; j < 10; j++)
38 f *= f; // this will overflow before
39 // the for loop terminates
40 return f;
41 }
42 #if defined(_MSC_VER)
43 #pragma warning(pop)
44 #endif
45
46 //-----------------------------------------------------
47 // Float-to-half conversion -- general case, including
48 // zeroes, denormalized numbers and exponent overflows.
49 //-----------------------------------------------------
ilFloatToHalf(ILuint i)50 INLINE ILushort ILAPIENTRY ilFloatToHalf(ILuint i) {
51 //
52 // Our floating point number, f, is represented by the bit
53 // pattern in integer i. Disassemble that bit pattern into
54 // the sign, s, the exponent, e, and the significand, m.
55 // Shift s into the position where it will go in in the
56 // resulting half number.
57 // Adjust e, accounting for the different exponent bias
58 // of float and half (127 versus 15).
59 //
60
61 register int s = (i >> 16) & 0x00008000;
62 register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
63 register int m = i & 0x007fffff;
64
65 //
66 // Now reassemble s, e and m into a half:
67 //
68
69 if (e <= 0)
70 {
71 if (e < -10)
72 {
73 //
74 // E is less than -10. The absolute value of f is
75 // less than HALF_MIN (f may be a small normalized
76 // float, a denormalized float or a zero).
77 //
78 // We convert f to a half zero.
79 //
80
81 return 0;
82 }
83
84 //
85 // E is between -10 and 0. F is a normalized float,
86 // whose magnitude is less than HALF_NRM_MIN.
87 //
88 // We convert f to a denormalized half.
89 //
90
91 m = (m | 0x00800000) >> (1 - e);
92
93 //
94 // Round to nearest, round "0.5" up.
95 //
96 // Rounding may cause the significand to overflow and make
97 // our number normalized. Because of the way a half's bits
98 // are laid out, we don't have to treat this case separately;
99 // the code below will handle it correctly.
100 //
101
102 if (m & 0x00001000)
103 m += 0x00002000;
104
105 //
106 // Assemble the half from s, e (zero) and m.
107 //
108
109 return s | (m >> 13);
110 }
111 else if (e == 0xff - (127 - 15))
112 {
113 if (m == 0)
114 {
115 //
116 // F is an infinity; convert f to a half
117 // infinity with the same sign as f.
118 //
119
120 return s | 0x7c00;
121 }
122 else
123 {
124 //
125 // F is a NAN; we produce a half NAN that preserves
126 // the sign bit and the 10 leftmost bits of the
127 // significand of f, with one exception: If the 10
128 // leftmost bits are all zero, the NAN would turn
129 // into an infinity, so we have to set at least one
130 // bit in the significand.
131 //
132
133 m >>= 13;
134 return s | 0x7c00 | m | (m == 0);
135 }
136 }
137 else
138 {
139 //
140 // E is greater than zero. F is a normalized float.
141 // We try to convert f to a normalized half.
142 //
143
144 //
145 // Round to nearest, round "0.5" up
146 //
147
148 if (m & 0x00001000)
149 {
150 m += 0x00002000;
151
152 if (m & 0x00800000)
153 {
154 m = 0; // overflow in significand,
155 e += 1; // adjust exponent
156 }
157 }
158
159 //
160 // Handle exponent overflow
161 //
162
163 if (e > 30)
164 {
165 ilFloatToHalfOverflow(); // Cause a hardware floating point overflow;
166 return s | 0x7c00; // if this returns, the half becomes an
167 } // infinity with the same sign as f.
168
169 //
170 // Assemble the half from s, e and m.
171 //
172
173 return s | (e << 10) | (m >> 13);
174 }
175 }
176
177 // Taken from OpenEXR
ilHalfToFloat(ILushort y)178 INLINE ILuint ILAPIENTRY ilHalfToFloat (ILushort y) {
179
180 int s = (y >> 15) & 0x00000001;
181 int e = (y >> 10) & 0x0000001f;
182 int m = y & 0x000003ff;
183
184 if (e == 0)
185 {
186 if (m == 0)
187 {
188 //
189 // Plus or minus zero
190 //
191
192 return s << 31;
193 }
194 else
195 {
196 //
197 // Denormalized number -- renormalize it
198 //
199
200 while (!(m & 0x00000400))
201 {
202 m <<= 1;
203 e -= 1;
204 }
205
206 e += 1;
207 m &= ~0x00000400;
208 }
209 }
210 else if (e == 31)
211 {
212 if (m == 0)
213 {
214 //
215 // Positive or negative infinity
216 //
217
218 return (s << 31) | 0x7f800000;
219 }
220 else
221 {
222 //
223 // Nan -- preserve sign and significand bits
224 //
225
226 return (s << 31) | 0x7f800000 | (m << 13);
227 }
228 }
229
230 //
231 // Normalized number
232 //
233
234 e = e + (127 - 15);
235 m = m << 13;
236
237 //
238 // Assemble s, e and m.
239 //
240
241 return (s << 31) | (e << 23) | m;
242 }
243 #endif //NOINLINE
244
245 #ifdef _cplusplus
246 }
247 #endif
248
249 #endif//MANIP_H
250