cmsintrp.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493
  1. //---------------------------------------------------------------------------------
  2. //
  3. // Little Color Management System
  4. // Copyright (c) 1998-2012 Marti Maria Saguer
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining
  7. // a copy of this software and associated documentation files (the "Software"),
  8. // to deal in the Software without restriction, including without limitation
  9. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10. // and/or sell copies of the Software, and to permit persons to whom the Software
  11. // is furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  18. // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  20. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  21. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  22. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. //
  24. //---------------------------------------------------------------------------------
  25. //
  26. #include "lcms2_internal.h"
  27. // This module incorporates several interpolation routines, for 1 to 8 channels on input and
  28. // up to 65535 channels on output. The user may change those by using the interpolation plug-in
  29. // Interpolation routines by default
  30. static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags);
  31. // This is the default factory
  32. static cmsInterpFnFactory Interpolators = DefaultInterpolatorsFactory;
  33. // Main plug-in entry
  34. cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Data)
  35. {
  36. cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data;
  37. if (Data == NULL) {
  38. Interpolators = DefaultInterpolatorsFactory;
  39. return TRUE;
  40. }
  41. // Set replacement functions
  42. Interpolators = Plugin ->InterpolatorsFactory;
  43. return TRUE;
  44. }
  45. // Set the interpolation method
  46. cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p)
  47. {
  48. // Invoke factory, possibly in the Plug-in
  49. p ->Interpolation = Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags);
  50. // If unsupported by the plug-in, go for the LittleCMS default.
  51. // If happens only if an extern plug-in is being used
  52. if (p ->Interpolation.Lerp16 == NULL)
  53. p ->Interpolation = DefaultInterpolatorsFactory(p ->nInputs, p ->nOutputs, p ->dwFlags);
  54. // Check for valid interpolator (we just check one member of the union)
  55. if (p ->Interpolation.Lerp16 == NULL) {
  56. return FALSE;
  57. }
  58. return TRUE;
  59. }
  60. // This function precalculates as many parameters as possible to speed up the interpolation.
  61. cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID,
  62. const cmsUInt32Number nSamples[],
  63. int InputChan, int OutputChan,
  64. const void *Table,
  65. cmsUInt32Number dwFlags)
  66. {
  67. cmsInterpParams* p;
  68. int i;
  69. // Check for maximum inputs
  70. if (InputChan > MAX_INPUT_DIMENSIONS) {
  71. cmsSignalError(ContextID, cmsERROR_RANGE, "Too many input channels (%d channels, max=%d)", InputChan, MAX_INPUT_DIMENSIONS);
  72. return NULL;
  73. }
  74. // Creates an empty object
  75. p = (cmsInterpParams*) _cmsMallocZero(ContextID, sizeof(cmsInterpParams));
  76. if (p == NULL) return NULL;
  77. // Keep original parameters
  78. p -> dwFlags = dwFlags;
  79. p -> nInputs = InputChan;
  80. p -> nOutputs = OutputChan;
  81. p ->Table = Table;
  82. p ->ContextID = ContextID;
  83. // Fill samples per input direction and domain (which is number of nodes minus one)
  84. for (i=0; i < InputChan; i++) {
  85. p -> nSamples[i] = nSamples[i];
  86. p -> Domain[i] = nSamples[i] - 1;
  87. }
  88. // Compute factors to apply to each component to index the grid array
  89. p -> opta[0] = p -> nOutputs;
  90. for (i=1; i < InputChan; i++)
  91. p ->opta[i] = p ->opta[i-1] * nSamples[InputChan-i];
  92. if (!_cmsSetInterpolationRoutine(p)) {
  93. cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan);
  94. _cmsFree(ContextID, p);
  95. return NULL;
  96. }
  97. // All seems ok
  98. return p;
  99. }
  100. // This one is a wrapper on the anterior, but assuming all directions have same number of nodes
  101. cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags)
  102. {
  103. int i;
  104. cmsUInt32Number Samples[MAX_INPUT_DIMENSIONS];
  105. // Fill the auxiliar array
  106. for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
  107. Samples[i] = nSamples;
  108. // Call the extended function
  109. return _cmsComputeInterpParamsEx(ContextID, Samples, InputChan, OutputChan, Table, dwFlags);
  110. }
  111. // Free all associated memory
  112. void _cmsFreeInterpParams(cmsInterpParams* p)
  113. {
  114. if (p != NULL) _cmsFree(p ->ContextID, p);
  115. }
  116. // Inline fixed point interpolation
  117. cmsINLINE cmsUInt16Number LinearInterp(cmsS15Fixed16Number a, cmsS15Fixed16Number l, cmsS15Fixed16Number h)
  118. {
  119. cmsUInt32Number dif = (cmsUInt32Number) (h - l) * a + 0x8000;
  120. dif = (dif >> 16) + l;
  121. return (cmsUInt16Number) (dif);
  122. }
  123. // Linear interpolation (Fixed-point optimized)
  124. static
  125. void LinLerp1D(register const cmsUInt16Number Value[],
  126. register cmsUInt16Number Output[],
  127. register const cmsInterpParams* p)
  128. {
  129. cmsUInt16Number y1, y0;
  130. int cell0, rest;
  131. int val3;
  132. const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
  133. // if last value...
  134. if (Value[0] == 0xffff) {
  135. Output[0] = LutTable[p -> Domain[0]];
  136. return;
  137. }
  138. val3 = p -> Domain[0] * Value[0];
  139. val3 = _cmsToFixedDomain(val3); // To fixed 15.16
  140. cell0 = FIXED_TO_INT(val3); // Cell is 16 MSB bits
  141. rest = FIXED_REST_TO_INT(val3); // Rest is 16 LSB bits
  142. y0 = LutTable[cell0];
  143. y1 = LutTable[cell0+1];
  144. Output[0] = LinearInterp(rest, y0, y1);
  145. }
  146. // Floating-point version of 1D interpolation
  147. static
  148. void LinLerp1Dfloat(const cmsFloat32Number Value[],
  149. cmsFloat32Number Output[],
  150. const cmsInterpParams* p)
  151. {
  152. cmsFloat32Number y1, y0;
  153. cmsFloat32Number val2, rest;
  154. int cell0, cell1;
  155. const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
  156. // if last value...
  157. if (Value[0] == 1.0) {
  158. Output[0] = LutTable[p -> Domain[0]];
  159. return;
  160. }
  161. val2 = p -> Domain[0] * Value[0];
  162. cell0 = (int) floor(val2);
  163. cell1 = (int) ceil(val2);
  164. // Rest is 16 LSB bits
  165. rest = val2 - cell0;
  166. y0 = LutTable[cell0] ;
  167. y1 = LutTable[cell1] ;
  168. Output[0] = y0 + (y1 - y0) * rest;
  169. }
  170. // Eval gray LUT having only one input channel
  171. static
  172. void Eval1Input(register const cmsUInt16Number Input[],
  173. register cmsUInt16Number Output[],
  174. register const cmsInterpParams* p16)
  175. {
  176. cmsS15Fixed16Number fk;
  177. cmsS15Fixed16Number k0, k1, rk, K0, K1;
  178. int v;
  179. cmsUInt32Number OutChan;
  180. const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
  181. v = Input[0] * p16 -> Domain[0];
  182. fk = _cmsToFixedDomain(v);
  183. k0 = FIXED_TO_INT(fk);
  184. rk = (cmsUInt16Number) FIXED_REST_TO_INT(fk);
  185. k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
  186. K0 = p16 -> opta[0] * k0;
  187. K1 = p16 -> opta[0] * k1;
  188. for (OutChan=0; OutChan < p16->nOutputs; OutChan++) {
  189. Output[OutChan] = LinearInterp(rk, LutTable[K0+OutChan], LutTable[K1+OutChan]);
  190. }
  191. }
  192. // Eval gray LUT having only one input channel
  193. static
  194. void Eval1InputFloat(const cmsFloat32Number Value[],
  195. cmsFloat32Number Output[],
  196. const cmsInterpParams* p)
  197. {
  198. cmsFloat32Number y1, y0;
  199. cmsFloat32Number val2, rest;
  200. int cell0, cell1;
  201. cmsUInt32Number OutChan;
  202. const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
  203. // if last value...
  204. if (Value[0] == 1.0) {
  205. Output[0] = LutTable[p -> Domain[0]];
  206. return;
  207. }
  208. val2 = p -> Domain[0] * Value[0];
  209. cell0 = (int) floor(val2);
  210. cell1 = (int) ceil(val2);
  211. // Rest is 16 LSB bits
  212. rest = val2 - cell0;
  213. cell0 *= p -> opta[0];
  214. cell1 *= p -> opta[0];
  215. for (OutChan=0; OutChan < p->nOutputs; OutChan++) {
  216. y0 = LutTable[cell0 + OutChan] ;
  217. y1 = LutTable[cell1 + OutChan] ;
  218. Output[OutChan] = y0 + (y1 - y0) * rest;
  219. }
  220. }
  221. // Bilinear interpolation (16 bits) - cmsFloat32Number version
  222. static
  223. void BilinearInterpFloat(const cmsFloat32Number Input[],
  224. cmsFloat32Number Output[],
  225. const cmsInterpParams* p)
  226. {
  227. # define LERP(a,l,h) (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
  228. # define DENS(i,j) (LutTable[(i)+(j)+OutChan])
  229. const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
  230. cmsFloat32Number px, py;
  231. int x0, y0,
  232. X0, Y0, X1, Y1;
  233. int TotalOut, OutChan;
  234. cmsFloat32Number fx, fy,
  235. d00, d01, d10, d11,
  236. dx0, dx1,
  237. dxy;
  238. TotalOut = p -> nOutputs;
  239. px = Input[0] * p->Domain[0];
  240. py = Input[1] * p->Domain[1];
  241. x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
  242. y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
  243. X0 = p -> opta[1] * x0;
  244. X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[1]);
  245. Y0 = p -> opta[0] * y0;
  246. Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[0]);
  247. for (OutChan = 0; OutChan < TotalOut; OutChan++) {
  248. d00 = DENS(X0, Y0);
  249. d01 = DENS(X0, Y1);
  250. d10 = DENS(X1, Y0);
  251. d11 = DENS(X1, Y1);
  252. dx0 = LERP(fx, d00, d10);
  253. dx1 = LERP(fx, d01, d11);
  254. dxy = LERP(fy, dx0, dx1);
  255. Output[OutChan] = dxy;
  256. }
  257. # undef LERP
  258. # undef DENS
  259. }
  260. // Bilinear interpolation (16 bits) - optimized version
  261. static
  262. void BilinearInterp16(register const cmsUInt16Number Input[],
  263. register cmsUInt16Number Output[],
  264. register const cmsInterpParams* p)
  265. {
  266. #define DENS(i,j) (LutTable[(i)+(j)+OutChan])
  267. #define LERP(a,l,h) (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
  268. const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
  269. int OutChan, TotalOut;
  270. cmsS15Fixed16Number fx, fy;
  271. register int rx, ry;
  272. int x0, y0;
  273. register int X0, X1, Y0, Y1;
  274. int d00, d01, d10, d11,
  275. dx0, dx1,
  276. dxy;
  277. TotalOut = p -> nOutputs;
  278. fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
  279. x0 = FIXED_TO_INT(fx);
  280. rx = FIXED_REST_TO_INT(fx); // Rest in 0..1.0 domain
  281. fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
  282. y0 = FIXED_TO_INT(fy);
  283. ry = FIXED_REST_TO_INT(fy);
  284. X0 = p -> opta[1] * x0;
  285. X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[1]);
  286. Y0 = p -> opta[0] * y0;
  287. Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[0]);
  288. for (OutChan = 0; OutChan < TotalOut; OutChan++) {
  289. d00 = DENS(X0, Y0);
  290. d01 = DENS(X0, Y1);
  291. d10 = DENS(X1, Y0);
  292. d11 = DENS(X1, Y1);
  293. dx0 = LERP(rx, d00, d10);
  294. dx1 = LERP(rx, d01, d11);
  295. dxy = LERP(ry, dx0, dx1);
  296. Output[OutChan] = (cmsUInt16Number) dxy;
  297. }
  298. # undef LERP
  299. # undef DENS
  300. }
  301. // Trilinear interpolation (16 bits) - cmsFloat32Number version
  302. static
  303. void TrilinearInterpFloat(const cmsFloat32Number Input[],
  304. cmsFloat32Number Output[],
  305. const cmsInterpParams* p)
  306. {
  307. # define LERP(a,l,h) (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
  308. # define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
  309. const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
  310. cmsFloat32Number px, py, pz;
  311. int x0, y0, z0,
  312. X0, Y0, Z0, X1, Y1, Z1;
  313. int TotalOut, OutChan;
  314. cmsFloat32Number fx, fy, fz,
  315. d000, d001, d010, d011,
  316. d100, d101, d110, d111,
  317. dx00, dx01, dx10, dx11,
  318. dxy0, dxy1, dxyz;
  319. TotalOut = p -> nOutputs;
  320. // We need some clipping here
  321. px = Input[0];
  322. py = Input[1];
  323. pz = Input[2];
  324. if (px < 0) px = 0;
  325. if (px > 1) px = 1;
  326. if (py < 0) py = 0;
  327. if (py > 1) py = 1;
  328. if (pz < 0) pz = 0;
  329. if (pz > 1) pz = 1;
  330. px *= p->Domain[0];
  331. py *= p->Domain[1];
  332. pz *= p->Domain[2];
  333. x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
  334. y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
  335. z0 = (int) _cmsQuickFloor(pz); fz = pz - (cmsFloat32Number) z0;
  336. X0 = p -> opta[2] * x0;
  337. X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
  338. Y0 = p -> opta[1] * y0;
  339. Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
  340. Z0 = p -> opta[0] * z0;
  341. Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
  342. for (OutChan = 0; OutChan < TotalOut; OutChan++) {
  343. d000 = DENS(X0, Y0, Z0);
  344. d001 = DENS(X0, Y0, Z1);
  345. d010 = DENS(X0, Y1, Z0);
  346. d011 = DENS(X0, Y1, Z1);
  347. d100 = DENS(X1, Y0, Z0);
  348. d101 = DENS(X1, Y0, Z1);
  349. d110 = DENS(X1, Y1, Z0);
  350. d111 = DENS(X1, Y1, Z1);
  351. dx00 = LERP(fx, d000, d100);
  352. dx01 = LERP(fx, d001, d101);
  353. dx10 = LERP(fx, d010, d110);
  354. dx11 = LERP(fx, d011, d111);
  355. dxy0 = LERP(fy, dx00, dx10);
  356. dxy1 = LERP(fy, dx01, dx11);
  357. dxyz = LERP(fz, dxy0, dxy1);
  358. Output[OutChan] = dxyz;
  359. }
  360. # undef LERP
  361. # undef DENS
  362. }
  363. // Trilinear interpolation (16 bits) - optimized version
  364. static
  365. void TrilinearInterp16(register const cmsUInt16Number Input[],
  366. register cmsUInt16Number Output[],
  367. register const cmsInterpParams* p)
  368. {
  369. #define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
  370. #define LERP(a,l,h) (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
  371. const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
  372. int OutChan, TotalOut;
  373. cmsS15Fixed16Number fx, fy, fz;
  374. register int rx, ry, rz;
  375. int x0, y0, z0;
  376. register int X0, X1, Y0, Y1, Z0, Z1;
  377. int d000, d001, d010, d011,
  378. d100, d101, d110, d111,
  379. dx00, dx01, dx10, dx11,
  380. dxy0, dxy1, dxyz;
  381. TotalOut = p -> nOutputs;
  382. fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
  383. x0 = FIXED_TO_INT(fx);
  384. rx = FIXED_REST_TO_INT(fx); // Rest in 0..1.0 domain
  385. fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
  386. y0 = FIXED_TO_INT(fy);
  387. ry = FIXED_REST_TO_INT(fy);
  388. fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
  389. z0 = FIXED_TO_INT(fz);
  390. rz = FIXED_REST_TO_INT(fz);
  391. X0 = p -> opta[2] * x0;
  392. X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
  393. Y0 = p -> opta[1] * y0;
  394. Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
  395. Z0 = p -> opta[0] * z0;
  396. Z1 = Z0 + (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
  397. for (OutChan = 0; OutChan < TotalOut; OutChan++) {
  398. d000 = DENS(X0, Y0, Z0);
  399. d001 = DENS(X0, Y0, Z1);
  400. d010 = DENS(X0, Y1, Z0);
  401. d011 = DENS(X0, Y1, Z1);
  402. d100 = DENS(X1, Y0, Z0);
  403. d101 = DENS(X1, Y0, Z1);
  404. d110 = DENS(X1, Y1, Z0);
  405. d111 = DENS(X1, Y1, Z1);
  406. dx00 = LERP(rx, d000, d100);
  407. dx01 = LERP(rx, d001, d101);
  408. dx10 = LERP(rx, d010, d110);
  409. dx11 = LERP(rx, d011, d111);
  410. dxy0 = LERP(ry, dx00, dx10);
  411. dxy1 = LERP(ry, dx01, dx11);
  412. dxyz = LERP(rz, dxy0, dxy1);
  413. Output[OutChan] = (cmsUInt16Number) dxyz;
  414. }
  415. # undef LERP
  416. # undef DENS
  417. }
  418. // Tetrahedral interpolation, using Sakamoto algorithm.
  419. #define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
  420. static
  421. void TetrahedralInterpFloat(const cmsFloat32Number Input[],
  422. cmsFloat32Number Output[],
  423. const cmsInterpParams* p)
  424. {
  425. const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
  426. cmsFloat32Number px, py, pz;
  427. int x0, y0, z0,
  428. X0, Y0, Z0, X1, Y1, Z1;
  429. cmsFloat32Number rx, ry, rz;
  430. cmsFloat32Number c0, c1=0, c2=0, c3=0;
  431. int OutChan, TotalOut;
  432. TotalOut = p -> nOutputs;
  433. // We need some clipping here
  434. px = Input[0];
  435. py = Input[1];
  436. pz = Input[2];
  437. if (px < 0) px = 0;
  438. if (px > 1) px = 1;
  439. if (py < 0) py = 0;
  440. if (py > 1) py = 1;
  441. if (pz < 0) pz = 0;
  442. if (pz > 1) pz = 1;
  443. px *= p->Domain[0];
  444. py *= p->Domain[1];
  445. pz *= p->Domain[2];
  446. x0 = (int) _cmsQuickFloor(px); rx = (px - (cmsFloat32Number) x0);
  447. y0 = (int) _cmsQuickFloor(py); ry = (py - (cmsFloat32Number) y0);
  448. z0 = (int) _cmsQuickFloor(pz); rz = (pz - (cmsFloat32Number) z0);
  449. X0 = p -> opta[2] * x0;
  450. X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
  451. Y0 = p -> opta[1] * y0;
  452. Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
  453. Z0 = p -> opta[0] * z0;
  454. Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
  455. for (OutChan=0; OutChan < TotalOut; OutChan++) {
  456. // These are the 6 Tetrahedral
  457. c0 = DENS(X0, Y0, Z0);
  458. if (rx >= ry && ry >= rz) {
  459. c1 = DENS(X1, Y0, Z0) - c0;
  460. c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
  461. c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
  462. }
  463. else
  464. if (rx >= rz && rz >= ry) {
  465. c1 = DENS(X1, Y0, Z0) - c0;
  466. c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
  467. c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
  468. }
  469. else
  470. if (rz >= rx && rx >= ry) {
  471. c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
  472. c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
  473. c3 = DENS(X0, Y0, Z1) - c0;
  474. }
  475. else
  476. if (ry >= rx && rx >= rz) {
  477. c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
  478. c2 = DENS(X0, Y1, Z0) - c0;
  479. c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
  480. }
  481. else
  482. if (ry >= rz && rz >= rx) {
  483. c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
  484. c2 = DENS(X0, Y1, Z0) - c0;
  485. c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
  486. }
  487. else
  488. if (rz >= ry && ry >= rx) {
  489. c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
  490. c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
  491. c3 = DENS(X0, Y0, Z1) - c0;
  492. }
  493. else {
  494. c1 = c2 = c3 = 0;
  495. }
  496. Output[OutChan] = c0 + c1 * rx + c2 * ry + c3 * rz;
  497. }
  498. }
  499. #undef DENS
  500. static
  501. void TetrahedralInterp16(register const cmsUInt16Number Input[],
  502. register cmsUInt16Number Output[],
  503. register const cmsInterpParams* p)
  504. {
  505. const cmsUInt16Number* LutTable = (cmsUInt16Number*) p -> Table;
  506. cmsS15Fixed16Number fx, fy, fz;
  507. cmsS15Fixed16Number rx, ry, rz;
  508. int x0, y0, z0;
  509. cmsS15Fixed16Number c0, c1, c2, c3, Rest;
  510. cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
  511. cmsUInt32Number TotalOut = p -> nOutputs;
  512. fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
  513. fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
  514. fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
  515. x0 = FIXED_TO_INT(fx);
  516. y0 = FIXED_TO_INT(fy);
  517. z0 = FIXED_TO_INT(fz);
  518. rx = FIXED_REST_TO_INT(fx);
  519. ry = FIXED_REST_TO_INT(fy);
  520. rz = FIXED_REST_TO_INT(fz);
  521. X0 = p -> opta[2] * x0;
  522. X1 = (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
  523. Y0 = p -> opta[1] * y0;
  524. Y1 = (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
  525. Z0 = p -> opta[0] * z0;
  526. Z1 = (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
  527. LutTable = &LutTable[X0+Y0+Z0];
  528. // Output should be computed as x = ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))
  529. // which expands as: x = (Rest + ((Rest+0x7fff)/0xFFFF) + 0x8000)>>16
  530. // This can be replaced by: t = Rest+0x8001, x = (t + (t>>16))>>16
  531. // at the cost of being off by one at 7fff and 17ffe.
  532. if (rx >= ry) {
  533. if (ry >= rz) {
  534. Y1 += X1;
  535. Z1 += Y1;
  536. for (; TotalOut; TotalOut--) {
  537. c1 = LutTable[X1];
  538. c2 = LutTable[Y1];
  539. c3 = LutTable[Z1];
  540. c0 = *LutTable++;
  541. c3 -= c2;
  542. c2 -= c1;
  543. c1 -= c0;
  544. Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
  545. *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
  546. }
  547. } else if (rz >= rx) {
  548. X1 += Z1;
  549. Y1 += X1;
  550. for (; TotalOut; TotalOut--) {
  551. c1 = LutTable[X1];
  552. c2 = LutTable[Y1];
  553. c3 = LutTable[Z1];
  554. c0 = *LutTable++;
  555. c2 -= c1;
  556. c1 -= c3;
  557. c3 -= c0;
  558. Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
  559. *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
  560. }
  561. } else {
  562. Z1 += X1;
  563. Y1 += Z1;
  564. for (; TotalOut; TotalOut--) {
  565. c1 = LutTable[X1];
  566. c2 = LutTable[Y1];
  567. c3 = LutTable[Z1];
  568. c0 = *LutTable++;
  569. c2 -= c3;
  570. c3 -= c1;
  571. c1 -= c0;
  572. Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
  573. *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
  574. }
  575. }
  576. } else {
  577. if (rx >= rz) {
  578. X1 += Y1;
  579. Z1 += X1;
  580. for (; TotalOut; TotalOut--) {
  581. c1 = LutTable[X1];
  582. c2 = LutTable[Y1];
  583. c3 = LutTable[Z1];
  584. c0 = *LutTable++;
  585. c3 -= c1;
  586. c1 -= c2;
  587. c2 -= c0;
  588. Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
  589. *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
  590. }
  591. } else if (ry >= rz) {
  592. Z1 += Y1;
  593. X1 += Z1;
  594. for (; TotalOut; TotalOut--) {
  595. c1 = LutTable[X1];
  596. c2 = LutTable[Y1];
  597. c3 = LutTable[Z1];
  598. c0 = *LutTable++;
  599. c1 -= c3;
  600. c3 -= c2;
  601. c2 -= c0;
  602. Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
  603. *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
  604. }
  605. } else {
  606. Y1 += Z1;
  607. X1 += Y1;
  608. for (; TotalOut; TotalOut--) {
  609. c1 = LutTable[X1];
  610. c2 = LutTable[Y1];
  611. c3 = LutTable[Z1];
  612. c0 = *LutTable++;
  613. c1 -= c2;
  614. c2 -= c3;
  615. c3 -= c0;
  616. Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
  617. *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
  618. }
  619. }
  620. }
  621. }
  622. #define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
  623. static
  624. void Eval4Inputs(register const cmsUInt16Number Input[],
  625. register cmsUInt16Number Output[],
  626. register const cmsInterpParams* p16)
  627. {
  628. const cmsUInt16Number* LutTable;
  629. cmsS15Fixed16Number fk;
  630. cmsS15Fixed16Number k0, rk;
  631. int K0, K1;
  632. cmsS15Fixed16Number fx, fy, fz;
  633. cmsS15Fixed16Number rx, ry, rz;
  634. int x0, y0, z0;
  635. cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
  636. cmsUInt32Number i;
  637. cmsS15Fixed16Number c0, c1, c2, c3, Rest;
  638. cmsUInt32Number OutChan;
  639. cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
  640. fk = _cmsToFixedDomain((int) Input[0] * p16 -> Domain[0]);
  641. fx = _cmsToFixedDomain((int) Input[1] * p16 -> Domain[1]);
  642. fy = _cmsToFixedDomain((int) Input[2] * p16 -> Domain[2]);
  643. fz = _cmsToFixedDomain((int) Input[3] * p16 -> Domain[3]);
  644. k0 = FIXED_TO_INT(fk);
  645. x0 = FIXED_TO_INT(fx);
  646. y0 = FIXED_TO_INT(fy);
  647. z0 = FIXED_TO_INT(fz);
  648. rk = FIXED_REST_TO_INT(fk);
  649. rx = FIXED_REST_TO_INT(fx);
  650. ry = FIXED_REST_TO_INT(fy);
  651. rz = FIXED_REST_TO_INT(fz);
  652. K0 = p16 -> opta[3] * k0;
  653. K1 = K0 + (Input[0] == 0xFFFFU ? 0 : p16->opta[3]);
  654. X0 = p16 -> opta[2] * x0;
  655. X1 = X0 + (Input[1] == 0xFFFFU ? 0 : p16->opta[2]);
  656. Y0 = p16 -> opta[1] * y0;
  657. Y1 = Y0 + (Input[2] == 0xFFFFU ? 0 : p16->opta[1]);
  658. Z0 = p16 -> opta[0] * z0;
  659. Z1 = Z0 + (Input[3] == 0xFFFFU ? 0 : p16->opta[0]);
  660. LutTable = (cmsUInt16Number*) p16 -> Table;
  661. LutTable += K0;
  662. for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
  663. c0 = DENS(X0, Y0, Z0);
  664. if (rx >= ry && ry >= rz) {
  665. c1 = DENS(X1, Y0, Z0) - c0;
  666. c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
  667. c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
  668. }
  669. else
  670. if (rx >= rz && rz >= ry) {
  671. c1 = DENS(X1, Y0, Z0) - c0;
  672. c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
  673. c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
  674. }
  675. else
  676. if (rz >= rx && rx >= ry) {
  677. c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
  678. c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
  679. c3 = DENS(X0, Y0, Z1) - c0;
  680. }
  681. else
  682. if (ry >= rx && rx >= rz) {
  683. c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
  684. c2 = DENS(X0, Y1, Z0) - c0;
  685. c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
  686. }
  687. else
  688. if (ry >= rz && rz >= rx) {
  689. c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
  690. c2 = DENS(X0, Y1, Z0) - c0;
  691. c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
  692. }
  693. else
  694. if (rz >= ry && ry >= rx) {
  695. c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
  696. c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
  697. c3 = DENS(X0, Y0, Z1) - c0;
  698. }
  699. else {
  700. c1 = c2 = c3 = 0;
  701. }
  702. Rest = c1 * rx + c2 * ry + c3 * rz;
  703. Tmp1[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
  704. }
  705. LutTable = (cmsUInt16Number*) p16 -> Table;
  706. LutTable += K1;
  707. for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
  708. c0 = DENS(X0, Y0, Z0);
  709. if (rx >= ry && ry >= rz) {
  710. c1 = DENS(X1, Y0, Z0) - c0;
  711. c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
  712. c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
  713. }
  714. else
  715. if (rx >= rz && rz >= ry) {
  716. c1 = DENS(X1, Y0, Z0) - c0;
  717. c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
  718. c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
  719. }
  720. else
  721. if (rz >= rx && rx >= ry) {
  722. c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
  723. c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
  724. c3 = DENS(X0, Y0, Z1) - c0;
  725. }
  726. else
  727. if (ry >= rx && rx >= rz) {
  728. c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
  729. c2 = DENS(X0, Y1, Z0) - c0;
  730. c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
  731. }
  732. else
  733. if (ry >= rz && rz >= rx) {
  734. c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
  735. c2 = DENS(X0, Y1, Z0) - c0;
  736. c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
  737. }
  738. else
  739. if (rz >= ry && ry >= rx) {
  740. c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
  741. c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
  742. c3 = DENS(X0, Y0, Z1) - c0;
  743. }
  744. else {
  745. c1 = c2 = c3 = 0;
  746. }
  747. Rest = c1 * rx + c2 * ry + c3 * rz;
  748. Tmp2[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
  749. }
  750. for (i=0; i < p16 -> nOutputs; i++) {
  751. Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
  752. }
  753. }
  754. #undef DENS
  755. // For more that 3 inputs (i.e., CMYK)
  756. // evaluate two 3-dimensional interpolations and then linearly interpolate between them.
  757. static
  758. void Eval4InputsFloat(const cmsFloat32Number Input[],
  759. cmsFloat32Number Output[],
  760. const cmsInterpParams* p)
  761. {
  762. const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
  763. cmsFloat32Number rest;
  764. cmsFloat32Number pk;
  765. int k0, K0, K1;
  766. const cmsFloat32Number* T;
  767. cmsUInt32Number i;
  768. cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
  769. cmsInterpParams p1;
  770. pk = Input[0] * p->Domain[0];
  771. k0 = _cmsQuickFloor(pk);
  772. rest = pk - (cmsFloat32Number) k0;
  773. K0 = p -> opta[3] * k0;
  774. K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[3]);
  775. p1 = *p;
  776. memmove(&p1.Domain[0], &p ->Domain[1], 3*sizeof(cmsUInt32Number));
  777. T = LutTable + K0;
  778. p1.Table = T;
  779. TetrahedralInterpFloat(Input + 1, Tmp1, &p1);
  780. T = LutTable + K1;
  781. p1.Table = T;
  782. TetrahedralInterpFloat(Input + 1, Tmp2, &p1);
  783. for (i=0; i < p -> nOutputs; i++)
  784. {
  785. cmsFloat32Number y0 = Tmp1[i];
  786. cmsFloat32Number y1 = Tmp2[i];
  787. Output[i] = y0 + (y1 - y0) * rest;
  788. }
  789. }
  790. static
  791. void Eval5Inputs(register const cmsUInt16Number Input[],
  792. register cmsUInt16Number Output[],
  793. register const cmsInterpParams* p16)
  794. {
  795. const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
  796. cmsS15Fixed16Number fk;
  797. cmsS15Fixed16Number k0, rk;
  798. int K0, K1;
  799. const cmsUInt16Number* T;
  800. cmsUInt32Number i;
  801. cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
  802. cmsInterpParams p1;
  803. fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
  804. k0 = FIXED_TO_INT(fk);
  805. rk = FIXED_REST_TO_INT(fk);
  806. K0 = p16 -> opta[4] * k0;
  807. K1 = p16 -> opta[4] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
  808. p1 = *p16;
  809. memmove(&p1.Domain[0], &p16 ->Domain[1], 4*sizeof(cmsUInt32Number));
  810. T = LutTable + K0;
  811. p1.Table = T;
  812. Eval4Inputs(Input + 1, Tmp1, &p1);
  813. T = LutTable + K1;
  814. p1.Table = T;
  815. Eval4Inputs(Input + 1, Tmp2, &p1);
  816. for (i=0; i < p16 -> nOutputs; i++) {
  817. Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
  818. }
  819. }
  820. static
  821. void Eval5InputsFloat(const cmsFloat32Number Input[],
  822. cmsFloat32Number Output[],
  823. const cmsInterpParams* p)
  824. {
  825. const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
  826. cmsFloat32Number rest;
  827. cmsFloat32Number pk;
  828. int k0, K0, K1;
  829. const cmsFloat32Number* T;
  830. cmsUInt32Number i;
  831. cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
  832. cmsInterpParams p1;
  833. pk = Input[0] * p->Domain[0];
  834. k0 = _cmsQuickFloor(pk);
  835. rest = pk - (cmsFloat32Number) k0;
  836. K0 = p -> opta[4] * k0;
  837. K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[4]);
  838. p1 = *p;
  839. memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number));
  840. T = LutTable + K0;
  841. p1.Table = T;
  842. Eval4InputsFloat(Input + 1, Tmp1, &p1);
  843. T = LutTable + K1;
  844. p1.Table = T;
  845. Eval4InputsFloat(Input + 1, Tmp2, &p1);
  846. for (i=0; i < p -> nOutputs; i++) {
  847. cmsFloat32Number y0 = Tmp1[i];
  848. cmsFloat32Number y1 = Tmp2[i];
  849. Output[i] = y0 + (y1 - y0) * rest;
  850. }
  851. }
  852. static
  853. void Eval6Inputs(register const cmsUInt16Number Input[],
  854. register cmsUInt16Number Output[],
  855. register const cmsInterpParams* p16)
  856. {
  857. const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
  858. cmsS15Fixed16Number fk;
  859. cmsS15Fixed16Number k0, rk;
  860. int K0, K1;
  861. const cmsUInt16Number* T;
  862. cmsUInt32Number i;
  863. cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
  864. cmsInterpParams p1;
  865. fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
  866. k0 = FIXED_TO_INT(fk);
  867. rk = FIXED_REST_TO_INT(fk);
  868. K0 = p16 -> opta[5] * k0;
  869. K1 = p16 -> opta[5] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
  870. p1 = *p16;
  871. memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number));
  872. T = LutTable + K0;
  873. p1.Table = T;
  874. Eval5Inputs(Input + 1, Tmp1, &p1);
  875. T = LutTable + K1;
  876. p1.Table = T;
  877. Eval5Inputs(Input + 1, Tmp2, &p1);
  878. for (i=0; i < p16 -> nOutputs; i++) {
  879. Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
  880. }
  881. }
  882. static
  883. void Eval6InputsFloat(const cmsFloat32Number Input[],
  884. cmsFloat32Number Output[],
  885. const cmsInterpParams* p)
  886. {
  887. const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
  888. cmsFloat32Number rest;
  889. cmsFloat32Number pk;
  890. int k0, K0, K1;
  891. const cmsFloat32Number* T;
  892. cmsUInt32Number i;
  893. cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
  894. cmsInterpParams p1;
  895. pk = Input[0] * p->Domain[0];
  896. k0 = _cmsQuickFloor(pk);
  897. rest = pk - (cmsFloat32Number) k0;
  898. K0 = p -> opta[5] * k0;
  899. K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[5]);
  900. p1 = *p;
  901. memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number));
  902. T = LutTable + K0;
  903. p1.Table = T;
  904. Eval5InputsFloat(Input + 1, Tmp1, &p1);
  905. T = LutTable + K1;
  906. p1.Table = T;
  907. Eval5InputsFloat(Input + 1, Tmp2, &p1);
  908. for (i=0; i < p -> nOutputs; i++) {
  909. cmsFloat32Number y0 = Tmp1[i];
  910. cmsFloat32Number y1 = Tmp2[i];
  911. Output[i] = y0 + (y1 - y0) * rest;
  912. }
  913. }
  914. static
  915. void Eval7Inputs(register const cmsUInt16Number Input[],
  916. register cmsUInt16Number Output[],
  917. register const cmsInterpParams* p16)
  918. {
  919. const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
  920. cmsS15Fixed16Number fk;
  921. cmsS15Fixed16Number k0, rk;
  922. int K0, K1;
  923. const cmsUInt16Number* T;
  924. cmsUInt32Number i;
  925. cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
  926. cmsInterpParams p1;
  927. fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
  928. k0 = FIXED_TO_INT(fk);
  929. rk = FIXED_REST_TO_INT(fk);
  930. K0 = p16 -> opta[6] * k0;
  931. K1 = p16 -> opta[6] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
  932. p1 = *p16;
  933. memmove(&p1.Domain[0], &p16 ->Domain[1], 6*sizeof(cmsUInt32Number));
  934. T = LutTable + K0;
  935. p1.Table = T;
  936. Eval6Inputs(Input + 1, Tmp1, &p1);
  937. T = LutTable + K1;
  938. p1.Table = T;
  939. Eval6Inputs(Input + 1, Tmp2, &p1);
  940. for (i=0; i < p16 -> nOutputs; i++) {
  941. Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
  942. }
  943. }
  944. static
  945. void Eval7InputsFloat(const cmsFloat32Number Input[],
  946. cmsFloat32Number Output[],
  947. const cmsInterpParams* p)
  948. {
  949. const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
  950. cmsFloat32Number rest;
  951. cmsFloat32Number pk;
  952. int k0, K0, K1;
  953. const cmsFloat32Number* T;
  954. cmsUInt32Number i;
  955. cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
  956. cmsInterpParams p1;
  957. pk = Input[0] * p->Domain[0];
  958. k0 = _cmsQuickFloor(pk);
  959. rest = pk - (cmsFloat32Number) k0;
  960. K0 = p -> opta[6] * k0;
  961. K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[6]);
  962. p1 = *p;
  963. memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number));
  964. T = LutTable + K0;
  965. p1.Table = T;
  966. Eval6InputsFloat(Input + 1, Tmp1, &p1);
  967. T = LutTable + K1;
  968. p1.Table = T;
  969. Eval6InputsFloat(Input + 1, Tmp2, &p1);
  970. for (i=0; i < p -> nOutputs; i++) {
  971. cmsFloat32Number y0 = Tmp1[i];
  972. cmsFloat32Number y1 = Tmp2[i];
  973. Output[i] = y0 + (y1 - y0) * rest;
  974. }
  975. }
  976. static
  977. void Eval8Inputs(register const cmsUInt16Number Input[],
  978. register cmsUInt16Number Output[],
  979. register const cmsInterpParams* p16)
  980. {
  981. const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
  982. cmsS15Fixed16Number fk;
  983. cmsS15Fixed16Number k0, rk;
  984. int K0, K1;
  985. const cmsUInt16Number* T;
  986. cmsUInt32Number i;
  987. cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
  988. cmsInterpParams p1;
  989. fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
  990. k0 = FIXED_TO_INT(fk);
  991. rk = FIXED_REST_TO_INT(fk);
  992. K0 = p16 -> opta[7] * k0;
  993. K1 = p16 -> opta[7] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
  994. p1 = *p16;
  995. memmove(&p1.Domain[0], &p16 ->Domain[1], 7*sizeof(cmsUInt32Number));
  996. T = LutTable + K0;
  997. p1.Table = T;
  998. Eval7Inputs(Input + 1, Tmp1, &p1);
  999. T = LutTable + K1;
  1000. p1.Table = T;
  1001. Eval7Inputs(Input + 1, Tmp2, &p1);
  1002. for (i=0; i < p16 -> nOutputs; i++) {
  1003. Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
  1004. }
  1005. }
  1006. static
  1007. void Eval8InputsFloat(const cmsFloat32Number Input[],
  1008. cmsFloat32Number Output[],
  1009. const cmsInterpParams* p)
  1010. {
  1011. const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
  1012. cmsFloat32Number rest;
  1013. cmsFloat32Number pk;
  1014. int k0, K0, K1;
  1015. const cmsFloat32Number* T;
  1016. cmsUInt32Number i;
  1017. cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
  1018. cmsInterpParams p1;
  1019. pk = Input[0] * p->Domain[0];
  1020. k0 = _cmsQuickFloor(pk);
  1021. rest = pk - (cmsFloat32Number) k0;
  1022. K0 = p -> opta[7] * k0;
  1023. K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[7]);
  1024. p1 = *p;
  1025. memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number));
  1026. T = LutTable + K0;
  1027. p1.Table = T;
  1028. Eval7InputsFloat(Input + 1, Tmp1, &p1);
  1029. T = LutTable + K1;
  1030. p1.Table = T;
  1031. Eval7InputsFloat(Input + 1, Tmp2, &p1);
  1032. for (i=0; i < p -> nOutputs; i++) {
  1033. cmsFloat32Number y0 = Tmp1[i];
  1034. cmsFloat32Number y1 = Tmp2[i];
  1035. Output[i] = y0 + (y1 - y0) * rest;
  1036. }
  1037. }
  1038. // The default factory
  1039. static
  1040. cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags)
  1041. {
  1042. cmsInterpFunction Interpolation;
  1043. cmsBool IsFloat = (dwFlags & CMS_LERP_FLAGS_FLOAT);
  1044. cmsBool IsTrilinear = (dwFlags & CMS_LERP_FLAGS_TRILINEAR);
  1045. memset(&Interpolation, 0, sizeof(Interpolation));
  1046. // Safety check
  1047. if (nInputChannels >= 4 && nOutputChannels >= MAX_STAGE_CHANNELS)
  1048. return Interpolation;
  1049. switch (nInputChannels) {
  1050. case 1: // Gray LUT / linear
  1051. if (nOutputChannels == 1) {
  1052. if (IsFloat)
  1053. Interpolation.LerpFloat = LinLerp1Dfloat;
  1054. else
  1055. Interpolation.Lerp16 = LinLerp1D;
  1056. }
  1057. else {
  1058. if (IsFloat)
  1059. Interpolation.LerpFloat = Eval1InputFloat;
  1060. else
  1061. Interpolation.Lerp16 = Eval1Input;
  1062. }
  1063. break;
  1064. case 2: // Duotone
  1065. if (IsFloat)
  1066. Interpolation.LerpFloat = BilinearInterpFloat;
  1067. else
  1068. Interpolation.Lerp16 = BilinearInterp16;
  1069. break;
  1070. case 3: // RGB et al
  1071. if (IsTrilinear) {
  1072. if (IsFloat)
  1073. Interpolation.LerpFloat = TrilinearInterpFloat;
  1074. else
  1075. Interpolation.Lerp16 = TrilinearInterp16;
  1076. }
  1077. else {
  1078. if (IsFloat)
  1079. Interpolation.LerpFloat = TetrahedralInterpFloat;
  1080. else {
  1081. Interpolation.Lerp16 = TetrahedralInterp16;
  1082. }
  1083. }
  1084. break;
  1085. case 4: // CMYK lut
  1086. if (IsFloat)
  1087. Interpolation.LerpFloat = Eval4InputsFloat;
  1088. else
  1089. Interpolation.Lerp16 = Eval4Inputs;
  1090. break;
  1091. case 5: // 5 Inks
  1092. if (IsFloat)
  1093. Interpolation.LerpFloat = Eval5InputsFloat;
  1094. else
  1095. Interpolation.Lerp16 = Eval5Inputs;
  1096. break;
  1097. case 6: // 6 Inks
  1098. if (IsFloat)
  1099. Interpolation.LerpFloat = Eval6InputsFloat;
  1100. else
  1101. Interpolation.Lerp16 = Eval6Inputs;
  1102. break;
  1103. case 7: // 7 inks
  1104. if (IsFloat)
  1105. Interpolation.LerpFloat = Eval7InputsFloat;
  1106. else
  1107. Interpolation.Lerp16 = Eval7Inputs;
  1108. break;
  1109. case 8: // 8 inks
  1110. if (IsFloat)
  1111. Interpolation.LerpFloat = Eval8InputsFloat;
  1112. else
  1113. Interpolation.Lerp16 = Eval8Inputs;
  1114. break;
  1115. break;
  1116. default:
  1117. Interpolation.Lerp16 = NULL;
  1118. }
  1119. return Interpolation;
  1120. }