/src/FreeImage/Source/LibMNG/libmng_cms.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 758 lines · 504 code · 133 blank · 121 comment · 117 complexity · 70f9d9de9d45716aafb320f70b1813b5 MD5 · raw file

  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. #include "libmng.h"
  75. #include "libmng_data.h"
  76. #include "libmng_error.h"
  77. #include "libmng_trace.h"
  78. #ifdef __BORLANDC__
  79. #pragma hdrstop
  80. #endif
  81. #include "libmng_objects.h"
  82. #include "libmng_cms.h"
  83. #if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
  84. #pragma option -A /* force ANSI-C */
  85. #endif
  86. /* ************************************************************************** */
  87. #ifdef MNG_INCLUDE_DISPLAY_PROCS
  88. /* ************************************************************************** */
  89. /* * * */
  90. /* * Little CMS helper routines * */
  91. /* * * */
  92. /* ************************************************************************** */
  93. #ifdef MNG_INCLUDE_LCMS
  94. #define MNG_CMS_FLAGS 0
  95. /* ************************************************************************** */
  96. void mnglcms_initlibrary ()
  97. {
  98. cmsErrorAction (LCMS_ERROR_IGNORE); /* LCMS should ignore errors! */
  99. }
  100. /* ************************************************************************** */
  101. mng_cmsprof mnglcms_createfileprofile (mng_pchar zFilename)
  102. {
  103. return cmsOpenProfileFromFile (zFilename, "r");
  104. }
  105. /* ************************************************************************** */
  106. mng_cmsprof mnglcms_creatememprofile (mng_uint32 iProfilesize,
  107. mng_ptr pProfile)
  108. {
  109. return cmsOpenProfileFromMem (pProfile, iProfilesize);
  110. }
  111. /* ************************************************************************** */
  112. mng_cmsprof mnglcms_createsrgbprofile (void)
  113. {
  114. cmsCIExyY D65;
  115. cmsCIExyYTRIPLE Rec709Primaries = {
  116. {0.6400, 0.3300, 1.0},
  117. {0.3000, 0.6000, 1.0},
  118. {0.1500, 0.0600, 1.0}
  119. };
  120. LPGAMMATABLE Gamma24[3];
  121. mng_cmsprof hsRGB;
  122. cmsWhitePointFromTemp(6504, &D65);
  123. Gamma24[0] = Gamma24[1] = Gamma24[2] = cmsBuildGamma(256, 2.4);
  124. hsRGB = cmsCreateRGBProfile(&D65, &Rec709Primaries, Gamma24);
  125. cmsFreeGamma(Gamma24[0]);
  126. return hsRGB;
  127. }
  128. /* ************************************************************************** */
  129. void mnglcms_freeprofile (mng_cmsprof hProf)
  130. {
  131. cmsCloseProfile (hProf);
  132. return;
  133. }
  134. /* ************************************************************************** */
  135. void mnglcms_freetransform (mng_cmstrans hTrans)
  136. {
  137. /* B001 start */
  138. cmsDeleteTransform (hTrans);
  139. /* B001 end */
  140. return;
  141. }
  142. /* ************************************************************************** */
  143. mng_retcode mng_clear_cms (mng_datap pData)
  144. {
  145. #ifdef MNG_SUPPORT_TRACE
  146. MNG_TRACE (pData, MNG_FN_CLEAR_CMS, MNG_LC_START);
  147. #endif
  148. if (pData->hTrans) /* transformation still active ? */
  149. mnglcms_freetransform (pData->hTrans);
  150. pData->hTrans = 0;
  151. if (pData->hProf1) /* file profile still active ? */
  152. mnglcms_freeprofile (pData->hProf1);
  153. pData->hProf1 = 0;
  154. #ifdef MNG_SUPPORT_TRACE
  155. MNG_TRACE (pData, MNG_FN_CLEAR_CMS, MNG_LC_END);
  156. #endif
  157. return MNG_NOERROR;
  158. }
  159. /* ************************************************************************** */
  160. #endif /* MNG_INCLUDE_LCMS */
  161. /* ************************************************************************** */
  162. /* * * */
  163. /* * Color-management initialization & correction routines * */
  164. /* * * */
  165. /* ************************************************************************** */
  166. #ifdef MNG_INCLUDE_LCMS
  167. mng_retcode mng_init_full_cms (mng_datap pData,
  168. mng_bool bGlobal,
  169. mng_bool bObject,
  170. mng_bool bRetrobj)
  171. {
  172. mng_cmsprof hProf;
  173. mng_cmstrans hTrans;
  174. mng_imagep pImage = MNG_NULL;
  175. mng_imagedatap pBuf = MNG_NULL;
  176. #ifdef MNG_SUPPORT_TRACE
  177. MNG_TRACE (pData, MNG_FN_INIT_FULL_CMS, MNG_LC_START);
  178. #endif
  179. if (bObject) /* use object if present ? */
  180. { /* current object ? */
  181. if ((mng_imagep)pData->pCurrentobj)
  182. pImage = (mng_imagep)pData->pCurrentobj;
  183. else /* if not; use object 0 */
  184. pImage = (mng_imagep)pData->pObjzero;
  185. }
  186. if (bRetrobj) /* retrieving from an object ? */
  187. pImage = (mng_imagep)pData->pRetrieveobj;
  188. if (pImage) /* are we using an object ? */
  189. pBuf = pImage->pImgbuf; /* then address the buffer */
  190. if ((!pBuf) || (!pBuf->bCorrected)) /* is the buffer already corrected ? */
  191. {
  192. #ifndef MNG_SKIPCHUNK_iCCP
  193. if (((pBuf) && (pBuf->bHasICCP)) || ((bGlobal) && (pData->bHasglobalICCP)))
  194. {
  195. if (!pData->hProf2) /* output profile not defined ? */
  196. { /* then assume sRGB !! */
  197. pData->hProf2 = mnglcms_createsrgbprofile ();
  198. if (!pData->hProf2) /* handle error ? */
  199. MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
  200. }
  201. if ((pBuf) && (pBuf->bHasICCP)) /* generate a profile handle */
  202. hProf = cmsOpenProfileFromMem (pBuf->pProfile, pBuf->iProfilesize);
  203. else
  204. hProf = cmsOpenProfileFromMem (pData->pGlobalProfile, pData->iGlobalProfilesize);
  205. pData->hProf1 = hProf; /* save for future use */
  206. if (!hProf) /* handle error ? */
  207. MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
  208. #ifndef MNG_NO_16BIT_SUPPORT
  209. if (pData->bIsRGBA16) /* 16-bit intermediates ? */
  210. hTrans = cmsCreateTransform (hProf, TYPE_RGBA_16_SE,
  211. pData->hProf2, TYPE_RGBA_16_SE,
  212. INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
  213. else
  214. #endif
  215. hTrans = cmsCreateTransform (hProf, TYPE_RGBA_8,
  216. pData->hProf2, TYPE_RGBA_8,
  217. INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
  218. pData->hTrans = hTrans; /* save for future use */
  219. if (!hTrans) /* handle error ? */
  220. MNG_ERRORL (pData, MNG_LCMS_NOTRANS);
  221. /* load color-correction routine */
  222. pData->fCorrectrow = (mng_fptr)mng_correct_full_cms;
  223. return MNG_NOERROR; /* and done */
  224. }
  225. else
  226. #endif
  227. if (((pBuf) && (pBuf->bHasSRGB)) || ((bGlobal) && (pData->bHasglobalSRGB)))
  228. {
  229. mng_uint8 iIntent;
  230. if (pData->bIssRGB) /* sRGB system ? */
  231. return MNG_NOERROR; /* no conversion required */
  232. if (!pData->hProf3) /* sRGB profile not defined ? */
  233. { /* then create it implicitly !! */
  234. pData->hProf3 = mnglcms_createsrgbprofile ();
  235. if (!pData->hProf3) /* handle error ? */
  236. MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
  237. }
  238. hProf = pData->hProf3; /* convert from sRGB profile */
  239. if ((pBuf) && (pBuf->bHasSRGB)) /* determine rendering intent */
  240. iIntent = pBuf->iRenderingintent;
  241. else
  242. iIntent = pData->iGlobalRendintent;
  243. if (pData->bIsRGBA16) /* 16-bit intermediates ? */
  244. hTrans = cmsCreateTransform (hProf, TYPE_RGBA_16_SE,
  245. pData->hProf2, TYPE_RGBA_16_SE,
  246. iIntent, MNG_CMS_FLAGS);
  247. else
  248. hTrans = cmsCreateTransform (hProf, TYPE_RGBA_8,
  249. pData->hProf2, TYPE_RGBA_8,
  250. iIntent, MNG_CMS_FLAGS);
  251. pData->hTrans = hTrans; /* save for future use */
  252. if (!hTrans) /* handle error ? */
  253. MNG_ERRORL (pData, MNG_LCMS_NOTRANS);
  254. /* load color-correction routine */
  255. pData->fCorrectrow = (mng_fptr)mng_correct_full_cms;
  256. return MNG_NOERROR; /* and done */
  257. }
  258. else
  259. if ( (((pBuf) && (pBuf->bHasCHRM)) || ((bGlobal) && (pData->bHasglobalCHRM))) &&
  260. ( ((pBuf) && (pBuf->bHasGAMA) && (pBuf->iGamma > 0)) ||
  261. ((bGlobal) && (pData->bHasglobalGAMA) && (pData->iGlobalGamma > 0)) ) )
  262. {
  263. mng_CIExyY sWhitepoint;
  264. mng_CIExyYTRIPLE sPrimaries;
  265. mng_gammatabp pGammatable[3];
  266. mng_float dGamma;
  267. if (!pData->hProf2) /* output profile not defined ? */
  268. { /* then assume sRGB !! */
  269. pData->hProf2 = mnglcms_createsrgbprofile ();
  270. if (!pData->hProf2) /* handle error ? */
  271. MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
  272. }
  273. #ifndef MNG_SKIPCHUNK_cHRM
  274. if ((pBuf) && (pBuf->bHasCHRM)) /* local cHRM ? */
  275. {
  276. sWhitepoint.x = (mng_float)pBuf->iWhitepointx / 100000;
  277. sWhitepoint.y = (mng_float)pBuf->iWhitepointy / 100000;
  278. sPrimaries.Red.x = (mng_float)pBuf->iPrimaryredx / 100000;
  279. sPrimaries.Red.y = (mng_float)pBuf->iPrimaryredy / 100000;
  280. sPrimaries.Green.x = (mng_float)pBuf->iPrimarygreenx / 100000;
  281. sPrimaries.Green.y = (mng_float)pBuf->iPrimarygreeny / 100000;
  282. sPrimaries.Blue.x = (mng_float)pBuf->iPrimarybluex / 100000;
  283. sPrimaries.Blue.y = (mng_float)pBuf->iPrimarybluey / 100000;
  284. }
  285. else
  286. {
  287. sWhitepoint.x = (mng_float)pData->iGlobalWhitepointx / 100000;
  288. sWhitepoint.y = (mng_float)pData->iGlobalWhitepointy / 100000;
  289. sPrimaries.Red.x = (mng_float)pData->iGlobalPrimaryredx / 100000;
  290. sPrimaries.Red.y = (mng_float)pData->iGlobalPrimaryredy / 100000;
  291. sPrimaries.Green.x = (mng_float)pData->iGlobalPrimarygreenx / 100000;
  292. sPrimaries.Green.y = (mng_float)pData->iGlobalPrimarygreeny / 100000;
  293. sPrimaries.Blue.x = (mng_float)pData->iGlobalPrimarybluex / 100000;
  294. sPrimaries.Blue.y = (mng_float)pData->iGlobalPrimarybluey / 100000;
  295. }
  296. #endif
  297. sWhitepoint.Y = /* Y component is always 1.0 */
  298. sPrimaries.Red.Y =
  299. sPrimaries.Green.Y =
  300. sPrimaries.Blue.Y = 1.0;
  301. if ((pBuf) && (pBuf->bHasGAMA)) /* get the gamma value */
  302. dGamma = (mng_float)pBuf->iGamma / 100000;
  303. else
  304. dGamma = (mng_float)pData->iGlobalGamma / 100000;
  305. dGamma = pData->dViewgamma / dGamma;
  306. pGammatable [0] = /* and build the lookup tables */
  307. pGammatable [1] =
  308. pGammatable [2] = cmsBuildGamma (256, dGamma);
  309. if (!pGammatable [0]) /* enough memory ? */
  310. MNG_ERRORL (pData, MNG_LCMS_NOMEM);
  311. /* create the profile */
  312. hProf = cmsCreateRGBProfile (&sWhitepoint, &sPrimaries, pGammatable);
  313. cmsFreeGamma (pGammatable [0]); /* free the temporary gamma tables ? */
  314. /* yes! but just the one! */
  315. pData->hProf1 = hProf; /* save for future use */
  316. if (!hProf) /* handle error ? */
  317. MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
  318. if (pData->bIsRGBA16) /* 16-bit intermediates ? */
  319. hTrans = cmsCreateTransform (hProf, TYPE_RGBA_16_SE,
  320. pData->hProf2, TYPE_RGBA_16_SE,
  321. INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
  322. else
  323. hTrans = cmsCreateTransform (hProf, TYPE_RGBA_8,
  324. pData->hProf2, TYPE_RGBA_8,
  325. INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
  326. pData->hTrans = hTrans; /* save for future use */
  327. if (!hTrans) /* handle error ? */
  328. MNG_ERRORL (pData, MNG_LCMS_NOTRANS);
  329. /* load color-correction routine */
  330. pData->fCorrectrow = (mng_fptr)mng_correct_full_cms;
  331. return MNG_NOERROR; /* and done */
  332. }
  333. }
  334. #ifdef MNG_SUPPORT_TRACE
  335. MNG_TRACE (pData, MNG_FN_INIT_FULL_CMS, MNG_LC_END);
  336. #endif
  337. /* if we get here, we'll only do gamma */
  338. return mng_init_gamma_only (pData, bGlobal, bObject, bRetrobj);
  339. }
  340. #endif /* MNG_INCLUDE_LCMS */
  341. /* ************************************************************************** */
  342. #ifdef MNG_INCLUDE_LCMS
  343. mng_retcode mng_correct_full_cms (mng_datap pData)
  344. {
  345. #ifdef MNG_SUPPORT_TRACE
  346. MNG_TRACE (pData, MNG_FN_CORRECT_FULL_CMS, MNG_LC_START);
  347. #endif
  348. cmsDoTransform (pData->hTrans, pData->pRGBArow, pData->pRGBArow, pData->iRowsamples);
  349. #ifdef MNG_SUPPORT_TRACE
  350. MNG_TRACE (pData, MNG_FN_CORRECT_FULL_CMS, MNG_LC_END);
  351. #endif
  352. return MNG_NOERROR;
  353. }
  354. #endif /* MNG_INCLUDE_LCMS */
  355. /* ************************************************************************** */
  356. #if defined(MNG_GAMMA_ONLY) || defined(MNG_FULL_CMS) || defined(MNG_APP_CMS)
  357. mng_retcode mng_init_gamma_only (mng_datap pData,
  358. mng_bool bGlobal,
  359. mng_bool bObject,
  360. mng_bool bRetrobj)
  361. {
  362. mng_float dGamma;
  363. mng_imagep pImage = MNG_NULL;
  364. mng_imagedatap pBuf = MNG_NULL;
  365. #ifdef MNG_SUPPORT_TRACE
  366. MNG_TRACE (pData, MNG_FN_INIT_GAMMA_ONLY, MNG_LC_START);
  367. #endif
  368. if (bObject) /* use object if present ? */
  369. { /* current object ? */
  370. if ((mng_imagep)pData->pCurrentobj)
  371. pImage = (mng_imagep)pData->pCurrentobj;
  372. else /* if not; use object 0 */
  373. pImage = (mng_imagep)pData->pObjzero;
  374. }
  375. if (bRetrobj) /* retrieving from an object ? */
  376. pImage = (mng_imagep)pData->pRetrieveobj;
  377. if (pImage) /* are we using an object ? */
  378. pBuf = pImage->pImgbuf; /* then address the buffer */
  379. if ((!pBuf) || (!pBuf->bCorrected)) /* is the buffer already corrected ? */
  380. {
  381. if ((pBuf) && (pBuf->bHasSRGB)) /* get the gamma value */
  382. dGamma = 0.45455;
  383. else
  384. if ((pBuf) && (pBuf->bHasGAMA))
  385. dGamma = (mng_float)pBuf->iGamma / 100000;
  386. else
  387. if ((bGlobal) && (pData->bHasglobalSRGB))
  388. dGamma = 0.45455;
  389. else
  390. if ((bGlobal) && (pData->bHasglobalGAMA))
  391. dGamma = (mng_float)pData->iGlobalGamma / 100000;
  392. else
  393. dGamma = pData->dDfltimggamma;
  394. if (dGamma > 0) /* ignore gamma=0 */
  395. {
  396. dGamma = pData->dViewgamma / (dGamma * pData->dDisplaygamma);
  397. if (dGamma != pData->dLastgamma) /* lookup table needs to be computed ? */
  398. {
  399. mng_int32 iX;
  400. pData->aGammatab [0] = 0;
  401. for (iX = 1; iX <= 255; iX++)
  402. pData->aGammatab [iX] = (mng_uint8)(pow (iX / 255.0, dGamma) * 255 + 0.5);
  403. pData->dLastgamma = dGamma; /* keep for next time */
  404. }
  405. /* load color-correction routine */
  406. pData->fCorrectrow = (mng_fptr)mng_correct_gamma_only;
  407. }
  408. }
  409. #ifdef MNG_SUPPORT_TRACE
  410. MNG_TRACE (pData, MNG_FN_INIT_GAMMA_ONLY, MNG_LC_END);
  411. #endif
  412. return MNG_NOERROR;
  413. }
  414. #endif /* MNG_GAMMA_ONLY || MNG_FULL_CMS || MNG_APP_CMS */
  415. /* ************************************************************************** */
  416. #if defined(MNG_GAMMA_ONLY) || defined(MNG_FULL_CMS) || defined(MNG_APP_CMS)
  417. mng_retcode mng_correct_gamma_only (mng_datap pData)
  418. {
  419. mng_uint8p pWork;
  420. mng_int32 iX;
  421. #ifdef MNG_SUPPORT_TRACE
  422. MNG_TRACE (pData, MNG_FN_CORRECT_GAMMA_ONLY, MNG_LC_START);
  423. #endif
  424. pWork = pData->pRGBArow; /* address intermediate row */
  425. if (pData->bIsRGBA16) /* 16-bit intermediate row ? */
  426. {
  427. /* TODO: 16-bit precision gamma processing */
  428. /* we'll just do the high-order byte for now */
  429. /* convert all samples in the row */
  430. for (iX = 0; iX < pData->iRowsamples; iX++)
  431. { /* using the precalculated gamma lookup table */
  432. *pWork = pData->aGammatab [*pWork];
  433. *(pWork+2) = pData->aGammatab [*(pWork+2)];
  434. *(pWork+4) = pData->aGammatab [*(pWork+4)];
  435. pWork += 8;
  436. }
  437. }
  438. else
  439. { /* convert all samples in the row */
  440. for (iX = 0; iX < pData->iRowsamples; iX++)
  441. { /* using the precalculated gamma lookup table */
  442. *pWork = pData->aGammatab [*pWork];
  443. *(pWork+1) = pData->aGammatab [*(pWork+1)];
  444. *(pWork+2) = pData->aGammatab [*(pWork+2)];
  445. pWork += 4;
  446. }
  447. }
  448. #ifdef MNG_SUPPORT_TRACE
  449. MNG_TRACE (pData, MNG_FN_CORRECT_GAMMA_ONLY, MNG_LC_END);
  450. #endif
  451. return MNG_NOERROR;
  452. }
  453. #endif /* MNG_GAMMA_ONLY || MNG_FULL_CMS || MNG_APP_CMS */
  454. /* ************************************************************************** */
  455. #ifdef MNG_APP_CMS
  456. mng_retcode mng_init_app_cms (mng_datap pData,
  457. mng_bool bGlobal,
  458. mng_bool bObject,
  459. mng_bool bRetrobj)
  460. {
  461. mng_imagep pImage = MNG_NULL;
  462. mng_imagedatap pBuf = MNG_NULL;
  463. mng_bool bDone = MNG_FALSE;
  464. mng_retcode iRetcode;
  465. #ifdef MNG_SUPPORT_TRACE
  466. MNG_TRACE (pData, MNG_FN_INIT_APP_CMS, MNG_LC_START);
  467. #endif
  468. if (bObject) /* use object if present ? */
  469. { /* current object ? */
  470. if ((mng_imagep)pData->pCurrentobj)
  471. pImage = (mng_imagep)pData->pCurrentobj;
  472. else /* if not; use object 0 */
  473. pImage = (mng_imagep)pData->pObjzero;
  474. }
  475. if (bRetrobj) /* retrieving from an object ? */
  476. pImage = (mng_imagep)pData->pRetrieveobj;
  477. if (pImage) /* are we using an object ? */
  478. pBuf = pImage->pImgbuf; /* then address the buffer */
  479. if ((!pBuf) || (!pBuf->bCorrected)) /* is the buffer already corrected ? */
  480. {
  481. #ifndef MNG_SKIPCHUNK_iCCP
  482. if ( (pData->fProcessiccp) &&
  483. (((pBuf) && (pBuf->bHasICCP)) || ((bGlobal) && (pData->bHasglobalICCP))) )
  484. {
  485. mng_uint32 iProfilesize;
  486. mng_ptr pProfile;
  487. if ((pBuf) && (pBuf->bHasICCP)) /* get the right profile */
  488. {
  489. iProfilesize = pBuf->iProfilesize;
  490. pProfile = pBuf->pProfile;
  491. }
  492. else
  493. {
  494. iProfilesize = pData->iGlobalProfilesize;
  495. pProfile = pData->pGlobalProfile;
  496. }
  497. /* inform the app */
  498. if (!pData->fProcessiccp ((mng_handle)pData, iProfilesize, pProfile))
  499. MNG_ERROR (pData, MNG_APPCMSERROR);
  500. /* load color-correction routine */
  501. pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
  502. bDone = MNG_TRUE;
  503. }
  504. #endif
  505. if ( (pData->fProcesssrgb) &&
  506. (((pBuf) && (pBuf->bHasSRGB)) || ((bGlobal) && (pData->bHasglobalSRGB))) )
  507. {
  508. mng_uint8 iIntent;
  509. if ((pBuf) && (pBuf->bHasSRGB)) /* determine rendering intent */
  510. iIntent = pBuf->iRenderingintent;
  511. else
  512. iIntent = pData->iGlobalRendintent;
  513. /* inform the app */
  514. if (!pData->fProcesssrgb ((mng_handle)pData, iIntent))
  515. MNG_ERROR (pData, MNG_APPCMSERROR);
  516. /* load color-correction routine */
  517. pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
  518. bDone = MNG_TRUE;
  519. }
  520. #ifndef MNG_SKIPCHUNK_cHRM
  521. if ( (pData->fProcesschroma) &&
  522. (((pBuf) && (pBuf->bHasCHRM)) || ((bGlobal) && (pData->bHasglobalCHRM))) )
  523. {
  524. mng_uint32 iWhitepointx, iWhitepointy;
  525. mng_uint32 iPrimaryredx, iPrimaryredy;
  526. mng_uint32 iPrimarygreenx, iPrimarygreeny;
  527. mng_uint32 iPrimarybluex, iPrimarybluey;
  528. if ((pBuf) && (pBuf->bHasCHRM)) /* local cHRM ? */
  529. {
  530. iWhitepointx = pBuf->iWhitepointx;
  531. iWhitepointy = pBuf->iWhitepointy;
  532. iPrimaryredx = pBuf->iPrimaryredx;
  533. iPrimaryredy = pBuf->iPrimaryredy;
  534. iPrimarygreenx = pBuf->iPrimarygreenx;
  535. iPrimarygreeny = pBuf->iPrimarygreeny;
  536. iPrimarybluex = pBuf->iPrimarybluex;
  537. iPrimarybluey = pBuf->iPrimarybluey;
  538. }
  539. else
  540. {
  541. iWhitepointx = pData->iGlobalWhitepointx;
  542. iWhitepointy = pData->iGlobalWhitepointy;
  543. iPrimaryredx = pData->iGlobalPrimaryredx;
  544. iPrimaryredy = pData->iGlobalPrimaryredy;
  545. iPrimarygreenx = pData->iGlobalPrimarygreenx;
  546. iPrimarygreeny = pData->iGlobalPrimarygreeny;
  547. iPrimarybluex = pData->iGlobalPrimarybluex;
  548. iPrimarybluey = pData->iGlobalPrimarybluey;
  549. }
  550. /* inform the app */
  551. if (!pData->fProcesschroma ((mng_handle)pData, iWhitepointx, iWhitepointy,
  552. iPrimaryredx, iPrimaryredy,
  553. iPrimarygreenx, iPrimarygreeny,
  554. iPrimarybluex, iPrimarybluey))
  555. MNG_ERROR (pData, MNG_APPCMSERROR);
  556. /* load color-correction routine */
  557. pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
  558. bDone = MNG_TRUE;
  559. }
  560. #endif
  561. if ( (pData->fProcessgamma) &&
  562. (((pBuf) && (pBuf->bHasGAMA)) || ((bGlobal) && (pData->bHasglobalGAMA))) )
  563. {
  564. mng_uint32 iGamma;
  565. if ((pBuf) && (pBuf->bHasGAMA)) /* get the gamma value */
  566. iGamma = pBuf->iGamma;
  567. else
  568. iGamma = pData->iGlobalGamma;
  569. /* inform the app */
  570. if (!pData->fProcessgamma ((mng_handle)pData, iGamma))
  571. { /* app wants us to use internal routines ! */
  572. iRetcode = mng_init_gamma_only (pData, bGlobal, bObject, bRetrobj);
  573. if (iRetcode) /* on error bail out */
  574. return iRetcode;
  575. }
  576. else
  577. { /* load color-correction routine */
  578. pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
  579. }
  580. bDone = MNG_TRUE;
  581. }
  582. if (!bDone) /* no color-info at all ? */
  583. {
  584. /* then use default image gamma ! */
  585. if (!pData->fProcessgamma ((mng_handle)pData,
  586. (mng_uint32)((pData->dDfltimggamma * 100000) + 0.5)))
  587. { /* app wants us to use internal routines ! */
  588. iRetcode = mng_init_gamma_only (pData, bGlobal, bObject, bRetrobj);
  589. if (iRetcode) /* on error bail out */
  590. return iRetcode;
  591. }
  592. else
  593. { /* load color-correction routine */
  594. pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
  595. }
  596. }
  597. }
  598. #ifdef MNG_SUPPORT_TRACE
  599. MNG_TRACE (pData, MNG_FN_INIT_APP_CMS, MNG_LC_END);
  600. #endif
  601. return MNG_NOERROR;
  602. }
  603. #endif /* MNG_APP_CMS */
  604. /* ************************************************************************** */
  605. #ifdef MNG_APP_CMS
  606. mng_retcode mng_correct_app_cms (mng_datap pData)
  607. {
  608. #ifdef MNG_SUPPORT_TRACE
  609. MNG_TRACE (pData, MNG_FN_CORRECT_APP_CMS, MNG_LC_START);
  610. #endif
  611. if (pData->fProcessarow) /* let the app do something with our row */
  612. if (!pData->fProcessarow ((mng_handle)pData, pData->iRowsamples,
  613. pData->bIsRGBA16, pData->pRGBArow))
  614. MNG_ERROR (pData, MNG_APPCMSERROR);
  615. #ifdef MNG_SUPPORT_TRACE
  616. MNG_TRACE (pData, MNG_FN_CORRECT_APP_CMS, MNG_LC_END);
  617. #endif
  618. return MNG_NOERROR;
  619. }
  620. #endif /* MNG_APP_CMS */
  621. /* ************************************************************************** */
  622. #endif /* MNG_INCLUDE_DISPLAY_PROCS */
  623. /* ************************************************************************** */
  624. /* * end of file * */
  625. /* ************************************************************************** */