Beispiel #1
0
// Load non-uniform data file and build a table
McoStatus Tweak_Patch::Load_Data(FILE *bf)
{
McoHandle tdH;
McoHandle tdrH;
double 	  *td,*tdr;
int32	i,num;

if (bf == 0L) return MCO_FILE_OPEN_ERROR;

fscanf(bf,"%d",&num);

tdH = McoNewHandle(sizeof(double)*num*3);
tdrH = McoNewHandle(sizeof(double)*num*3);

td = (double *)McoLockHandle(tdH);
tdr = (double *)McoLockHandle(tdrH);

for (i=0; i<num; i++)
	{
	fscanf(bf,"%lf %lf %lf",&td[0],&td[1],&td[2]);
	td += 3;
	}
for (i=0; i<num; i++)
	{
	fscanf(bf,"%lf %lf %lf",&tdr[0],&tdr[1],&tdr[2]);	
	tdr += 3;
	}
McoUnlockHandle(tdH);
McoUnlockHandle(tdrH);
Build_Table(tdH,tdrH,num);
McoDeleteHandle(tdH);
McoDeleteHandle(tdrH);
return MCO_SUCCESS;
}
Beispiel #2
0
// fix the L values when saturation is zero
McoStatus FindBlack::fixmanyBlackL(void)
{
int i,j,k,l,sk;
double	h,a;
double	start_L,end_L;
double	*gammutSurfaceManyBlack,*gammutSurfaceManyBlackL;

gammutSurfaceManyBlack = (double*)McoLockHandle(_gammutSurfaceManyBlackH);
gammutSurfaceManyBlackL = (double*)McoLockHandle(_gammutSurfaceManyBlackLH);

for (i=0; i<GAM_DIM_K; i++)
	{
	for (j=0; j<72; j++)
		{
		for (k=0; k<50; k++)
			{
			if (gammutSurfaceManyBlack[i*3600+j*50+k] > 0) break;
			}
		if (k != 50)
			{
			sk = k;
			end_L = gammutSurfaceManyBlackL[i*3600+j*50+k];
			}
		for (k=49; k>=0; k--)
			{
			if (gammutSurfaceManyBlack[i*3600+j*50+k] > 0) break;
			}
		if ((k != -1) && (k != sk))
			{
			h = (k-sk);
			start_L = gammutSurfaceManyBlackL[i*3600+j*50+k];
			for (l=0; l<50; l++)
				{
				a = ((double)l-sk)/h;
				gammutSurfaceManyBlackL[i*3600+j*50+l] = end_L*(1-a)+start_L*a;
				}
			}
		else if (k == sk)
			{
			end_L = gammutSurfaceManyBlackL[i*3600+j*50+k]+2;
			start_L = gammutSurfaceManyBlackL[i*3600+j*50+k]-2;
			k +=1;
			sk -=1;
			h = (k-sk);
			for (l=0; l<50; l++)
				{
				a = ((double)l-sk)/h;
				gammutSurfaceManyBlackL[i*3600+j*50+l] = end_L*(1-a)+start_L*a;
				}
			}
		}
	}
McoUnlockHandle(_gammutSurfaceManyBlackH);
McoUnlockHandle(_gammutSurfaceManyBlackLH);
return MCO_SUCCESS;
}
Beispiel #3
0
// Build a table using non-uniform data
McoStatus Tweak_Patch::Build_Table(McoHandle tdH,McoHandle tdrH, int32 num)
{
McoStatus status;
double	*tweakData;
double	*tweakDataRef;
int	i,j,k,m;
double 	L, a, b;
double  *lab;
double  labt[3];
double  stepL = 100.0/32.0;
short	end;
Linearcal		*calib;


tweakData = (double*)McoLockHandle(tdH);
tweakDataRef = (double*)McoLockHandle(tdrH);

	calib = new Linearcal(20,num,num);
	if (calib == 0L) return MCO_MEM_ALLOC_ERROR;

	end = 0;
	while(1){
		//forword calibration(C(L,a,b)) 
		status = calib->loaddirect(tweakData, tweakDataRef, &end);
		//reverse calibration(L(C,M,Y))
		//status = calib->loaddirect(_patchref, _patch, &end);
		if(status != MCO_SUCCESS)
			return status;
		if(end == 1) //compute
			break;
	}	
	
	status = calib->compute();
	
	lab = (double *)McoLockHandle(labTableH);
	
	for(i = 0; i < 33; i++){
		L = i*stepL;
		for(j = -16; j <= 16; j++){				
			if (j < 16) a = j*8;
			else a = 127.0;
			for(m = -16; m <= 16; m++){
				if (m < 16) b = m*8;
				else b = 127.0;
				calib->_applyf(L,a,b,lab);
				lab +=3;
			}
		}
	}
	
McoUnlockHandle(labTableH);
McoUnlockHandle(tdH);
McoUnlockHandle(tdrH);
return MCO_SUCCESS;
}
Beispiel #4
0
// Modify the table with an individual tweak
McoStatus Tweak_Patch::Modify_Table(double *lab_d,double *lab_p,double Lr,double Cr)
{
int i,j,k,m,n = 0;
double	L_dist,a_dist,b_dist;
double  dL,da,db;
double *lab,*labp;
double	L,a,b;
double	L2,a2,b2;
double	scale;
double stepL;

stepL = 100.0/32.0;
lab = (double *)McoLockHandle(labTableH);
labp = lab;

dL = lab_p[0] - lab_d[0];
da = lab_p[1] - lab_d[1];
db = lab_p[2] - lab_d[2];

Cr = Cr * 2.55;

if ((Lr == 0) || (Cr == 0)) return MCO_FAILURE;
Lr = (12500*0.00008*100+100*(Lr*Lr)-12500*2.995732274)/(Lr*Lr);
Cr = (12500*0.00008*100+100*(Cr*Cr)-12500*2.995732274)/(Cr*Cr);


	for(i = 0; i < 33; i++){
		L = i*stepL;
		L_dist = L-lab_d[0];
		L_dist *= L_dist;
		L_dist *= (100-Lr)*0.00008;
		for(j = -16; j <= 16; j++){				
			if (j < 16) a = j*8;
			else a = 127.0;
			a_dist = a - lab_d[1];
			a_dist *= a_dist;
			a_dist *= (100-Cr)*0.00008;
			for(m = -16; m <= 16; m++){
				if (m < 16) b = m*8;
				else b = 127.0;
				b_dist = b - lab_d[2];
				b_dist *= b_dist;
				b_dist *= (100-Cr)*0.00008;
				scale = exp(-(L_dist+a_dist+b_dist));	
				//save to a structure
				L2 = L+dL;
				a2 = a+da;
				b2 = b+db;
				lab[0] = (1-scale)*lab[0]+scale*L2;
				lab[1] = (1-scale)*lab[1]+scale*a2;
				lab[2] = (1-scale)*lab[2]+scale*b2;
				lab +=3;
				n+=3;
			}
		}
	}
McoUnlockHandle(labTableH);
return MCO_SUCCESS;
}
Beispiel #5
0
McoStatus Tweak_Patch::Init_Table(void)
{
int i,j,k,m,n;
double	L_dist,a_dist,b_dist;
double  dL,da,db;
double *lab;
double L,a,b;
double stepL;

stepL = 100.0/32.0;

lab = (double *)McoLockHandle(labTableH);

if (type == Calibrate_Tweak)
	for(i = 0; i < 33; i++){
		L = i*stepL;
		for(j = -16; j <= 16; j++){				
			if (j < 16) a = j*8;
			else a = 127.0;
			for(m = -16; m <= 16; m++){
				if (m < 16) b = m*8;
				else b = 127.0;
				lab[0] = L;
				lab[1] = a;
				lab[2] = b;
				lab +=3;
			}
		}
	}
else 	// set to zero
	for(i = 0; i < 33; i++){
		L = i*stepL;
		for(j = -16; j <= 16; j++){				
			if (j < 16) a = j*8;
			else a = 127.0;
			for(m = -16; m <= 16; m++){
				if (m < 16) b = m*8;
				else b = 127.0;
				lab[0] = 0;
				lab[1] = 0;
				lab[2] = 0;
				lab +=3;
			}
		}
	}
McoUnlockHandle(labTableH);
return MCO_SUCCESS;
}
Beispiel #6
0
//save to input black table when window is closed
McoStatus	PrinterType::setblack(McoHandle blacktableH)
{
	short 	i;
	double *black;
	double *y2_hands;
	double ypn;
	
	y2_hands = new double[num_hands];
	
	black = (double*)McoLockHandle(blacktableH);
	
	ypn=(y_hands[num_hands-1]-y_hands[num_hands-2])/
		(x_hands[num_hands-1]-x_hands[num_hands-2]);
	
	spline_0(x_hands,y_hands,num_hands,1E30,1E30,y2_hands);
//L to Black table	
	for( i = 0; i <= 100; i++)
		splint_0(x_hands,y_hands,y2_hands,num_hands,i, black+i);

//fix on 8/23
//clipping the _yd_points which on the left of letfmost hand
//to the value of the leftmost hand
//on the right of rightmost hand to the value of the rightmost hand
	for( i = 0; i <= 100; i++){
		if( i <= x_hands[0] ) //left of the leftmost hand
			black[i] = y_hands[0];
		if( i >= x_hands[num_hands-1] ) //left of the leftmost hand
			black[i] = y_hands[num_hands-1];
	}

//clipping the table and normaliz to 1
	for( i = 0; i <= 100; i++){
		if(black[i] < 0)
			black[i] = 0;
		else if(black[i] > 100)
			black[i] = 1.0;
		else
			black[i] /= 100.0;
	}

				
	McoUnlockHandle(blacktableH);
	
	delete y2_hands;
	
	return MCO_SUCCESS;
}	
Beispiel #7
0
// Save the table
McoStatus Tweak_Patch::Save_Table(FileFormat *fileF)
{
McoStatus state;
double *table;
int32	magic = TWEAK_MAGIC_NUM;
int32	version = TWEAK_VERSION_NUM;

state = fileF->relWrite(sizeof(int32),(char*)&magic);
if (state != MCO_SUCCESS) return state;

state = fileF->relWrite(sizeof(int32),(char*)&version);
if (state != MCO_SUCCESS) return state;

table = (double *)McoLockHandle(labTableH);
state = fileF->relWrite(sizeof(double)*33*33*33*3,(char*)table);
if (state != MCO_SUCCESS) return state;
McoUnlockHandle(labTableH);
return MCO_SUCCESS;
}
Beispiel #8
0
// Load a table
McoStatus Tweak_Patch::Load_Table(FileFormat *fileF)
{
McoStatus state;
double *table;
int32	magic,version;

state = fileF->relRead(sizeof(int32),(char*)&magic);
if (state != MCO_SUCCESS) return state;
if (magic != TWEAK_MAGIC_NUM) return MCO_FILE_DATA_ERROR;

state = fileF->relRead(sizeof(int32),(char*)&version);
if (state != MCO_SUCCESS) return state;
if (version != TWEAK_VERSION_NUM) return MCO_FILE_DATA_ERROR;

table = (double *)McoLockHandle(labTableH);
state = fileF->relRead(sizeof(double)*33*33*33*3,(char*)table);
if (state != MCO_SUCCESS) return state;
McoUnlockHandle(labTableH);
return MCO_SUCCESS;
}
Beispiel #9
0
McoStatus FindBlack::findMinMaxOpt(double *lab, double *Kmin,double *Kmax,double *Kopt)
{
int32 i,km,kp,c;
double *gammutSurfaceManyBlack;
double *gammutSurfaceManyBlackL;
double x23[2];
double lch[3];
double x11[101]; // find 100 black values
double y[101];
double x2n[50];
double y2n[GAM_DIM_K*50];
Boolean start = TRUE;
double	best_s;
double Kmint,Kmaxt;

Kmint = -1;
Kmaxt = -1;

labtolch(lab,lch);

km = floor(*Kmin);
kp = ceil(*Kmax);

if ((lab[1]*lab[1]+lab[2]*lab[2]) <= 1.0)
	{
	
	for (i=0; i<50; i++) x2n[i] = (double)i*2;
	
	for (i=km; i<=kp; i++) x11[i] = (double)i/100;
	
	c = 1+kp-km;
	
	spline2(x1,x2n,neutralmins,GAM_DIM_K,50,y2n);
	splint2_clip(x1,x2n,neutralmins,y2n,GAM_DIM_K,50,lab[0],x11,c,y);
	}
else
	{

	gammutSurfaceManyBlack = (double*)McoLockHandle(_gammutSurfaceManyBlackH);
	gammutSurfaceManyBlackL = (double*)McoLockHandle(_gammutSurfaceManyBlackLH);

	x23[0] = lch[2];
	x23[1] = lab[0];


	for (i=km; i<=kp; i++) x11[i] = (double)i/100;
	
	c = 1+kp-km;

	splint3_s3_clip(x1,x2,gammutSurfaceManyBlackL,gammutSurfaceManyBlack,y2a,GAM_DIM_K,72,50,x23,x11,c,y);

	McoUnlockHandle(_gammutSurfaceManyBlackH);
	McoUnlockHandle(_gammutSurfaceManyBlackLH);
	}
best_s = 0;

c = 0;


for (i=km; i<=kp; i++)
	{
	if ((y[c] > 0) && (y[c] + 0.8 > lch[1])) // insert a small tolerence here
		{
		if (start) 
			{
			Kmint = (double)i;
			start = FALSE;
			}
		Kmaxt = (double)i;
		}
	if (y[c] > best_s) 
		{
		best_s = y[c];
		*Kopt = (double)i;
		}
	c++;
	}
*Kmin = Kmint;
*Kmax = Kmaxt;	
	
	
if (*Kmin == -1) *Kmin = *Kopt;	
if (*Kmax == -1) *Kmax = *Kopt;	

return MCO_SUCCESS;
}
Beispiel #10
0
// extend the range of gammutsurfacemany black by convolving with a Gaussian kernal
// interpolation errors often reduce the range of the gamut, this extends that range back out
McoStatus FindBlack::extendRange(void)
{
int i,j,k,l,m;
int count;
double *gammutSurfaceManyBlack;
double kernal[5];
double sum[6];
double temp[50];
double a;

gammutSurfaceManyBlack = (double*)McoLockHandle(_gammutSurfaceManyBlackH);

for (i=0; i<6; i++) sum[i] = 0.0;

// create the kernal
for (i=-2; i<3; i++) 
	{
	kernal[i+2] = exp(-(double)(i*i)*0.9);
	sum[5] += kernal[i+2];
	}
// the sums at the edges
sum[3] = 1+kernal[1]+kernal[0];
sum[4] = 1+kernal[1]*2+kernal[0];

for (i=0; i<GAM_DIM_K; i++)
	{
	// for all 72 hues
	for (j=0; j<72; j++)
		{
		// a temp buffer
		for (k=0; k<50; k++) temp[k] = gammutSurfaceManyBlack[k+j*50+i*50*72];
		for (k=0; k<50; k++)
			{
			count = 0;
			a = 0;
			for (l=-2; l<3; l++)
				{
				m = l+k;
				if ((m >=0) && (m <50))
					{
					count ++;
					a += temp[m]*kernal[l+2];
					}
				}
			gammutSurfaceManyBlack[k+j*50+i*50*72] = a/sum[count];
			}
		}
	// now do the same for the neutral data
	for (k=0; k<50; k++) temp[k] = neutralmins[k+i*50];
	for (k=0; k<50; k++)
		{
		count = 0;
		a = 0;
		for (l=-2; l<3; l++)
			{
			m = l+k;
			if ((m >=0) && (m <50))
				{
				count ++;
				a += temp[m]*kernal[l+2];
				}
			}
		neutralmins[k+i*50] = a/sum[count];
		}	
	}
McoUnlockHandle(_gammutSurfaceManyBlackH);
return MCO_SUCCESS;
}
Beispiel #11
0
FindBlack::FindBlack(double *bL, double *bK, double *a, double *b, int32 nB, 
					 double u_g, double miL, double maL, double *bT,
					 McoHandle gsmbH,McoHandle gsmbLH,double minGam, double maxGam,calib_base *cal)
{
double	*tx,*ty,yd1,ydn;
int i;
double *gammutSurfaceManyBlack;
double *gammutSurfaceManyBlackL;
double	gam_dim_k_vals[] = GAM_DIM_K_VALS;

	_gammutSurfaceManyBlackH = gsmbH;
	_gammutSurfaceManyBlackLH = gsmbLH;

	numB = nB;
	
	calib = cal;
	
	blackL = 0L;
	
	
/*	blackL = new double[numB];
	for (i=0; i<numB; i++)
		{
		blackL[i] = 100-bL[i];
		}
*/	
	//blackL = bL;
	blackK = bK;
	blacka = a;
	blackb = b;

//	tx = blackL;
	ty = blackK;
	
	K2 = new double[numB];
	if (!K2) goto bail;
	a2 = new double[numB];
	if (!a2) goto bail;
	b2 = new double[numB];
	if (!b2) goto bail;
	
//	yd1=(ty[2]-ty[1])/(tx[2]-tx[1])/4;
//	ydn=(ty[numB-1]-ty[numB-2])/(tx[numB-1]-tx[numB-2])/4;
	
//	spline(tx-1,ty-1,numB,yd1,ydn,K2-1);
	
	tx = blackK;
	ty = blacka;
	
	yd1=(ty[2]-ty[1])/(tx[2]-tx[1])/4;
	ydn=(ty[numB-1]-ty[numB-2])/(tx[numB-1]-tx[numB-2])/4;
	
	spline(tx-1,ty-1,numB,yd1,ydn,a2-1);
	
	tx = blackK;
	ty = blackb;
	
	yd1=(ty[2]-ty[1])/(tx[2]-tx[1])/4;
	ydn=(ty[numB-1]-ty[numB-2])/(tx[numB-1]-tx[numB-2])/4;
	
	spline(tx-1,ty-1,numB,yd1,ydn,b2-1);
	
	ucrgcr = u_g;
	//ucrgcr = u_g;
	
	minL = miL;
	maxL = maL;
	blackTable = bT;
	
	y2a = new double[GAM_DIM_K*50*72];
	if (!y2a) goto bail;
	
	fixmanyBlackL();
	
	gammutSurfaceManyBlack = (double*)McoLockHandle(_gammutSurfaceManyBlackH);
	gammutSurfaceManyBlackL = (double*)McoLockHandle(_gammutSurfaceManyBlackLH);

	
	x1 = new double[GAM_DIM_K];
	if (!x1) goto bail;
	x2 = new double[72];
	if (!x2) goto bail;
	x3 = new double[72];
	if (!x3) goto bail;
	
	
	for (i=0; i<GAM_DIM_K; i++) 
		{
		x1[i] = gam_dim_k_vals[i]/100.0;
		}
	for (i=0; i<72; i++) x2[i] = (double)i*5.0;

	spline3_s3(x1,x2,gammutSurfaceManyBlackL,gammutSurfaceManyBlack,GAM_DIM_K,72,50, y2a);

	McoUnlockHandle(_gammutSurfaceManyBlackH);
	McoUnlockHandle(_gammutSurfaceManyBlackH);

	findNeutralMins();
	extendRange();
	
	error = MCO_SUCCESS;
	return;	
bail:
	error = MCO_MEM_ALLOC_ERROR;
	return;
}
Beispiel #12
0
// evaluate using the table (for gamut compression)
// labo = the original lab value
// labg = the gamut compressed lab value
// labt = the tweaked compressed value
McoStatus Tweak_Patch::eval(double *labo,double *labg,double *labt,int32 num)
{
int	i;
double	a,b,c;
int32	a1,a2,b1,b2,c1,c2;
int32	ai1,ai2,bi1,bi2,ci1,ci2;
double t,u,v;
double	r1,r2,r3,r4,r5,r6,r7,r8;
double	*p1,*p2,*p3,*p4,*p5,*p6,*p7,*p8;
double *table;
double	lch[3];

if (type == Calibrate_Tweak) return MCO_FAILURE;

table = (double *)McoLockHandle(labTableH);

for (i=0; i<num; i++)	
	{
	a = labo[0]*0.32;
	b = 16 + labo[1]*0.125;
	c = 16 + labo[2]*0.125;

	if (a >= 32) a = 31.999999;
	if (a < 0) a = 0;
	if (b >= 32) b = 31.999999;
	if (b < 0) b = 0;
	if (c >= 32) c = 31.999999;
	if (c < 0) c = 0;
				
	a1 = ((int32)a)*3267;
	a2 = a1 + 3267;
	b1 = ((int32)b)*99;
	b2 = b1 + 99;
	c1 = ((int32)c)*3;
	c2 = c1 + 3;

	t = a - (int32)a;
	u = b - (int32)b;
	v = c - (int32)c;

	r1 = (1-u)*(1-v);
	r2 = (1-u)*v;
	r3 = u*(1-v);
	r4 = u*v;
	r5 = t*r1;
	r6 = t*r2;
	r7 = t*r3;
	r8 = t*r4;
	a = (1-t);
	r1 = a*r1;
	r2 = a*r2;
	r3 = a*r3;
	r4 = a*r4;

	p1 = table +a1+b1+c1;
	p2 = table +a1+b1+c2;
	p3 = table +a1+b2+c1;
	p4 = table +a1+b2+c2;
	p5 = table +a2+b1+c1;
	p6 = table +a2+b1+c2;
	p7 = table +a2+b2+c1;
	p8 = table +a2+b2+c2;
				
	labtolch(labg,lch);			
				
	lch[0] += r1*(*(p1++)) +
		r2*(*(p2++)) +
		r3*(*(p3++)) +
		r4*(*(p4++)) +
		r5*(*(p5++)) +
		r6*(*(p6++)) +
		r7*(*(p7++)) +
		r8*(*(p8++));
		
	lch[1] += r1*(*(p1++)) +
		r2*(*(p2++)) +
		r3*(*(p3++)) +
		r4*(*(p4++)) +
		r5*(*(p5++)) +
		r6*(*(p6++)) +
		r7*(*(p7++)) +
		r8*(*(p8++));	
		
	lch[2] += r1*(*(p1)) +
		r2*(*(p2)) +
		r3*(*(p3)) +
		r4*(*(p4)) +
		r5*(*(p5)) +
		r6*(*(p6)) +
		r7*(*(p7)) +
		r8*(*(p8));
		
	if (lch[2] <0) lch[2] = 360 + lch[2];
	if (lch[2] >=360) lch[2] = lch[2] - 360;	
		
	lchtolab(lch,labt);		
		
	labo+=3;
	labg+=3;
	labt+=3;
	}	
	
	
McoUnlockHandle(labTableH);							 
return MCO_SUCCESS;
}
Beispiel #13
0
// Modify the table with a list of tweaks
McoStatus Tweak_Patch::Modify_Table(int num_tw,Tweak_Element **tweaks)
{
int i,j,k,m,n = 0;
double	L_dist,a_dist,b_dist;
double  dL,da,db,dc,dh;
double *lab,*labp;
double	L,a,b;
double	L2,a2,b2;
double	scale;
double stepL;
double Lr,Cr;
double lch1[3],lch2[3],labt[3];

stepL = 100.0/32.0;
lab = (double *)McoLockHandle(labTableH);
labp = lab;


if (type == Calibrate_Tweak) 
	{
	for (k=0; k<num_tw; k++) if (tweaks[k]->type == Calibrate_Tweak)
		{
		lab = labp;
		dL = tweaks[k]->lab_p[0] - tweaks[k]->lab_g[0];
		da = tweaks[k]->lab_p[1] - tweaks[k]->lab_g[1];
		db = tweaks[k]->lab_p[2] - tweaks[k]->lab_g[2];

		Lr = tweaks[k]->Lr;
		Cr = tweaks[k]->Cr;
		Cr = Cr * 2.55;
		
		if ((Lr == 0) || (Cr == 0)) return MCO_FAILURE;
		Lr = (12500*0.00008*100+100*(Lr*Lr)-12500*2.995732274)/(Lr*Lr);
		Cr = (12500*0.00008*100+100*(Cr*Cr)-12500*2.995732274)/(Cr*Cr);

			for(i = 0; i < 33; i++){
				L = i*stepL;
				L_dist = L-tweaks[k]->lab_g[0];
				L_dist *= L_dist;
				L_dist *= (100-Lr)*0.00008;
				for(j = -16; j <= 16; j++){				
					if (j < 16) a = j*8;
					else a = 127.0;
					a_dist = a - tweaks[k]->lab_g[1];
					a_dist *= a_dist;
					a_dist *= (100-Cr)*0.00008;
					for(m = -16; m <= 16; m++){
						if (m < 16) b = m*8;
						else b = 127.0;
						b_dist = b - tweaks[k]->lab_g[2];
						b_dist *= b_dist;
						b_dist *= (100-Cr)*0.00008;
						scale = exp(-(L_dist+a_dist+b_dist));	
						//save to a structure
						L2 = L+dL;
						a2 = a+da;
						b2 = b+db;
						lab[0] = (1-scale)*lab[0]+scale*L2;
						lab[1] = (1-scale)*lab[1]+scale*a2;
						lab[2] = (1-scale)*lab[2]+scale*b2;
						lab +=3;
						n+=3;
					}
				}
			}
		}
	}
else if (type == GamutComp_Tweak) 
	{	
	for (k=0; k<num_tw; k++) if (tweaks[k]->type == GamutComp_Tweak)
		{
		lab = labp;
		labtolch(tweaks[k]->lab_p,lch1);
		labtolch(tweaks[k]->lab_g,lch2);
		dL = lch2[0] - lch1[0];
		dc = lch2[1] - lch1[1];
		dh = lch2[2] - lch1[2];
		
		if (dh > 180) dh = dh - 360;
		if (dh < -180) dh = 360 + dh;

		Lr = tweaks[k]->Lr;
		Cr = tweaks[k]->Cr;
		Cr = Cr * 2.55;
		
		if ((Lr == 0) || (Cr == 0)) return MCO_FAILURE;
		Lr = (12500*0.00008*100+100*(Lr*Lr)-12500*2.995732274)/(Lr*Lr);
		Cr = (12500*0.00008*100+100*(Cr*Cr)-12500*2.995732274)/(Cr*Cr);

			for(i = 0; i < 33; i++){
				L = i*stepL;
				L_dist = L-tweaks[k]->lab_d[0];
				L_dist *= L_dist;
				L_dist *= (100-Lr)*0.00008;
				for(j = -16; j <= 16; j++){				
					if (j < 16) a = j*8;
					else a = 127.0;
					a_dist = a - tweaks[k]->lab_d[1];
					a_dist *= a_dist;
					a_dist *= (100-Cr)*0.00008;
					for(m = -16; m <= 16; m++){
						if (m < 16) b = m*8;
						else b = 127.0;
						b_dist = b - tweaks[k]->lab_d[2];
						b_dist *= b_dist;
						b_dist *= (100-Cr)*0.00008;
						scale = exp(-(L_dist+a_dist+b_dist));	
						//save to a structure
						lab[0] = (1-scale)*lab[0]+scale*dL;
						lab[1] = (1-scale)*lab[1]+scale*dc;
						lab[2] = (1-scale)*lab[2]+scale*dh;
						lab +=3;
						n+=3;
					}
				}
			}
		}
	}
McoUnlockHandle(labTableH);
return MCO_SUCCESS;
}