DevIL: /home/dwoods/DevIL/src-IL/include/il_manip.h Source File

- Main Page
- Data Structures
- Files

# /home/dwoods/DevIL/src-IL/include/il_manip.h

    00001 //-----------------------------------------------------------------------------
    00002 //
    00003 // ImageLib Sources
    00004 // Copyright (C) 2001-2002 by Denton Woods
    00005 // Last modified: 05/25/2001 <--Y2K Compliant! =]
    00006 //
    00007 // Filename: src-IL/include/il_manip.h
    00008 //
    00009 // Description: Image manipulation
    00010 //
    00011 //-----------------------------------------------------------------------------
    00012
    00013 #ifndef MANIP_H
    00014 #define MANIP_H
    00015
    00016 #ifdef _cplusplus
    00017 extern "C" {
    00018 #endif
    00019
    00020 ILboolean ilFlipImage(void);
    00021 ILboolean ilMirrorImage(void);  //@JASON New routine created 03/28/2001
    00022
    00023 //-----------------------------------------------
    00024 // Overflow handler for float-to-half conversion;
    00025 // generates a hardware floating-point overflow,
    00026 // which may be trapped by the operating system.
    00027 //-----------------------------------------------
    00028 #ifndef NOINLINE
    00029
    00030 #if defined(_MSC_VER)
    00031         #pragma warning(push)
    00032         #pragma warning(disable : 4756)  // Disables 'named type definition in parentheses' warning
    00033 #endif
    00034 INLINE ILfloat /*ILAPIENTRY*/ ilFloatToHalfOverflow() {
    00035         ILfloat f = 1e10;
    00036         ILint j;
    00037         for (j = 0; j < 10; j++)
    00038                 f *= f;                         // this will overflow before
    00039         // the for loop terminates
    00040         return f;
    00041 }
    00042 #if defined(_MSC_VER)
    00043         #pragma warning(pop)
    00044 #endif
    00045
    00046 //-----------------------------------------------------
    00047 // Float-to-half conversion -- general case, including
    00048 // zeroes, denormalized numbers and exponent overflows.
    00049 //-----------------------------------------------------
    00050 INLINE ILushort ILAPIENTRY ilFloatToHalf(ILuint i) {
    00051         //
    00052         // Our floating point number, f, is represented by the bit
    00053         // pattern in integer i.  Disassemble that bit pattern into
    00054         // the sign, s, the exponent, e, and the significand, m.
    00055         // Shift s into the position where it will go in in the
    00056         // resulting half number.
    00057         // Adjust e, accounting for the different exponent bias
    00058         // of float and half (127 versus 15).
    00059         //
    00060
    00061         register int s =  (i >> 16) & 0x00008000;
    00062         register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
    00063         register int m =   i        & 0x007fffff;
    00064
    00065         //
    00066         // Now reassemble s, e and m into a half:
    00067         //
    00068
    00069         if (e <= 0)
    00070         {
    00071                 if (e < -10)
    00072                 {
    00073                         //
    00074                         // E is less than -10.  The absolute value of f is
    00075                         // less than HALF_MIN (f may be a small normalized
    00076                         // float, a denormalized float or a zero).
    00077                         //
    00078                         // We convert f to a half zero.
    00079                         //
    00080
    00081                         return 0;
    00082                 }
    00083
    00084                 //
    00085                 // E is between -10 and 0.  F is a normalized float,
    00086                 // whose magnitude is less than HALF_NRM_MIN.
    00087                 //
    00088                 // We convert f to a denormalized half.
    00089                 //
    00090
    00091                 m = (m | 0x00800000) >> (1 - e);
    00092
    00093                 //
    00094                 // Round to nearest, round "0.5" up.
    00095                 //
    00096                 // Rounding may cause the significand to overflow and make
    00097                 // our number normalized.  Because of the way a half's bits
    00098                 // are laid out, we don't have to treat this case separately;
    00099                 // the code below will handle it correctly.
    00100                 //
    00101
    00102                 if (m &  0x00001000)
    00103                         m += 0x00002000;
    00104
    00105                 //
    00106                 // Assemble the half from s, e (zero) and m.
    00107                 //
    00108
    00109                 return s | (m >> 13);
    00110         }
    00111         else if (e == 0xff - (127 - 15))
    00112         {
    00113                 if (m == 0)
    00114                 {
    00115                         //
    00116                         // F is an infinity; convert f to a half
    00117                         // infinity with the same sign as f.
    00118                         //
    00119
    00120                         return s | 0x7c00;
    00121                 }
    00122                 else
    00123                 {
    00124                         //
    00125                         // F is a NAN; we produce a half NAN that preserves
    00126                         // the sign bit and the 10 leftmost bits of the
    00127                         // significand of f, with one exception: If the 10
    00128                         // leftmost bits are all zero, the NAN would turn
    00129                         // into an infinity, so we have to set at least one
    00130                         // bit in the significand.
    00131                         //
    00132
    00133                         m >>= 13;
    00134                         return s | 0x7c00 | m | (m == 0);
    00135                 }
    00136         }
    00137         else
    00138         {
    00139                 //
    00140                 // E is greater than zero.  F is a normalized float.
    00141                 // We try to convert f to a normalized half.
    00142                 //
    00143
    00144                 //
    00145                 // Round to nearest, round "0.5" up
    00146                 //
    00147
    00148                 if (m &  0x00001000)
    00149                 {
    00150                         m += 0x00002000;
    00151
    00152                         if (m & 0x00800000)
    00153                         {
    00154                                 m =  0;         // overflow in significand,
    00155                                 e += 1;         // adjust exponent
    00156                         }
    00157                 }
    00158
    00159                 //
    00160                 // Handle exponent overflow
    00161                 //
    00162
    00163                 if (e > 30)
    00164                 {
    00165                         ilFloatToHalfOverflow();        // Cause a hardware floating point overflow;
    00166                         return s | 0x7c00;      // if this returns, the half becomes an
    00167                 }                       // infinity with the same sign as f.
    00168
    00169                 //
    00170                 // Assemble the half from s, e and m.
    00171                 //
    00172
    00173                 return s | (e << 10) | (m >> 13);
    00174         }
    00175 }
    00176
    00177 // Taken from OpenEXR
    00178 INLINE ILuint ILAPIENTRY ilHalfToFloat (ILushort y) {
    00179
    00180         int s = (y >> 15) & 0x00000001;
    00181         int e = (y >> 10) & 0x0000001f;
    00182         int m =  y                & 0x000003ff;
    00183
    00184         if (e == 0)
    00185         {
    00186                 if (m == 0)
    00187                 {
    00188                         //
    00189                         // Plus or minus zero
    00190                         //
    00191
    00192                         return s << 31;
    00193                 }
    00194                 else
    00195                 {
    00196                         //
    00197                         // Denormalized number -- renormalize it
    00198                         //
    00199
    00200                         while (!(m & 0x00000400))
    00201                         {
    00202                                 m <<= 1;
    00203                                 e -=  1;
    00204                         }
    00205
    00206                         e += 1;
    00207                         m &= ~0x00000400;
    00208                 }
    00209         }
    00210         else if (e == 31)
    00211         {
    00212                 if (m == 0)
    00213                 {
    00214                         //
    00215                         // Positive or negative infinity
    00216                         //
    00217
    00218                         return (s << 31) | 0x7f800000;
    00219                 }
    00220                 else
    00221                 {
    00222                         //
    00223                         // Nan -- preserve sign and significand bits
    00224                         //
    00225
    00226                         return (s << 31) | 0x7f800000 | (m << 13);
    00227                 }
    00228         }
    00229
    00230         //
    00231         // Normalized number
    00232         //
    00233
    00234         e = e + (127 - 15);
    00235         m = m << 13;
    00236
    00237         //
    00238         // Assemble s, e and m.
    00239         //
    00240
    00241         return (s << 31) | (e << 23) | m;
    00242 }
    00243 #endif //NOINLINE
    00244
    00245 #ifdef _cplusplus
    00246 }
    00247 #endif
    00248
    00249 #endif//MANIP_H