Game Accessibility Library logo SourceForge.net Logo
Game Accessibility Suite: CAT/CBMagInfo.h Source File

CBMagInfo.h

Go to the documentation of this file.
00001 /// \file CBMagInfo.h
00002 /// \brief Color Modification Information for CodeBlind.
00003 /// \ingroup CAT
00004 ///
00005 /// Copyright (c) 2002-2008 by Michael Ellison.
00006 /// See COPYING.txt for the \ref gaslicense License (MIT License).
00007 ///
00008 // $Author: mikeellison $
00009 // $Date: 2008-01-21 08:33:12 -0600 (Mon, 21 Jan 2008) $
00010 // $Revision:   $
00011 // $NoKeywords: $
00012 
00013 //----------------------------------------------------------------------
00014 // Magnification and Color Modification Information for CodeBlind.
00015 //----------------------------------------------------------------------
00016 //
00017 // This is the storage and processing class for the Magnification
00018 // and Color Modification data for CodeBlind.  Ideally, you should
00019 // be able to take this file, plop it into a project on just about
00020 // any 32-bit platform, and be able to load CodeBlind's save files
00021 // and process images in the same way.
00022 //
00023 //----------------------------------------------------------------------
00024 //                                Technical Notes:
00025 //----------------------------------------------------------------------
00026 //
00027 //   Magnification is not implemented in the processing.  In CodeBlind,
00028 // it's a lot easier to use the magnification level as a 
00029 // region of interest (ROI) selector to calculate the offsets and 
00030 // procWidth/procHeight.  Then, I'm simply copying from that ROI after 
00031 // processing it (via StretchBlt on win32).
00032 //
00033 // Parameter validation is performed on file loads / struct copies.  
00034 // This may seem slow, but at least in the uses I expect the variables 
00035 // don't change much - only the ProcessImage() function is worth 
00036 // optimizing.  The robustness gains seem worthwhile to me.
00037 //
00038 // This file is tested under Win32 with Microsoft's Visual C++ 6.0.  
00039 // I've tried to make it operable for other platforms, but those 
00040 // functions have not been fully tested.
00041 //----------------------------------------------------------------------
00042 //
00043 #ifndef _CBMAGINFO_H_
00044 #define _CBMAGINFO_H_
00045 
00046 #include <stdio.h>
00047 
00048 //----------------------------------------------------------------------
00049 // Constants
00050 //----------------------------------------------------------------------
00051 #define   CBRGBTOGREY(r,g,b)   ((CATUInt8)( 0.3f*(r) + 0.59f*(g) + 0.11f*(b)))
00052 // Buffer should be kCBMagMaxNameLength + 1 for null
00053 const int kCBMagMaxNameLength  = 127;
00054 const int kCBMagNameBufferSize = kCBMagMaxNameLength + 1;
00055 
00056 // Current version of the structure
00057 const int kCBMagVersion           = 1;
00058 // CBMagInfo error / status codes
00059 enum CBMAGRESULT
00060 {
00061     // Success code
00062     CBMAG_SUCCESS = 0,
00063 
00064     // Status codes
00065     CBMAG_STAT_NEW_VERSION,                   // Newer version of struct detected.
00066     CBMAG_STAT_ENDIAN_FLIPPED,                // Endian was flipped on struct
00067     
00068     // Error codes
00069     CBMAG_ERROR = 0x80000000,                 // Unknown error
00070     CBMAG_ERR_INVALID_PARAMETER,              // Invalid parameter in function
00071     CBMAG_ERR_PARAMETER_OUT_OF_RANGE,         // Parameter is out of range and was adjusted
00072     CBMAG_ERR_FILE_CREATE,                    // Error creating output file
00073     CBMAG_ERR_FILE_OPEN,                      // Error opening input file
00074     CBMAG_ERR_FILE_READ_FAIL,                 // Error reading from input file
00075     CBMAG_ERR_FILE_WRITE_FAIL,                // Error writing to output file
00076     CBMAG_ERR_FILE_CORRUPT,                   // File is corrupt or not a CBMG file
00077     CBMAG_ERR_OUT_OF_MEMORY,                  // Out of memory - can be thrown by constructors too
00078     CBMAG_ERR_BUF_TOO_SMALL,                  // Buffer is too small for all of the data
00079 };
00080 
00081 
00082 //----------------------------------------------------------------------
00083 // Defines
00084 //----------------------------------------------------------------------
00085 
00086 // Quick macros for success / failure on the above results.
00087 #define CBMAGSUCCESS(x)  ( ( (x) & 0x80000000 ) == 0 )
00088 #define CBMAGFAILED(x)   ( ( (x) & 0x80000000 ) != 0 )
00089 
00090 // Ye old min/max macros
00091 #ifndef CBMAX
00092     #define CBMAX(a,b)            (((a) > (b)) ? (a) : (b))
00093 #endif
00094 
00095 #ifndef CBMIN
00096     #define CBMIN(a,b)            (((a) < (b)) ? (a) : (b))
00097 #endif
00098 
00099 
00100 //----------------------------------------------------------------------
00101 // Structs
00102 //----------------------------------------------------------------------
00103 
00104 // Pack the struct to 1-bytes for file saving.
00105 #pragma pack(push)
00106 #pragma pack(1)
00107 
00108 struct CBMAGINFOSTRUCT
00109 {    
00110     union    // 'CBMG' for big-endian, 'GMBC' for little endian.
00111     {
00112         char    fCBMagSig[4];
00113         int     fCBMagSigInt;
00114     };
00115     
00116     int         fVersion;                            // Version of file
00117     char        fInfoName[kCBMagNameBufferSize];     // User-defined name        
00118 
00119     // Magnifier options - most people won't really use these, but
00120     // it allows people to create fully compatible magnifiers if
00121     // they want.
00122     int         fAllowFeedback;                    // Allow feedback 
00123                                                    // loops in magnifier?
00124     int         fRefresh;                          // milliseconds between refresh
00125     int         fOnTop;                            // Is wnd on top?    
00126     float       fMagnificationLevel;               // 1.0x - 10.0x multiplier
00127     float       fFilterMouse;                      // Low pass filter on mouse movements
00128                                                    // Smooths moves quite a bit.    
00129     int         fNegative;                         // Negate image first?
00130 
00131     // The values here are directly from the knobs.
00132     // They are between 0.0f and 1.0f, and are linear.
00133     // 0.5f should be none.  We'll map them to a proper
00134     // curve when building the lookup tables.
00135         
00136     float       fGamma;
00137 
00138     float       fBright_Red;
00139     float       fBright_Green;
00140     float       fBright_Blue;        
00141 
00142     // convert colors to grey
00143     float       fGreyRed;
00144     float       fGreyGreen;
00145     float       fGreyBlue;
00146     float       fGreyYellow;
00147     float       fGreyCyan;
00148     float       fGreyMagenta;
00149     
00150     float       fHue;                                 // Hue rotation
00151     float       fHueCompress;                         // Hue space compression
00152 
00153     int         fSwapType;                            // Swap value (see SWAPTYPE)    
00154     int         fMergeType;                           // Merge type - see MERGETYPE
00155     
00156     float       fSeverity;                            // Severity of simulation
00157     int         fReserved [31];                       // Pad for future official use.    
00158     int         fThirdParty[32];                      // Third party use. Have fun.
00159 };
00160 
00161 #pragma pack(pop)
00162 
00163 //--------------------------------------------------------------------
00164 // MagInfo class.
00165 //--------------------------------------------------------------------
00166 class CBMagInfo
00167 {    
00168     //-----------------------------------------------------------------
00169     public:
00170         
00171         enum SWAPTYPE
00172         {
00173             SWAP_NONE,
00174             SWAP_GREEN_BLUE,
00175             SWAP_RED_BLUE,
00176             SWAP_RED_GREEN,
00177             SWAP_LAST_TYPE = SWAP_RED_GREEN,
00178         };
00179 
00180         enum MERGETYPE
00181         {
00182             MERGE_NONE,
00183             MERGE_Red,
00184             MERGE_Blue,
00185             MERGE_ALL,
00186             MERGE_Green,
00187             MERGE_LAST_TYPE = MERGE_Green
00188         };    
00189     
00190     //-----------------------------------------------------------------
00191     public:        
00192 
00193         // Constructors
00194         // Note: All of these may throw a CBMAGRESUlT on error.
00195         //       Currently the only one that may be thrown is
00196         //       the CBMAG_ERR_OUT_OF_MEMORY. However, that one may
00197         //       be thrown instead of your usual memory exception,
00198         //       so please check this in your code.
00199         CBMagInfo();        
00200         CBMagInfo( const CBMAGINFOSTRUCT& copyStruct);
00201         CBMagInfo( const CBMagInfo&       copyInfo  );
00202         
00203         // Destructor
00204         virtual ~CBMagInfo();        
00205         
00206         // Copy operators
00207         CBMagInfo& operator= (const CBMAGINFOSTRUCT& copyStruct);
00208         CBMagInfo& operator= (const CBMagInfo&            copyInfo);
00209 
00210         // Load a MagInfo file
00211         CBMAGRESULT LoadFromFile   (const char* filename);
00212         CBMAGRESULT LoadFromHandle (FILE*       fp);
00213         
00214         // Save our config to a MagInfo file
00215         CBMAGRESULT SaveToFile     (const char* filename);
00216         CBMAGRESULT SaveToHandle   (FILE*       fp);
00217 
00218         void Reset();
00219 
00220         //--------------------------------------------------------------
00221         // Main processing function
00222         //
00223         // RGB buffer is an array for 24-bit RGB pixels.
00224         // Right now, assumes it's in B,G,R order for wintel.
00225         // Buffer is top down (y = 0 is at the top)
00226         //            
00227         // imgWidth and imgHeight are the total image buffer
00228         // sizes. They are assumed not to be width-padded.
00229         // i.e. imgWidth*3 should be the total width of a line.
00230         //            
00231         // xOff and yOff are the offsets to the top-left of
00232         // the region of interest within the image array to
00233         // be processed.
00234         //
00235         // procWidth and procHeight are the width and height
00236         // of the region of interest to be processed.
00237         void            ProcessImage    (   unsigned char*    rgbBuffer,
00238                                             int               imgWidth,
00239                                             int               imgHeight,
00240                                             int               xOff,
00241                                             int               yOff,
00242                                             int               procWidth,
00243                                             int               procHeight);
00244 
00245         //--------------------------------------------------------------
00246         // Accessors w/validation
00247 
00248         CBMAGRESULT SetName         (const char* name        );
00249         CBMAGRESULT SetFeedback     (bool        allow       );
00250         CBMAGRESULT SetRefresh      (int         refresh     );
00251         CBMAGRESULT SetOnTop        (bool        onTop       );
00252         CBMAGRESULT SetMagLevel     (float       magLvl      );
00253         CBMAGRESULT SetFilterMouse  (float       coefficient );
00254         CBMAGRESULT SetNegative     (bool        negative    );
00255         CBMAGRESULT SetGamma        (float       gamma       );
00256         CBMAGRESULT SetBrightRed    (float       brightRed   );
00257         CBMAGRESULT SetBrightGreen  (float       brightGreen );
00258         CBMAGRESULT SetBrightBlue   (float       brightBlue  );
00259         CBMAGRESULT SetHue          (float       hue         );
00260         CBMAGRESULT SetSeverity     (float       severity    );
00261         CBMAGRESULT SetGreyRed      (float       greyRed     );
00262         CBMAGRESULT SetGreyGreen    (float       greyGreen   );
00263         CBMAGRESULT SetGreyBlue     (float       greyBlue    );
00264         CBMAGRESULT SetGreyYellow   (float       greyYellow  );
00265         CBMAGRESULT SetGreyCyan     (float       greyCyan    );
00266         CBMAGRESULT SetGreyMagenta  (float       greyMagenta );
00267         CBMAGRESULT SetCompress     (float       compress    );
00268         CBMAGRESULT SetSwapType     (SWAPTYPE    swapType    );
00269         CBMAGRESULT SetMergeType    (MERGETYPE   mergeType   );
00270         
00271 
00272         //--------------------------------------------------------------
00273         // Retrieval Accessors
00274         CBMAGRESULT GetName         (char*       nameBuffer, 
00275                                      int&        bufLen) const;
00276 
00277         int         GetRefresh      () const;        
00278         bool        GetFeedback     () const;
00279         bool        GetOnTop        () const;
00280         bool        GetNegative     () const;
00281         float       GetMagLevel     () const;
00282         float       GetFilterMouse  () const;
00283         float       GetGamma        () const;
00284         float       GetBrightRed    () const;
00285         float       GetBrightGreen  () const;
00286         float       GetBrightBlue   () const;
00287         float       GetHue          () const;
00288         float       GetSeverity     () const;
00289         float       GetGreyRed      () const;
00290         float       GetGreyGreen    () const;
00291         float       GetGreyBlue     () const;
00292         float       GetGreyYellow   () const;
00293         float       GetGreyCyan     () const;
00294         float       GetGreyMagenta  () const;
00295         float       GetCompress     () const;
00296         SWAPTYPE    GetSwapType     () const;
00297         MERGETYPE   GetMergeType    () const;
00298         
00299 
00300     //---------------------------------------------------------------
00301     // Lookup table builder - this rebuilds the LUTs for the
00302     // ProcessImage() function from the CBMAGINFOSTRUCT.  It's called
00303     // automatically if the fStructDirty flag is set and ProcessImage
00304     // gets called, but if for some reason this ends up being a long
00305     // function you can call it ahead of time to avoid the speed hit
00306     // on the first process func.
00307     //
00308     void BuildLookupTables();
00309     
00310     void BuildGamma(bool buildRed, 
00311                     bool buildGreen, 
00312                     bool buildBlue);
00313     
00314     void BuildGreys(bool buildRed, 
00315                     bool buildYellow, 
00316                     bool buildGreen, 
00317                     bool buildCyan, 
00318                     bool buildBlue, 
00319                     bool buildMag);
00320 
00321     void BuildHue();
00322     void BuildSeverity();
00323         
00324     //---------------------------------------------------------------
00325     // Static utility functions
00326 
00327     // Setup a mag info struct with the defaults (no process)
00328     static CBMAGRESULT SetupDefaults (  CBMAGINFOSTRUCT*    magInfo );
00329 
00330     // Endian flippers for xplat
00331     static void FlipEndian       (      int&                value);
00332     static void FlipEndian       (      float&              value);        
00333     static void FlipEndian       (      CBMAGINFOSTRUCT&    infoStruct);
00334 
00335     // Red, green, blue to Hue, saturation, intensity
00336     static _inline void RGBtoHSI( unsigned char& rh, unsigned char& gs, unsigned char& bi);
00337     static _inline void HSItoRGB( unsigned char& rh, unsigned char& gs, unsigned char& bi);
00338 
00339     // This will flip it to native.
00340     static CBMAGRESULT CorrectEndian    (    CBMAGINFOSTRUCT&    infoStruct);
00341     //-------------------------------------------------------------------
00342     protected:
00343         void InitLUTs();
00344         void FreeLUTs();
00345 
00346     //-------------------------------------------------------------------
00347     protected:        
00348         CBMAGINFOSTRUCT                   fInfo;            // All our parameters.
00349         bool                              fFileDirty;       // Have we modified from the file?
00350         bool                              fStructDirty;     // Do we need to rebuild lookups?
00351         
00352         // Lookup Tables
00353         unsigned char*                    fRedLUT;          // gamma/brightness lookups
00354         unsigned char*                    fGreenLUT;        
00355         unsigned char*                    fBlueLUT;
00356         unsigned char*                    fIntLUTRed;       // Intensity lookups
00357         unsigned char*                    fIntLUTGreen;
00358         unsigned char*                    fIntLUTBlue;
00359         unsigned char*                    fIntLUTYellow;    // Intensity lookups
00360         unsigned char*                    fIntLUTCyan;
00361         unsigned char*                    fIntLUTMagenta;
00362         unsigned char*                    fSatLUTRed;       // Saturation lookups
00363         unsigned char*                    fSatLUTGreen;
00364         unsigned char*                    fSatLUTBlue;
00365         unsigned char*                    fSatLUTYellow;    // Saturation lookups
00366         unsigned char*                    fSatLUTCyan;
00367         unsigned char*                    fSatLUTMagenta;
00368         unsigned char*                    fHueLUT;          // Hue lookups
00369         unsigned char*                    fMergeGreenLUT;   // Merge lut's for Greens
00370         unsigned char*                    fMergeRedLUT;     // Merge lut for Reds
00371         unsigned char*                    fMergeBlueLUT;    // Merge lut's
00372         unsigned char*                    fSevLUT;          // Severity LUT
00373 
00374         unsigned char*                    fGreyRedLUT;      // Convert red->intensity
00375         unsigned char*                    fGreyGreenLUT;    // Convert green->intensity
00376         unsigned char*                    fGreyBlueLUT;     // convert blue->intensity
00377 };
00378 
00379 //---------------------------------------------------
00380 //  RGBtoHSI
00381 //        RGB to HSI conversion (integer)
00382 //        All values are 0-255.
00383 //        Based on code by Jace/TBL posted to comp.graphics.algorithms on 6/18/1999
00384 _inline void CBMagInfo::RGBtoHSI (unsigned char &rh, unsigned char &gs, unsigned char &bi)
00385 {
00386     int maxVal,midVal,minVal;
00387     // Find min/max/middle colors for intensity and
00388     // to determine the hue quadrant
00389 
00390     if (rh>=gs)
00391     { // rh > gs
00392         if (rh>=bi)
00393         { // rh > gs,bi
00394             if (gs>=bi)
00395             { // rh > gs > bi
00396                 maxVal = rh;
00397                 midVal = gs;
00398                 minVal = bi;
00399                 rh = 0;
00400             }
00401             else
00402             { // rh > bi > gs
00403                 maxVal = rh;
00404                 midVal = bi;
00405                 minVal = gs;
00406                 rh = 5;
00407             }
00408         }
00409         else
00410         { // bi > rh > gs
00411             maxVal = bi;
00412             midVal = rh;
00413             minVal = gs;
00414             rh = 4;
00415         }
00416     } 
00417     else
00418     { // gs > rh
00419         if (gs>=bi)
00420         { // gs > rh,bi
00421             if (rh>=bi)
00422             { // gs > rh > bi
00423                 maxVal = gs;
00424                 midVal = rh;
00425                 minVal = bi;
00426                 rh = 1;
00427             }
00428             else
00429             { // gs > bi > rh
00430                 maxVal = gs;
00431                 midVal = bi;
00432                 minVal = rh;
00433                 rh = 2;
00434             }
00435         }
00436         else
00437         { // bi > gs > rh
00438             maxVal = bi;
00439             midVal = gs;
00440             minVal = rh;
00441             rh = 3;
00442         }
00443     }
00444     // colors are split into maxVal,midVal,minVal and base h.
00445     
00446     
00447     // if (min == max), it's grey
00448     if (minVal == maxVal) 
00449     { 
00450         rh=0; 
00451         gs=0; 
00452         return; 
00453     } 
00454     
00455     // Saturation is the amount of spread between min/max
00456     gs = 255 - ((minVal<<8)/maxVal);
00457 
00458     // intensity is the brightness
00459     bi = maxVal;
00460     
00461     midVal = maxVal - (maxVal * (maxVal-midVal))/(maxVal-minVal);
00462     minVal = ( midVal << 8) / maxVal;
00463     if (rh & 1) 
00464         minVal = 256 - minVal;
00465     
00466     rh = (( ( rh << 8 ) + minVal) / 6) & 255;
00467 }
00468 
00469 
00470 //---------------------------------------------------
00471 //  HSItoRGB
00472 //        HSI to RGB conversion (integer)
00473 //        All values are 0-255.
00474 //        Based on code by Jace/TBL posted to comp.graphics.algorithms on 6/18/1999
00475 _inline void CBMagInfo::HSItoRGB (unsigned char &hr, unsigned char &sg, unsigned char &ib)
00476 {
00477     // hue (hr) becomes red, saturation (sg) becomes green, intensity (ib) becomes blue
00478     int maxVal,midVal,minVal,hue;
00479     
00480     hue = 6*hr;
00481     maxVal = ib;
00482     
00483     minVal = (maxVal * (256-sg)) >> 8;
00484     
00485     midVal = ( ( (hue & 255 ) + 1 ) * maxVal) >> 8;
00486         
00487     if ( hue & 256) 
00488     {
00489         midVal = maxVal-midVal;
00490     }
00491 
00492     midVal = maxVal-(( (maxVal - midVal) * (sg + 1)) >>8);
00493     
00494     hue >>= 8;
00495 
00496     switch(hue)
00497     {
00498         case 0: hr=maxVal; sg=midVal; ib=minVal; break;
00499         case 1: hr=midVal; sg=maxVal; ib=minVal; break;
00500         case 2: hr=minVal; sg=maxVal; ib=midVal; break;
00501         case 3: hr=minVal; sg=midVal; ib=maxVal; break;
00502         case 4: hr=midVal; sg=minVal; ib=maxVal; break;
00503         case 5: hr=maxVal; sg=minVal; ib=midVal; break;
00504     }
00505 }
00506 
00507 //-------------------------------------------------------------------
00508 #endif // _CBMAGINFO_H_

Generated on Mon Feb 11 04:09:50 2008 for Game Accessibility Suite by doxygen 1.5.4