src/3rdparty/libmng/libmng_cms.c
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /* ************************************************************************** */
       
     2 /* *             For conditions of distribution and use,                    * */
       
     3 /* *                see copyright notice in libmng.h                        * */
       
     4 /* ************************************************************************** */
       
     5 /* *                                                                        * */
       
     6 /* * project   : libmng                                                     * */
       
     7 /* * file      : libmng_cms.c              copyright (c) 2000-2004 G.Juyn   * */
       
     8 /* * version   : 1.0.9                                                      * */
       
     9 /* *                                                                        * */
       
    10 /* * purpose   : color management routines (implementation)                 * */
       
    11 /* *                                                                        * */
       
    12 /* * author    : G.Juyn                                                     * */
       
    13 /* *                                                                        * */
       
    14 /* * comment   : implementation of the color management routines            * */
       
    15 /* *                                                                        * */
       
    16 /* * changes   : 0.5.1 - 05/01/2000 - G.Juyn                                * */
       
    17 /* *             - B001(105795) - fixed a typo and misconception about      * */
       
    18 /* *               freeing allocated gamma-table. (reported by Marti Maria) * */
       
    19 /* *             0.5.1 - 05/08/2000 - G.Juyn                                * */
       
    20 /* *             - changed strict-ANSI stuff                                * */
       
    21 /* *             0.5.1 - 05/09/2000 - G.Juyn                                * */
       
    22 /* *             - filled application-based color-management routines       * */
       
    23 /* *             0.5.1 - 05/11/2000 - G.Juyn                                * */
       
    24 /* *             - added creatememprofile                                   * */
       
    25 /* *             - added callback error-reporting support                   * */
       
    26 /* *             0.5.1 - 05/12/2000 - G.Juyn                                * */
       
    27 /* *             - changed trace to macro for callback error-reporting      * */
       
    28 /* *                                                                        * */
       
    29 /* *             0.5.2 - 06/10/2000 - G.Juyn                                * */
       
    30 /* *             - fixed some compilation-warnings (contrib Jason Morris)   * */
       
    31 /* *                                                                        * */
       
    32 /* *             0.5.3 - 06/21/2000 - G.Juyn                                * */
       
    33 /* *             - fixed problem with color-correction for stored images    * */
       
    34 /* *             0.5.3 - 06/23/2000 - G.Juyn                                * */
       
    35 /* *             - fixed problem with incorrect gamma-correction            * */
       
    36 /* *                                                                        * */
       
    37 /* *             0.9.2 - 08/05/2000 - G.Juyn                                * */
       
    38 /* *             - changed file-prefixes                                    * */
       
    39 /* *                                                                        * */
       
    40 /* *             0.9.3 - 08/31/2000 - G.Juyn                                * */
       
    41 /* *             - fixed sRGB precedence for gamma_only corection           * */
       
    42 /* *                                                                        * */
       
    43 /* *             0.9.4 - 12/16/2000 - G.Juyn                                * */
       
    44 /* *             - fixed mixup of data- & function-pointers (thanks Dimitri)* */
       
    45 /* *                                                                        * */
       
    46 /* *             1.0.1 - 03/31/2001 - G.Juyn                                * */
       
    47 /* *             - ignore gamma=0 (see png-list for more info)              * */
       
    48 /* *             1.0.1 - 04/25/2001 - G.Juyn (reported by Gregg Kelly)      * */
       
    49 /* *             - fixed problem with cms profile being created multiple    * */
       
    50 /* *               times when both iCCP & cHRM/gAMA are present             * */
       
    51 /* *             1.0.1 - 04/25/2001 - G.Juyn                                * */
       
    52 /* *             - moved mng_clear_cms to libmng_cms                        * */
       
    53 /* *             1.0.1 - 05/02/2001 - G.Juyn                                * */
       
    54 /* *             - added "default" sRGB generation (Thanks Marti!)          * */
       
    55 /* *                                                                        * */
       
    56 /* *             1.0.5 - 08/19/2002 - G.Juyn                                * */
       
    57 /* *             - B597134 - libmng pollutes the linker namespace           * */
       
    58 /* *             1.0.5 - 09/19/2002 - G.Juyn                                * */
       
    59 /* *             - optimized color-correction routines                      * */
       
    60 /* *             1.0.5 - 09/23/2002 - G.Juyn                                * */
       
    61 /* *             - added in-memory color-correction of abstract images      * */
       
    62 /* *             1.0.5 - 11/08/2002 - G.Juyn                                * */
       
    63 /* *             - fixed issues in init_app_cms()                           * */
       
    64 /* *                                                                        * */
       
    65 /* *             1.0.6 - 04/11/2003 - G.Juyn                                * */
       
    66 /* *             - B719420 - fixed several MNG_APP_CMS problems             * */
       
    67 /* *             1.0.6 - 07/11/2003 - G. R-P                                * */
       
    68 /* *             - added conditional MNG_SKIPCHUNK_cHRM/iCCP                * */
       
    69 /* *                                                                        * */
       
    70 /* *             1.0.9 - 12/20/2004 - G.Juyn                                * */
       
    71 /* *             - cleaned up macro-invocations (thanks to D. Airlie)       * */
       
    72 /* *                                                                        * */
       
    73 /* ************************************************************************** */
       
    74 
       
    75 #include "libmng.h"
       
    76 #include "libmng_data.h"
       
    77 #include "libmng_error.h"
       
    78 #include "libmng_trace.h"
       
    79 #ifdef __BORLANDC__
       
    80 #pragma hdrstop
       
    81 #endif
       
    82 #include "libmng_objects.h"
       
    83 #include "libmng_cms.h"
       
    84 
       
    85 #if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
       
    86 #pragma option -A                      /* force ANSI-C */
       
    87 #endif
       
    88 
       
    89 /* ************************************************************************** */
       
    90 
       
    91 #ifdef MNG_INCLUDE_DISPLAY_PROCS
       
    92 
       
    93 /* ************************************************************************** */
       
    94 /* *                                                                        * */
       
    95 /* * Little CMS helper routines                                             * */
       
    96 /* *                                                                        * */
       
    97 /* ************************************************************************** */
       
    98 
       
    99 #ifdef MNG_INCLUDE_LCMS
       
   100 
       
   101 #define MNG_CMS_FLAGS 0
       
   102 
       
   103 /* ************************************************************************** */
       
   104 
       
   105 void mnglcms_initlibrary ()
       
   106 {
       
   107   cmsErrorAction (LCMS_ERROR_IGNORE);  /* LCMS should ignore errors! */
       
   108 }
       
   109 
       
   110 /* ************************************************************************** */
       
   111 
       
   112 mng_cmsprof mnglcms_createfileprofile (mng_pchar zFilename)
       
   113 {
       
   114   return cmsOpenProfileFromFile (zFilename, "r");
       
   115 }
       
   116 
       
   117 /* ************************************************************************** */
       
   118 
       
   119 mng_cmsprof mnglcms_creatememprofile (mng_uint32 iProfilesize,
       
   120                                       mng_ptr    pProfile)
       
   121 {
       
   122   return cmsOpenProfileFromMem (pProfile, iProfilesize);
       
   123 }
       
   124 
       
   125 /* ************************************************************************** */
       
   126 
       
   127 mng_cmsprof mnglcms_createsrgbprofile (void)
       
   128 {
       
   129   cmsCIExyY       D65;
       
   130   cmsCIExyYTRIPLE Rec709Primaries = {
       
   131                                       {0.6400, 0.3300, 1.0},
       
   132                                       {0.3000, 0.6000, 1.0},
       
   133                                       {0.1500, 0.0600, 1.0}
       
   134                                     };
       
   135   LPGAMMATABLE    Gamma24[3];
       
   136   mng_cmsprof     hsRGB;
       
   137 
       
   138   cmsWhitePointFromTemp(6504, &D65);
       
   139   Gamma24[0] = Gamma24[1] = Gamma24[2] = cmsBuildGamma(256, 2.4);
       
   140   hsRGB = cmsCreateRGBProfile(&D65, &Rec709Primaries, Gamma24);
       
   141   cmsFreeGamma(Gamma24[0]);
       
   142 
       
   143   return hsRGB;
       
   144 }
       
   145 
       
   146 /* ************************************************************************** */
       
   147 
       
   148 void mnglcms_freeprofile (mng_cmsprof hProf)
       
   149 {
       
   150   cmsCloseProfile (hProf);
       
   151   return;
       
   152 }
       
   153 
       
   154 /* ************************************************************************** */
       
   155 
       
   156 void mnglcms_freetransform (mng_cmstrans hTrans)
       
   157 {
       
   158 /* B001 start */
       
   159   cmsDeleteTransform (hTrans);
       
   160 /* B001 end */
       
   161   return;
       
   162 }
       
   163 
       
   164 /* ************************************************************************** */
       
   165 
       
   166 mng_retcode mng_clear_cms (mng_datap pData)
       
   167 {
       
   168 #ifdef MNG_SUPPORT_TRACE
       
   169   MNG_TRACE (pData, MNG_FN_CLEAR_CMS, MNG_LC_START);
       
   170 #endif
       
   171 
       
   172   if (pData->hTrans)                   /* transformation still active ? */
       
   173     mnglcms_freetransform (pData->hTrans);
       
   174 
       
   175   pData->hTrans = 0;
       
   176 
       
   177   if (pData->hProf1)                   /* file profile still active ? */
       
   178     mnglcms_freeprofile (pData->hProf1);
       
   179 
       
   180   pData->hProf1 = 0;
       
   181 
       
   182 #ifdef MNG_SUPPORT_TRACE
       
   183   MNG_TRACE (pData, MNG_FN_CLEAR_CMS, MNG_LC_END);
       
   184 #endif
       
   185 
       
   186   return MNG_NOERROR;
       
   187 }
       
   188 
       
   189 /* ************************************************************************** */
       
   190 
       
   191 #endif /* MNG_INCLUDE_LCMS */
       
   192 
       
   193 /* ************************************************************************** */
       
   194 /* *                                                                        * */
       
   195 /* * Color-management initialization & correction routines                  * */
       
   196 /* *                                                                        * */
       
   197 /* ************************************************************************** */
       
   198 
       
   199 #ifdef MNG_INCLUDE_LCMS
       
   200 
       
   201 mng_retcode mng_init_full_cms (mng_datap pData,
       
   202                                mng_bool  bGlobal,
       
   203                                mng_bool  bObject,
       
   204                                mng_bool  bRetrobj)
       
   205 {
       
   206   mng_cmsprof    hProf;
       
   207   mng_cmstrans   hTrans;
       
   208   mng_imagep     pImage = MNG_NULL;
       
   209   mng_imagedatap pBuf   = MNG_NULL;
       
   210 
       
   211 #ifdef MNG_SUPPORT_TRACE
       
   212   MNG_TRACE (pData, MNG_FN_INIT_FULL_CMS, MNG_LC_START);
       
   213 #endif
       
   214 
       
   215   if (bObject)                         /* use object if present ? */
       
   216   {                                    /* current object ? */
       
   217     if ((mng_imagep)pData->pCurrentobj)
       
   218       pImage = (mng_imagep)pData->pCurrentobj;
       
   219     else                               /* if not; use object 0 */
       
   220       pImage = (mng_imagep)pData->pObjzero;
       
   221   }
       
   222 
       
   223   if (bRetrobj)                        /* retrieving from an object ? */
       
   224     pImage = (mng_imagep)pData->pRetrieveobj;
       
   225 
       
   226   if (pImage)                          /* are we using an object ? */
       
   227     pBuf = pImage->pImgbuf;            /* then address the buffer */
       
   228 
       
   229   if ((!pBuf) || (!pBuf->bCorrected))  /* is the buffer already corrected ? */
       
   230   {
       
   231 #ifndef MNG_SKIPCHUNK_iCCP
       
   232     if (((pBuf) && (pBuf->bHasICCP)) || ((bGlobal) && (pData->bHasglobalICCP)))
       
   233     {
       
   234       if (!pData->hProf2)              /* output profile not defined ? */
       
   235       {                                /* then assume sRGB !! */
       
   236         pData->hProf2 = mnglcms_createsrgbprofile ();
       
   237 
       
   238         if (!pData->hProf2)            /* handle error ? */
       
   239           MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
       
   240       }
       
   241 
       
   242       if ((pBuf) && (pBuf->bHasICCP))  /* generate a profile handle */
       
   243         hProf = cmsOpenProfileFromMem (pBuf->pProfile, pBuf->iProfilesize);
       
   244       else
       
   245         hProf = cmsOpenProfileFromMem (pData->pGlobalProfile, pData->iGlobalProfilesize);
       
   246 
       
   247       pData->hProf1 = hProf;           /* save for future use */
       
   248 
       
   249       if (!hProf)                      /* handle error ? */
       
   250         MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
       
   251 
       
   252 #ifndef MNG_NO_16BIT_SUPPORT
       
   253       if (pData->bIsRGBA16)            /* 16-bit intermediates ? */
       
   254         hTrans = cmsCreateTransform (hProf,         TYPE_RGBA_16_SE,
       
   255                                      pData->hProf2, TYPE_RGBA_16_SE,
       
   256                                      INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
       
   257       else
       
   258 #endif
       
   259         hTrans = cmsCreateTransform (hProf,         TYPE_RGBA_8,
       
   260                                      pData->hProf2, TYPE_RGBA_8,
       
   261                                      INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
       
   262 
       
   263       pData->hTrans = hTrans;          /* save for future use */
       
   264 
       
   265       if (!hTrans)                     /* handle error ? */
       
   266         MNG_ERRORL (pData, MNG_LCMS_NOTRANS);
       
   267                                        /* load color-correction routine */
       
   268       pData->fCorrectrow = (mng_fptr)mng_correct_full_cms;
       
   269 
       
   270       return MNG_NOERROR;              /* and done */
       
   271     }
       
   272     else
       
   273 #endif
       
   274     if (((pBuf) && (pBuf->bHasSRGB)) || ((bGlobal) && (pData->bHasglobalSRGB)))
       
   275     {
       
   276       mng_uint8 iIntent;
       
   277 
       
   278       if (pData->bIssRGB)              /* sRGB system ? */
       
   279         return MNG_NOERROR;            /* no conversion required */
       
   280 
       
   281       if (!pData->hProf3)              /* sRGB profile not defined ? */
       
   282       {                                /* then create it implicitly !! */
       
   283         pData->hProf3 = mnglcms_createsrgbprofile ();
       
   284 
       
   285         if (!pData->hProf3)            /* handle error ? */
       
   286           MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
       
   287       }
       
   288 
       
   289       hProf = pData->hProf3;           /* convert from sRGB profile */
       
   290 
       
   291       if ((pBuf) && (pBuf->bHasSRGB))  /* determine rendering intent */
       
   292         iIntent = pBuf->iRenderingintent;
       
   293       else
       
   294         iIntent = pData->iGlobalRendintent;
       
   295 
       
   296       if (pData->bIsRGBA16)            /* 16-bit intermediates ? */
       
   297         hTrans = cmsCreateTransform (hProf,         TYPE_RGBA_16_SE,
       
   298                                      pData->hProf2, TYPE_RGBA_16_SE,
       
   299                                      iIntent, MNG_CMS_FLAGS);
       
   300       else
       
   301         hTrans = cmsCreateTransform (hProf,         TYPE_RGBA_8,
       
   302                                      pData->hProf2, TYPE_RGBA_8,
       
   303                                      iIntent, MNG_CMS_FLAGS);
       
   304 
       
   305       pData->hTrans = hTrans;          /* save for future use */
       
   306 
       
   307       if (!hTrans)                     /* handle error ? */
       
   308         MNG_ERRORL (pData, MNG_LCMS_NOTRANS);
       
   309                                        /* load color-correction routine */
       
   310       pData->fCorrectrow = (mng_fptr)mng_correct_full_cms;
       
   311 
       
   312       return MNG_NOERROR;              /* and done */
       
   313     }
       
   314     else
       
   315     if ( (((pBuf) && (pBuf->bHasCHRM)) || ((bGlobal) && (pData->bHasglobalCHRM))) &&
       
   316          ( ((pBuf) && (pBuf->bHasGAMA) && (pBuf->iGamma > 0)) ||
       
   317            ((bGlobal) && (pData->bHasglobalGAMA) && (pData->iGlobalGamma > 0))  )    )
       
   318     {
       
   319       mng_CIExyY       sWhitepoint;
       
   320       mng_CIExyYTRIPLE sPrimaries;
       
   321       mng_gammatabp    pGammatable[3];
       
   322       mng_float        dGamma;
       
   323 
       
   324       if (!pData->hProf2)              /* output profile not defined ? */
       
   325       {                                /* then assume sRGB !! */
       
   326         pData->hProf2 = mnglcms_createsrgbprofile ();
       
   327 
       
   328         if (!pData->hProf2)            /* handle error ? */
       
   329           MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
       
   330       }
       
   331 
       
   332 #ifndef MNG_SKIPCHUNK_cHRM
       
   333       if ((pBuf) && (pBuf->bHasCHRM))  /* local cHRM ? */
       
   334       {
       
   335         sWhitepoint.x      = (mng_float)pBuf->iWhitepointx   / 100000;
       
   336         sWhitepoint.y      = (mng_float)pBuf->iWhitepointy   / 100000;
       
   337         sPrimaries.Red.x   = (mng_float)pBuf->iPrimaryredx   / 100000;
       
   338         sPrimaries.Red.y   = (mng_float)pBuf->iPrimaryredy   / 100000;
       
   339         sPrimaries.Green.x = (mng_float)pBuf->iPrimarygreenx / 100000;
       
   340         sPrimaries.Green.y = (mng_float)pBuf->iPrimarygreeny / 100000;
       
   341         sPrimaries.Blue.x  = (mng_float)pBuf->iPrimarybluex  / 100000;
       
   342         sPrimaries.Blue.y  = (mng_float)pBuf->iPrimarybluey  / 100000;
       
   343       }
       
   344       else
       
   345       {
       
   346         sWhitepoint.x      = (mng_float)pData->iGlobalWhitepointx   / 100000;
       
   347         sWhitepoint.y      = (mng_float)pData->iGlobalWhitepointy   / 100000;
       
   348         sPrimaries.Red.x   = (mng_float)pData->iGlobalPrimaryredx   / 100000;
       
   349         sPrimaries.Red.y   = (mng_float)pData->iGlobalPrimaryredy   / 100000;
       
   350         sPrimaries.Green.x = (mng_float)pData->iGlobalPrimarygreenx / 100000;
       
   351         sPrimaries.Green.y = (mng_float)pData->iGlobalPrimarygreeny / 100000;
       
   352         sPrimaries.Blue.x  = (mng_float)pData->iGlobalPrimarybluex  / 100000;
       
   353         sPrimaries.Blue.y  = (mng_float)pData->iGlobalPrimarybluey  / 100000;
       
   354       }
       
   355 #endif
       
   356 
       
   357       sWhitepoint.Y      =             /* Y component is always 1.0 */
       
   358       sPrimaries.Red.Y   =
       
   359       sPrimaries.Green.Y =
       
   360       sPrimaries.Blue.Y  = 1.0;
       
   361 
       
   362       if ((pBuf) && (pBuf->bHasGAMA))  /* get the gamma value */
       
   363         dGamma = (mng_float)pBuf->iGamma / 100000;
       
   364       else
       
   365         dGamma = (mng_float)pData->iGlobalGamma / 100000;
       
   366 
       
   367       dGamma = pData->dViewgamma / dGamma;
       
   368 
       
   369       pGammatable [0] =                /* and build the lookup tables */
       
   370       pGammatable [1] =
       
   371       pGammatable [2] = cmsBuildGamma (256, dGamma);
       
   372 
       
   373       if (!pGammatable [0])            /* enough memory ? */
       
   374         MNG_ERRORL (pData, MNG_LCMS_NOMEM);
       
   375                                        /* create the profile */
       
   376       hProf = cmsCreateRGBProfile (&sWhitepoint, &sPrimaries, pGammatable);
       
   377 
       
   378       cmsFreeGamma (pGammatable [0]);  /* free the temporary gamma tables ? */
       
   379                                        /* yes! but just the one! */
       
   380 
       
   381       pData->hProf1 = hProf;           /* save for future use */
       
   382 
       
   383       if (!hProf)                      /* handle error ? */
       
   384         MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
       
   385 
       
   386       if (pData->bIsRGBA16)            /* 16-bit intermediates ? */
       
   387         hTrans = cmsCreateTransform (hProf,         TYPE_RGBA_16_SE,
       
   388                                      pData->hProf2, TYPE_RGBA_16_SE,
       
   389                                      INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
       
   390       else
       
   391         hTrans = cmsCreateTransform (hProf,         TYPE_RGBA_8,
       
   392                                      pData->hProf2, TYPE_RGBA_8,
       
   393                                      INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
       
   394 
       
   395       pData->hTrans = hTrans;          /* save for future use */
       
   396 
       
   397       if (!hTrans)                     /* handle error ? */
       
   398         MNG_ERRORL (pData, MNG_LCMS_NOTRANS);
       
   399                                        /* load color-correction routine */
       
   400       pData->fCorrectrow = (mng_fptr)mng_correct_full_cms;
       
   401 
       
   402       return MNG_NOERROR;              /* and done */
       
   403     }
       
   404   }
       
   405 
       
   406 #ifdef MNG_SUPPORT_TRACE
       
   407   MNG_TRACE (pData, MNG_FN_INIT_FULL_CMS, MNG_LC_END);
       
   408 #endif
       
   409                                        /* if we get here, we'll only do gamma */
       
   410   return mng_init_gamma_only (pData, bGlobal, bObject, bRetrobj);
       
   411 }
       
   412 #endif /* MNG_INCLUDE_LCMS */
       
   413 
       
   414 /* ************************************************************************** */
       
   415 
       
   416 #ifdef MNG_INCLUDE_LCMS
       
   417 mng_retcode mng_correct_full_cms (mng_datap pData)
       
   418 {
       
   419 #ifdef MNG_SUPPORT_TRACE
       
   420   MNG_TRACE (pData, MNG_FN_CORRECT_FULL_CMS, MNG_LC_START);
       
   421 #endif
       
   422 
       
   423   cmsDoTransform (pData->hTrans, pData->pRGBArow, pData->pRGBArow, pData->iRowsamples);
       
   424 
       
   425 #ifdef MNG_SUPPORT_TRACE
       
   426   MNG_TRACE (pData, MNG_FN_CORRECT_FULL_CMS, MNG_LC_END);
       
   427 #endif
       
   428 
       
   429   return MNG_NOERROR;
       
   430 }
       
   431 #endif /* MNG_INCLUDE_LCMS */
       
   432 
       
   433 /* ************************************************************************** */
       
   434 
       
   435 #if defined(MNG_GAMMA_ONLY) || defined(MNG_FULL_CMS) || defined(MNG_APP_CMS)
       
   436 mng_retcode mng_init_gamma_only (mng_datap pData,
       
   437                                  mng_bool  bGlobal,
       
   438                                  mng_bool  bObject,
       
   439                                  mng_bool  bRetrobj)
       
   440 {
       
   441   mng_float      dGamma;
       
   442   mng_imagep     pImage = MNG_NULL;
       
   443   mng_imagedatap pBuf   = MNG_NULL;
       
   444 
       
   445 #ifdef MNG_SUPPORT_TRACE
       
   446   MNG_TRACE (pData, MNG_FN_INIT_GAMMA_ONLY, MNG_LC_START);
       
   447 #endif
       
   448 
       
   449   if (bObject)                         /* use object if present ? */
       
   450   {                                    /* current object ? */
       
   451     if ((mng_imagep)pData->pCurrentobj)
       
   452       pImage = (mng_imagep)pData->pCurrentobj;
       
   453     else                               /* if not; use object 0 */
       
   454       pImage = (mng_imagep)pData->pObjzero;
       
   455   }
       
   456 
       
   457   if (bRetrobj)                        /* retrieving from an object ? */
       
   458     pImage = (mng_imagep)pData->pRetrieveobj;
       
   459 
       
   460   if (pImage)                          /* are we using an object ? */
       
   461     pBuf = pImage->pImgbuf;            /* then address the buffer */
       
   462 
       
   463   if ((!pBuf) || (!pBuf->bCorrected))  /* is the buffer already corrected ? */
       
   464   {
       
   465     if ((pBuf) && (pBuf->bHasSRGB))    /* get the gamma value */
       
   466       dGamma = 0.45455;
       
   467     else
       
   468     if ((pBuf) && (pBuf->bHasGAMA))
       
   469       dGamma = (mng_float)pBuf->iGamma / 100000;
       
   470     else
       
   471     if ((bGlobal) && (pData->bHasglobalSRGB))
       
   472       dGamma = 0.45455;
       
   473     else
       
   474     if ((bGlobal) && (pData->bHasglobalGAMA))
       
   475       dGamma = (mng_float)pData->iGlobalGamma / 100000;
       
   476     else
       
   477       dGamma = pData->dDfltimggamma;
       
   478 
       
   479     if (dGamma > 0)                    /* ignore gamma=0 */
       
   480     {
       
   481       dGamma = pData->dViewgamma / (dGamma * pData->dDisplaygamma);
       
   482 
       
   483       if (dGamma != pData->dLastgamma) /* lookup table needs to be computed ? */
       
   484       {
       
   485         mng_int32 iX;
       
   486 
       
   487         pData->aGammatab [0] = 0;
       
   488 
       
   489         for (iX = 1; iX <= 255; iX++)
       
   490           pData->aGammatab [iX] = (mng_uint8)(pow (iX / 255.0, dGamma) * 255 + 0.5);
       
   491 
       
   492         pData->dLastgamma = dGamma;    /* keep for next time */
       
   493       }
       
   494                                        /* load color-correction routine */
       
   495       pData->fCorrectrow = (mng_fptr)mng_correct_gamma_only;
       
   496     }
       
   497   }
       
   498 
       
   499 #ifdef MNG_SUPPORT_TRACE
       
   500   MNG_TRACE (pData, MNG_FN_INIT_GAMMA_ONLY, MNG_LC_END);
       
   501 #endif
       
   502 
       
   503   return MNG_NOERROR;
       
   504 }
       
   505 #endif /* MNG_GAMMA_ONLY || MNG_FULL_CMS || MNG_APP_CMS */
       
   506 
       
   507 /* ************************************************************************** */
       
   508 
       
   509 #if defined(MNG_GAMMA_ONLY) || defined(MNG_FULL_CMS) || defined(MNG_APP_CMS)
       
   510 mng_retcode mng_correct_gamma_only (mng_datap pData)
       
   511 {
       
   512   mng_uint8p pWork;
       
   513   mng_int32  iX;
       
   514 
       
   515 #ifdef MNG_SUPPORT_TRACE
       
   516   MNG_TRACE (pData, MNG_FN_CORRECT_GAMMA_ONLY, MNG_LC_START);
       
   517 #endif
       
   518 
       
   519   pWork = pData->pRGBArow;             /* address intermediate row */
       
   520 
       
   521   if (pData->bIsRGBA16)                /* 16-bit intermediate row ? */
       
   522   {
       
   523 
       
   524   
       
   525      /* TODO: 16-bit precision gamma processing */
       
   526      /* we'll just do the high-order byte for now */
       
   527 
       
   528      
       
   529                                        /* convert all samples in the row */
       
   530      for (iX = 0; iX < pData->iRowsamples; iX++)
       
   531      {                                 /* using the precalculated gamma lookup table */
       
   532        *pWork     = pData->aGammatab [*pWork];
       
   533        *(pWork+2) = pData->aGammatab [*(pWork+2)];
       
   534        *(pWork+4) = pData->aGammatab [*(pWork+4)];
       
   535 
       
   536        pWork += 8;
       
   537      }
       
   538   }
       
   539   else
       
   540   {                                    /* convert all samples in the row */
       
   541      for (iX = 0; iX < pData->iRowsamples; iX++)
       
   542      {                                 /* using the precalculated gamma lookup table */
       
   543        *pWork     = pData->aGammatab [*pWork];
       
   544        *(pWork+1) = pData->aGammatab [*(pWork+1)];
       
   545        *(pWork+2) = pData->aGammatab [*(pWork+2)];
       
   546 
       
   547        pWork += 4;
       
   548      }
       
   549   }
       
   550 
       
   551 #ifdef MNG_SUPPORT_TRACE
       
   552   MNG_TRACE (pData, MNG_FN_CORRECT_GAMMA_ONLY, MNG_LC_END);
       
   553 #endif
       
   554 
       
   555   return MNG_NOERROR;
       
   556 }
       
   557 #endif /* MNG_GAMMA_ONLY || MNG_FULL_CMS || MNG_APP_CMS */
       
   558 
       
   559 /* ************************************************************************** */
       
   560 
       
   561 #ifdef MNG_APP_CMS
       
   562 mng_retcode mng_init_app_cms (mng_datap pData,
       
   563                               mng_bool  bGlobal,
       
   564                               mng_bool  bObject,
       
   565                               mng_bool  bRetrobj)
       
   566 {
       
   567   mng_imagep     pImage = MNG_NULL;
       
   568   mng_imagedatap pBuf   = MNG_NULL;
       
   569   mng_bool       bDone  = MNG_FALSE;
       
   570   mng_retcode    iRetcode;
       
   571   
       
   572 #ifdef MNG_SUPPORT_TRACE
       
   573   MNG_TRACE (pData, MNG_FN_INIT_APP_CMS, MNG_LC_START);
       
   574 #endif
       
   575 
       
   576   if (bObject)                         /* use object if present ? */
       
   577   {                                    /* current object ? */
       
   578     if ((mng_imagep)pData->pCurrentobj)
       
   579       pImage = (mng_imagep)pData->pCurrentobj;
       
   580     else                               /* if not; use object 0 */
       
   581       pImage = (mng_imagep)pData->pObjzero;
       
   582   }
       
   583 
       
   584   if (bRetrobj)                        /* retrieving from an object ? */
       
   585     pImage = (mng_imagep)pData->pRetrieveobj;
       
   586 
       
   587   if (pImage)                          /* are we using an object ? */
       
   588     pBuf = pImage->pImgbuf;            /* then address the buffer */
       
   589 
       
   590   if ((!pBuf) || (!pBuf->bCorrected))  /* is the buffer already corrected ? */
       
   591   {
       
   592 #ifndef MNG_SKIPCHUNK_iCCP
       
   593     if ( (pData->fProcessiccp) &&
       
   594          (((pBuf) && (pBuf->bHasICCP)) || ((bGlobal) && (pData->bHasglobalICCP))) )
       
   595     {
       
   596       mng_uint32 iProfilesize;
       
   597       mng_ptr    pProfile;
       
   598 
       
   599       if ((pBuf) && (pBuf->bHasICCP))  /* get the right profile */
       
   600       {
       
   601         iProfilesize = pBuf->iProfilesize;
       
   602         pProfile     = pBuf->pProfile;
       
   603       }
       
   604       else
       
   605       {
       
   606         iProfilesize = pData->iGlobalProfilesize;
       
   607         pProfile     = pData->pGlobalProfile;
       
   608       }
       
   609                                        /* inform the app */
       
   610       if (!pData->fProcessiccp ((mng_handle)pData, iProfilesize, pProfile))
       
   611         MNG_ERROR (pData, MNG_APPCMSERROR);
       
   612                                        /* load color-correction routine */
       
   613       pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
       
   614       bDone              = MNG_TRUE;
       
   615     }
       
   616 #endif
       
   617 
       
   618     if ( (pData->fProcesssrgb) &&
       
   619          (((pBuf) && (pBuf->bHasSRGB)) || ((bGlobal) && (pData->bHasglobalSRGB))) )
       
   620     {
       
   621       mng_uint8 iIntent;
       
   622 
       
   623       if ((pBuf) && (pBuf->bHasSRGB))  /* determine rendering intent */
       
   624         iIntent = pBuf->iRenderingintent;
       
   625       else
       
   626         iIntent = pData->iGlobalRendintent;
       
   627                                        /* inform the app */
       
   628       if (!pData->fProcesssrgb ((mng_handle)pData, iIntent))
       
   629         MNG_ERROR (pData, MNG_APPCMSERROR);
       
   630                                        /* load color-correction routine */
       
   631       pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
       
   632       bDone              = MNG_TRUE;
       
   633     }
       
   634 
       
   635 #ifndef MNG_SKIPCHUNK_cHRM
       
   636     if ( (pData->fProcesschroma) &&
       
   637          (((pBuf) && (pBuf->bHasCHRM)) || ((bGlobal) && (pData->bHasglobalCHRM))) )
       
   638     {
       
   639       mng_uint32 iWhitepointx,   iWhitepointy;
       
   640       mng_uint32 iPrimaryredx,   iPrimaryredy;
       
   641       mng_uint32 iPrimarygreenx, iPrimarygreeny;
       
   642       mng_uint32 iPrimarybluex,  iPrimarybluey;
       
   643 
       
   644       if ((pBuf) && (pBuf->bHasCHRM))  /* local cHRM ? */
       
   645       {
       
   646         iWhitepointx   = pBuf->iWhitepointx;
       
   647         iWhitepointy   = pBuf->iWhitepointy;
       
   648         iPrimaryredx   = pBuf->iPrimaryredx;
       
   649         iPrimaryredy   = pBuf->iPrimaryredy;
       
   650         iPrimarygreenx = pBuf->iPrimarygreenx;
       
   651         iPrimarygreeny = pBuf->iPrimarygreeny;
       
   652         iPrimarybluex  = pBuf->iPrimarybluex;
       
   653         iPrimarybluey  = pBuf->iPrimarybluey;
       
   654       }
       
   655       else
       
   656       {
       
   657         iWhitepointx   = pData->iGlobalWhitepointx;
       
   658         iWhitepointy   = pData->iGlobalWhitepointy;
       
   659         iPrimaryredx   = pData->iGlobalPrimaryredx;
       
   660         iPrimaryredy   = pData->iGlobalPrimaryredy;
       
   661         iPrimarygreenx = pData->iGlobalPrimarygreenx;
       
   662         iPrimarygreeny = pData->iGlobalPrimarygreeny;
       
   663         iPrimarybluex  = pData->iGlobalPrimarybluex;
       
   664         iPrimarybluey  = pData->iGlobalPrimarybluey;
       
   665       }
       
   666                                        /* inform the app */
       
   667       if (!pData->fProcesschroma ((mng_handle)pData, iWhitepointx,   iWhitepointy,
       
   668                                                      iPrimaryredx,   iPrimaryredy,
       
   669                                                      iPrimarygreenx, iPrimarygreeny,
       
   670                                                      iPrimarybluex,  iPrimarybluey))
       
   671         MNG_ERROR (pData, MNG_APPCMSERROR);
       
   672                                        /* load color-correction routine */
       
   673       pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
       
   674       bDone              = MNG_TRUE;
       
   675     }
       
   676 #endif
       
   677 
       
   678     if ( (pData->fProcessgamma) &&
       
   679          (((pBuf) && (pBuf->bHasGAMA)) || ((bGlobal) && (pData->bHasglobalGAMA))) )
       
   680     {
       
   681       mng_uint32 iGamma;
       
   682 
       
   683       if ((pBuf) && (pBuf->bHasGAMA))  /* get the gamma value */
       
   684         iGamma = pBuf->iGamma;
       
   685       else
       
   686         iGamma = pData->iGlobalGamma;
       
   687                                        /* inform the app */
       
   688       if (!pData->fProcessgamma ((mng_handle)pData, iGamma))
       
   689       {                                /* app wants us to use internal routines ! */
       
   690         iRetcode = mng_init_gamma_only (pData, bGlobal, bObject, bRetrobj);
       
   691         if (iRetcode)                  /* on error bail out */
       
   692           return iRetcode;
       
   693       }
       
   694       else
       
   695       {                                /* load color-correction routine */
       
   696         pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
       
   697       }
       
   698 
       
   699       bDone = MNG_TRUE;
       
   700     }
       
   701 
       
   702     if (!bDone)                        /* no color-info at all ? */
       
   703     {
       
   704                                        /* then use default image gamma ! */
       
   705       if (!pData->fProcessgamma ((mng_handle)pData,
       
   706                                  (mng_uint32)((pData->dDfltimggamma * 100000) + 0.5)))
       
   707       {                                /* app wants us to use internal routines ! */
       
   708         iRetcode = mng_init_gamma_only (pData, bGlobal, bObject, bRetrobj);
       
   709         if (iRetcode)                  /* on error bail out */
       
   710           return iRetcode;
       
   711       }
       
   712       else
       
   713       {                                /* load color-correction routine */
       
   714         pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
       
   715       }  
       
   716     }
       
   717   }
       
   718 
       
   719 #ifdef MNG_SUPPORT_TRACE
       
   720   MNG_TRACE (pData, MNG_FN_INIT_APP_CMS, MNG_LC_END);
       
   721 #endif
       
   722 
       
   723   return MNG_NOERROR;
       
   724 }
       
   725 #endif /* MNG_APP_CMS */
       
   726 
       
   727 /* ************************************************************************** */
       
   728 
       
   729 #ifdef MNG_APP_CMS
       
   730 mng_retcode mng_correct_app_cms (mng_datap pData)
       
   731 {
       
   732 #ifdef MNG_SUPPORT_TRACE
       
   733   MNG_TRACE (pData, MNG_FN_CORRECT_APP_CMS, MNG_LC_START);
       
   734 #endif
       
   735 
       
   736   if (pData->fProcessarow)             /* let the app do something with our row */
       
   737     if (!pData->fProcessarow ((mng_handle)pData, pData->iRowsamples,
       
   738                               pData->bIsRGBA16, pData->pRGBArow))
       
   739       MNG_ERROR (pData, MNG_APPCMSERROR);
       
   740 
       
   741 #ifdef MNG_SUPPORT_TRACE
       
   742   MNG_TRACE (pData, MNG_FN_CORRECT_APP_CMS, MNG_LC_END);
       
   743 #endif
       
   744 
       
   745   return MNG_NOERROR;
       
   746 }
       
   747 #endif /* MNG_APP_CMS */
       
   748 
       
   749 /* ************************************************************************** */
       
   750 
       
   751 #endif /* MNG_INCLUDE_DISPLAY_PROCS */
       
   752 
       
   753 /* ************************************************************************** */
       
   754 /* * end of file                                                            * */
       
   755 /* ************************************************************************** */
       
   756 
       
   757 
       
   758