/* ************************************************************************** */ | |
/* * For conditions of distribution and use, * */ | |
/* * see copyright notice in libmng.h * */ | |
/* ************************************************************************** */ | |
/* * * */ | |
/* * project : libmng * */ | |
/* * file : libmng_cms.c copyright (c) 2000-2004 G.Juyn * */ | |
/* * version : 1.0.9 * */ | |
/* * * */ | |
/* * purpose : color management routines (implementation) * */ | |
/* * * */ | |
/* * author : G.Juyn * */ | |
/* * * */ | |
/* * comment : implementation of the color management routines * */ | |
/* * * */ | |
/* * changes : 0.5.1 - 05/01/2000 - G.Juyn * */ | |
/* * - B001(105795) - fixed a typo and misconception about * */ | |
/* * freeing allocated gamma-table. (reported by Marti Maria) * */ | |
/* * 0.5.1 - 05/08/2000 - G.Juyn * */ | |
/* * - changed strict-ANSI stuff * */ | |
/* * 0.5.1 - 05/09/2000 - G.Juyn * */ | |
/* * - filled application-based color-management routines * */ | |
/* * 0.5.1 - 05/11/2000 - G.Juyn * */ | |
/* * - added creatememprofile * */ | |
/* * - added callback error-reporting support * */ | |
/* * 0.5.1 - 05/12/2000 - G.Juyn * */ | |
/* * - changed trace to macro for callback error-reporting * */ | |
/* * * */ | |
/* * 0.5.2 - 06/10/2000 - G.Juyn * */ | |
/* * - fixed some compilation-warnings (contrib Jason Morris) * */ | |
/* * * */ | |
/* * 0.5.3 - 06/21/2000 - G.Juyn * */ | |
/* * - fixed problem with color-correction for stored images * */ | |
/* * 0.5.3 - 06/23/2000 - G.Juyn * */ | |
/* * - fixed problem with incorrect gamma-correction * */ | |
/* * * */ | |
/* * 0.9.2 - 08/05/2000 - G.Juyn * */ | |
/* * - changed file-prefixes * */ | |
/* * * */ | |
/* * 0.9.3 - 08/31/2000 - G.Juyn * */ | |
/* * - fixed sRGB precedence for gamma_only corection * */ | |
/* * * */ | |
/* * 0.9.4 - 12/16/2000 - G.Juyn * */ | |
/* * - fixed mixup of data- & function-pointers (thanks Dimitri)* */ | |
/* * * */ | |
/* * 1.0.1 - 03/31/2001 - G.Juyn * */ | |
/* * - ignore gamma=0 (see png-list for more info) * */ | |
/* * 1.0.1 - 04/25/2001 - G.Juyn (reported by Gregg Kelly) * */ | |
/* * - fixed problem with cms profile being created multiple * */ | |
/* * times when both iCCP & cHRM/gAMA are present * */ | |
/* * 1.0.1 - 04/25/2001 - G.Juyn * */ | |
/* * - moved mng_clear_cms to libmng_cms * */ | |
/* * 1.0.1 - 05/02/2001 - G.Juyn * */ | |
/* * - added "default" sRGB generation (Thanks Marti!) * */ | |
/* * * */ | |
/* * 1.0.5 - 08/19/2002 - G.Juyn * */ | |
/* * - B597134 - libmng pollutes the linker namespace * */ | |
/* * 1.0.5 - 09/19/2002 - G.Juyn * */ | |
/* * - optimized color-correction routines * */ | |
/* * 1.0.5 - 09/23/2002 - G.Juyn * */ | |
/* * - added in-memory color-correction of abstract images * */ | |
/* * 1.0.5 - 11/08/2002 - G.Juyn * */ | |
/* * - fixed issues in init_app_cms() * */ | |
/* * * */ | |
/* * 1.0.6 - 04/11/2003 - G.Juyn * */ | |
/* * - B719420 - fixed several MNG_APP_CMS problems * */ | |
/* * 1.0.6 - 07/11/2003 - G. R-P * */ | |
/* * - added conditional MNG_SKIPCHUNK_cHRM/iCCP * */ | |
/* * * */ | |
/* * 1.0.9 - 12/20/2004 - G.Juyn * */ | |
/* * - cleaned up macro-invocations (thanks to D. Airlie) * */ | |
/* * * */ | |
/* ************************************************************************** */ | |
#include "libmng.h" | |
#include "libmng_data.h" | |
#include "libmng_error.h" | |
#include "libmng_trace.h" | |
#ifdef __BORLANDC__ | |
#pragma hdrstop | |
#endif | |
#include "libmng_objects.h" | |
#include "libmng_cms.h" | |
#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI) | |
#pragma option -A /* force ANSI-C */ | |
#endif | |
/* ************************************************************************** */ | |
#ifdef MNG_INCLUDE_DISPLAY_PROCS | |
/* ************************************************************************** */ | |
/* * * */ | |
/* * Little CMS helper routines * */ | |
/* * * */ | |
/* ************************************************************************** */ | |
#ifdef MNG_INCLUDE_LCMS | |
#define MNG_CMS_FLAGS 0 | |
/* ************************************************************************** */ | |
void mnglcms_initlibrary () | |
{ | |
cmsErrorAction (LCMS_ERROR_IGNORE); /* LCMS should ignore errors! */ | |
} | |
/* ************************************************************************** */ | |
mng_cmsprof mnglcms_createfileprofile (mng_pchar zFilename) | |
{ | |
return cmsOpenProfileFromFile (zFilename, "r"); | |
} | |
/* ************************************************************************** */ | |
mng_cmsprof mnglcms_creatememprofile (mng_uint32 iProfilesize, | |
mng_ptr pProfile) | |
{ | |
return cmsOpenProfileFromMem (pProfile, iProfilesize); | |
} | |
/* ************************************************************************** */ | |
mng_cmsprof mnglcms_createsrgbprofile (void) | |
{ | |
cmsCIExyY D65; | |
cmsCIExyYTRIPLE Rec709Primaries = { | |
{0.6400, 0.3300, 1.0}, | |
{0.3000, 0.6000, 1.0}, | |
{0.1500, 0.0600, 1.0} | |
}; | |
LPGAMMATABLE Gamma24[3]; | |
mng_cmsprof hsRGB; | |
cmsWhitePointFromTemp(6504, &D65); | |
Gamma24[0] = Gamma24[1] = Gamma24[2] = cmsBuildGamma(256, 2.4); | |
hsRGB = cmsCreateRGBProfile(&D65, &Rec709Primaries, Gamma24); | |
cmsFreeGamma(Gamma24[0]); | |
return hsRGB; | |
} | |
/* ************************************************************************** */ | |
void mnglcms_freeprofile (mng_cmsprof hProf) | |
{ | |
cmsCloseProfile (hProf); | |
return; | |
} | |
/* ************************************************************************** */ | |
void mnglcms_freetransform (mng_cmstrans hTrans) | |
{ | |
/* B001 start */ | |
cmsDeleteTransform (hTrans); | |
/* B001 end */ | |
return; | |
} | |
/* ************************************************************************** */ | |
mng_retcode mng_clear_cms (mng_datap pData) | |
{ | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_CLEAR_CMS, MNG_LC_START); | |
#endif | |
if (pData->hTrans) /* transformation still active ? */ | |
mnglcms_freetransform (pData->hTrans); | |
pData->hTrans = 0; | |
if (pData->hProf1) /* file profile still active ? */ | |
mnglcms_freeprofile (pData->hProf1); | |
pData->hProf1 = 0; | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_CLEAR_CMS, MNG_LC_END); | |
#endif | |
return MNG_NOERROR; | |
} | |
/* ************************************************************************** */ | |
#endif /* MNG_INCLUDE_LCMS */ | |
/* ************************************************************************** */ | |
/* * * */ | |
/* * Color-management initialization & correction routines * */ | |
/* * * */ | |
/* ************************************************************************** */ | |
#ifdef MNG_INCLUDE_LCMS | |
mng_retcode mng_init_full_cms (mng_datap pData, | |
mng_bool bGlobal, | |
mng_bool bObject, | |
mng_bool bRetrobj) | |
{ | |
mng_cmsprof hProf; | |
mng_cmstrans hTrans; | |
mng_imagep pImage = MNG_NULL; | |
mng_imagedatap pBuf = MNG_NULL; | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_INIT_FULL_CMS, MNG_LC_START); | |
#endif | |
if (bObject) /* use object if present ? */ | |
{ /* current object ? */ | |
if ((mng_imagep)pData->pCurrentobj) | |
pImage = (mng_imagep)pData->pCurrentobj; | |
else /* if not; use object 0 */ | |
pImage = (mng_imagep)pData->pObjzero; | |
} | |
if (bRetrobj) /* retrieving from an object ? */ | |
pImage = (mng_imagep)pData->pRetrieveobj; | |
if (pImage) /* are we using an object ? */ | |
pBuf = pImage->pImgbuf; /* then address the buffer */ | |
if ((!pBuf) || (!pBuf->bCorrected)) /* is the buffer already corrected ? */ | |
{ | |
#ifndef MNG_SKIPCHUNK_iCCP | |
if (((pBuf) && (pBuf->bHasICCP)) || ((bGlobal) && (pData->bHasglobalICCP))) | |
{ | |
if (!pData->hProf2) /* output profile not defined ? */ | |
{ /* then assume sRGB !! */ | |
pData->hProf2 = mnglcms_createsrgbprofile (); | |
if (!pData->hProf2) /* handle error ? */ | |
MNG_ERRORL (pData, MNG_LCMS_NOHANDLE); | |
} | |
if ((pBuf) && (pBuf->bHasICCP)) /* generate a profile handle */ | |
hProf = cmsOpenProfileFromMem (pBuf->pProfile, pBuf->iProfilesize); | |
else | |
hProf = cmsOpenProfileFromMem (pData->pGlobalProfile, pData->iGlobalProfilesize); | |
pData->hProf1 = hProf; /* save for future use */ | |
if (!hProf) /* handle error ? */ | |
MNG_ERRORL (pData, MNG_LCMS_NOHANDLE); | |
#ifndef MNG_NO_16BIT_SUPPORT | |
if (pData->bIsRGBA16) /* 16-bit intermediates ? */ | |
hTrans = cmsCreateTransform (hProf, TYPE_RGBA_16_SE, | |
pData->hProf2, TYPE_RGBA_16_SE, | |
INTENT_PERCEPTUAL, MNG_CMS_FLAGS); | |
else | |
#endif | |
hTrans = cmsCreateTransform (hProf, TYPE_RGBA_8, | |
pData->hProf2, TYPE_RGBA_8, | |
INTENT_PERCEPTUAL, MNG_CMS_FLAGS); | |
pData->hTrans = hTrans; /* save for future use */ | |
if (!hTrans) /* handle error ? */ | |
MNG_ERRORL (pData, MNG_LCMS_NOTRANS); | |
/* load color-correction routine */ | |
pData->fCorrectrow = (mng_fptr)mng_correct_full_cms; | |
return MNG_NOERROR; /* and done */ | |
} | |
else | |
#endif | |
if (((pBuf) && (pBuf->bHasSRGB)) || ((bGlobal) && (pData->bHasglobalSRGB))) | |
{ | |
mng_uint8 iIntent; | |
if (pData->bIssRGB) /* sRGB system ? */ | |
return MNG_NOERROR; /* no conversion required */ | |
if (!pData->hProf3) /* sRGB profile not defined ? */ | |
{ /* then create it implicitly !! */ | |
pData->hProf3 = mnglcms_createsrgbprofile (); | |
if (!pData->hProf3) /* handle error ? */ | |
MNG_ERRORL (pData, MNG_LCMS_NOHANDLE); | |
} | |
hProf = pData->hProf3; /* convert from sRGB profile */ | |
if ((pBuf) && (pBuf->bHasSRGB)) /* determine rendering intent */ | |
iIntent = pBuf->iRenderingintent; | |
else | |
iIntent = pData->iGlobalRendintent; | |
if (pData->bIsRGBA16) /* 16-bit intermediates ? */ | |
hTrans = cmsCreateTransform (hProf, TYPE_RGBA_16_SE, | |
pData->hProf2, TYPE_RGBA_16_SE, | |
iIntent, MNG_CMS_FLAGS); | |
else | |
hTrans = cmsCreateTransform (hProf, TYPE_RGBA_8, | |
pData->hProf2, TYPE_RGBA_8, | |
iIntent, MNG_CMS_FLAGS); | |
pData->hTrans = hTrans; /* save for future use */ | |
if (!hTrans) /* handle error ? */ | |
MNG_ERRORL (pData, MNG_LCMS_NOTRANS); | |
/* load color-correction routine */ | |
pData->fCorrectrow = (mng_fptr)mng_correct_full_cms; | |
return MNG_NOERROR; /* and done */ | |
} | |
else | |
if ( (((pBuf) && (pBuf->bHasCHRM)) || ((bGlobal) && (pData->bHasglobalCHRM))) && | |
( ((pBuf) && (pBuf->bHasGAMA) && (pBuf->iGamma > 0)) || | |
((bGlobal) && (pData->bHasglobalGAMA) && (pData->iGlobalGamma > 0)) ) ) | |
{ | |
mng_CIExyY sWhitepoint; | |
mng_CIExyYTRIPLE sPrimaries; | |
mng_gammatabp pGammatable[3]; | |
mng_float dGamma; | |
if (!pData->hProf2) /* output profile not defined ? */ | |
{ /* then assume sRGB !! */ | |
pData->hProf2 = mnglcms_createsrgbprofile (); | |
if (!pData->hProf2) /* handle error ? */ | |
MNG_ERRORL (pData, MNG_LCMS_NOHANDLE); | |
} | |
#ifndef MNG_SKIPCHUNK_cHRM | |
if ((pBuf) && (pBuf->bHasCHRM)) /* local cHRM ? */ | |
{ | |
sWhitepoint.x = (mng_float)pBuf->iWhitepointx / 100000; | |
sWhitepoint.y = (mng_float)pBuf->iWhitepointy / 100000; | |
sPrimaries.Red.x = (mng_float)pBuf->iPrimaryredx / 100000; | |
sPrimaries.Red.y = (mng_float)pBuf->iPrimaryredy / 100000; | |
sPrimaries.Green.x = (mng_float)pBuf->iPrimarygreenx / 100000; | |
sPrimaries.Green.y = (mng_float)pBuf->iPrimarygreeny / 100000; | |
sPrimaries.Blue.x = (mng_float)pBuf->iPrimarybluex / 100000; | |
sPrimaries.Blue.y = (mng_float)pBuf->iPrimarybluey / 100000; | |
} | |
else | |
{ | |
sWhitepoint.x = (mng_float)pData->iGlobalWhitepointx / 100000; | |
sWhitepoint.y = (mng_float)pData->iGlobalWhitepointy / 100000; | |
sPrimaries.Red.x = (mng_float)pData->iGlobalPrimaryredx / 100000; | |
sPrimaries.Red.y = (mng_float)pData->iGlobalPrimaryredy / 100000; | |
sPrimaries.Green.x = (mng_float)pData->iGlobalPrimarygreenx / 100000; | |
sPrimaries.Green.y = (mng_float)pData->iGlobalPrimarygreeny / 100000; | |
sPrimaries.Blue.x = (mng_float)pData->iGlobalPrimarybluex / 100000; | |
sPrimaries.Blue.y = (mng_float)pData->iGlobalPrimarybluey / 100000; | |
} | |
#endif | |
sWhitepoint.Y = /* Y component is always 1.0 */ | |
sPrimaries.Red.Y = | |
sPrimaries.Green.Y = | |
sPrimaries.Blue.Y = 1.0; | |
if ((pBuf) && (pBuf->bHasGAMA)) /* get the gamma value */ | |
dGamma = (mng_float)pBuf->iGamma / 100000; | |
else | |
dGamma = (mng_float)pData->iGlobalGamma / 100000; | |
dGamma = pData->dViewgamma / dGamma; | |
pGammatable [0] = /* and build the lookup tables */ | |
pGammatable [1] = | |
pGammatable [2] = cmsBuildGamma (256, dGamma); | |
if (!pGammatable [0]) /* enough memory ? */ | |
MNG_ERRORL (pData, MNG_LCMS_NOMEM); | |
/* create the profile */ | |
hProf = cmsCreateRGBProfile (&sWhitepoint, &sPrimaries, pGammatable); | |
cmsFreeGamma (pGammatable [0]); /* free the temporary gamma tables ? */ | |
/* yes! but just the one! */ | |
pData->hProf1 = hProf; /* save for future use */ | |
if (!hProf) /* handle error ? */ | |
MNG_ERRORL (pData, MNG_LCMS_NOHANDLE); | |
if (pData->bIsRGBA16) /* 16-bit intermediates ? */ | |
hTrans = cmsCreateTransform (hProf, TYPE_RGBA_16_SE, | |
pData->hProf2, TYPE_RGBA_16_SE, | |
INTENT_PERCEPTUAL, MNG_CMS_FLAGS); | |
else | |
hTrans = cmsCreateTransform (hProf, TYPE_RGBA_8, | |
pData->hProf2, TYPE_RGBA_8, | |
INTENT_PERCEPTUAL, MNG_CMS_FLAGS); | |
pData->hTrans = hTrans; /* save for future use */ | |
if (!hTrans) /* handle error ? */ | |
MNG_ERRORL (pData, MNG_LCMS_NOTRANS); | |
/* load color-correction routine */ | |
pData->fCorrectrow = (mng_fptr)mng_correct_full_cms; | |
return MNG_NOERROR; /* and done */ | |
} | |
} | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_INIT_FULL_CMS, MNG_LC_END); | |
#endif | |
/* if we get here, we'll only do gamma */ | |
return mng_init_gamma_only (pData, bGlobal, bObject, bRetrobj); | |
} | |
#endif /* MNG_INCLUDE_LCMS */ | |
/* ************************************************************************** */ | |
#ifdef MNG_INCLUDE_LCMS | |
mng_retcode mng_correct_full_cms (mng_datap pData) | |
{ | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_CORRECT_FULL_CMS, MNG_LC_START); | |
#endif | |
cmsDoTransform (pData->hTrans, pData->pRGBArow, pData->pRGBArow, pData->iRowsamples); | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_CORRECT_FULL_CMS, MNG_LC_END); | |
#endif | |
return MNG_NOERROR; | |
} | |
#endif /* MNG_INCLUDE_LCMS */ | |
/* ************************************************************************** */ | |
#if defined(MNG_GAMMA_ONLY) || defined(MNG_FULL_CMS) || defined(MNG_APP_CMS) | |
mng_retcode mng_init_gamma_only (mng_datap pData, | |
mng_bool bGlobal, | |
mng_bool bObject, | |
mng_bool bRetrobj) | |
{ | |
mng_float dGamma; | |
mng_imagep pImage = MNG_NULL; | |
mng_imagedatap pBuf = MNG_NULL; | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_INIT_GAMMA_ONLY, MNG_LC_START); | |
#endif | |
if (bObject) /* use object if present ? */ | |
{ /* current object ? */ | |
if ((mng_imagep)pData->pCurrentobj) | |
pImage = (mng_imagep)pData->pCurrentobj; | |
else /* if not; use object 0 */ | |
pImage = (mng_imagep)pData->pObjzero; | |
} | |
if (bRetrobj) /* retrieving from an object ? */ | |
pImage = (mng_imagep)pData->pRetrieveobj; | |
if (pImage) /* are we using an object ? */ | |
pBuf = pImage->pImgbuf; /* then address the buffer */ | |
if ((!pBuf) || (!pBuf->bCorrected)) /* is the buffer already corrected ? */ | |
{ | |
if ((pBuf) && (pBuf->bHasSRGB)) /* get the gamma value */ | |
dGamma = 0.45455; | |
else | |
if ((pBuf) && (pBuf->bHasGAMA)) | |
dGamma = (mng_float)pBuf->iGamma / 100000; | |
else | |
if ((bGlobal) && (pData->bHasglobalSRGB)) | |
dGamma = 0.45455; | |
else | |
if ((bGlobal) && (pData->bHasglobalGAMA)) | |
dGamma = (mng_float)pData->iGlobalGamma / 100000; | |
else | |
dGamma = pData->dDfltimggamma; | |
if (dGamma > 0) /* ignore gamma=0 */ | |
{ | |
dGamma = pData->dViewgamma / (dGamma * pData->dDisplaygamma); | |
if (dGamma != pData->dLastgamma) /* lookup table needs to be computed ? */ | |
{ | |
mng_int32 iX; | |
pData->aGammatab [0] = 0; | |
for (iX = 1; iX <= 255; iX++) | |
pData->aGammatab [iX] = (mng_uint8)(pow (iX / 255.0, dGamma) * 255 + 0.5); | |
pData->dLastgamma = dGamma; /* keep for next time */ | |
} | |
/* load color-correction routine */ | |
pData->fCorrectrow = (mng_fptr)mng_correct_gamma_only; | |
} | |
} | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_INIT_GAMMA_ONLY, MNG_LC_END); | |
#endif | |
return MNG_NOERROR; | |
} | |
#endif /* MNG_GAMMA_ONLY || MNG_FULL_CMS || MNG_APP_CMS */ | |
/* ************************************************************************** */ | |
#if defined(MNG_GAMMA_ONLY) || defined(MNG_FULL_CMS) || defined(MNG_APP_CMS) | |
mng_retcode mng_correct_gamma_only (mng_datap pData) | |
{ | |
mng_uint8p pWork; | |
mng_int32 iX; | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_CORRECT_GAMMA_ONLY, MNG_LC_START); | |
#endif | |
pWork = pData->pRGBArow; /* address intermediate row */ | |
if (pData->bIsRGBA16) /* 16-bit intermediate row ? */ | |
{ | |
/* TODO: 16-bit precision gamma processing */ | |
/* we'll just do the high-order byte for now */ | |
/* convert all samples in the row */ | |
for (iX = 0; iX < pData->iRowsamples; iX++) | |
{ /* using the precalculated gamma lookup table */ | |
*pWork = pData->aGammatab [*pWork]; | |
*(pWork+2) = pData->aGammatab [*(pWork+2)]; | |
*(pWork+4) = pData->aGammatab [*(pWork+4)]; | |
pWork += 8; | |
} | |
} | |
else | |
{ /* convert all samples in the row */ | |
for (iX = 0; iX < pData->iRowsamples; iX++) | |
{ /* using the precalculated gamma lookup table */ | |
*pWork = pData->aGammatab [*pWork]; | |
*(pWork+1) = pData->aGammatab [*(pWork+1)]; | |
*(pWork+2) = pData->aGammatab [*(pWork+2)]; | |
pWork += 4; | |
} | |
} | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_CORRECT_GAMMA_ONLY, MNG_LC_END); | |
#endif | |
return MNG_NOERROR; | |
} | |
#endif /* MNG_GAMMA_ONLY || MNG_FULL_CMS || MNG_APP_CMS */ | |
/* ************************************************************************** */ | |
#ifdef MNG_APP_CMS | |
mng_retcode mng_init_app_cms (mng_datap pData, | |
mng_bool bGlobal, | |
mng_bool bObject, | |
mng_bool bRetrobj) | |
{ | |
mng_imagep pImage = MNG_NULL; | |
mng_imagedatap pBuf = MNG_NULL; | |
mng_bool bDone = MNG_FALSE; | |
mng_retcode iRetcode; | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_INIT_APP_CMS, MNG_LC_START); | |
#endif | |
if (bObject) /* use object if present ? */ | |
{ /* current object ? */ | |
if ((mng_imagep)pData->pCurrentobj) | |
pImage = (mng_imagep)pData->pCurrentobj; | |
else /* if not; use object 0 */ | |
pImage = (mng_imagep)pData->pObjzero; | |
} | |
if (bRetrobj) /* retrieving from an object ? */ | |
pImage = (mng_imagep)pData->pRetrieveobj; | |
if (pImage) /* are we using an object ? */ | |
pBuf = pImage->pImgbuf; /* then address the buffer */ | |
if ((!pBuf) || (!pBuf->bCorrected)) /* is the buffer already corrected ? */ | |
{ | |
#ifndef MNG_SKIPCHUNK_iCCP | |
if ( (pData->fProcessiccp) && | |
(((pBuf) && (pBuf->bHasICCP)) || ((bGlobal) && (pData->bHasglobalICCP))) ) | |
{ | |
mng_uint32 iProfilesize; | |
mng_ptr pProfile; | |
if ((pBuf) && (pBuf->bHasICCP)) /* get the right profile */ | |
{ | |
iProfilesize = pBuf->iProfilesize; | |
pProfile = pBuf->pProfile; | |
} | |
else | |
{ | |
iProfilesize = pData->iGlobalProfilesize; | |
pProfile = pData->pGlobalProfile; | |
} | |
/* inform the app */ | |
if (!pData->fProcessiccp ((mng_handle)pData, iProfilesize, pProfile)) | |
MNG_ERROR (pData, MNG_APPCMSERROR); | |
/* load color-correction routine */ | |
pData->fCorrectrow = (mng_fptr)mng_correct_app_cms; | |
bDone = MNG_TRUE; | |
} | |
#endif | |
if ( (pData->fProcesssrgb) && | |
(((pBuf) && (pBuf->bHasSRGB)) || ((bGlobal) && (pData->bHasglobalSRGB))) ) | |
{ | |
mng_uint8 iIntent; | |
if ((pBuf) && (pBuf->bHasSRGB)) /* determine rendering intent */ | |
iIntent = pBuf->iRenderingintent; | |
else | |
iIntent = pData->iGlobalRendintent; | |
/* inform the app */ | |
if (!pData->fProcesssrgb ((mng_handle)pData, iIntent)) | |
MNG_ERROR (pData, MNG_APPCMSERROR); | |
/* load color-correction routine */ | |
pData->fCorrectrow = (mng_fptr)mng_correct_app_cms; | |
bDone = MNG_TRUE; | |
} | |
#ifndef MNG_SKIPCHUNK_cHRM | |
if ( (pData->fProcesschroma) && | |
(((pBuf) && (pBuf->bHasCHRM)) || ((bGlobal) && (pData->bHasglobalCHRM))) ) | |
{ | |
mng_uint32 iWhitepointx, iWhitepointy; | |
mng_uint32 iPrimaryredx, iPrimaryredy; | |
mng_uint32 iPrimarygreenx, iPrimarygreeny; | |
mng_uint32 iPrimarybluex, iPrimarybluey; | |
if ((pBuf) && (pBuf->bHasCHRM)) /* local cHRM ? */ | |
{ | |
iWhitepointx = pBuf->iWhitepointx; | |
iWhitepointy = pBuf->iWhitepointy; | |
iPrimaryredx = pBuf->iPrimaryredx; | |
iPrimaryredy = pBuf->iPrimaryredy; | |
iPrimarygreenx = pBuf->iPrimarygreenx; | |
iPrimarygreeny = pBuf->iPrimarygreeny; | |
iPrimarybluex = pBuf->iPrimarybluex; | |
iPrimarybluey = pBuf->iPrimarybluey; | |
} | |
else | |
{ | |
iWhitepointx = pData->iGlobalWhitepointx; | |
iWhitepointy = pData->iGlobalWhitepointy; | |
iPrimaryredx = pData->iGlobalPrimaryredx; | |
iPrimaryredy = pData->iGlobalPrimaryredy; | |
iPrimarygreenx = pData->iGlobalPrimarygreenx; | |
iPrimarygreeny = pData->iGlobalPrimarygreeny; | |
iPrimarybluex = pData->iGlobalPrimarybluex; | |
iPrimarybluey = pData->iGlobalPrimarybluey; | |
} | |
/* inform the app */ | |
if (!pData->fProcesschroma ((mng_handle)pData, iWhitepointx, iWhitepointy, | |
iPrimaryredx, iPrimaryredy, | |
iPrimarygreenx, iPrimarygreeny, | |
iPrimarybluex, iPrimarybluey)) | |
MNG_ERROR (pData, MNG_APPCMSERROR); | |
/* load color-correction routine */ | |
pData->fCorrectrow = (mng_fptr)mng_correct_app_cms; | |
bDone = MNG_TRUE; | |
} | |
#endif | |
if ( (pData->fProcessgamma) && | |
(((pBuf) && (pBuf->bHasGAMA)) || ((bGlobal) && (pData->bHasglobalGAMA))) ) | |
{ | |
mng_uint32 iGamma; | |
if ((pBuf) && (pBuf->bHasGAMA)) /* get the gamma value */ | |
iGamma = pBuf->iGamma; | |
else | |
iGamma = pData->iGlobalGamma; | |
/* inform the app */ | |
if (!pData->fProcessgamma ((mng_handle)pData, iGamma)) | |
{ /* app wants us to use internal routines ! */ | |
iRetcode = mng_init_gamma_only (pData, bGlobal, bObject, bRetrobj); | |
if (iRetcode) /* on error bail out */ | |
return iRetcode; | |
} | |
else | |
{ /* load color-correction routine */ | |
pData->fCorrectrow = (mng_fptr)mng_correct_app_cms; | |
} | |
bDone = MNG_TRUE; | |
} | |
if (!bDone) /* no color-info at all ? */ | |
{ | |
/* then use default image gamma ! */ | |
if (!pData->fProcessgamma ((mng_handle)pData, | |
(mng_uint32)((pData->dDfltimggamma * 100000) + 0.5))) | |
{ /* app wants us to use internal routines ! */ | |
iRetcode = mng_init_gamma_only (pData, bGlobal, bObject, bRetrobj); | |
if (iRetcode) /* on error bail out */ | |
return iRetcode; | |
} | |
else | |
{ /* load color-correction routine */ | |
pData->fCorrectrow = (mng_fptr)mng_correct_app_cms; | |
} | |
} | |
} | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_INIT_APP_CMS, MNG_LC_END); | |
#endif | |
return MNG_NOERROR; | |
} | |
#endif /* MNG_APP_CMS */ | |
/* ************************************************************************** */ | |
#ifdef MNG_APP_CMS | |
mng_retcode mng_correct_app_cms (mng_datap pData) | |
{ | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_CORRECT_APP_CMS, MNG_LC_START); | |
#endif | |
if (pData->fProcessarow) /* let the app do something with our row */ | |
if (!pData->fProcessarow ((mng_handle)pData, pData->iRowsamples, | |
pData->bIsRGBA16, pData->pRGBArow)) | |
MNG_ERROR (pData, MNG_APPCMSERROR); | |
#ifdef MNG_SUPPORT_TRACE | |
MNG_TRACE (pData, MNG_FN_CORRECT_APP_CMS, MNG_LC_END); | |
#endif | |
return MNG_NOERROR; | |
} | |
#endif /* MNG_APP_CMS */ | |
/* ************************************************************************** */ | |
#endif /* MNG_INCLUDE_DISPLAY_PROCS */ | |
/* ************************************************************************** */ | |
/* * end of file * */ | |
/* ************************************************************************** */ | |