Color.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. static Color ColorArray[]=
  6. {
  7. RED , GREEN, BLUE ,
  8. YELLOW, CYAN , PURPLE,
  9. ORANGE, TURQ , BROWN ,
  10. };
  11. /******************************************************************************/
  12. Color::Color(C Vec &color)
  13. {
  14. r=FltToByte(color.x);
  15. g=FltToByte(color.y);
  16. b=FltToByte(color.z);
  17. a=255;
  18. }
  19. Color::Color(C Vec4 &color)
  20. {
  21. r=FltToByte(color.x);
  22. g=FltToByte(color.y);
  23. b=FltToByte(color.z);
  24. a=FltToByte(color.w);
  25. }
  26. Color::Color(C VecB &color)
  27. {
  28. r=color.x;
  29. g=color.y;
  30. b=color.z;
  31. a=255;
  32. }
  33. Color::Color(C VecB4 &color)
  34. {
  35. #if 0
  36. r=color.x;
  37. g=color.y;
  38. b=color.z;
  39. a=color.w;
  40. #else
  41. u=color.u;
  42. #endif
  43. }
  44. Vec Color::asVec()C
  45. {
  46. return Vec(r/255.0f,
  47. g/255.0f,
  48. b/255.0f);
  49. }
  50. Vec4 Color::asVec4()C
  51. {
  52. return Vec4(r/255.0f,
  53. g/255.0f,
  54. b/255.0f,
  55. a/255.0f);
  56. }
  57. StrO Color::asText()C {StrO s; s.reserve(18); s+=r; s+=", "; s+=g; s+=", "; s+=b; s+=", "; s+=a; return s;} // 18 because of 4x"255" + 3x", " = 4*3 + 3*2 = 12 + 6 = 18
  58. StrO Color::asHex ()C {ASSERT(SIZE(T)==4); return TextHexMem(this, SIZE(T), false);}
  59. Bool Color::fromHex(C Str &t)
  60. {
  61. ASSERT(SIZE(T)==4); return TextHexMem(t, this, SIZE(T));
  62. }
  63. /******************************************************************************/
  64. Color ColorI(Int i) {return ColorArray[Mod(i, Elms(ColorArray))];}
  65. /******************************************************************************/
  66. Color ColorInverse(C Color &color)
  67. {
  68. return Color(255-color.r, 255-color.g, 255-color.b, color.a);
  69. }
  70. Color ColorBrightness(Flt brightness)
  71. {
  72. Byte b=FltToByte(brightness);
  73. return Color(b, b, b);
  74. }
  75. Color ColorBrightness(C Color &color, Flt brightness)
  76. {
  77. return Color(Mid(RoundPos(color.r*brightness), 0, 255),
  78. Mid(RoundPos(color.g*brightness), 0, 255),
  79. Mid(RoundPos(color.b*brightness), 0, 255), color.a);
  80. }
  81. Color ColorBrightnessB(C Color &color, Byte brightness)
  82. {
  83. return Color((color.r*brightness+128)/255,
  84. (color.g*brightness+128)/255,
  85. (color.b*brightness+128)/255, color.a);
  86. }
  87. Color ColorAlpha(Flt alpha)
  88. {
  89. return Color(255, 255, 255, FltToByte(alpha));
  90. }
  91. Color ColorAlpha(C Color &color, Flt alpha)
  92. {
  93. return Color(color.r, color.g, color.b, Mid(RoundPos(color.a*alpha), 0, 255));
  94. }
  95. Color ColorBA(Flt brightness, Flt alpha)
  96. {
  97. Byte b=FltToByte(brightness);
  98. return Color(b, b, b, FltToByte(alpha ));
  99. }
  100. Color ColorBA(C Color &color, Flt brightness, Flt alpha)
  101. {
  102. return Color(Mid(RoundPos(color.r*brightness), 0, 255),
  103. Mid(RoundPos(color.g*brightness), 0, 255),
  104. Mid(RoundPos(color.b*brightness), 0, 255),
  105. Mid(RoundPos(color.a*alpha ), 0, 255));
  106. }
  107. Color ColorMul(Flt mul)
  108. {
  109. Byte x=FltToByte(mul);
  110. return Color(x, x, x, x);
  111. }
  112. Color ColorMul(C Color &color, Flt mul)
  113. {
  114. return Color(Mid(RoundPos(color.r*mul), 0, 255),
  115. Mid(RoundPos(color.g*mul), 0, 255),
  116. Mid(RoundPos(color.b*mul), 0, 255),
  117. Mid(RoundPos(color.a*mul), 0, 255));
  118. }
  119. Color ColorMul(C Color &c0, C Color &c1)
  120. {
  121. return Color((c0.r*c1.r+128)/255,
  122. (c0.g*c1.g+128)/255,
  123. (c0.b*c1.b+128)/255,
  124. (c0.a*c1.a+128)/255);
  125. }
  126. Color ColorMul(C Color &c0, C Color &c1, C Color &c2)
  127. {
  128. const UInt div=255*255, div_2=div/2;
  129. return Color((c0.r*c1.r*c2.r+div_2)/div,
  130. (c0.g*c1.g*c2.g+div_2)/div,
  131. (c0.b*c1.b*c2.b+div_2)/div,
  132. (c0.a*c1.a*c2.a+div_2)/div);
  133. }
  134. Color ColorAdd(C Color &c0, C Color &c1)
  135. {
  136. return Color(Mid(c0.r+c1.r, 0, 255),
  137. Mid(c0.g+c1.g, 0, 255),
  138. Mid(c0.b+c1.b, 0, 255),
  139. Mid(c0.a+c1.a, 0, 255));
  140. }
  141. Color ColorAdd(C Color &c0, C Color &c1, C Color &c2)
  142. {
  143. return Color(Mid(c0.r+c1.r+c2.r, 0, 255),
  144. Mid(c0.g+c1.g+c2.g, 0, 255),
  145. Mid(c0.b+c1.b+c2.b, 0, 255),
  146. Mid(c0.a+c1.a+c2.a, 0, 255));
  147. }
  148. Color ColorMulZeroAlpha(C Color &color, Flt mul)
  149. {
  150. return Color(Mid(RoundPos(color.r*mul), 0, 255),
  151. Mid(RoundPos(color.g*mul), 0, 255),
  152. Mid(RoundPos(color.b*mul), 0, 255), 0);
  153. }
  154. Color ColorMulZeroAlpha(C Color &c0, C Color &c1)
  155. {
  156. return Color((c0.r*c1.r+128)/255,
  157. (c0.g*c1.g+128)/255,
  158. (c0.b*c1.b+128)/255, 0);
  159. }
  160. /******************************************************************************/
  161. Color Avg(C Color &c0, C Color &c1)
  162. {
  163. return Color((c0.r+c1.r+1)>>1,
  164. (c0.g+c1.g+1)>>1,
  165. (c0.b+c1.b+1)>>1,
  166. (c0.a+c1.a+1)>>1);
  167. }
  168. Color Avg(C Color &c0, C Color &c1, C Color &c2)
  169. {
  170. return Color((c0.r+c1.r+c2.r+1)/3,
  171. (c0.g+c1.g+c2.g+1)/3,
  172. (c0.b+c1.b+c2.b+1)/3,
  173. (c0.a+c1.a+c2.a+1)/3);
  174. }
  175. Color Avg(C Color &c0, C Color &c1, C Color &c2, C Color &c3)
  176. {
  177. return Color((c0.r+c1.r+c2.r+c3.r+2)>>2,
  178. (c0.g+c1.g+c2.g+c3.g+2)>>2,
  179. (c0.b+c1.b+c2.b+c3.b+2)>>2,
  180. (c0.a+c1.a+c2.a+c3.a+2)>>2);
  181. }
  182. /******************************************************************************/
  183. Color Lerp(C Color &c0, C Color &c1, Flt step)
  184. {
  185. Flt step1=1-step;
  186. return Color(Mid(RoundPos(c0.r*step1 + c1.r*step), 0, 255),
  187. Mid(RoundPos(c0.g*step1 + c1.g*step), 0, 255),
  188. Mid(RoundPos(c0.b*step1 + c1.b*step), 0, 255),
  189. Mid(RoundPos(c0.a*step1 + c1.a*step), 0, 255));
  190. }
  191. Color Lerp(C Color &c0, C Color &c1, C Color &c2, C Vec &blend)
  192. {
  193. return Color(Mid(RoundPos(c0.r*blend.x + c1.r*blend.y + c2.r*blend.z), 0, 255),
  194. Mid(RoundPos(c0.g*blend.x + c1.g*blend.y + c2.g*blend.z), 0, 255),
  195. Mid(RoundPos(c0.b*blend.x + c1.b*blend.y + c2.b*blend.z), 0, 255),
  196. Mid(RoundPos(c0.a*blend.x + c1.a*blend.y + c2.a*blend.z), 0, 255));
  197. }
  198. /******************************************************************************/
  199. Color ColorHue(Flt hue)
  200. {
  201. hue=6*Frac(hue);
  202. Byte x=RoundU(Frac(hue)*255);
  203. if(hue<1)return Color(255 , x, 0);
  204. if(hue<2)return Color(255-x, 255 , 0);
  205. if(hue<3)return Color( 0, 255 , x);
  206. if(hue<4)return Color( 0, 255-x, 255 );
  207. if(hue<5)return Color( x, 0, 255 );
  208. return Color( 255, 0, 255-x);
  209. }
  210. Color ColorHue(C Color &color, Flt hue)
  211. {
  212. Vec hsb=RgbToHsb(color.asVec());
  213. Color c=ColorHSB(hsb.x+hue, hsb.y, hsb.z); c.a=color.a;
  214. return c;
  215. }
  216. Vec ColorHue(C Vec &color, Flt hue)
  217. {
  218. Vec hsb=RgbToHsb(color); hsb.x+=hue; return HsbToRgb(hsb);
  219. }
  220. Color ColorHSB(Flt h, Flt s, Flt b)
  221. {
  222. SAT(s);
  223. SAT(b)*=255;
  224. h=6*Frac(h);
  225. Flt f= Frac(h);
  226. Byte v=RoundU(b),
  227. p=RoundU(b*(1-s)),
  228. q=RoundU(b*(1-s*f)),
  229. t=RoundU(b*(1-s*(1-f)));
  230. if(h<1)return Color(v, t, p);
  231. if(h<2)return Color(q, v, p);
  232. if(h<3)return Color(p, v, t);
  233. if(h<4)return Color(p, q, v);
  234. if(h<5)return Color(t, p, v);
  235. return Color(v, p, q);
  236. }
  237. Vec RgbToHsb(C Vec &rgb)
  238. {
  239. Flt max=rgb.max(),
  240. min=rgb.min(),
  241. d =max-min;
  242. Vec O;
  243. if(d <= 0)O.x=0;else
  244. if(rgb.x>=max)
  245. {
  246. if(rgb.y>=rgb.z)O.x=(rgb.y-rgb.z)/d;
  247. else O.x=(rgb.y-rgb.z)/d+6;
  248. }else
  249. if(rgb.y>=max)O.x=(rgb.z-rgb.x)/d+2;
  250. else O.x=(rgb.x-rgb.y)/d+4;
  251. O.x/=6;
  252. O.y =(max ? 1-min/max : 1);
  253. O.z = max;
  254. return O;
  255. }
  256. Vec HsbToRgb(C Vec &hsb)
  257. {
  258. Flt h=Frac(hsb.x)*6,
  259. s=Sat (hsb.y),
  260. f=Frac(h),
  261. v=hsb.z,
  262. p=hsb.z*(1-s ),
  263. q=hsb.z*(1-s*( f)),
  264. t=hsb.z*(1-s*(1-f));
  265. if(h<1)return Vec(v, t, p);
  266. if(h<2)return Vec(q, v, p);
  267. if(h<3)return Vec(p, v, t);
  268. if(h<4)return Vec(p, q, v);
  269. if(h<5)return Vec(t, p, v);
  270. return Vec(v, p, q);
  271. }
  272. /******************************************************************************/
  273. Vec RgbToYuv(C Vec &rgb)
  274. {
  275. return Vec( 66/256.0f*rgb.x + 129/256.0f*rgb.y + 25/256.0f*rgb.z + 16/256.0f,
  276. -38/256.0f*rgb.x - 74/256.0f*rgb.y + 112/256.0f*rgb.z + 128/256.0f,
  277. 112/256.0f*rgb.x - 94/256.0f*rgb.y - 18/256.0f*rgb.z + 128/256.0f);
  278. }
  279. Vec YuvToRgb(C Vec &yuv)
  280. {
  281. Vec YUV(yuv.x - 16/256.0f,
  282. yuv.y - 128/256.0f,
  283. yuv.z - 128/256.0f);
  284. return Vec(298/256.0f * YUV.x + 409/256.0f * YUV.z,
  285. 298/256.0f * YUV.x - 100/256.0f * YUV.y - 208/256.0f * YUV.z,
  286. 298/256.0f * YUV.x + 516/256.0f * YUV.y );
  287. }
  288. /******************************************************************************/
  289. Int ColorDiffSum(C Color &x, C Color &y)
  290. {
  291. return Abs(x.r - y.r)
  292. +Abs(x.g - y.g)
  293. +Abs(x.b - y.b)
  294. +Abs(x.a - y.a);
  295. }
  296. Int ColorDiffMax(C Color &x, C Color &y)
  297. {
  298. return Max(Abs(x.r - y.r),
  299. Abs(x.g - y.g),
  300. Abs(x.b - y.b),
  301. Abs(x.a - y.a));
  302. }
  303. Flt ColorDiffMax(C Vec &x, C Vec &y)
  304. {
  305. return Max(Abs(x.x - y.x),
  306. Abs(x.y - y.y),
  307. Abs(x.z - y.z));
  308. }
  309. /******************************************************************************/
  310. Color Blend(C Color &base, C Color &color)
  311. {
  312. Color out;
  313. #if 1 // faster Int version
  314. UInt base_w=(255-color.a)*base.a, // "1-color.w" because of standard 'Lerp' (to make base insignificant if new color is fully opaque and covers the base), mul by 'base.w' because if the 'base' is mostly transparent, then we want to make it even more insignificant - for example transparent red 'base' (1, 0, 0, 0) blended with half transparent black 'color' (0, 0, 0, 0.5) would normally blend into (0.5, 0, 0, 0.5)
  315. color_w= color.a *255 ; // 'color.w' because of standard 'Lerp', this shouldn't be multiplied by additional 'color.w' because if base.w is 1, and color.w is 0.5 then we would blend it by 0.25 which is not what we want, mul by 255 to match the scale of 'base_w'
  316. if(UInt sum=base_w+color_w)
  317. {
  318. base_w=(base_w*0xFFFF + sum/2)/sum;
  319. color_w=0xFFFF-base_w;
  320. out.r=(base.r*base_w + color.r*color_w + 0x8000)>>16;
  321. out.g=(base.g*base_w + color.g*color_w + 0x8000)>>16;
  322. out.b=(base.b*base_w + color.b*color_w + 0x8000)>>16;
  323. }else out.r=out.g=out.b=0;
  324. #else // slower Flt version
  325. Flt base_w=((255-color.a)*base.a)/255.0f, // "1-color.w" because of standard 'Lerp' (to make base insignificant if new color is fully opaque and covers the base), mul by 'base.w' because if the 'base' is mostly transparent, then we want to make it even more insignificant - for example transparent red 'base' (1, 0, 0, 0) blended with half transparent black 'color' (0, 0, 0, 0.5) would normally blend into (0.5, 0, 0, 0.5), divide by 255.0f to match the scale of 'color_w' which is 0..255, it will be normalized with 'sum' below
  326. color_w= color.a ; // 'color.w' because of standard 'Lerp', this shouldn't be multiplied by additional 'color.w' because if base.w is 1, and color.w is 0.5 then we would blend it by 0.25 which is not what we want
  327. if(Flt sum=base_w+color_w)
  328. {
  329. base_w/=sum; color_w=1-base_w; // faster than "color_w/=sum;"
  330. out.r=RoundU(base.r*base_w + color.r*color_w);
  331. out.g=RoundU(base.g*base_w + color.g*color_w);
  332. out.b=RoundU(base.b*base_w + color.b*color_w);
  333. }else out.r=out.g=out.b=0;
  334. #endif
  335. out.a=base.a+(color.a*(255-base.a)+128)/255;
  336. return out;
  337. }
  338. Vec4 FastBlend(C Vec4 &base, C Vec4 &color)
  339. {
  340. return Vec4(base.xyz*(1-color.w) + color.xyz* color.w ,
  341. base.w + color.w *(1-base.w));
  342. }
  343. Vec4 Blend(C Vec4 &base, C Vec4 &color)
  344. {
  345. Vec4 out;
  346. Flt base_w=(1-color.w)*base.w, // "1-color.w" because of standard 'Lerp' (to make base insignificant if new color is fully opaque and covers the base), mul by 'base.w' because if the 'base' is mostly transparent, then we want to make it even more insignificant - for example transparent red 'base' (1, 0, 0, 0) blended with half transparent black 'color' (0, 0, 0, 0.5) would normally blend into (0.5, 0, 0, 0.5)
  347. color_w= color.w ; // 'color.w' because of standard 'Lerp', this shouldn't be multiplied by additional 'color.w' because if base.w is 1, and color.w is 0.5 then we would blend it by 0.25 which is not what we want
  348. if(Flt sum=base_w+color_w)
  349. {
  350. base_w/=sum; color_w=1-base_w; // faster than "color_w/=sum;"
  351. out.xyz=base.xyz*base_w + color.xyz*color_w;
  352. }else out.xyz.zero();
  353. out.w=base.w+color.w*(1-base.w);
  354. return out;
  355. }
  356. Vec4 FastPremultipliedBlend(C Vec4 &base, C Vec4 &color)
  357. {
  358. return Vec4(base.xyz*(1-color.w) + color.xyz ,
  359. base.w + color.w*(1-base.w));
  360. }
  361. Vec4 PremultipliedBlend(C Vec4 &base, C Vec4 &color)
  362. {
  363. Vec4 out;
  364. Flt base_w=(1-color.w)*base.w, // "1-color.w" because of standard 'Lerp' (to make base insignificant if new color is fully opaque and covers the base), mul by 'base.w' because if the 'base' is mostly transparent, then we want to make it even more insignificant - for example transparent red 'base' (1, 0, 0, 0) blended with half transparent black 'color' (0, 0, 0, 0.5) would normally blend into (0.5, 0, 0, 0.5)
  365. color_w= color.w ; // 'color.w' because of standard 'Lerp', this shouldn't be multiplied by additional 'color.w' because if base.w is 1, and color.w is 0.5 then we would blend it by 0.25 which is not what we want
  366. if(Flt sum=base_w+color_w)
  367. {
  368. base_w/=sum; color_w=1-base_w; // faster than "color_w/=sum;"
  369. out.xyz=base.xyz*base_w + color.xyz;
  370. }else out.xyz.zero();
  371. out.w=base.w+color.w*(1-base.w);
  372. return out;
  373. }
  374. Vec4 AdditiveBlend(C Vec4 &base, C Vec4 &color)
  375. {
  376. Vec4 out;
  377. out.xyz=base.xyz*base .w + color.xyz*color.w;
  378. out.w =base.w +color.w*(1-base.w);
  379. if(out.w)out.xyz/=out.w;
  380. return out;
  381. }
  382. /******************************************************************************/
  383. Flt SRGBToLinear(Flt s) {return (s<=0.04045f ) ? s/12.92f : Pow((s+0.055f)/1.055f, 2.4f);} // convert 0..1 srgb to 0..1 linear
  384. Flt LinearToSRGB(Flt l) {return (l<=0.0031308f) ? l*12.92f : Pow(l, 1/2.4f)*1.055f-0.055f;} // convert 0..1 linear to 0..1 srgb
  385. Vec SRGBToLinear(C Vec &s) {return Vec(SRGBToLinear(s.x), SRGBToLinear(s.y), SRGBToLinear(s.z));}
  386. Vec LinearToSRGB(C Vec &l) {return Vec(LinearToSRGB(l.x), LinearToSRGB(l.y), LinearToSRGB(l.z));}
  387. Flt LinearLumOfLinearColor(C Vec &l) {return Dot( l , ColorLumWeight2) ;}
  388. Flt LinearLumOfSRGBColor (C Vec &s) {return Dot(SRGBToLinear(s), ColorLumWeight2) ;}
  389. Flt SRGBLumOfLinearColor(C Vec &l) {return LinearToSRGB(Dot( l , ColorLumWeight2));}
  390. Flt SRGBLumOfSRGBColor (C Vec &s) {return LinearToSRGB(Dot(SRGBToLinear(s), ColorLumWeight2));}
  391. /******************************************************************************/
  392. #if WINDOWS_OLD && DX11
  393. #include <Icm.h>
  394. #endif
  395. Str GetColorProfilePath() // get the path for current monitor color profile
  396. {
  397. #if WINDOWS_OLD && DX11
  398. if(SwapChain)
  399. {
  400. IDXGIOutput *output=null; SwapChain->GetContainingOutput(&output); if(output)
  401. {
  402. DXGI_OUTPUT_DESC desc; Bool ok=OK(output->GetDesc(&desc)); output->Release();
  403. if(ok)
  404. {
  405. DISPLAY_DEVICEW displayDevice; Zero(displayDevice); displayDevice.cb=SIZE(displayDevice);
  406. for(Int i=0; EnumDisplayDevicesW(desc.DeviceName, i, &displayDevice, 0); i++)
  407. //if(FlagAll(displayDevice.StateFlags, DISPLAY_DEVICE_ACTIVE|DISPLAY_DEVICE_ATTACHED))
  408. {
  409. wchar_t file_name[MAX_PATH];
  410. DLL mscms; if(mscms.createFile("Mscms.dll"))
  411. if(auto WcsGetDefaultColorProfile=(decltype(&::WcsGetDefaultColorProfile))mscms.getFunc("WcsGetDefaultColorProfile")) // available on Vista+
  412. //if(BOOL (WINAPI *WcsGetDefaultColorProfile)(WCS_PROFILE_MANAGEMENT_SCOPE scope, PCWSTR pDeviceName, COLORPROFILETYPE cptColorProfileType, COLORPROFILESUBTYPE cpstColorProfileSubType, DWORD dwProfileID, DWORD cbProfileName, LPWSTR pProfileName)=(decltype(WcsGetDefaultColorProfile))mscms.getFunc("WcsGetDefaultColorProfile")) // available on Vista+
  413. if(WcsGetDefaultColorProfile(WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER, displayDevice.DeviceKey, CPT_ICC, CPST_RGB_WORKING_SPACE, 0, SIZE(file_name), file_name))
  414. if(file_name[0])
  415. {
  416. if(FullPath(WChar(file_name)))return file_name;
  417. return SystemPath(SP_SYSTEM).tailSlash(true)+"spool/drivers/color/"+file_name;
  418. }
  419. break;
  420. }
  421. }
  422. }
  423. }
  424. #endif
  425. return S;
  426. }
  427. /******************************************************************************
  428. #include "../../../ThirdPartyLibs/QCMS/lib/qcms.h"
  429. Str p=GetColorProfilePath(); if(p.is())
  430. {
  431. #if 0
  432. PROFILE profile;
  433. profile.dwType =PROFILE_FILENAME;
  434. profile.pProfileData=ConstCast(p());
  435. profile.cbDataSize =(p.length()+1)*SIZE(Char);
  436. if(HPROFILE dest_profile=OpenColorProfileW(&profile, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING))
  437. {
  438. LOGCOLORSPACEA lcs; Zero(lcs);
  439. lcs.lcsSignature=LCS_SIGNATURE;
  440. lcs.lcsVersion=0x400;
  441. lcs.lcsSize=SIZE(lcs);
  442. lcs.lcsCSType=LCS_sRGB;
  443. lcs.lcsIntent=LCS_GM_GRAPHICS; // this is Relative Colorimetric, alternatively try LCS_GM_ABS_COLORIMETRIC
  444. if(HTRANSFORM transform=CreateColorTransformA(&lcs, dest_profile, null, BEST_MODE|USE_RELATIVE_COLORIMETRIC))
  445. {
  446. COLOR src, dest;
  447. REPD(y, img.h())
  448. REPD(x, img.w())
  449. {
  450. Vec4 c=img.colorF(x, y);
  451. src.rgb.red =Mid(RoundPos(c.x*65535), 0, 65535);
  452. src.rgb.green=Mid(RoundPos(c.y*65535), 0, 65535);
  453. src.rgb.blue =Mid(RoundPos(c.z*65535), 0, 65535);
  454. TranslateColors(transform, &src, 1, COLOR_RGB, &dest, COLOR_RGB);
  455. c.x=dest.rgb.red /65535.0f;
  456. c.y=dest.rgb.green/65535.0f;
  457. c.z=dest.rgb.blue /65535.0f;
  458. img.colorF(x, y, c);
  459. }
  460. DeleteColorTransform(transform);
  461. }
  462. CloseColorProfile(dest_profile);
  463. }
  464. #else
  465. if(qcms_profile *qcms_dest=qcms_profile_from_unicode_path(p))
  466. {
  467. if(qcms_profile *qcms_srgb=qcms_profile_sRGB())
  468. {
  469. if(qcms_transform *transform=qcms_transform_create(qcms_srgb, QCMS_DATA_RGB_8, qcms_dest, QCMS_DATA_RGB_8, QCMS_INTENT_RELATIVE_COLORIMETRIC))
  470. {
  471. REPD(y, img.h())
  472. REPD(x, img.w())
  473. {
  474. Color c=img.color(x, y), d;
  475. qcms_transform_data(transform, &c, &d, 1); d.a=c.a;
  476. img.color(x, y, d);
  477. }
  478. qcms_transform_release(transform);
  479. }
  480. qcms_profile_release(qcms_srgb);
  481. }
  482. qcms_profile_release(qcms_dest);
  483. }
  484. #endif
  485. }
  486. /******************************************************************************/
  487. }
  488. /******************************************************************************/