icStatusCMM CIccEvalCompare::EvaluateProfile(CIccProfile *pProfile, icUInt8Number nGran/* =0 */, icRenderingIntent nIntent/* =icUnknownIntent */, icXformInterp nInterp/* =icInterpLinear */, bool buseMpeTags/* =true */) { if (!pProfile) { return icCmmStatCantOpenProfile; } if (pProfile->m_Header.deviceClass!=icSigInputClass && pProfile->m_Header.deviceClass!=icSigDisplayClass && pProfile->m_Header.deviceClass!=icSigOutputClass && pProfile->m_Header.deviceClass!=icSigColorSpaceClass) { return icCmmStatInvalidProfile; } CIccCmm dev2Lab(icSigUnknownData, icSigLabData); CIccCmm Lab2Dev2Lab(icSigLabData, icSigLabData, false); icStatusCMM result; result = dev2Lab.AddXform(*pProfile, nIntent, nInterp, icXformLutColor, buseMpeTags); if (result!=icCmmStatOk) { return result; } result = dev2Lab.Begin(); if (result != icCmmStatOk) { return result; } result = Lab2Dev2Lab.AddXform(*pProfile, nIntent, nInterp, icXformLutColor, buseMpeTags); if (result != icCmmStatOk) { return result; } result = Lab2Dev2Lab.AddXform(*pProfile, nIntent, nInterp, icXformLutColor, buseMpeTags); if (result != icCmmStatOk) { return result; } result = Lab2Dev2Lab.Begin(); if (result != icCmmStatOk) { return result; } icFloatNumber sPixel[15]; icFloatNumber devPcs[15], roundPcs1[15], roundPcs2[15]; int ndim = icGetSpaceSamples(pProfile->m_Header.colorSpace); int ndim1 = ndim+1; // determine granularity if (!nGran) { CIccTagLutAtoB* pTag = (CIccTagLutAtoB*)pProfile->FindTag(icSigAToB0Tag+(nIntent==icAbsoluteColorimetric ? icRelativeColorimetric : nIntent)); if (!pTag || ndim==3) { nGran = 33; } else { CIccCLUT* pClut = pTag->GetCLUT(); if (pClut) nGran = pClut->GridPoints()+2; else nGran = 33; } } int i, j; icFloatNumber stepsize = (icFloatNumber)(1.0/(icFloatNumber)(nGran-1)); icFloatNumber* steps = new icFloatNumber[ndim1]; icFloatNumber nstart = 0.0; icFloatNumber nEnd = (icFloatNumber)(1.0+stepsize/2.0); for(j=0; j<ndim1; j++) { steps[j] = nstart; } while(steps[0]==nstart) { for(j=0; j<ndim; j++) { sPixel[j] = icMin(steps[j+1],1.0); } steps[ndim] = (steps[ndim]+stepsize); for(i=ndim; i>=0; i--) { if(steps[i]>nEnd) { steps[i] = nstart; steps[i-1] = (steps[i-1]+stepsize); } else break; } dev2Lab.Apply(devPcs, sPixel); //Convert device value to pcs from input table Lab2Dev2Lab.Apply(roundPcs1, devPcs); //First round trip gets color into output gamut Lab2Dev2Lab.Apply(roundPcs2, roundPcs1); //Second round trip find reproducibility error icLabFromPcs(devPcs); icLabFromPcs(roundPcs1); icLabFromPcs(roundPcs2); Compare(sPixel, devPcs, roundPcs1, roundPcs2); } delete[] steps; return icCmmStatOk; }
int main(int argc, icChar* argv[]) { int minargs = 4; // minimum number of arguments if(argc<minargs) { Usage(); return -1; } int nNumProfiles, temp; temp = argc - minargs; if(temp%2 != 0) { printf("\nMissing arguments!\n"); Usage(); return -1; } nNumProfiles = temp/2; std::ifstream InputData(argv[1]); if(!InputData) { printf("\nFile [%s] cannot be opened.\n", argv[1]); return false; } icChar ColorSig[7], tempBuf[5000]; InputData.getline(tempBuf, sizeof(tempBuf)); int i; for (i = 0; (i<4 || tempBuf[i+1]!='\'') && i < 6; i++) { ColorSig[i] = tempBuf[i+1]; } for (;i<7; i++) ColorSig[i] = '\0'; icColorSpaceSignature SrcspaceSig = (icColorSpaceSignature)icGetSigVal(ColorSig); int nSamples = icGetSpaceSamples(SrcspaceSig); if(SrcspaceSig != icSigNamedData) { if(!nSamples) { printf("Source color space signature not recognized.\n"); return -1; } } InputData.getline(tempBuf, sizeof(tempBuf)); sscanf(tempBuf, "%s", tempBuf); icFloatColorEncoding srcEncoding, destEncoding; srcEncoding = CIccCmm::GetFloatColorEncoding(tempBuf); if(srcEncoding == icEncodeUnknown) { printf("Source color data encoding not recognized.\n"); return false; } destEncoding = (icFloatColorEncoding)atoi(argv[2]); icXformInterp nInterp = (icXformInterp)atoi(argv[3]); int nIntent, nType; CIccNamedColorCmm namedCmm(SrcspaceSig, icSigUnknownData, !IsSpacePCS(SrcspaceSig)); IccProfilePtrList pccList; int nCount; bool bUseMPE; icCmmEnvSigMap sigMap; for(i = 0, nCount=minargs; i<nNumProfiles; i++, nCount+=2) { if (!strnicmp(argv[nCount], "-ENV:", 5)) { //check for -ENV: to allow for Cmm Environment variables to be defined for next transform icSignature sig = icGetSigVal(argv[nCount]+5); icFloatNumber val = (icFloatNumber)atof(argv[nCount+1]); sigMap[sig]=val; } else if (stricmp(argv[nCount], "-PCC")) { //check for -PCC arg to allow for profile connection conditions to be defined bUseMPE = true; nIntent = atoi(argv[nCount+1]); nType = abs(nIntent) / 10; nIntent = nIntent % 10; CIccProfile *pPccProfile = NULL; CIccCreateXformHintManager Hint; switch(nType) { case 1: nType = 0; bUseMPE = false; break; case 4: nType = 0; Hint.AddHint(new CIccApplyBPCHint()); break; } if (i+1<nNumProfiles && !stricmp(argv[nCount+2], "-PCC")) { pPccProfile = OpenIccProfile(argv[nCount+3]); if (!pPccProfile) { printf("Unable to open Profile Connections Conditions from '%s'\n", argv[nCount+3]); return -1; } //Keep track of pPccProfile for until after cmm.Begin is called pccList.push_back(pPccProfile); } if (sigMap.size()>0) { Hint.AddHint(new CIccCmmEnvVarHint(sigMap)); } if (namedCmm.AddXform(argv[nCount], nIntent<0 ? icUnknownIntent : (icRenderingIntent)nIntent, nInterp, pPccProfile, (icXformLutType)nType, bUseMPE, &Hint)) { printf("Invalid Profile: %s\n", argv[nCount]); return -1; } sigMap.clear(); } } icStatusCMM stat; if((stat=namedCmm.Begin())) { printf("Error %d - Unable to begin profile application - Possibly invalid or incompatible profiles\n", stat); return -1; } //Now we can release the pccProfile nodes. IccProfilePtrList::iterator pcc; for (pcc=pccList.begin(); pcc!=pccList.end(); pcc++) { CIccProfile *pPccProfile = *pcc; delete pPccProfile; } pccList.clear(); SrcspaceSig = namedCmm.GetSourceSpace(); int nSrcSamples = icGetSpaceSamples(SrcspaceSig); icColorSpaceSignature DestspaceSig = namedCmm.GetDestSpace(); int nDestSamples = icGetSpaceSamples(DestspaceSig); std::string OutPutData; char SrcNameBuf[256], DestNameBuf[256]; CIccPixelBuf SrcPixel(nSrcSamples+16), DestPixel(nDestSamples+16), Pixel(icIntMax(nSrcSamples, nDestSamples)+16); sprintf(tempBuf,"%s\t; ", icGetColorSig(tempBuf, DestspaceSig, false)); OutPutData += tempBuf; OutPutData += "Data Format\n"; if(DestspaceSig==icSigNamedData) destEncoding = icEncodeValue; sprintf(tempBuf, "%s\t; ", CIccCmm::GetFloatColorEncoding(destEncoding)); OutPutData += tempBuf; OutPutData += "Encoding\n\n"; OutPutData += ";Source Data Format: "; sprintf(tempBuf,"%s\n", icGetColorSig(tempBuf, SrcspaceSig, false)); OutPutData += tempBuf; if(SrcspaceSig==icSigNamedData) srcEncoding = icEncodeValue; OutPutData += ";Source Data Encoding: "; sprintf(tempBuf, "%s\n", CIccCmm::GetFloatColorEncoding(srcEncoding)); OutPutData += tempBuf; OutPutData += ";Source data is after semicolon\n"; OutPutData += "\n;Profiles applied\n"; for(i = 0, nCount=minargs; i<nNumProfiles; i++, nCount+=2) { OutPutData += "; "; if (stricmp(argv[nCount], "-PCC") && strnicmp(argv[nCount], "-ENV:", 5)) { if (i+1<nNumProfiles && !stricmp(argv[nCount+2], "-PCC")) { sprintf(tempBuf, "%s -PCC %s\n", argv[nCount], argv[nCount+3]); OutPutData += tempBuf; nCount += 2; nNumProfiles--; } else { sprintf(tempBuf, "%s\n", argv[nCount]); OutPutData += tempBuf; } } } OutPutData += "\n"; fwrite(OutPutData.c_str(), 1, OutPutData.length(), stdout); while(!InputData.eof()) { if(SrcspaceSig==icSigNamedData) { InputData.getline(tempBuf, sizeof(tempBuf)); if(!ParseName(SrcNameBuf, tempBuf)) continue; icChar *numptr = strstr(tempBuf, "\" }"); if (numptr) numptr+=3; icFloatNumber tint; if (!ParseNextNumber(tint, &numptr)) tint = 1.0; OutPutData.erase(); switch(namedCmm.GetInterface()) { case icApplyNamed2Pixel: { if(namedCmm.Apply(DestPixel, SrcNameBuf, tint)) { printf("Profile application failed.\n"); return -1; } if(CIccCmm::FromInternalEncoding(DestspaceSig, destEncoding, DestPixel, DestPixel, destEncoding!=icEncodeFloat)) { printf("Invalid final data encoding\n"); return -1; } for(i = 0; i<nDestSamples; i++) { sprintf(tempBuf, "%9.4lf ", DestPixel[i]); OutPutData += tempBuf; } OutPutData += "\t; "; break; } case icApplyNamed2Named: { if(namedCmm.Apply(DestNameBuf, SrcNameBuf, tint)) { printf("Profile application failed.\n"); return -1; } sprintf(tempBuf, "{ \"%s\" }\t; ", DestNameBuf); OutPutData += tempBuf; break; } case icApplyPixel2Pixel: case icApplyPixel2Named: default: printf("Incorrect interface.\n"); return -1; } if (tint==1.0) sprintf(tempBuf, "{ \"%s\" }\n", SrcNameBuf); else sprintf(tempBuf, "{ \"%s\" } %.4f\n", SrcNameBuf, tint); OutPutData += tempBuf; } else { InputData.getline(tempBuf, sizeof(tempBuf)); if(!ParseNumbers(Pixel, tempBuf, nSamples)) continue; OutPutData.erase(); if(CIccCmm::ToInternalEncoding(SrcspaceSig, srcEncoding, SrcPixel, Pixel)) { printf("Invalid source data encoding\n"); return -1; } switch(namedCmm.GetInterface()) { case icApplyPixel2Pixel: { if(namedCmm.Apply(DestPixel, SrcPixel)) { printf("Profile application failed.\n"); return -1; } if(CIccCmm::FromInternalEncoding(DestspaceSig, destEncoding, DestPixel, DestPixel)) { printf("Invalid final data encoding\n"); return -1; } for(i = 0; i<nDestSamples; i++) { sprintf(tempBuf, "%9.4lf ", DestPixel[i]); OutPutData += tempBuf; } OutPutData += "\t; "; break; } case icApplyPixel2Named: { if(namedCmm.Apply(DestNameBuf, SrcPixel)) { printf("Profile application failed.\n"); return -1; } sprintf(tempBuf, "{ \"%s\" }\t; ", DestNameBuf); OutPutData += tempBuf; break; } case icApplyNamed2Pixel: case icApplyNamed2Named: default: printf("Incorrect interface.\n"); return -1; } for(i = 0; i<nSamples; i++) { sprintf(tempBuf, "%9.4lf ", Pixel[i]); OutPutData += tempBuf; } OutPutData += "\n"; } fwrite(OutPutData.c_str(), 1, OutPutData.length(), stdout); } return 0; }