コード例 #1
0
ファイル: ccmx.c プロジェクト: beku/Argyll-Releases
/* Lookup an XYZ or Lab color */
static void xform(
ccmx *p,						/* This */
double *out,				/* Output XYZ */
double *in					/* Input XYZ */
) {
	icmMulBy3x3(out, p->matrix, in);
}
コード例 #2
0
ファイル: hcfr.c プロジェクト: comstock/hargyllcms
/* Return the dtp error code */
static inst_code
hcfr_read_sample(
inst *pp,
char *name,			/* Strip name (7 chars) */
ipatch *val) {		/* Pointer to instrument patch value */
	hcfr *p = (hcfr *)pp;
	inst_code ev;
	double rgb[3];
	int user_trig = 0;

	if (p->trig == inst_opt_trig_keyb) {
		int se;
		if ((se = icoms_poll_user(p->icom, 1)) != ICOM_TRIG) {
			/* Abort, term or command */
			return hcfr_interp_code((inst *)p, icoms2hcfr_err(se));
		}
		user_trig = 1;
		if (p->trig_return)
			printf("\n");
	}

	if ((ev = hcfr_get_rgb(p, rgb)) != inst_ok)
		return ev;

	if (p->cal_mode == 0) {	/* CRT */
		icmMulBy3x3(val->aXYZ, p->crt, rgb);

	} else if (p->cal_mode == 1) {	/* LCD */
		icmMulBy3x3(val->aXYZ, p->lcd, rgb);

	} else {				/* Raw */
		val->aXYZ[0] = rgb[0];
		val->aXYZ[1] = rgb[1];
		val->aXYZ[2] = rgb[2];
	}
	val->aXYZ_v = 1;		/* These are absolute XYZ readings */
	val->XYZ_v = 0;
	val->Lab_v = 0;
	val->sp.spec_n = 0;
	val->duration = 0.0;

	if (user_trig)
		return inst_user_trig;
	return inst_ok;
}
コード例 #3
0
ファイル: ccmx.c プロジェクト: beku/Argyll-Releases
/* It's not clear if the white weighting is advantagous or not. */
double optf(void *fdata, double *tp) {
	cntx *cx = (cntx *)fdata;
	int i;
	double de;
	double m[3][3];

	m[0][0] = tp[0];
	m[0][1] = tp[1];
	m[0][2] = tp[2];
	m[1][0] = tp[3];
	m[1][1] = tp[4];
	m[1][2] = tp[5];
	m[2][0] = tp[6];
	m[2][1] = tp[7];
	m[2][2] = tp[8];

	for (de = 0.0, i = 0; i < cx->npat; i++) {
		double tlab[3], xyz[3], lab[3];
		icmXYZ2Lab(&cx->wh, tlab, cx->refs[i]);

		icmMulBy3x3(xyz, m, cx->cols[i]);
		icmXYZ2Lab(&cx->wh, lab, xyz);

		if (i == cx->wix)
			de += cx->npat/4.0 * wCIE94sq(tlab, lab);	/* Make white weight = 1/4 all others */
		else
			de += wCIE94sq(tlab, lab);
//printf("~1 %d: txyz %f %f %f, tlab %f %f %f\n", i,cx->refs[i][0], cx->refs[i][1], cx->refs[i][2], tlab[0], tlab[1], tlab[2]);
//printf("~1 %d: xyz %f %f %f\n", i,cx->cols[i][0], cx->cols[i][1], cx->cols[i][2]);
//printf("~1 %d: mxyz %f %f %f, lab %f %f %f\n", i,xyz[0], xyz[1], xyz[2], lab[0], lab[1], lab[2]);
//printf("~1 %d: de %f\n", i,wCIE94(tlab, lab));
	}

	de /= cx->npat;
#ifdef DEBUG
//	printf("~1 return values = %f\n",de);
#endif

	return de;
}
コード例 #4
0
ファイル: refine.c プロジェクト: comstock/hargyllcms
int
main(int argc, char *argv[]) {
	int fa,nfa;				/* argument we're looking at */
	struct {
		char name[MAXNAMEL+1];	/* Patch filename  */
		int npat;				/* Number of patches */
		pval *pat;				/* patch values */
	} cg[2];					/* Target and current patch file information */
	char dev_name[MAXNAMEL+1];	/* Output device ICC filename for gamut */
	char rd_name[MAXNAMEL+1];	/* Abstract profile ICC to modify */
	char wr_name[MAXNAMEL+1];	/* Modified/created abstract profile ICC */

	int dorel = 0;				/* Do white point relative match */
	int *match;					/* Array mapping first list indexes to corresponding second */
	int fwacomp = 0;			/* FWA compensation on spectral ? */
	int spec = 0;				/* Use spectral data flag */
	icxIllumeType illum = icxIT_D50;	/* Spectral defaults */
	xspect cust_illum;					/* Custom illumination spectrum */
	icxObserverType observ = icxOT_Judd_Voss_2;
	callback cb;				/* Callback support stucture for setting abstract profile */

	icmFile *rd_fp = NULL;		/* Existing abstract profile to modify */
	icc *rd_icc = NULL;

	icmFile *wr_fp;				/* Modified/created abstract profile to write */
	icc *wr_icc;

	int verb = 0;
	int nogamut = 0;					/* Don't impose a gamut limit */
	int docreate = 0;					/* Create an initial abstract correction profile */
	int clutres = DEF_CLUTRES;			/* Output abstract profile clut resolution */
	double damp1 = DEF_DAMP1;			/* Initial damping factor */
	double damp2 = DEF_DAMP2;			/* Subsequent damping factor */
	double smoothf = SMOOTHF;			/* RSPL Smoothing factor */
	double avgdev[MXDO];				/* RSPL Average Deviation */
	double wweight = WWEIGHT;			/* weak default function weight */
	int whitepatch = -1;				/* Index of white patch */
	double merr = 0.0, aerr = 0.0;		/* Stats on color change */
	int i, j, e, n, rv = 0;

	error_program = argv[0];

	if (argc < 6)
		usage("Too few arguments");

	/* Process the arguments */
	for(fa = 1;fa < argc;fa++) {
		nfa = fa;					/* skip to nfa if next argument is used */
		if (argv[fa][0] == '-')	{	/* Look for any flags */
			char *na = NULL;		/* next argument after flag, null if none */

			if (argv[fa][2] != '\000')
				na = &argv[fa][2];		/* next is directly after flag */
			else {
				if ((fa+1) < argc) {
					if (argv[fa+1][0] != '-') {
						nfa = fa + 1;
						na = argv[nfa];		/* next is seperate non-flag argument */
					}
				}
			}

			if (argv[fa][1] == '?')
				usage("Usage requested");

			/* Verbosity */
			else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') {
				verb = 1;
			}
			/* Create initial abstract correction profile */
			else if (argv[fa][1] == 'c' || argv[fa][1] == 'C') {
				docreate = 1;
			}
			/* Don't impose a gamut limit */
			else if (argv[fa][1] == 'g' || argv[fa][1] == 'G') {
				nogamut = 1;
			}
			/* Override the correction clut resolution */
			else if (argv[fa][1] == 'r') {
				fa = nfa;
				if (na == NULL) usage("Expect argument to -r");
				clutres = atoi(na);
			}
			/* Override the damping factor */
			else if (argv[fa][1] == 'd' || argv[fa][1] == 'D') {
				fa = nfa;
				if (na == NULL) usage("Expect argument to -d");
				damp2 = atof(na);
			}
			/* Aim for white point relative match */
			else if (argv[fa][1] == 'R') {
				dorel = 1;
			}

			/* Spectral Illuminant type */
			else if (argv[fa][1] == 'i' || argv[fa][1] == 'I') {
				fa = nfa;
				if (na == NULL) usage("Expect argument to -i");
				if (strcmp(na, "A") == 0) {
					spec = 1;
					illum = icxIT_A;
				} else if (strcmp(na, "C") == 0) {
					spec = 1;
					illum = icxIT_C;
				} else if (strcmp(na, "D50") == 0) {
					spec = 1;
					illum = icxIT_D50;
				} else if (strcmp(na, "D65") == 0) {
					spec = 1;
					illum = icxIT_D65;
				} else if (strcmp(na, "F5") == 0) {
					spec = 1;
					illum = icxIT_F5;
				} else if (strcmp(na, "F8") == 0) {
					spec = 1;
					illum = icxIT_F8;
				} else if (strcmp(na, "F10") == 0) {
					spec = 1;
					illum = icxIT_F10;
				} else {	/* Assume it's a filename */
					spec = 1;
					illum = icxIT_custom;
					if (read_xspect(&cust_illum, na) != 0)
						usage("Unable to read custom spectrum '%s'",na);
				}
			}

			/* Spectral Observer type */
			else if (argv[fa][1] == 'o' || argv[fa][1] == 'O') {
				fa = nfa;
				if (na == NULL) usage("Expected argument to -o");
				if (strcmp(na, "1931_2") == 0) {			/* Classic 2 degree */
					spec = 1;
					observ = icxOT_CIE_1931_2;
				} else if (strcmp(na, "1964_10") == 0) {	/* Classic 10 degree */
					spec = 1;
					observ = icxOT_CIE_1964_10;
				} else if (strcmp(na, "1955_2") == 0) {		/* Stiles and Burch 1955 2 degree */
					spec = 1;
					observ = icxOT_Stiles_Burch_2;
				} else if (strcmp(na, "1978_2") == 0) {		/* Judd and Voss 1978 2 degree */
					spec = 1;
					observ = icxOT_Judd_Voss_2;
				} else if (strcmp(na, "shaw") == 0) {		/* Shaw and Fairchilds 1997 2 degree */
					spec = 1;
					observ = icxOT_Shaw_Fairchild_2;
				} else
					usage("Unrecogised argument '%s' to -o",na);
			}

			/* FWA compensation */
			else if (argv[fa][1] == 'f' || argv[fa][1] == 'F')
				fwacomp = 1;

			else 
				usage("Unrecognised flag -%c",argv[fa][1]);
		} else
			break;
	}

	/* Grab all the filenames: */

	/* The two CIE value files */
	if (fa >= argc || argv[fa][0] == '-') usage("Expected cietarget file argument");
	strncpy(cg[0].name,argv[fa++],MAXNAMEL); cg[0].name[MAXNAMEL] = '\000';

	if (fa >= argc || argv[fa][0] == '-') usage("Expected ciecurrent file argument");
	strncpy(cg[1].name,argv[fa++],MAXNAMEL); cg[1].name[MAXNAMEL] = '\000';

	/* Optional output device name */
	if (nogamut == 0) {
		if (fa >= argc || argv[fa][0] == '-') usage("Expected outdevicc file argument");
		strncpy(dev_name,argv[fa++],MAXNAMEL); dev_name[MAXNAMEL] = '\000';
	}

	/* Optional input abstract profile name */
	if (docreate == 0) {
		if (fa >= argc || argv[fa][0] == '-') usage("Expected inabs file argument");
		strncpy(rd_name,argv[fa++],MAXNAMEL); rd_name[MAXNAMEL] = '\000';
	}

	/* Output abstract profile name */
	if (fa >= argc || argv[fa][0] == '-') usage("Expected outabs file argument");
	strncpy(wr_name,argv[fa++],MAXNAMEL); wr_name[MAXNAMEL] = '\000';

	/* ======================= */
	/* Open up each CIE file in turn, target then measured, */
	/* and read in the CIE values. */
	for (n = 0; n < 2; n++) {
		cgats *cgf = NULL;			/* cgats file data */
		int isLab = 0;				/* 0 if file CIE is XYZ, 1 if is Lab */
		int sidx;					/* Sample ID index */
		int xix, yix, zix;

		/* Open CIE target values */
		cgf = new_cgats();			/* Create a CGATS structure */
		cgf->add_other(cgf, ""); 	/* Allow any signature file */
	
		if (cgf->read_name(cgf, cg[n].name))
			error("CGATS file '%s' read error : %s",cg[n].name,cgf->err);
	
		if (cgf->ntables < 1)
			error ("Input file '%s' doesn't contain at least one table",cg[n].name);
	
		/* Check if the file is suitable */
		if (!spec
		 && cgf->find_field(cgf, 0, "LAB_L") < 0
		 && cgf->find_field(cgf, 0, "XYZ_X") < 0) {
	
			if (cgf->find_kword(cgf, 0, "SPECTRAL_BANDS") < 0)
				error ("Neither CIE nor spectral data found in file '%s'",cg[n].name);
	
			/* Switch to using spectral information */
			if (verb)
				printf("No CIE data found, switching to spectral with standard observer & D50 for file '%s'\n",cg[n].name);
			spec = 1;
			illum = icxIT_D50;
			observ = icxOT_CIE_1931_2;
		}
		if (spec && cgf->find_kword(cgf, 0, "SPECTRAL_BANDS") < 0)
			error ("No spectral data data found in file '%s' when spectral expected",cg[n].name);
	
		if (!spec && cgf->find_field(cgf, 0, "LAB_L") >= 0)
			isLab = 1;
		
		cg[n].npat = cgf->t[0].nsets;		/* Number of patches */
	
		/* Read all the target patches */
		if (cg[n].npat <= 0)
			error("No sets of data in file '%s'",cg[n].name);
	
		if (verb && n == 0) {
			fprintf(verbo,"No of test patches = %d\n",cg[n].npat);
		}
	
		/* Allocate arrays to hold test patch input and output values */
		if ((cg[n].pat = (pval *)malloc(sizeof(pval) * cg[n].npat)) == NULL)
			error("Malloc failed - pat[]");
	
		/* Read in the CGATs fields */
		if ((sidx = cgf->find_field(cgf, 0, "SAMPLE_ID")) < 0
		 && (sidx = cgf->find_field(cgf, 0, "SampleName")) < 0
		 && (sidx = cgf->find_field(cgf, 0, "Sample_Name")) < 0
		 && (sidx = cgf->find_field(cgf, 0, "SAMPLE_NAME")) < 0
		 && (sidx = cgf->find_field(cgf, 0, "SAMPLE_LOC")) < 0)
			error("Input file '%s' doesn't contain field SAMPLE_ID, SampleName, Sample_Name, SAMPLE_NAME or SAMPLE_LOC",cg[n].name);
		if (cgf->t[0].ftype[sidx] != nqcs_t
		 && cgf->t[0].ftype[sidx] != cs_t)
			error("Sample ID/Name field isn't a quoted or non quoted character string");

		if (spec == 0) { 		/* Using instrument tristimulous value */

			if (isLab) {		/* Expect Lab */
				if ((xix = cgf->find_field(cgf, 0, "LAB_L")) < 0)
					error("Input file '%s' doesn't contain field LAB_L",cg[n].name);
				if (cgf->t[0].ftype[xix] != r_t)
					error("Field LAB_L is wrong type");
				if ((yix = cgf->find_field(cgf, 0, "LAB_A")) < 0)
					error("Input file '%s' doesn't contain field LAB_A",cg[n].name);
				if (cgf->t[0].ftype[yix] != r_t)
					error("Field LAB_A is wrong type");
				if ((zix = cgf->find_field(cgf, 0, "LAB_B")) < 0)
					error("Input file '%s' doesn't contain field LAB_B",cg[n].name);
				if (cgf->t[0].ftype[zix] != r_t)
					error("Field LAB_B is wrong type");

			} else { 		/* Expect XYZ */
				if ((xix = cgf->find_field(cgf, 0, "XYZ_X")) < 0)
					error("Input file '%s' doesn't contain field XYZ_X",cg[n].name);
				if (cgf->t[0].ftype[xix] != r_t)
					error("Field XYZ_X is wrong type");
				if ((yix = cgf->find_field(cgf, 0, "XYZ_Y")) < 0)
					error("Input file '%s' doesn't contain field XYZ_Y",cg[n].name);
				if (cgf->t[0].ftype[yix] != r_t)
					error("Field XYZ_Y is wrong type");
				if ((zix = cgf->find_field(cgf, 0, "XYZ_Z")) < 0)
					error("Input file '%s' doesn't contain field XYZ_Z",cg[n].name);
				if (cgf->t[0].ftype[zix] != r_t)
					error("Field XYZ_Z is wrong type");
			}

			for (i = 0; i < cg[n].npat; i++) {
				strcpy(cg[n].pat[i].sid, (char *)cgf->t[0].fdata[i][sidx]);
				cg[n].pat[i].v[0] = *((double *)cgf->t[0].fdata[i][xix]);
				cg[n].pat[i].v[1] = *((double *)cgf->t[0].fdata[i][yix]);
				cg[n].pat[i].v[2] = *((double *)cgf->t[0].fdata[i][zix]);
				if (!isLab) {
					cg[n].pat[i].v[0] /= 100.0;		/* Normalise XYZ to range 0.0 - 1.0 */
					cg[n].pat[i].v[1] /= 100.0;
					cg[n].pat[i].v[2] /= 100.0;
				}
				if (!isLab) { /* Convert test patch result XYZ to PCS (D50 Lab) */
					icmXYZ2Lab(&icmD50, cg[n].pat[i].v, cg[n].pat[i].v);
				}
			}

		} else { 		/* Using spectral data */
			int ii;
			xspect sp;
			char buf[100];
			int  spi[XSPECT_MAX_BANDS];	/* CGATS indexes for each wavelength */
			xsp2cie *sp2cie;	/* Spectral conversion object */

			if ((ii = cgf->find_kword(cgf, 0, "SPECTRAL_BANDS")) < 0)
				error ("Input file doesn't contain keyword SPECTRAL_BANDS");
			sp.spec_n = atoi(cgf->t[0].kdata[ii]);
			if ((ii = cgf->find_kword(cgf, 0, "SPECTRAL_START_NM")) < 0)
				error ("Input file doesn't contain keyword SPECTRAL_START_NM");
			sp.spec_wl_short = atof(cgf->t[0].kdata[ii]);
			if ((ii = cgf->find_kword(cgf, 0, "SPECTRAL_END_NM")) < 0)
				error ("Input file doesn't contain keyword SPECTRAL_END_NM");
			sp.spec_wl_long = atof(cgf->t[0].kdata[ii]);
			sp.norm = 100.0;

			/* Find the fields for spectral values */
			for (j = 0; j < sp.spec_n; j++) {
				int nm;
		
				/* Compute nearest integer wavelength */
				nm = (int)(sp.spec_wl_short + ((double)j/(sp.spec_n-1.0))
				            * (sp.spec_wl_long - sp.spec_wl_short) + 0.5);
				
				sprintf(buf,"SPEC_%03d",nm);

				if ((spi[j] = cgf->find_field(cgf, 0, buf)) < 0)
					error("Input file doesn't contain field %s",buf);
			}

			/* Figure out what sort of device it is */
			{
				int ti;
		
				if ((ti = cgf->find_kword(cgf, 0, "DEVICE_CLASS")) < 0)
					error ("Input file '%s' doesn't contain keyword DEVICE_CLASS",cg[n].name);
		
				if (strcmp(cgf->t[0].kdata[ti],"DISPLAY") == 0) {
					illum = icxIT_none;		/* Displays are assumed to be self luminous */
				}
			}

			/* Create a spectral conversion object */
			if ((sp2cie = new_xsp2cie(illum, illum == icxIT_none ? NULL : &cust_illum,
			                          observ, NULL, icSigLabData)) == NULL)
				error("Creation of spectral conversion object failed");

			if (fwacomp) {
				int ti;
				xspect mwsp;			/* Medium spectrum */
				instType itype;			/* Spectral instrument type */
				xspect insp;			/* Instrument illuminant */

				mwsp = sp;		/* Struct copy */

	 			if ((ti = cgf->find_kword(cgf, 0, "TARGET_INSTRUMENT")) < 0)
					error ("Can't find target instrument in '%s' needed for FWA compensation",cg[n].name);

				if ((itype = inst_enum(cgf->t[0].kdata[ti])) == instUnknown)
					error ("Unrecognised target instrument '%s'", cgf->t[0].kdata[ti]);

				if (inst_illuminant(&insp, itype) != 0)
					error ("Instrument doesn't have an FWA illuminent");

				/* Determine a media white spectral reflectance */
				for (j = 0; j < mwsp.spec_n; j++)
					mwsp.spec[j] = 0.0;

				/* Track the maximum reflectance for any band to determine white. */
				/* This might silently fail, if there isn't white in the sampe set. */
				for (i = 0; i < cg[0].npat; i++) {
					for (j = 0; j < mwsp.spec_n; j++) {
						double rv = *((double *)cgf->t[0].fdata[i][spi[j]]);
						if (rv > mwsp.spec[j])
							mwsp.spec[j] = rv;
					}
				}
				if (sp2cie->set_fwa(sp2cie, &insp, &mwsp)) 
					error ("Set FWA on sp2cie failed");
			}

			for (i = 0; i < cg[0].npat; i++) {

				strcpy(cg[n].pat[i].sid, (char *)cgf->t[0].fdata[i][sidx]);

				/* Read the spectral values for this patch */
				for (j = 0; j < sp.spec_n; j++) {
					sp.spec[j] = *((double *)cgf->t[0].fdata[i][spi[j]]);
				}

				/* Convert it to CIE space */
				sp2cie->convert(sp2cie, cg[n].pat[i].v, &sp);
			}

			sp2cie->del(sp2cie);		/* Done with this */

		}	/* End of reading in CGATs file */
		cgf->del(cgf);		/* Clean up */
	}

	/* Check that the number of test patches matches */
	if (cg[0].npat != cg[1].npat)
		error("Number of patches between '%s' and '%s' doesn't match",cg[0].name,cg[1].name);
	
	/* Create a list to map the second list (measured) of patches to the first (target) */
	if ((match = (int *)malloc(sizeof(int) * cg[0].npat)) == NULL)
		error("Malloc failed - match[]");
	for (i = 0; i < cg[0].npat; i++) {
		for (j = 0; j < cg[1].npat; j++) {
			if (strcmp(cg[0].pat[i].sid, cg[1].pat[j].sid) == 0)
				break;			/* Found it */
		}
		if (j < cg[1].npat) {
			match[i] = j;
		} else {
			error("Failed to find matching patch to '%s'",cg[0].pat[i].sid);
		}
	}

	/* Try and figure out which is the white patch */
	{
		double hL = -1.0;
		for (i = 0; i < cg[0].npat; i++) {
			if (cg[0].pat[i].v[0] > hL) {
				hL = cg[0].pat[i].v[0];
				whitepatch = i;
			}
		}
	}

	/* If we are aiming for a white point relative match, adjust the */
	/* measured and target values to have a D50 white point */
	if (dorel) {
		for (n = 0; n < 2; n++) {
			int wpix;			/* White patch index */
			double wp_xyz[3];
			icmXYZNumber wp;	/* White value */
			double mat[3][3];	/* Chromatic transform */
			
			if (n == 0)
				wpix = whitepatch;
			else
				wpix = match[whitepatch];
		

			/* Compute a chromatic correction matrix */
			icmLab2XYZ(&icmD50, wp_xyz, cg[n].pat[wpix].v);
			icmAry2XYZ(wp, wp_xyz);

			icmChromAdaptMatrix(ICM_CAM_BRADFORD, icmD50, wp, mat);

			for (i = 0; i < cg[n].npat; i++) {
				icmLab2XYZ(&icmD50, cg[n].pat[i].v, cg[n].pat[i].v);
				icmMulBy3x3(cg[n].pat[i].v, mat, cg[n].pat[i].v);
				icmXYZ2Lab(&icmD50, cg[n].pat[i].v, cg[n].pat[i].v);
//printf("Table %d, patch %d, Lab %f %f %f\n",n,i,cg[n].pat[i].v[0],cg[n].pat[i].v[1],cg[n].pat[i].v[2]);
			}
		}
	}

	/* Compute the delta E's just for information */
	for (i = 0; i < cg[0].npat; i++) {
		double de = icmLabDE(cg[0].pat[i].v, cg[1].pat[match[i]].v);
		cg[0].pat[i].de = de;
		if (de > merr)
			merr = de;
		aerr += de;
	}
	if (cg[0].npat > 0)
		aerr /= (double)cg[0].npat;

	if (verb) {
		fprintf(verbo,"No of correction patches = %d\n",cg[0].npat);
		fprintf(verbo,"Average dE = %f, Maximum dE = %f\n",aerr,merr);
		fprintf(verbo,"White patch assumed to be patch %s\n",cg[0].pat[whitepatch].sid);
	}

	/* ======================= */
	/* Possible limiting gamut */
	if (nogamut == 0) {
		icmFile *dev_fp;
		icc *dev_icc;
		xicc *dev_xicc;
		icxLuBase *dev_luo;
		icxInk ink;							/* Ink parameters */

		/* Open up the device ICC profile, so that we can create a gamut */
		/* and get an absolute PCS->device conversion */
		if ((dev_fp = new_icmFileStd_name(dev_name,"r")) == NULL)
			error ("Can't open file '%s'",dev_name);
	
		if ((dev_icc = new_icc()) == NULL)
			error("Creation of ICC object failed");
	
		/* Read header etc. */
		if ((rv = dev_icc->read(dev_icc,dev_fp,0)) != 0)
			error("Reading profile '%s' failed: %d, %s",dev_name,rv,dev_icc->err);
	
		/* Check that the profile is appropriate */
		if (dev_icc->header->deviceClass != icSigInputClass
		 && dev_icc->header->deviceClass != icSigDisplayClass
		 && dev_icc->header->deviceClass != icSigOutputClass)
			error("Device Profile '%s' isn't a device profile",dev_name);

		ink.tlimit = -1.0;		/* No ink limit by default */
		ink.klimit = -1.0;

		/* Wrap with an expanded icc */
		if ((dev_xicc = new_xicc(dev_icc)) == NULL)
			error ("Creation of xicc failed");

		/* Use a heuristic to guess the ink limit */
		icxGetLimits(dev_xicc, &ink.tlimit, &ink.klimit);
		ink.tlimit += 0.05;		/* allow a slight margine */

		if (verb)
			printf("Estimated Total inklimit is %f%%, Black %f%% \n",100.0 * ink.tlimit,ink.klimit < 0.0 ? 100.0 : 100.0 * ink.klimit);

		/* Get a expanded color conversion object suitable for gamut */
		if ((dev_luo = dev_xicc->get_luobj(dev_xicc, ICX_CLIP_NEAREST, icmFwd,
		     dorel ? icRelativeColorimetric : icAbsoluteColorimetric,
		     icSigLabData, icmLuOrdNorm, NULL, &ink)) == NULL)
			error ("%d, %s",dev_xicc->errc, dev_xicc->err);
	
		/* Creat a gamut surface */
		if ((cb.dev_gam = dev_luo->get_gamut(dev_luo, GAMRES)) == NULL)
			error ("%d, %s",dev_xicc->errc, dev_xicc->err);

		dev_luo->del(dev_luo);
		dev_xicc->del(dev_xicc);
		dev_icc->del(dev_icc);
		dev_fp->del(dev_fp);
	} else {
		cb.dev_gam = NULL;
	}

	/* ======================= */
	/* Open up the existing abstract profile that is to be refined. */
	if (docreate == 0) {
		if ((rd_fp = new_icmFileStd_name(rd_name,"r")) == NULL)
			error ("Can't open file '%s'",rd_name);
	
		if ((rd_icc = new_icc()) == NULL)
			error ("Creation of ICC object failed");
	
		/* Read header etc. */
		if ((rv = rd_icc->read(rd_icc,rd_fp,0)) != 0)
			error ("%d, %s",rv,rd_icc->err);
	
		if (rd_icc->header->deviceClass != icSigAbstractClass)
			error("Input Profile '%s' isn't abstract type",rd_name);

		if ((cb.rd_luo = rd_icc->get_luobj(rd_icc, icmFwd,
		        dorel ? icRelativeColorimetric : icAbsoluteColorimetric,
		        icSigLabData, icmLuOrdNorm)) == NULL)
				error ("%d, %s",rd_icc->errc, rd_icc->err);
	} else {
		cb.rd_luo = NULL;
	}

	/* ======================= */
	/* Create refining rspl */
	{
		cow *rp;		/* rspl setup points */
		int npnts = 0;	/* Total number of test points */
		int gres[MXDI];	/* rspl grid resolution */
		double damp;
		datai mn, mx;

		if ((rp = (cow *)malloc(sizeof(cow) * cg[0].npat)) == NULL)
			error("Malloc failed - rp[]");
		
		/* Create mapping points */
		for (i = 0; i < cg[0].npat; i++) {
			double temp[3];
			double ccor[3], cmag;				/* Current correction vector */
			double ncor[3], nmag;				/* New correction vector */

			/* Input is target [0] */
			for (j = 0; j < 3; j++)
				rp[i].p[j] = cg[0].pat[i].v[j];

			/* Cull out of range points */
			if (rp[i].p[0] < 0.0 || rp[i].p[0] > 100.0
			 || rp[i].p[1] < -127.0 || rp[i].p[1] > 127.0
			 || rp[i].p[2] < -127.0 || rp[i].p[2] > 127.0) {
#ifdef DEBUG1
			printf("Ignoring %f %f %f\n",rp[i].p[0],rp[i].p[1],rp[i].p[2]);
#endif
				continue;
			}
			
#ifdef DEBUG1
			printf("%d: Target        %f %f %f\n",i,rp[i].p[0],rp[i].p[1],rp[i].p[2]);
#endif

			damp = cb.rd_luo != NULL ? damp2 : damp1;
			ccor[0] = ccor[1] = ccor[2] = 0.0;
			cmag = 0.0;

			/* Lookup the current correction applied to the target */
			if (cb.rd_luo != NULL) {		/* Subsequent pass */
				double corval[3];
				cb.rd_luo->lookup(cb.rd_luo, corval, cg[0].pat[i].v);
				icmSub3(ccor, corval, cg[0].pat[i].v);
				cmag = icmNorm3(ccor);
#ifdef DEBUG1
				printf("%d: ccor          %f %f %f, mag %f\n",i, ccor[0],ccor[1],ccor[2],cmag);
#endif
			}

			/* Create a trial 100% full correction point */
			for (j = 0; j < 3; j++)
				rp[i].v[j] = ccor[j] + 2.0 * cg[0].pat[i].v[j] - cg[1].pat[match[i]].v[j];

			/* If a first pass and the target or the correction are out of gamut, */
			/* use a damping factor of 1.0 */
			if (cb.rd_luo == NULL
			 && cb.dev_gam != NULL
			 && cb.dev_gam->nradial(cb.dev_gam, temp, rp[i].p) > 1.0
			 && cb.dev_gam->nradial(cb.dev_gam, temp, rp[i].v) > 1.0) {
				damp = 1.0;
			}

#ifdef DEBUG1
			printf("%d: damp =         %f\n",i, damp);
#endif

			/* Create a new correction that does a damped correction to the current error */
			/* [0] = target, [1] = measured */
			for (j = 0; j < 3; j++)
				ncor[j] = ccor[j] + damp * (cg[0].pat[i].v[j] - cg[1].pat[match[i]].v[j]);
			nmag = icmNorm3(ncor);

#ifdef DEBUG1
			printf("%d: ncor          %f %f %f, mag %f\n",i, ncor[0],ncor[1],ncor[2],nmag);
#endif

			/* If this is not the first pass, limit the new correction */
			/* to be 1 + damp as big as the previous correction */
			if (cb.rd_luo != NULL) {
				if ((nmag/cmag) > (1.0 + damp2)) {
#ifdef DEBUG1
					printf("%d: Limited cor mag from %f to %f\n",i, nmag, (1.0 + damp2) * cmag);
#endif
					icmScale3(ncor, ncor, (1.0 + damp2) * cmag/nmag);
				}
			}

			/* Create correction point */
			for (j = 0; j < 3; j++)
				rp[i].v[j] = cg[0].pat[i].v[j] + ncor[j];

			/* If the target point or corrected point is likely to be outside */
			/* the gamut, limit the magnitude of the correction to be the same */
			/* as the previous correction. */ 
			if (cb.rd_luo != NULL && cb.dev_gam != NULL) {
				if (cb.dev_gam->nradial(cb.dev_gam, temp, rp[i].p) > 1.0
				 || cb.dev_gam->nradial(cb.dev_gam, temp, rp[i].v) > 1.0) {
#ifdef DEBUG1
					printf("%d: Limited cor mag from %f to %f\n",i, nmag, cmag);
#endif
					icmScale3(ncor, ncor, cmag/nmag);
				}
				/* Create correction point again */
				for (j = 0; j < 3; j++)
					rp[i].v[j] = cg[0].pat[i].v[j] + ncor[j];
			}

#ifdef DEBUG1
			printf("%d: Was           %f %f %f\n",i, cg[1].pat[match[i]].v[0], cg[1].pat[match[i]].v[1], cg[1].pat[match[i]].v[2]);
			printf("%d: Correction to %f %f %f\n",i, rp[i].v[0], rp[i].v[1], rp[i].v[2]);
#endif

#ifdef COMPLOOKUP
			/* Remove current correction from new change */
			for (j = 0; j < 3; j++)
				rp[i].v[j] -= ccor[j];
#endif
			/* Set weighting */
			if (i == whitepatch)
				rp[i].w = WHITEWEIGHT;
			else
				rp[i].w = 1.0;
			npnts++;

#ifdef DEBUG3
			{
				char fname[50], tmp[50];
				FILE *lf;
				int mi = match[i];
				double tig, cig, rig;  
				double vv[3], temp[3];
				double del[3], delt;
				double corrdel[3], corrdelt;
				double pcval[3], pcorrdel[3], pcorrdelt;

				for (j = 0;; j++) {
					if (poi[j] == (i+1) || poi[j] < 0)
						break;
				}
				if (poi[j] < 0) {
					continue;
				}

#ifdef COMPLOOKUP
				/* Compute total correction point */
				for (j = 0; j < 3; j++)
					vv[j] = rp[i].v[j] + ccor[j];
#else
				for (j = 0; j < 3; j++)
					vv[j] = rp[i].v[j];
#endif
				sprintf(fname,"patch%04d.log",i+1);
				if ((lf = fopen(fname, "a")) == NULL)
					error("Unable to open debug3 log file '%s'\n",fname);

	 			cig = cb.dev_gam->nradial(cb.dev_gam, temp, cg[1].pat[mi].v) - 1.0;
				if (cig > 0.0)
					sprintf(tmp, " OUT %f",cig);
				else
					sprintf(tmp, "");
				fprintf(lf,"Currently  %f %f %f%s\n", cg[1].pat[mi].v[0], cg[1].pat[mi].v[1], cg[1].pat[mi].v[2], tmp);

	 			tig = cb.dev_gam->nradial(cb.dev_gam, temp, cg[0].pat[i].v) - 1.0;
				if (tig > 0.0)
					sprintf(tmp, " OUT %f",tig);
				else
					sprintf(tmp, "");
				fprintf(lf,"Target     %f %f %f%s\n", cg[0].pat[i].v[0], cg[0].pat[i].v[1], cg[0].pat[i].v[2], tmp);

				icmSub3(del, cg[1].pat[mi].v, cg[0].pat[i].v);
				delt = icmNorm3(del);
				fprintf(lf,"DE         %f %f %f (%f)\n", del[0], del[1], del[2], delt);
				
				rig = cb.dev_gam->nradial(cb.dev_gam, temp, vv) - 1.0;
				if (rig > 0.0)
					sprintf(tmp, " OUT %f",rig);
				else
					sprintf(tmp, "");
				fprintf(lf,"Correction %f %f %f%s\n", vv[0], vv[1], vv[2], tmp);
				icmSub3(corrdel, vv, cg[0].pat[i].v);
				corrdelt = icmNorm3(corrdel);
				fprintf(lf,"CorrDelta  %f %f %f (%f)\n", corrdel[0], corrdel[1], corrdel[2], corrdelt);
				/* Note the previous correction we're compunded with */
				if (cb.rd_luo != NULL) {
					cb.rd_luo->lookup(cb.rd_luo, pcval, cg[0].pat[i].v);
					icmSub3(pcorrdel, pcval, cg[0].pat[i].v);
					pcorrdelt = icmNorm3(pcorrdel);
					fprintf(lf,"PrevCorrDelta %f %f %f (%f)\n", pcorrdel[0], pcorrdel[1], pcorrdel[2], pcorrdelt);
				}
				fprintf(lf,"\n");

				fclose(lf);
			}
#endif /* DEBUG3 */
		}

		/* Create refining rspl */
		mn[0] =   0.0, mn[1] = mn[2] = -128.0;			/* Allow for 16 bit grid range */
		mx[0] = 100.0, mx[1] = mx[2] =  (65535.0 * 255.0)/65280.0 - 128.0;
		cb.verb = verb;
		if ((cb.r = new_rspl(RSPL_NOFLAGS, 3, 3)) == NULL)
			error("new_rspl failed");

		for (e = 0; e < 3; e++)
			gres[e] = clutres;
		for (e = 0; e < 3; e++)
			avgdev[e] = AVGDEV;

		cb.r->fit_rspl_w_df(cb.r,
		           RSPLFLAGS			/* Extra flags */
		           | verb ? RSPL_VERBOSE : 0,
		           rp,					/* Test points */
		           npnts,				/* Number of test points */
		           mn, mx, gres,		/* Low, high, resolution of grid */
		           NULL, NULL,			/* Default data scale */
		           smoothf,				/* Smoothing */
		           avgdev,				/* Average Deviation */
		           NULL,				/* Grid width */
                   wweight,				/* weak default function weight */
				   NULL,				/* No context */
		           wfunc				/* Weak function */
		);
		if (verb) printf("\n");

		/* Report how good the fit is */
		if (verb) {
			co tco;	/* Test point */
			double maxe = -1e6, avge = 0.0;

			for (i = 0; i < npnts; i++) {
				double de;

				icmAry2Ary(tco.p, rp[i].p);
				cb.r->interp(cb.r, &tco);

				de = icmLabDE(tco.v, rp[i].v);
				if (de > maxe)
					maxe = de;
				avge += de;
			}
			avge /= (double)npnts;
			printf("Refining transform has error to defining points avg: %f, max %f\n",avge,maxe);
		}
		free(rp);
	}

	/* ======================= */
	/* Create new abstract ICC profile */
	if ((wr_fp = new_icmFileStd_name(wr_name,"w")) == NULL)
		error ("Can't open file '%s' for writing",wr_name);

	if ((wr_icc = new_icc()) == NULL)
		error ("Creation of write ICC object failed");

	/* Add all the tags required */

	/* The header: */
	{
		icmHeader *wh = wr_icc->header;

		/* Values that must be set before writing */
		wh->deviceClass     = icSigAbstractClass;
    	wh->colorSpace      = icSigLabData;
    	wh->pcs             = icSigLabData;
		if (dorel)
	    	wh->renderingIntent = icRelativeColorimetric;	/* White point relative */
		else
	    	wh->renderingIntent = icAbsoluteColorimetric;	/* Instrument reading based */
	}
	/* Profile Description Tag: */
	{
		icmTextDescription *wo;
		char *dst = "Argyll refine output";
		if ((wo = (icmTextDescription *)wr_icc->add_tag(
		           wr_icc, icSigProfileDescriptionTag,	icSigTextDescriptionType)) == NULL) 
			error("add_tag failed: %d, %s",wr_icc->errc,wr_icc->err);

		wo->size = strlen(dst)+1; 	/* Allocated and used size of desc, inc null */
		wo->allocate((icmBase *)wo);/* Allocate space */
		strcpy(wo->desc, dst);		/* Copy the string in */
	}
	/* Copyright Tag: */
	{
		icmText *wo;
		char *crt = "Copyright the user who created it";
		if ((wo = (icmText *)wr_icc->add_tag(
		           wr_icc, icSigCopyrightTag,	icSigTextType)) == NULL) 
			error("add_tag failed: %d, %s",wr_icc->errc,wr_icc->err);

		wo->size = strlen(crt)+1; 	/* Allocated and used size of text, inc null */
		wo->allocate((icmBase *)wo);/* Allocate space */
		strcpy(wo->data, crt);		/* Copy the text in */
	}
	/* White Point Tag: */
	{
		icmXYZArray *wo;
		/* Note that tag types icSigXYZType and icSigXYZArrayType are identical */
		if ((wo = (icmXYZArray *)wr_icc->add_tag(
		           wr_icc, icSigMediaWhitePointTag, icSigXYZArrayType)) == NULL) 
			error("add_tag failed: %d, %s",wr_icc->errc,wr_icc->err);

		wo->size = 1;
		wo->allocate((icmBase *)wo);	/* Allocate space */
		wo->data[0] = icmD50;			/* So absolute/relative rendering is the same */
	}
	/* 16 bit pcs -> pcs lut: */
	{
		icmLut *wo;
		int flags = ICM_CLUT_SET_EXACT;	/* Assume we're setting from RSPL's */

		/* Intent 0 = default/perceptual */
		if ((wo = (icmLut *)wr_icc->add_tag(
		           wr_icc, icSigAToB0Tag,	icSigLut16Type)) == NULL) 
			error("add_tag failed: %d, %s",wr_icc->errc,wr_icc->err);

		wo->inputChan = 3;
		wo->outputChan = 3;
    	wo->clutPoints = clutres;
    	wo->inputEnt = 256;				/* Not actually used */
    	wo->outputEnt = 256;
		wo->allocate((icmBase *)wo);/* Allocate space */

		/* The matrix is only applicable to XYZ input space, */
		/* so it is not used here. */

		/* Use helper function to do the hard work. */
		if (cb.verb) {
			int extra;
			for (cb.total = 1, i = 0; i < 3; i++, cb.total *= wo->clutPoints)
				; 
			/* Add in cell center points */
			for (extra = 1, i = 0; i < wo->inputChan; i++, extra *= (wo->clutPoints-1))
				;
			cb.total += extra;
			cb.count = 0;
			cb.last = -1;
			printf(" 0%%"), fflush(stdout);
		}

#ifdef COMPLOOKUP
		/* Compound with previous correction */
		if (cb.rd_luo != NULL)
			flags = ICM_CLUT_SET_APXLS;	/* Won't be least squares, so do extra sampling */
#endif

		if (wo->set_tables(wo,
				flags,
				&cb,
				icSigLabData, 			/* Input color space */
				icSigLabData, 			/* Output color space */
				NULL,					/* Linear input transform Lab->Lab' (NULL = default) */
				NULL, NULL,				/* Use default Maximum range of Lab' values */
				PCSp_PCSp,				/* Lab' -> Lab' transfer function */
				NULL, NULL,				/* Use default Maximum range of Lab' values */
				NULL					/* Linear output transform Lab'->Lab */
		) != 0)
			error("Setting 16 bit Lab->Lab Lut failed: %d, %s",wr_icc->errc,wr_icc->err);

		if (verb)
			printf("\n");
#ifdef WARN_CLUT_CLIPPING
		if (wr_icc->warnc)
			warning("Values clipped in setting abstract LUT");
#endif /* WARN_CLUT_CLIPPING */
		if (verb)
			printf("Done filling abstract table\n");
	}
	/* Write the file out */
	if ((rv = wr_icc->write(wr_icc,wr_fp,0)) != 0)
		error ("Write file: %d, %s",rv,wr_icc->err);
	
	/* ======================================= */
	
	/* Clean everything up */
	wr_icc->del(wr_icc);
	wr_fp->del(wr_fp);

	if (docreate == 0) {
		cb.rd_luo->del(cb.rd_luo);
		rd_icc->del(rd_icc);
		rd_fp->del(rd_fp);
	}

	if (nogamut == 0) {
		cb.dev_gam->del(cb.dev_gam);
	}

	cb.r->del(cb.r);

	free(match);
	free(cg[0].pat);
	free(cg[1].pat);

	return 0;
}
コード例 #5
0
ファイル: mkDispProf.c プロジェクト: beku/Argyll-Releases
int
main(
int argc,
char *argv[]
) {
	int fa,nfa;
	char out_name[1000];
	icmFile *wr_fp;
	icc *wr_icco;
	int rv = 0;
	int verb = 0;

	if (argc < 2)
		usage();

	/* Process the arguments */
	for(fa = 1;fa < argc;fa++) {
		nfa = fa;					/* skip to nfa if next argument is used */
		if (argv[fa][0] == '-')	{	/* Look for any flags */
			char *na = NULL;		/* next argument after flag, null if none */

			if (argv[fa][2] != '\000')
				na = &argv[fa][2];		/* next is directly after flag */
			else {
				if ((fa+1) < argc) {
					if (argv[fa+1][0] != '-') {
						nfa = fa + 1;
						na = argv[nfa];		/* next is seperate non-flag argument */
					}
				}
			}

			if (argv[fa][1] == '?')
				usage();

			/* Verbosity */
			else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') {
				verb = 1;
			}

			else 
				usage();
		}
		else
			break;
	}

	if (fa >= argc || argv[fa][0] == '-') usage();
	strcpy(out_name,argv[fa]);

	/* ---------------------------------------- */
	/* Create a matrix/shaper based XYZ profile */
	/* ---------------------------------------- */

	/* Open up the file for writing */
	if ((wr_fp = new_icmFileStd_name(out_name,"w")) == NULL)
		error ("Write: Can't open file '%s'",out_name);

	if ((wr_icco = new_icc()) == NULL)
		error ("Write: Creation of ICC object failed");

	/* Add all the tags required */

	/* The header: */
	{
		icmHeader *wh = wr_icco->header;

		/* Values that must be set before writing */
		wh->deviceClass     = icSigDisplayClass;
    	wh->colorSpace      = icSigRgbData;			/* It's RGB space */
    	wh->pcs             = icSigXYZData;
    	wh->renderingIntent = icPerceptual;

		/* Values that should be set before writing */
		wh->manufacturer = str2tag("????");
    	wh->model        = str2tag("????");
	}
	/* Profile Description Tag: */
	{
		icmTextDescription *wo;
		char *dst;

		dst = "sRGB like Matrix Display profile";
		if ((wo = (icmTextDescription *)wr_icco->add_tag(
		           wr_icco, icSigProfileDescriptionTag,	icSigTextDescriptionType)) == NULL) 
			error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err);

		wo->size = strlen(dst)+1; 	/* Allocated and used size of desc, inc null */
		wo->scCode = 0;
		wo->scSize = strlen(dst)+1;
		if (wo->scSize > 67)
			error("Description scriptCode string longer than 67");
		wo->allocate((icmBase *)wo);/* Allocate space */
		strcpy(wo->desc, dst);		/* Copy the string in */
		strcpy((char *)wo->scDesc, dst);	/* Copy the string in */
	}
	/* Copyright Tag: */
	{
		icmText *wo;
		char *crt = "Copyright tag goes here";
		if ((wo = (icmText *)wr_icco->add_tag(
		           wr_icco, icSigCopyrightTag,	icSigTextType)) == NULL) 
			error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err);

		wo->size = strlen(crt)+1; 	/* Allocated and used size of text, inc null */
		wo->allocate((icmBase *)wo);/* Allocate space */
		strcpy(wo->data, crt);		/* Copy the text in */
	}

	/* Could add other relevant tags here, such as:

	   Device Manufacturers Description Tag
	   Device Model Description Tag
	   Device technology Tag
	   Viewing conditions Description Tag
	   Viewing conditions
	   Display Luminance Tag
	   Measurement information Tag

	   etc.
	 */

	/* Setup the primaries */
	{
		/* Compute primaries as XYZ */
		double wrgb[4][3] = {		/* Primaries in Yxy from the standard */
			{ 1.0, 0.3127, 0.3290 },	/* White */
			{ 1.0, 0.6400, 0.3300 },	/* Red */
			{ 1.0, 0.3000, 0.6000 },	/* Green */
			{ 1.0, 0.1500, 0.0600 }		/* Blue */
		};
		double mat[3][3];
		int i;

		/* Convert yxy to normalised 3x3 matrix */
		icmRGBYxyprim2matrix(wrgb[1], wrgb[2], wrgb[3], wrgb[0], mat, wrgb[0]);
		icmTranspose3x3(mat, mat);

#ifdef NEVER		/* Dump XYZ */
		printf("sRGB: XYZ\n");
		printf("{ %f, %f, %f }, /* Red */\n"
		       "{ %f, %f, %f }, /* Green */\n"
		       "{ %f, %f, %f }, /* Blue */\n"
		       "{ %f, %f, %f }  /* White */\n",
		mat[0][0], mat[0][1], mat[0][2],
		mat[1][0], mat[1][1], mat[1][2],
		mat[2][0], mat[2][1], mat[2][2],
		wrgb[0][0], wrgb[0][1], wrgb[0][2]);
#endif

#ifdef NEVER		/* Dump xyz */
{
	double mat2[4][3];
	double tt;

	for (i = 0; i < 3; i++) {
	
		tt = mat[i][0] + mat[i][1] + mat[i][2];
		mat2[i][0] = mat[i][0] / tt;
		mat2[i][1] = mat[i][1] / tt;
		mat2[i][2] = mat[i][2] / tt;
	}
	tt = wrgb[0][0] + wrgb[0][1] + wrgb[0][2];
	mat2[i][0] = wrgb[0][0] / tt;
	mat2[i][1] = wrgb[0][1] / tt;
	mat2[i][2] = wrgb[0][2] / tt;

	printf("sRGB: xyz\n");
	printf("{ %f, %f, %f },		/* Red */\n"
	       "{ %f, %f, %f },		/* Green */\n"
	       "{ %f, %f, %f },		/* Blue */\n"
	       "{ %f, %f, %f }		/* White */\n",
	mat2[0][0], mat2[0][1], mat2[0][2],
	mat2[1][0], mat2[1][1], mat2[1][2],
	mat2[2][0], mat2[2][1], mat2[2][2],
	mat2[3][0], mat2[3][1], mat2[3][2]);
}
#endif

		/* White Point Tag: */
		{
			icmXYZArray *wo;

			if ((wo = (icmXYZArray *)wr_icco->add_tag(
			           wr_icco, icSigMediaWhitePointTag, icSigXYZArrayType)) == NULL) 
				error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err);

			wo->size = 1;
			wo->allocate((icmBase *)wo);	/* Allocate space */
			wo->data[0].X = wrgb[0][0];
			wo->data[0].Y = wrgb[0][1];
			wo->data[0].Z = wrgb[0][2]; 
		}
		/* Black Point Tag: */
		{
			icmXYZArray *wo;

			if ((wo = (icmXYZArray *)wr_icco->add_tag(
			           wr_icco, icSigMediaBlackPointTag, icSigXYZArrayType)) == NULL) 
				error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err);

			wo->size = 1;
			wo->allocate((icmBase *)wo);	/* Allocate space */
			wo->data[0].X = 0.00;
			wo->data[0].Y = 0.00;
			wo->data[0].Z = 0.00;
		}
		/* Red, Green and Blue Colorant Tags: */
		{
			icmXYZNumber white;
			icmXYZArray *wor, *wog, *wob;
			double fromAbs[3][3];
			double d50m[3][3];

			/* Convert to D50 adapated */
			icmAry2XYZ(white, wrgb[0]);
			wr_icco->chromAdaptMatrix(wr_icco, ICM_CAM_NONE, icmD50, white, fromAbs);
			icmMulBy3x3(d50m[0], fromAbs, mat[0]);
			icmMulBy3x3(d50m[1], fromAbs, mat[1]);
			icmMulBy3x3(d50m[2], fromAbs, mat[2]);

			/* Make sure rounding doesn't wreck white point */
			quantizeRGBprimsS15Fixed16(d50m);

			if ((wor = (icmXYZArray *)wr_icco->add_tag(
			           wr_icco, icSigRedColorantTag, icSigXYZArrayType)) == NULL) 
					error("add_tag failed: %d, %s",rv,wr_icco->err);
			if ((wog = (icmXYZArray *)wr_icco->add_tag(
			           wr_icco, icSigGreenColorantTag, icSigXYZArrayType)) == NULL) 
				error("add_tag failed: %d, %s",rv,wr_icco->err);
			if ((wob = (icmXYZArray *)wr_icco->add_tag(
			           wr_icco, icSigBlueColorantTag, icSigXYZArrayType)) == NULL) 
				error("add_tag failed: %d, %s",rv,wr_icco->err);

			wor->size = wog->size = wob->size = 1;
			wor->allocate((icmBase *)wor);	/* Allocate space */
			wog->allocate((icmBase *)wog);
			wob->allocate((icmBase *)wob);
			wor->data[0].X = d50m[0][0]; wor->data[0].Y = d50m[0][1]; wor->data[0].Z = d50m[0][2];
			wog->data[0].X = d50m[1][0]; wog->data[0].Y = d50m[1][1]; wog->data[0].Z = d50m[1][2];
			wob->data[0].X = d50m[2][0]; wob->data[0].Y = d50m[2][1]; wob->data[0].Z = d50m[2][2];
		}
	}
	/* Red, Green and Blue Gamma Curve Tags: */
	{
		icmCurve *wor, *wog, *wob;
		int i;

		if ((wor = (icmCurve *)wr_icco->add_tag(
		           wr_icco, icSigRedTRCTag, icSigCurveType)) == NULL) 
			error("add_tag failed: %d, %s",rv,wr_icco->err);
		wor->flag = icmCurveSpec;
		wor->size = 1024;
		wor->allocate((icmBase *)wor);	/* Allocate space */
		for (i = 0; i < wor->size; i++)
			wor->data[i] = gdv2dv(i/(wor->size-1.0));

		/* Link other channels to the red */
		if ((wog = (icmCurve *)wr_icco->link_tag(
		           wr_icco, icSigGreenTRCTag, icSigRedTRCTag)) == NULL) 
			error("link_tag failed: %d, %s",rv,wr_icco->err);
		if ((wob = (icmCurve *)wr_icco->link_tag(
		           wr_icco, icSigBlueTRCTag, icSigRedTRCTag)) == NULL) 
			error("link_tag failed: %d, %s",rv,wr_icco->err);
	}

	/* Write the file out */
	if ((rv = wr_icco->write(wr_icco,wr_fp,0)) != 0)
		error ("Write file: %d, %s",rv,wr_icco->err);
	
	wr_icco->del(wr_icco);
	wr_fp->del(wr_fp);

	return 0;
}
コード例 #6
0
ファイル: ccmx.c プロジェクト: beku/Argyll-Releases
/* Create a ccmx from measurements. return nz on error. */
static int create_ccmx(ccmx *p,
char *desc,			/* General description (optional) */
char *inst,			/* Instrument description to copy from */
char *disp,			/* Display make and model (optional) */
disptech dtech,		/* Display technology enum */
int refrmode,		/* Display refresh mode, -1 = unknown, 0 = n, 1 = yes */
int cbid,			/* Display type calibration base index, 0 = unknown */
char *sel,			/* UI selector characters - NULL for none */
char *refd,			/* Reference spectrometer description (optional) */
int oem,			/* NZ if OEM source */
int npat,			/* Number of samples in following arrays */
double (*refs)[3],	/* Array of XYZ values from spectrometer */
double (*cols)[3]		/* Array of XYZ values from colorimeter */
) {
	int i, mxix;
	double maxy = -1e6;
	cntx cx;
	double cp[9], sa[9];

	if ((p->desc = desc) != NULL && (p->desc = strdup(desc)) == NULL) {
		sprintf(p->err, "create_ccmx: malloc failed");
		return 2;
	}
	if ((p->inst = inst) != NULL && (p->inst = strdup(inst)) == NULL) {
		sprintf(p->err, "create_ccmx: malloc failed");
		return 2;
	}
	if ((p->disp = disp) != NULL && (p->disp = strdup(disp)) == NULL) {
		sprintf(p->err, "create_ccmx: malloc failed");
		return 2;
	}
	p->dtech = dtech;
	p->refrmode = refrmode;
	p->cc_cbid = cbid;

	if (sel != NULL) {
		if ((p->sel = strdup(sel)) == NULL) {
			sprintf(p->err, "create_ccmx: malloc sel failed");
			return 2;
		}
	}

	if ((p->ref = refd) != NULL && (p->ref = strdup(refd)) == NULL) {
		sprintf(p->err, "create_ccmx: malloc failed");
		return 2;
	}

	p->oem = oem;

	/* Find the white patch */

	cx.npat = npat;
	cx.refs = refs;
	cx.cols = cols;

	for (i = 0; i < npat; i++) {
		if (refs[i][1] > maxy) {
			maxy = refs[i][1];
			cx.wix = i;
		}
	}
#ifdef DEBUG
	printf("white = %f %f %f\n",refs[cx.wix][0],refs[cx.wix][1],refs[cx.wix][1]);
#endif
	cx.wh.X = refs[cx.wix][0];
	cx.wh.Y = refs[cx.wix][1];
	cx.wh.Z = refs[cx.wix][2];

	/* Starting matrix */
	cp[0] = 1.0; cp[1] = 0.0; cp[2] = 0.0;
	cp[3] = 0.0; cp[4] = 1.0; cp[5] = 0.0;
	cp[6] = 0.0; cp[7] = 0.0; cp[8] = 1.0;

	for (i = 0; i < 9; i++)
		sa[i] = 0.1;

	if (powell(NULL, 9, cp, sa, 1e-6, 2000, optf, &cx, NULL, NULL) < 0.0) {
		sprintf(p->err, "create_ccmx: powell() failed");
		return 1;
	}

	p->matrix[0][0] = cp[0];
	p->matrix[0][1] = cp[1];
	p->matrix[0][2] = cp[2];
	p->matrix[1][0] = cp[3];
	p->matrix[1][1] = cp[4];
	p->matrix[1][2] = cp[5];
	p->matrix[2][0] = cp[6];
	p->matrix[2][1] = cp[7];
	p->matrix[2][2] = cp[8];

	/* Compute the average and max errors */
	p->av_err = p->mx_err = 0.0;
	for (i = 0; i < npat; i++) {
		double tlab[3], xyz[3], lab[3], de;
		icmXYZ2Lab(&cx.wh, tlab, cx.refs[i]);
		icmMulBy3x3(xyz, p->matrix, cx.cols[i]);
		icmXYZ2Lab(&cx.wh, lab, xyz);
		de = icmCIE94(tlab, lab);
		p->av_err += de;
		if (de > p->mx_err) {
			p->mx_err = de;
			mxix = i;
		}
//printf("~1 %d: de %f, tlab %f %f %f, lab %f %f %f\n",i,de,tlab[0], tlab[1], tlab[2], lab[0], lab[1], lab[2]);
	}
	p->av_err /= (double)npat;

//printf("~1 max error is index %d\n",mxix);

#ifdef DEBUG
	printf("Average error %f, max %f\n",p->av_err,p->mx_err);
	printf("Correction matrix is:\n");
	printf("  %f %f %f\n", cp[0], cp[1], cp[2]);
	printf("  %f %f %f\n", cp[3], cp[4], cp[5]);
	printf("  %f %f %f\n", cp[6], cp[7], cp[8]);
#endif

	return 0;
}