| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493 |
- //---------------------------------------------------------------------------------
- //
- // Little Color Management System
- // Copyright (c) 1998-2012 Marti Maria Saguer
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the "Software"),
- // to deal in the Software without restriction, including without limitation
- // the rights to use, copy, modify, merge, publish, distribute, sublicense,
- // and/or sell copies of the Software, and to permit persons to whom the Software
- // is furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- //---------------------------------------------------------------------------------
- //
- #include "lcms2_internal.h"
- // This module incorporates several interpolation routines, for 1 to 8 channels on input and
- // up to 65535 channels on output. The user may change those by using the interpolation plug-in
- // Interpolation routines by default
- static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags);
- // This is the default factory
- static cmsInterpFnFactory Interpolators = DefaultInterpolatorsFactory;
- // Main plug-in entry
- cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Data)
- {
- cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data;
- if (Data == NULL) {
- Interpolators = DefaultInterpolatorsFactory;
- return TRUE;
- }
- // Set replacement functions
- Interpolators = Plugin ->InterpolatorsFactory;
- return TRUE;
- }
- // Set the interpolation method
- cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p)
- {
- // Invoke factory, possibly in the Plug-in
- p ->Interpolation = Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags);
- // If unsupported by the plug-in, go for the LittleCMS default.
- // If happens only if an extern plug-in is being used
- if (p ->Interpolation.Lerp16 == NULL)
- p ->Interpolation = DefaultInterpolatorsFactory(p ->nInputs, p ->nOutputs, p ->dwFlags);
- // Check for valid interpolator (we just check one member of the union)
- if (p ->Interpolation.Lerp16 == NULL) {
- return FALSE;
- }
- return TRUE;
- }
- // This function precalculates as many parameters as possible to speed up the interpolation.
- cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID,
- const cmsUInt32Number nSamples[],
- int InputChan, int OutputChan,
- const void *Table,
- cmsUInt32Number dwFlags)
- {
- cmsInterpParams* p;
- int i;
- // Check for maximum inputs
- if (InputChan > MAX_INPUT_DIMENSIONS) {
- cmsSignalError(ContextID, cmsERROR_RANGE, "Too many input channels (%d channels, max=%d)", InputChan, MAX_INPUT_DIMENSIONS);
- return NULL;
- }
- // Creates an empty object
- p = (cmsInterpParams*) _cmsMallocZero(ContextID, sizeof(cmsInterpParams));
- if (p == NULL) return NULL;
- // Keep original parameters
- p -> dwFlags = dwFlags;
- p -> nInputs = InputChan;
- p -> nOutputs = OutputChan;
- p ->Table = Table;
- p ->ContextID = ContextID;
- // Fill samples per input direction and domain (which is number of nodes minus one)
- for (i=0; i < InputChan; i++) {
- p -> nSamples[i] = nSamples[i];
- p -> Domain[i] = nSamples[i] - 1;
- }
- // Compute factors to apply to each component to index the grid array
- p -> opta[0] = p -> nOutputs;
- for (i=1; i < InputChan; i++)
- p ->opta[i] = p ->opta[i-1] * nSamples[InputChan-i];
- if (!_cmsSetInterpolationRoutine(p)) {
- cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan);
- _cmsFree(ContextID, p);
- return NULL;
- }
- // All seems ok
- return p;
- }
- // This one is a wrapper on the anterior, but assuming all directions have same number of nodes
- cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags)
- {
- int i;
- cmsUInt32Number Samples[MAX_INPUT_DIMENSIONS];
- // Fill the auxiliar array
- for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
- Samples[i] = nSamples;
- // Call the extended function
- return _cmsComputeInterpParamsEx(ContextID, Samples, InputChan, OutputChan, Table, dwFlags);
- }
- // Free all associated memory
- void _cmsFreeInterpParams(cmsInterpParams* p)
- {
- if (p != NULL) _cmsFree(p ->ContextID, p);
- }
- // Inline fixed point interpolation
- cmsINLINE cmsUInt16Number LinearInterp(cmsS15Fixed16Number a, cmsS15Fixed16Number l, cmsS15Fixed16Number h)
- {
- cmsUInt32Number dif = (cmsUInt32Number) (h - l) * a + 0x8000;
- dif = (dif >> 16) + l;
- return (cmsUInt16Number) (dif);
- }
- // Linear interpolation (Fixed-point optimized)
- static
- void LinLerp1D(register const cmsUInt16Number Value[],
- register cmsUInt16Number Output[],
- register const cmsInterpParams* p)
- {
- cmsUInt16Number y1, y0;
- int cell0, rest;
- int val3;
- const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
- // if last value...
- if (Value[0] == 0xffff) {
- Output[0] = LutTable[p -> Domain[0]];
- return;
- }
- val3 = p -> Domain[0] * Value[0];
- val3 = _cmsToFixedDomain(val3); // To fixed 15.16
- cell0 = FIXED_TO_INT(val3); // Cell is 16 MSB bits
- rest = FIXED_REST_TO_INT(val3); // Rest is 16 LSB bits
- y0 = LutTable[cell0];
- y1 = LutTable[cell0+1];
- Output[0] = LinearInterp(rest, y0, y1);
- }
- // Floating-point version of 1D interpolation
- static
- void LinLerp1Dfloat(const cmsFloat32Number Value[],
- cmsFloat32Number Output[],
- const cmsInterpParams* p)
- {
- cmsFloat32Number y1, y0;
- cmsFloat32Number val2, rest;
- int cell0, cell1;
- const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
- // if last value...
- if (Value[0] == 1.0) {
- Output[0] = LutTable[p -> Domain[0]];
- return;
- }
- val2 = p -> Domain[0] * Value[0];
- cell0 = (int) floor(val2);
- cell1 = (int) ceil(val2);
- // Rest is 16 LSB bits
- rest = val2 - cell0;
- y0 = LutTable[cell0] ;
- y1 = LutTable[cell1] ;
- Output[0] = y0 + (y1 - y0) * rest;
- }
- // Eval gray LUT having only one input channel
- static
- void Eval1Input(register const cmsUInt16Number Input[],
- register cmsUInt16Number Output[],
- register const cmsInterpParams* p16)
- {
- cmsS15Fixed16Number fk;
- cmsS15Fixed16Number k0, k1, rk, K0, K1;
- int v;
- cmsUInt32Number OutChan;
- const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
- v = Input[0] * p16 -> Domain[0];
- fk = _cmsToFixedDomain(v);
- k0 = FIXED_TO_INT(fk);
- rk = (cmsUInt16Number) FIXED_REST_TO_INT(fk);
- k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
- K0 = p16 -> opta[0] * k0;
- K1 = p16 -> opta[0] * k1;
- for (OutChan=0; OutChan < p16->nOutputs; OutChan++) {
- Output[OutChan] = LinearInterp(rk, LutTable[K0+OutChan], LutTable[K1+OutChan]);
- }
- }
- // Eval gray LUT having only one input channel
- static
- void Eval1InputFloat(const cmsFloat32Number Value[],
- cmsFloat32Number Output[],
- const cmsInterpParams* p)
- {
- cmsFloat32Number y1, y0;
- cmsFloat32Number val2, rest;
- int cell0, cell1;
- cmsUInt32Number OutChan;
- const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
- // if last value...
- if (Value[0] == 1.0) {
- Output[0] = LutTable[p -> Domain[0]];
- return;
- }
- val2 = p -> Domain[0] * Value[0];
- cell0 = (int) floor(val2);
- cell1 = (int) ceil(val2);
- // Rest is 16 LSB bits
- rest = val2 - cell0;
- cell0 *= p -> opta[0];
- cell1 *= p -> opta[0];
- for (OutChan=0; OutChan < p->nOutputs; OutChan++) {
- y0 = LutTable[cell0 + OutChan] ;
- y1 = LutTable[cell1 + OutChan] ;
- Output[OutChan] = y0 + (y1 - y0) * rest;
- }
- }
- // Bilinear interpolation (16 bits) - cmsFloat32Number version
- static
- void BilinearInterpFloat(const cmsFloat32Number Input[],
- cmsFloat32Number Output[],
- const cmsInterpParams* p)
- {
- # define LERP(a,l,h) (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
- # define DENS(i,j) (LutTable[(i)+(j)+OutChan])
- const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
- cmsFloat32Number px, py;
- int x0, y0,
- X0, Y0, X1, Y1;
- int TotalOut, OutChan;
- cmsFloat32Number fx, fy,
- d00, d01, d10, d11,
- dx0, dx1,
- dxy;
- TotalOut = p -> nOutputs;
- px = Input[0] * p->Domain[0];
- py = Input[1] * p->Domain[1];
- x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
- y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
- X0 = p -> opta[1] * x0;
- X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[1]);
- Y0 = p -> opta[0] * y0;
- Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[0]);
- for (OutChan = 0; OutChan < TotalOut; OutChan++) {
- d00 = DENS(X0, Y0);
- d01 = DENS(X0, Y1);
- d10 = DENS(X1, Y0);
- d11 = DENS(X1, Y1);
- dx0 = LERP(fx, d00, d10);
- dx1 = LERP(fx, d01, d11);
- dxy = LERP(fy, dx0, dx1);
- Output[OutChan] = dxy;
- }
- # undef LERP
- # undef DENS
- }
- // Bilinear interpolation (16 bits) - optimized version
- static
- void BilinearInterp16(register const cmsUInt16Number Input[],
- register cmsUInt16Number Output[],
- register const cmsInterpParams* p)
- {
- #define DENS(i,j) (LutTable[(i)+(j)+OutChan])
- #define LERP(a,l,h) (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
- const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
- int OutChan, TotalOut;
- cmsS15Fixed16Number fx, fy;
- register int rx, ry;
- int x0, y0;
- register int X0, X1, Y0, Y1;
- int d00, d01, d10, d11,
- dx0, dx1,
- dxy;
- TotalOut = p -> nOutputs;
- fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
- x0 = FIXED_TO_INT(fx);
- rx = FIXED_REST_TO_INT(fx); // Rest in 0..1.0 domain
- fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
- y0 = FIXED_TO_INT(fy);
- ry = FIXED_REST_TO_INT(fy);
- X0 = p -> opta[1] * x0;
- X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[1]);
- Y0 = p -> opta[0] * y0;
- Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[0]);
- for (OutChan = 0; OutChan < TotalOut; OutChan++) {
- d00 = DENS(X0, Y0);
- d01 = DENS(X0, Y1);
- d10 = DENS(X1, Y0);
- d11 = DENS(X1, Y1);
- dx0 = LERP(rx, d00, d10);
- dx1 = LERP(rx, d01, d11);
- dxy = LERP(ry, dx0, dx1);
- Output[OutChan] = (cmsUInt16Number) dxy;
- }
- # undef LERP
- # undef DENS
- }
- // Trilinear interpolation (16 bits) - cmsFloat32Number version
- static
- void TrilinearInterpFloat(const cmsFloat32Number Input[],
- cmsFloat32Number Output[],
- const cmsInterpParams* p)
- {
- # define LERP(a,l,h) (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
- # define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
- const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
- cmsFloat32Number px, py, pz;
- int x0, y0, z0,
- X0, Y0, Z0, X1, Y1, Z1;
- int TotalOut, OutChan;
- cmsFloat32Number fx, fy, fz,
- d000, d001, d010, d011,
- d100, d101, d110, d111,
- dx00, dx01, dx10, dx11,
- dxy0, dxy1, dxyz;
- TotalOut = p -> nOutputs;
- // We need some clipping here
- px = Input[0];
- py = Input[1];
- pz = Input[2];
- if (px < 0) px = 0;
- if (px > 1) px = 1;
- if (py < 0) py = 0;
- if (py > 1) py = 1;
- if (pz < 0) pz = 0;
- if (pz > 1) pz = 1;
- px *= p->Domain[0];
- py *= p->Domain[1];
- pz *= p->Domain[2];
- x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
- y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
- z0 = (int) _cmsQuickFloor(pz); fz = pz - (cmsFloat32Number) z0;
- X0 = p -> opta[2] * x0;
- X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
- Y0 = p -> opta[1] * y0;
- Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
- Z0 = p -> opta[0] * z0;
- Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
- for (OutChan = 0; OutChan < TotalOut; OutChan++) {
- d000 = DENS(X0, Y0, Z0);
- d001 = DENS(X0, Y0, Z1);
- d010 = DENS(X0, Y1, Z0);
- d011 = DENS(X0, Y1, Z1);
- d100 = DENS(X1, Y0, Z0);
- d101 = DENS(X1, Y0, Z1);
- d110 = DENS(X1, Y1, Z0);
- d111 = DENS(X1, Y1, Z1);
- dx00 = LERP(fx, d000, d100);
- dx01 = LERP(fx, d001, d101);
- dx10 = LERP(fx, d010, d110);
- dx11 = LERP(fx, d011, d111);
- dxy0 = LERP(fy, dx00, dx10);
- dxy1 = LERP(fy, dx01, dx11);
- dxyz = LERP(fz, dxy0, dxy1);
- Output[OutChan] = dxyz;
- }
- # undef LERP
- # undef DENS
- }
- // Trilinear interpolation (16 bits) - optimized version
- static
- void TrilinearInterp16(register const cmsUInt16Number Input[],
- register cmsUInt16Number Output[],
- register const cmsInterpParams* p)
- {
- #define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
- #define LERP(a,l,h) (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
- const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
- int OutChan, TotalOut;
- cmsS15Fixed16Number fx, fy, fz;
- register int rx, ry, rz;
- int x0, y0, z0;
- register int X0, X1, Y0, Y1, Z0, Z1;
- int d000, d001, d010, d011,
- d100, d101, d110, d111,
- dx00, dx01, dx10, dx11,
- dxy0, dxy1, dxyz;
- TotalOut = p -> nOutputs;
- fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
- x0 = FIXED_TO_INT(fx);
- rx = FIXED_REST_TO_INT(fx); // Rest in 0..1.0 domain
- fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
- y0 = FIXED_TO_INT(fy);
- ry = FIXED_REST_TO_INT(fy);
- fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
- z0 = FIXED_TO_INT(fz);
- rz = FIXED_REST_TO_INT(fz);
- X0 = p -> opta[2] * x0;
- X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
- Y0 = p -> opta[1] * y0;
- Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
- Z0 = p -> opta[0] * z0;
- Z1 = Z0 + (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
- for (OutChan = 0; OutChan < TotalOut; OutChan++) {
- d000 = DENS(X0, Y0, Z0);
- d001 = DENS(X0, Y0, Z1);
- d010 = DENS(X0, Y1, Z0);
- d011 = DENS(X0, Y1, Z1);
- d100 = DENS(X1, Y0, Z0);
- d101 = DENS(X1, Y0, Z1);
- d110 = DENS(X1, Y1, Z0);
- d111 = DENS(X1, Y1, Z1);
- dx00 = LERP(rx, d000, d100);
- dx01 = LERP(rx, d001, d101);
- dx10 = LERP(rx, d010, d110);
- dx11 = LERP(rx, d011, d111);
- dxy0 = LERP(ry, dx00, dx10);
- dxy1 = LERP(ry, dx01, dx11);
- dxyz = LERP(rz, dxy0, dxy1);
- Output[OutChan] = (cmsUInt16Number) dxyz;
- }
- # undef LERP
- # undef DENS
- }
- // Tetrahedral interpolation, using Sakamoto algorithm.
- #define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
- static
- void TetrahedralInterpFloat(const cmsFloat32Number Input[],
- cmsFloat32Number Output[],
- const cmsInterpParams* p)
- {
- const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
- cmsFloat32Number px, py, pz;
- int x0, y0, z0,
- X0, Y0, Z0, X1, Y1, Z1;
- cmsFloat32Number rx, ry, rz;
- cmsFloat32Number c0, c1=0, c2=0, c3=0;
- int OutChan, TotalOut;
- TotalOut = p -> nOutputs;
- // We need some clipping here
- px = Input[0];
- py = Input[1];
- pz = Input[2];
- if (px < 0) px = 0;
- if (px > 1) px = 1;
- if (py < 0) py = 0;
- if (py > 1) py = 1;
- if (pz < 0) pz = 0;
- if (pz > 1) pz = 1;
- px *= p->Domain[0];
- py *= p->Domain[1];
- pz *= p->Domain[2];
- x0 = (int) _cmsQuickFloor(px); rx = (px - (cmsFloat32Number) x0);
- y0 = (int) _cmsQuickFloor(py); ry = (py - (cmsFloat32Number) y0);
- z0 = (int) _cmsQuickFloor(pz); rz = (pz - (cmsFloat32Number) z0);
- X0 = p -> opta[2] * x0;
- X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
- Y0 = p -> opta[1] * y0;
- Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
- Z0 = p -> opta[0] * z0;
- Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
- for (OutChan=0; OutChan < TotalOut; OutChan++) {
- // These are the 6 Tetrahedral
- c0 = DENS(X0, Y0, Z0);
- if (rx >= ry && ry >= rz) {
- c1 = DENS(X1, Y0, Z0) - c0;
- c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
- c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
- }
- else
- if (rx >= rz && rz >= ry) {
- c1 = DENS(X1, Y0, Z0) - c0;
- c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
- c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
- }
- else
- if (rz >= rx && rx >= ry) {
- c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
- c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
- c3 = DENS(X0, Y0, Z1) - c0;
- }
- else
- if (ry >= rx && rx >= rz) {
- c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
- c2 = DENS(X0, Y1, Z0) - c0;
- c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
- }
- else
- if (ry >= rz && rz >= rx) {
- c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
- c2 = DENS(X0, Y1, Z0) - c0;
- c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
- }
- else
- if (rz >= ry && ry >= rx) {
- c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
- c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
- c3 = DENS(X0, Y0, Z1) - c0;
- }
- else {
- c1 = c2 = c3 = 0;
- }
- Output[OutChan] = c0 + c1 * rx + c2 * ry + c3 * rz;
- }
- }
- #undef DENS
- static
- void TetrahedralInterp16(register const cmsUInt16Number Input[],
- register cmsUInt16Number Output[],
- register const cmsInterpParams* p)
- {
- const cmsUInt16Number* LutTable = (cmsUInt16Number*) p -> Table;
- cmsS15Fixed16Number fx, fy, fz;
- cmsS15Fixed16Number rx, ry, rz;
- int x0, y0, z0;
- cmsS15Fixed16Number c0, c1, c2, c3, Rest;
- cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
- cmsUInt32Number TotalOut = p -> nOutputs;
- fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
- fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
- fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
- x0 = FIXED_TO_INT(fx);
- y0 = FIXED_TO_INT(fy);
- z0 = FIXED_TO_INT(fz);
- rx = FIXED_REST_TO_INT(fx);
- ry = FIXED_REST_TO_INT(fy);
- rz = FIXED_REST_TO_INT(fz);
- X0 = p -> opta[2] * x0;
- X1 = (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
- Y0 = p -> opta[1] * y0;
- Y1 = (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
- Z0 = p -> opta[0] * z0;
- Z1 = (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
- LutTable = &LutTable[X0+Y0+Z0];
- // Output should be computed as x = ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))
- // which expands as: x = (Rest + ((Rest+0x7fff)/0xFFFF) + 0x8000)>>16
- // This can be replaced by: t = Rest+0x8001, x = (t + (t>>16))>>16
- // at the cost of being off by one at 7fff and 17ffe.
- if (rx >= ry) {
- if (ry >= rz) {
- Y1 += X1;
- Z1 += Y1;
- for (; TotalOut; TotalOut--) {
- c1 = LutTable[X1];
- c2 = LutTable[Y1];
- c3 = LutTable[Z1];
- c0 = *LutTable++;
- c3 -= c2;
- c2 -= c1;
- c1 -= c0;
- Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
- *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
- }
- } else if (rz >= rx) {
- X1 += Z1;
- Y1 += X1;
- for (; TotalOut; TotalOut--) {
- c1 = LutTable[X1];
- c2 = LutTable[Y1];
- c3 = LutTable[Z1];
- c0 = *LutTable++;
- c2 -= c1;
- c1 -= c3;
- c3 -= c0;
- Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
- *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
- }
- } else {
- Z1 += X1;
- Y1 += Z1;
- for (; TotalOut; TotalOut--) {
- c1 = LutTable[X1];
- c2 = LutTable[Y1];
- c3 = LutTable[Z1];
- c0 = *LutTable++;
- c2 -= c3;
- c3 -= c1;
- c1 -= c0;
- Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
- *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
- }
- }
- } else {
- if (rx >= rz) {
- X1 += Y1;
- Z1 += X1;
- for (; TotalOut; TotalOut--) {
- c1 = LutTable[X1];
- c2 = LutTable[Y1];
- c3 = LutTable[Z1];
- c0 = *LutTable++;
- c3 -= c1;
- c1 -= c2;
- c2 -= c0;
- Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
- *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
- }
- } else if (ry >= rz) {
- Z1 += Y1;
- X1 += Z1;
- for (; TotalOut; TotalOut--) {
- c1 = LutTable[X1];
- c2 = LutTable[Y1];
- c3 = LutTable[Z1];
- c0 = *LutTable++;
- c1 -= c3;
- c3 -= c2;
- c2 -= c0;
- Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
- *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
- }
- } else {
- Y1 += Z1;
- X1 += Y1;
- for (; TotalOut; TotalOut--) {
- c1 = LutTable[X1];
- c2 = LutTable[Y1];
- c3 = LutTable[Z1];
- c0 = *LutTable++;
- c1 -= c2;
- c2 -= c3;
- c3 -= c0;
- Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
- *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
- }
- }
- }
- }
- #define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
- static
- void Eval4Inputs(register const cmsUInt16Number Input[],
- register cmsUInt16Number Output[],
- register const cmsInterpParams* p16)
- {
- const cmsUInt16Number* LutTable;
- cmsS15Fixed16Number fk;
- cmsS15Fixed16Number k0, rk;
- int K0, K1;
- cmsS15Fixed16Number fx, fy, fz;
- cmsS15Fixed16Number rx, ry, rz;
- int x0, y0, z0;
- cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
- cmsUInt32Number i;
- cmsS15Fixed16Number c0, c1, c2, c3, Rest;
- cmsUInt32Number OutChan;
- cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
- fk = _cmsToFixedDomain((int) Input[0] * p16 -> Domain[0]);
- fx = _cmsToFixedDomain((int) Input[1] * p16 -> Domain[1]);
- fy = _cmsToFixedDomain((int) Input[2] * p16 -> Domain[2]);
- fz = _cmsToFixedDomain((int) Input[3] * p16 -> Domain[3]);
- k0 = FIXED_TO_INT(fk);
- x0 = FIXED_TO_INT(fx);
- y0 = FIXED_TO_INT(fy);
- z0 = FIXED_TO_INT(fz);
- rk = FIXED_REST_TO_INT(fk);
- rx = FIXED_REST_TO_INT(fx);
- ry = FIXED_REST_TO_INT(fy);
- rz = FIXED_REST_TO_INT(fz);
- K0 = p16 -> opta[3] * k0;
- K1 = K0 + (Input[0] == 0xFFFFU ? 0 : p16->opta[3]);
- X0 = p16 -> opta[2] * x0;
- X1 = X0 + (Input[1] == 0xFFFFU ? 0 : p16->opta[2]);
- Y0 = p16 -> opta[1] * y0;
- Y1 = Y0 + (Input[2] == 0xFFFFU ? 0 : p16->opta[1]);
- Z0 = p16 -> opta[0] * z0;
- Z1 = Z0 + (Input[3] == 0xFFFFU ? 0 : p16->opta[0]);
- LutTable = (cmsUInt16Number*) p16 -> Table;
- LutTable += K0;
- for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
- c0 = DENS(X0, Y0, Z0);
- if (rx >= ry && ry >= rz) {
- c1 = DENS(X1, Y0, Z0) - c0;
- c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
- c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
- }
- else
- if (rx >= rz && rz >= ry) {
- c1 = DENS(X1, Y0, Z0) - c0;
- c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
- c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
- }
- else
- if (rz >= rx && rx >= ry) {
- c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
- c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
- c3 = DENS(X0, Y0, Z1) - c0;
- }
- else
- if (ry >= rx && rx >= rz) {
- c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
- c2 = DENS(X0, Y1, Z0) - c0;
- c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
- }
- else
- if (ry >= rz && rz >= rx) {
- c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
- c2 = DENS(X0, Y1, Z0) - c0;
- c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
- }
- else
- if (rz >= ry && ry >= rx) {
- c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
- c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
- c3 = DENS(X0, Y0, Z1) - c0;
- }
- else {
- c1 = c2 = c3 = 0;
- }
- Rest = c1 * rx + c2 * ry + c3 * rz;
- Tmp1[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
- }
- LutTable = (cmsUInt16Number*) p16 -> Table;
- LutTable += K1;
- for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
- c0 = DENS(X0, Y0, Z0);
- if (rx >= ry && ry >= rz) {
- c1 = DENS(X1, Y0, Z0) - c0;
- c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
- c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
- }
- else
- if (rx >= rz && rz >= ry) {
- c1 = DENS(X1, Y0, Z0) - c0;
- c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
- c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
- }
- else
- if (rz >= rx && rx >= ry) {
- c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
- c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
- c3 = DENS(X0, Y0, Z1) - c0;
- }
- else
- if (ry >= rx && rx >= rz) {
- c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
- c2 = DENS(X0, Y1, Z0) - c0;
- c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
- }
- else
- if (ry >= rz && rz >= rx) {
- c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
- c2 = DENS(X0, Y1, Z0) - c0;
- c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
- }
- else
- if (rz >= ry && ry >= rx) {
- c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
- c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
- c3 = DENS(X0, Y0, Z1) - c0;
- }
- else {
- c1 = c2 = c3 = 0;
- }
- Rest = c1 * rx + c2 * ry + c3 * rz;
- Tmp2[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
- }
- for (i=0; i < p16 -> nOutputs; i++) {
- Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
- }
- }
- #undef DENS
- // For more that 3 inputs (i.e., CMYK)
- // evaluate two 3-dimensional interpolations and then linearly interpolate between them.
- static
- void Eval4InputsFloat(const cmsFloat32Number Input[],
- cmsFloat32Number Output[],
- const cmsInterpParams* p)
- {
- const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
- cmsFloat32Number rest;
- cmsFloat32Number pk;
- int k0, K0, K1;
- const cmsFloat32Number* T;
- cmsUInt32Number i;
- cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
- cmsInterpParams p1;
- pk = Input[0] * p->Domain[0];
- k0 = _cmsQuickFloor(pk);
- rest = pk - (cmsFloat32Number) k0;
- K0 = p -> opta[3] * k0;
- K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[3]);
- p1 = *p;
- memmove(&p1.Domain[0], &p ->Domain[1], 3*sizeof(cmsUInt32Number));
- T = LutTable + K0;
- p1.Table = T;
- TetrahedralInterpFloat(Input + 1, Tmp1, &p1);
- T = LutTable + K1;
- p1.Table = T;
- TetrahedralInterpFloat(Input + 1, Tmp2, &p1);
- for (i=0; i < p -> nOutputs; i++)
- {
- cmsFloat32Number y0 = Tmp1[i];
- cmsFloat32Number y1 = Tmp2[i];
- Output[i] = y0 + (y1 - y0) * rest;
- }
- }
- static
- void Eval5Inputs(register const cmsUInt16Number Input[],
- register cmsUInt16Number Output[],
- register const cmsInterpParams* p16)
- {
- const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
- cmsS15Fixed16Number fk;
- cmsS15Fixed16Number k0, rk;
- int K0, K1;
- const cmsUInt16Number* T;
- cmsUInt32Number i;
- cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
- cmsInterpParams p1;
- fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
- k0 = FIXED_TO_INT(fk);
- rk = FIXED_REST_TO_INT(fk);
- K0 = p16 -> opta[4] * k0;
- K1 = p16 -> opta[4] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
- p1 = *p16;
- memmove(&p1.Domain[0], &p16 ->Domain[1], 4*sizeof(cmsUInt32Number));
- T = LutTable + K0;
- p1.Table = T;
- Eval4Inputs(Input + 1, Tmp1, &p1);
- T = LutTable + K1;
- p1.Table = T;
- Eval4Inputs(Input + 1, Tmp2, &p1);
- for (i=0; i < p16 -> nOutputs; i++) {
- Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
- }
- }
- static
- void Eval5InputsFloat(const cmsFloat32Number Input[],
- cmsFloat32Number Output[],
- const cmsInterpParams* p)
- {
- const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
- cmsFloat32Number rest;
- cmsFloat32Number pk;
- int k0, K0, K1;
- const cmsFloat32Number* T;
- cmsUInt32Number i;
- cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
- cmsInterpParams p1;
- pk = Input[0] * p->Domain[0];
- k0 = _cmsQuickFloor(pk);
- rest = pk - (cmsFloat32Number) k0;
- K0 = p -> opta[4] * k0;
- K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[4]);
- p1 = *p;
- memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number));
- T = LutTable + K0;
- p1.Table = T;
- Eval4InputsFloat(Input + 1, Tmp1, &p1);
- T = LutTable + K1;
- p1.Table = T;
- Eval4InputsFloat(Input + 1, Tmp2, &p1);
- for (i=0; i < p -> nOutputs; i++) {
- cmsFloat32Number y0 = Tmp1[i];
- cmsFloat32Number y1 = Tmp2[i];
- Output[i] = y0 + (y1 - y0) * rest;
- }
- }
- static
- void Eval6Inputs(register const cmsUInt16Number Input[],
- register cmsUInt16Number Output[],
- register const cmsInterpParams* p16)
- {
- const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
- cmsS15Fixed16Number fk;
- cmsS15Fixed16Number k0, rk;
- int K0, K1;
- const cmsUInt16Number* T;
- cmsUInt32Number i;
- cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
- cmsInterpParams p1;
- fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
- k0 = FIXED_TO_INT(fk);
- rk = FIXED_REST_TO_INT(fk);
- K0 = p16 -> opta[5] * k0;
- K1 = p16 -> opta[5] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
- p1 = *p16;
- memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number));
- T = LutTable + K0;
- p1.Table = T;
- Eval5Inputs(Input + 1, Tmp1, &p1);
- T = LutTable + K1;
- p1.Table = T;
- Eval5Inputs(Input + 1, Tmp2, &p1);
- for (i=0; i < p16 -> nOutputs; i++) {
- Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
- }
- }
- static
- void Eval6InputsFloat(const cmsFloat32Number Input[],
- cmsFloat32Number Output[],
- const cmsInterpParams* p)
- {
- const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
- cmsFloat32Number rest;
- cmsFloat32Number pk;
- int k0, K0, K1;
- const cmsFloat32Number* T;
- cmsUInt32Number i;
- cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
- cmsInterpParams p1;
- pk = Input[0] * p->Domain[0];
- k0 = _cmsQuickFloor(pk);
- rest = pk - (cmsFloat32Number) k0;
- K0 = p -> opta[5] * k0;
- K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[5]);
- p1 = *p;
- memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number));
- T = LutTable + K0;
- p1.Table = T;
- Eval5InputsFloat(Input + 1, Tmp1, &p1);
- T = LutTable + K1;
- p1.Table = T;
- Eval5InputsFloat(Input + 1, Tmp2, &p1);
- for (i=0; i < p -> nOutputs; i++) {
- cmsFloat32Number y0 = Tmp1[i];
- cmsFloat32Number y1 = Tmp2[i];
- Output[i] = y0 + (y1 - y0) * rest;
- }
- }
- static
- void Eval7Inputs(register const cmsUInt16Number Input[],
- register cmsUInt16Number Output[],
- register const cmsInterpParams* p16)
- {
- const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
- cmsS15Fixed16Number fk;
- cmsS15Fixed16Number k0, rk;
- int K0, K1;
- const cmsUInt16Number* T;
- cmsUInt32Number i;
- cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
- cmsInterpParams p1;
- fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
- k0 = FIXED_TO_INT(fk);
- rk = FIXED_REST_TO_INT(fk);
- K0 = p16 -> opta[6] * k0;
- K1 = p16 -> opta[6] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
- p1 = *p16;
- memmove(&p1.Domain[0], &p16 ->Domain[1], 6*sizeof(cmsUInt32Number));
- T = LutTable + K0;
- p1.Table = T;
- Eval6Inputs(Input + 1, Tmp1, &p1);
- T = LutTable + K1;
- p1.Table = T;
- Eval6Inputs(Input + 1, Tmp2, &p1);
- for (i=0; i < p16 -> nOutputs; i++) {
- Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
- }
- }
- static
- void Eval7InputsFloat(const cmsFloat32Number Input[],
- cmsFloat32Number Output[],
- const cmsInterpParams* p)
- {
- const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
- cmsFloat32Number rest;
- cmsFloat32Number pk;
- int k0, K0, K1;
- const cmsFloat32Number* T;
- cmsUInt32Number i;
- cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
- cmsInterpParams p1;
- pk = Input[0] * p->Domain[0];
- k0 = _cmsQuickFloor(pk);
- rest = pk - (cmsFloat32Number) k0;
- K0 = p -> opta[6] * k0;
- K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[6]);
- p1 = *p;
- memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number));
- T = LutTable + K0;
- p1.Table = T;
- Eval6InputsFloat(Input + 1, Tmp1, &p1);
- T = LutTable + K1;
- p1.Table = T;
- Eval6InputsFloat(Input + 1, Tmp2, &p1);
- for (i=0; i < p -> nOutputs; i++) {
- cmsFloat32Number y0 = Tmp1[i];
- cmsFloat32Number y1 = Tmp2[i];
- Output[i] = y0 + (y1 - y0) * rest;
- }
- }
- static
- void Eval8Inputs(register const cmsUInt16Number Input[],
- register cmsUInt16Number Output[],
- register const cmsInterpParams* p16)
- {
- const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
- cmsS15Fixed16Number fk;
- cmsS15Fixed16Number k0, rk;
- int K0, K1;
- const cmsUInt16Number* T;
- cmsUInt32Number i;
- cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
- cmsInterpParams p1;
- fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
- k0 = FIXED_TO_INT(fk);
- rk = FIXED_REST_TO_INT(fk);
- K0 = p16 -> opta[7] * k0;
- K1 = p16 -> opta[7] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
- p1 = *p16;
- memmove(&p1.Domain[0], &p16 ->Domain[1], 7*sizeof(cmsUInt32Number));
- T = LutTable + K0;
- p1.Table = T;
- Eval7Inputs(Input + 1, Tmp1, &p1);
- T = LutTable + K1;
- p1.Table = T;
- Eval7Inputs(Input + 1, Tmp2, &p1);
- for (i=0; i < p16 -> nOutputs; i++) {
- Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
- }
- }
- static
- void Eval8InputsFloat(const cmsFloat32Number Input[],
- cmsFloat32Number Output[],
- const cmsInterpParams* p)
- {
- const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
- cmsFloat32Number rest;
- cmsFloat32Number pk;
- int k0, K0, K1;
- const cmsFloat32Number* T;
- cmsUInt32Number i;
- cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
- cmsInterpParams p1;
- pk = Input[0] * p->Domain[0];
- k0 = _cmsQuickFloor(pk);
- rest = pk - (cmsFloat32Number) k0;
- K0 = p -> opta[7] * k0;
- K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[7]);
- p1 = *p;
- memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number));
- T = LutTable + K0;
- p1.Table = T;
- Eval7InputsFloat(Input + 1, Tmp1, &p1);
- T = LutTable + K1;
- p1.Table = T;
- Eval7InputsFloat(Input + 1, Tmp2, &p1);
- for (i=0; i < p -> nOutputs; i++) {
- cmsFloat32Number y0 = Tmp1[i];
- cmsFloat32Number y1 = Tmp2[i];
- Output[i] = y0 + (y1 - y0) * rest;
- }
- }
- // The default factory
- static
- cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags)
- {
- cmsInterpFunction Interpolation;
- cmsBool IsFloat = (dwFlags & CMS_LERP_FLAGS_FLOAT);
- cmsBool IsTrilinear = (dwFlags & CMS_LERP_FLAGS_TRILINEAR);
- memset(&Interpolation, 0, sizeof(Interpolation));
- // Safety check
- if (nInputChannels >= 4 && nOutputChannels >= MAX_STAGE_CHANNELS)
- return Interpolation;
- switch (nInputChannels) {
- case 1: // Gray LUT / linear
- if (nOutputChannels == 1) {
- if (IsFloat)
- Interpolation.LerpFloat = LinLerp1Dfloat;
- else
- Interpolation.Lerp16 = LinLerp1D;
- }
- else {
- if (IsFloat)
- Interpolation.LerpFloat = Eval1InputFloat;
- else
- Interpolation.Lerp16 = Eval1Input;
- }
- break;
- case 2: // Duotone
- if (IsFloat)
- Interpolation.LerpFloat = BilinearInterpFloat;
- else
- Interpolation.Lerp16 = BilinearInterp16;
- break;
- case 3: // RGB et al
- if (IsTrilinear) {
- if (IsFloat)
- Interpolation.LerpFloat = TrilinearInterpFloat;
- else
- Interpolation.Lerp16 = TrilinearInterp16;
- }
- else {
- if (IsFloat)
- Interpolation.LerpFloat = TetrahedralInterpFloat;
- else {
- Interpolation.Lerp16 = TetrahedralInterp16;
- }
- }
- break;
- case 4: // CMYK lut
- if (IsFloat)
- Interpolation.LerpFloat = Eval4InputsFloat;
- else
- Interpolation.Lerp16 = Eval4Inputs;
- break;
- case 5: // 5 Inks
- if (IsFloat)
- Interpolation.LerpFloat = Eval5InputsFloat;
- else
- Interpolation.Lerp16 = Eval5Inputs;
- break;
- case 6: // 6 Inks
- if (IsFloat)
- Interpolation.LerpFloat = Eval6InputsFloat;
- else
- Interpolation.Lerp16 = Eval6Inputs;
- break;
- case 7: // 7 inks
- if (IsFloat)
- Interpolation.LerpFloat = Eval7InputsFloat;
- else
- Interpolation.Lerp16 = Eval7Inputs;
- break;
- case 8: // 8 inks
- if (IsFloat)
- Interpolation.LerpFloat = Eval8InputsFloat;
- else
- Interpolation.Lerp16 = Eval8Inputs;
- break;
- break;
- default:
- Interpolation.Lerp16 = NULL;
- }
- return Interpolation;
- }
|