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