From: <marti@li...>  20021122 09:04:20

Hi, Since your question is quite interesting, I've also forwarded to mailing list. Hope this is not a problem to you. > I have been looking at your LCMS 1.09 code, and I have a question > concerning your interpolation routines, specifically the tetrahedral > interpolation routine using the Sakamoto algorithm. I have an > application that requires the use of such an algorithm, and (I hope you > don't mind) I was going to borrow this routine from your code. The > function in question is cmsTetrahedralInterp16(). Of course you can borrow any routine, this is the goal of open source, at least for me. And what you are asking for, is a very frequent question. So frequent, that I did promote this part to lcms API in ver 1.09 You can use the low level routines, or, and I will recommend this latter, use the LUT interface to accomplish same. The LUT interface is easy to use and allows also to add pre/post linearization, and if you plan to convert RGB > XYZ the prelinearization part is really a must. It can increase a lot the precission whilst lowering the amount of data (CLUT points) required. Then, here are the functions needed. More details in lcmsapi.txt LPLUT cmsAllocLUT(void); LPLUT cmsAllocLinearTable(LPLUT Lut, LPGAMMATABLE Tables[], int nTable); LPLUT cmsAlloc3DGrid(LPLUT Lut, int clutPoints, int inputChan, int outputChan); int cmsSample3DGrid(LPLUT Lut, _cmsSAMPLER Sampler, LPVOID Cargo, DWORD dwFlags); void cmsFreeLUT(LPLUT Lut); void cmsEvalLUT(LPLUT Lut, WORD In[], WORD Out[]); The typical procedure is:  First you allocate an empty LUT by calling cmsAllocLUT()  Then you add whatsever linearization by means of cmsAllocLinearTable()  Then you declare your multidimensional table size using cmsAlloc3DGrid()  Finally, you fill the table by using a callback function and cmsSample3DGrid() This gives to you a ready to use LUT. You can then evaluate values across this LUT by using cmsEvalLUT(). Where done, use cmsFreeLUT() to get rid of the memory. A couple of comments. If you plan to use RGB > XYZ, you should use a prelinearization table for decoupling gamma of RGB space. You could use cmsBuildGamma() to create such curve. For example, sRGB to XYZ needs a gamma curve of approximately gamma=2.2 Avoiding this table will result in quantization errors due to "impedance" mismatch between both spaces, XYZ has an aparent gamma of 1.0! You can use then lcms as a static library and only the needed routines will got linked. I tried to adjust granularity of library to allow very lightweight overhead in such cases. Ok, anyway I will try to answer about the implementation details as well. > Input[] appears to be the input values, which in my case would be the > X, Y and Z (input) values I enter to find the corresponding RGB > (output) values. Output[] appears to be the result of the > interpolation; the R, G, and B values the function identifies as > corresponding to my input X, Y and Z values. Correct? Yes, that is. > LutTable[] appears to be used by the function DENS, but I am not sure > about the pointers to Domain and nOutputs. I am assuming that nOutputs > is the total number of output channels (in my case 3)? But, I am not > sure about Domain; does that represent the last count in my CLUT (in my > case 728)? You can fill the L6PARAMS struct by calling cmsCalcCLUT16Params(int nSamples, int InputChan, int OutputChan, LPL16PARAMS p); You need to specify the cube (or hypercube in case of CMYK) side, and the number of input/output channels. In your case I assume 729 means a cube of 9 gridponts in each side. L16PARAMS params; cmsCalcCLUT16Params(9, 3, 3, ¶ms); ... cmsTetrahedralInterp16(Input[], Output[], Dens[], ¶ms); But again, please note that 9 points is not enough without linearization table. For my testings, you need at least 48!!! points to decouple gamma. But a simple 6 points prelinearization and 6 points on grid gives same accurancy as 48 points, so this step is really required. Hope this helps, Martí Maria The little cms project http://www.littlecms.com marti@...  Original Message  From: "Christopher Brown" Sent: Friday, November 22, 2002 12:27 AM Subject: Tetrahedral Interpolation > Hello Marti  > > I have been looking at your LCMS 1.09 code, and I have a question > concerning your interpolation routines, specifically the tetrahedral > interpolation routine using the Sakamoto algorithm. I have an > application that requires the use of such an algorithm, and (I hope you > don't mind) I was going to borrow this routine from your code. The > function in question is cmsTetrahedralInterp16(). > > Basically, what I have is a CLUT comprised of 729 RGB values with > corresponding XYZ values. The idea would be to take any given set of > XYZ values, and locate the appropriate corresponding RGB values, based > on the 729 data points contained in my CLUT. The values in the CLUT are > currently 16bits each in the range 0 to 65535. > > Now, I think I understand basically what this routine is doing. > However, I just want to verify a few things. There appear to be four > values passed to the function: Input[], Output[], LutTable[] and > LPL16PARAMS. > > Input[] appears to be the input values, which in my case would be the > X, Y and Z (input) values I enter to find the corresponding RGB > (output) values. Output[] appears to be the result of the > interpolation; the R, G, and B values the function identifies as > corresponding to my input X, Y and Z values. Correct? > > LutTable[] appears to be used by the function DENS, but I am not sure > about the pointers to Domain and nOutputs. I am assuming that nOutputs > is the total number of output channels (in my case 3)? But, I am not > sure about Domain; does that represent the last count in my CLUT (in my > case 728)? > > Based on this, please let me know if the following is correct: > > Domain = 728 (last count in CLUT, 0  728) > clutPoints = 729 (Domain + 1) > nOutputs = 3 > TotalOut = nOutputs > Input[] = Input values X, Y and Z > Output[] = Output values R, G and B > px = (X * 728) / 65535 > py = (Y * 728) / 65535 > pz = (Z * 728) / 65535 > > LutTable[] I am not entirely sure about. But, I am assuming that, if > RGB is my output, then c1 would look at R values, c2 at G values and c3 > at B values? This is the part that I am not clear on. Finally, what is > LPL16PARAMS? > > I apologize for asking so many questions; I want to thank you in > advance for any help you can give. Do you happen to have any > information regarding the Sakamoto algorithm, or can you point me to > any papers written on the topic? Also, what is your feeling as to how > this routine compares with your other tetrahedral and trilinear > interpolation routines, in terms of speed and accuracy? How does it > compare to the CatmullRom interpolation (that is remarked out in your > code)? > > Thanks again for all your help! > > Kind Regards, > >  Chris Brown > > > 