McoStatus ScanCal::_localcal(PWlinear **linear, MultiLcal *gcal, MultiLcal **lcal, long num, double *in, double *out) { McoStatus status; long i, m, j, local; double rgb[3], lch[3], caled[3]; double white[3]; white[0] = 96.42; white[1] = 100.0; white[2] = 82.49; m = 0; for (i=0; i<num; i++){ rgb[0] = in[m]; rgb[1] = in[m+1]; rgb[2] = in[m+2]; status = _linearstrech(3, linear, 1, rgb); if(status != MCO_SUCCESS) return status; for(j = 0; j < 3; j++){ if(rgb[j] < 0) rgb[j] = 0; if(rgb[j] > 255) rgb[j] = 255.0; } status = gcal->apply(1, rgb, caled); if(status != MCO_SUCCESS) return status; xyztonxyzinplace(caled, white, 1); nxyztoLabinplace(caled, 1); labtolch(caled, lch); if(lch[1] > GRAY_THRESHOLD){ local = _select_local(lch); status = lcal[local]->apply(1, rgb, caled); if(status != MCO_SUCCESS) return status; xyztonxyzinplace(caled, white, 1); nxyztoLabinplace(caled, 1); } //fix cyan here, may introduce new bug /* if(lch[1] > GRAY_THRESHOLD && lch[2] > 215 && lch[2] < 250){ status = _cyan->apply(1, rgb, caled); if(status != MCO_SUCCESS) return status; xyztonxyzinplace(caled, white, 1); nxyztoLabinplace(caled, 1); } */ out[m] = caled[0]; out[m+1] = caled[1]; out[m+2] = caled[2]; m += 3; } return MCO_SUCCESS; }
void labtolchinplace(double *LAB, long num) { long i; for(i = 0; i < num; i++){ labtolch(LAB, LAB); LAB += 3; } }
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; }
// 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; }
// 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; }