Esempio n. 1
0
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;
}
Esempio n. 2
0
int main(int argc, char* argv[])
{
  int nArg = 1;

  if (argc<=1) {
    printf("Usage: iccGamutMapGirdle profile num_hue {rendering_intent=3 {use_mpe=0}}\n");
    printf("  where\n");
	  printf("   num_hue is number of equal spaced hue steps\n");
	  printf("   rendering_intent is (0=perceptual, 1=relative, 2=saturation, 3=absolute)\n");
    return -1;
  }

  icRenderingIntent nIntent = icAbsoluteColorimetric;
  int nUseMPE = 0;
  int nHueSteps = atoi(argv[2]);

  if (argc>3) {
    nIntent = (icRenderingIntent)atoi(argv[3]);
    if (argc>4) {
      nUseMPE = atoi(argv[4]);
    }
  }

  CIccCmm cmm(icSigLabData, icSigLabData, false);

  if (cmm.AddXform(argv[1], nIntent, icInterpTetrahedral, icXformLutColor, nUseMPE==1)!=icCmmStatOk) {
    printf("Unable to add '%s' to cmm\n", argv[1]);
    return -2;
  }
  if (cmm.AddXform(argv[1], nIntent, icInterpTetrahedral, icXformLutColor, nUseMPE==1)!=icCmmStatOk) {
    printf("Unable to append '%s' to cmm\n", argv[1]);
    return -2;
  }

  if (cmm.Begin()!=icCmmStatOk) {
    printf("Unable to begin profile apply\n");
    return -3;
  }
  
  icFloatNumber pixel[16], bestLCH[3];

  icFloatNumber hue, hueStep;
  icFloatNumber Lval, Cval;
  icFloatNumber maxC;

  hueStep = 360.0f /(icFloatNumber)nHueSteps;

  printf("L*\tC*\tH*\n");
  for (hue=0.0; hue<360.0; hue += hueStep) {
    maxC=-10;
    memset(bestLCH, 0, sizeof(bestLCH));
    for (Lval = 100.0; Lval>=0.0; Lval-=.5) {
      pixel[0] = Lval;
      pixel[1] = 128;
      pixel[2] = hue;
      icLch2Lab(pixel);
      icLabToPcs(pixel);

      cmm.Apply(pixel,pixel);

      icLabFromPcs(pixel);
      icLab2Lch(pixel);
      if (pixel[1]>maxC) {
        maxC = pixel[1];
        memcpy(bestLCH, pixel, 3*sizeof(icFloatNumber));
      }
    }
    for (Cval=25; Cval<128; Cval+=.5) {
      pixel[0] = 100;
      pixel[1] = Cval;
      pixel[2] = hue;
      icLch2Lab(pixel);
      icLabToPcs(pixel);

      cmm.Apply(pixel,pixel);

      icLabFromPcs(pixel);
      icLab2Lch(pixel);
      if (pixel[1]>maxC) {
        maxC = pixel[1];
        memcpy(bestLCH, pixel, 3*sizeof(icFloatNumber));
      }

      pixel[0] = 0;
      pixel[1] = Cval;
      pixel[2] = hue;
      icLch2Lab(pixel);
      icLabToPcs(pixel);

      cmm.Apply(pixel,pixel);

      icLabFromPcs(pixel);
      icLab2Lch(pixel);
      if (pixel[1]>maxC) {
        maxC = pixel[1];
        memcpy(bestLCH, pixel, 3*sizeof(icFloatNumber));
      }
    }
    printf("%.2f\t%.2f\t%.2f\n", bestLCH[0], bestLCH[1], bestLCH[2]);
  }

  return 0;
}
bool Apply(const char *szSrcImage,
           const char *szSrcProfile,
           const char *szDstProfile,
           const char *szDstImage,
           int nIntent)
{
  unsigned long i, j, k, sn, sphoto, dn, photo, space;
  CTiffImg SrcImg, DstImg;
  CIccCmm cmm;
  unsigned char *sptr, *dptr;
  bool bSuccess = true;
  bool bConvert = false;

  if (cmm.AddXform(szSrcProfile, nIntent<0 ? icUnknownIntent : (icRenderingIntent)nIntent/*, icInterpTetrahedral*/)) {
    printf("Invalid Profile:  %s\n", szSrcProfile);
    return false;
  }
  
  if (szDstProfile && *szDstProfile && cmm.AddXform(szDstProfile/*, icUnknownIntent, icInterpTetrahedral*/)) {
    printf("Invalid Profile:  %s\n", szDstProfile);
    return false;
  }

  if (cmm.Begin() != icCmmStatOk) {
    printf("Invalid Profile:\n  %s\n  %s'\n", szSrcProfile, szDstProfile);
    return false;
  }

  if (!SrcImg.Open(szSrcImage)) {
    printf("Invalid Tiff file - '%s'\n", szSrcImage);
    return false;
  }
  sn = SrcImg.GetSamples();
  sphoto = SrcImg.GetPhoto();
  space = cmm.GetSourceSpace();

  if (SrcImg.GetBitsPerSample()!=8 ||
      !((space==icSigRgbData && sn==3 && sphoto==PHOTO_MINISBLACK) ||
        (space==icSigLabData && sn==3 && sphoto==PHOTO_CIELAB) ||
        (space==icSigXYZData && sn==3 && sphoto==PHOTO_CIELAB) ||
        (space==icSigCmykData && sn==4 && sphoto==PHOTO_MINISWHITE) ||
        (space==icSigMCH4Data && sn==4 && sphoto==PHOTO_MINISWHITE) ||
        (space==icSigMCH5Data && sn==5 && sphoto==PHOTO_MINISWHITE) ||
        (space==icSigMCH6Data && sn==6 && sphoto==PHOTO_MINISWHITE))) {
    printf("Invalid source profile/image pixel format\n");
    return false;
  }

  switch (cmm.GetDestSpace()) {
  case icSigRgbData:
    photo = PHOTO_MINISBLACK;
    dn = 3;
    break;

  case icSigCmyData:
    photo = PHOTO_MINISWHITE;
    dn = 3;
    break;

  case icSigXYZData:
    bConvert = true;
    //Fall through - No break here

  case icSigLabData:
    photo = PHOTO_CIELAB;
    dn = 3;
    break;

  case icSigCmykData:
  case icSig4colorData:
    photo = PHOTO_MINISWHITE;
    dn = 4;
    break;

  case icSig5colorData:
    photo = PHOTO_MINISWHITE;
    dn = 5;
    break;

  case icSig6colorData:
    photo = PHOTO_MINISWHITE;
    dn = 6;
    break;

  case icSig7colorData:
    photo = PHOTO_MINISWHITE;
    dn = 7;
    break;

  case icSig8colorData:
    photo = PHOTO_MINISWHITE;
    dn = 8;
    break;

  default:
    printf("Invalid destination profile/image pixel format\n");
    return false;
  }

  if (!DstImg.Create(szDstImage, SrcImg.GetWidth(), SrcImg.GetHeight(), 8, photo, dn, SrcImg.GetXRes(), SrcImg.GetYRes(), false)) {
    printf("Unable to create Tiff file - '%s'\n", szDstImage);
    return false;
  }

  unsigned char *pSBuf = (unsigned char *)malloc(SrcImg.GetBytesPerLine());
  unsigned char *pDBuf = (unsigned char *)malloc(DstImg.GetBytesPerLine());
  icFloatNumber Pixel[16];

  if (!pSBuf) {
    printf("Out of Memory!\n");
    return false;
  }

  if (!pDBuf) {
    printf("Out of Memory!\n");
    free(pSBuf);
    return false;
  }

  for (i=0; i<SrcImg.GetHeight(); i++) {
    if (!SrcImg.ReadLine(pSBuf)) {
      bSuccess = false;
      break;
    }
    for (sptr=pSBuf, dptr=pDBuf, j=0; j<SrcImg.GetWidth(); j++, sptr+=sn, dptr+=dn) {
      if (sphoto==PHOTO_CIELAB) {
        Pixel[0] = (icFloatNumber)sptr[0] / 255.0f;
        Pixel[1] = ((icFloatNumber)((signed char)sptr[1]) + 128.0f) / 255.0f;
        Pixel[2] = ((icFloatNumber)((signed char)sptr[2]) + 128.0f) / 255.0f;

        if (space==icSigXYZData) {
          icLabFromPcs(Pixel);

          icLabtoXYZ(Pixel);

          icXyzToPcs(Pixel);
        }
      }
      else {
        for (k=0; k<sn; k++) {
          Pixel[k] = (icFloatNumber)sptr[k] / 255.0f;
        }
      }

      cmm.Apply(Pixel, Pixel);

      if (photo==PHOTO_CIELAB) {
        if (bConvert) {
          icXyzFromPcs(Pixel);

          icXYZtoLab(Pixel);

          icLabToPcs(Pixel);
        }
        dptr[0] = (unsigned char)(UnitClip(Pixel[0]) * 255.0 + 0.5);
        dptr[1] = (unsigned char)(UnitClip(Pixel[1]) * 255.0 - 128.0);
        dptr[2] = (unsigned char)(UnitClip(Pixel[2]) * 255.0 - 128.0);
      }
      else {
        for (k=0; k<dn; k++) {
          dptr[k] = (unsigned char)(UnitClip(Pixel[k]) * 255.0 + 0.5);
        }
      }
    }
    if (!DstImg.WriteLine(pDBuf)) {
      bSuccess = false;
      break;
    }
  }

  SrcImg.Close();

  free(pSBuf);
  free(pDBuf);

  return bSuccess;
}