Blob Blame Raw


void filterIcy(Img *img, Img *icyCurve, Img *icyColor, double size, int withWind) {
  if (!img->data) return;
  size = fabs(size);
  if (!(size > IMG_PRECISION)) withWind = FALSE;

  const int    optNoiseWidth0 = (int)round(size/4);
  const int    optNoiseWidth1 = (int)round(size);
  const double optNoise0 = 1;
  const double optNoise1 = 0.75;
  const double optBright0 = 1.1;
  const double optBright1 = 1.4;

  const double optWind = 0.75;
  const int    optWindWidth0 = (int)round(size/4);
  const int    optWindWidth1 = (int)round(size/2);
  const double optWindNoise0 = 0.5;
  const double optWindNoise1 = 0.75;
  const double optWindAtt = withWind ? pow(0.95, 4/size) : 0;

  double blurSize = size/2;
  if (optNoiseWidth0) filterMulNoiseGray(img, img->w/optNoiseWidth0, img->h/optNoiseWidth0, 1-optNoise0, 1);
  if (optNoiseWidth1) filterMulNoiseGray(img, img->w/optNoiseWidth1, img->h/optNoiseWidth1, 1-optNoise1, 1);
  filterFillCh(img, 3, 1);
  filterBlurGauss(img, blurSize, blurSize);

  ClMat m;
  clmMulColor(&m, optBright0);
  filterMatrix(img, &m);

  if (icyCurve && icyCurve->data) {
    //int mi = 0;
    //for(int i = 1; i < icyCurve->w; ++i)
    //  if (imgPixel(icyCurve, i-1, 0)[0] - IMG_PRECISION <= imgPixel(icyCurve, i, 0)[0])
    //    mi = i; else break;
    int mi = 128;
    int mmi = size > 4 ? round(mi*4/size) : mi;
    if (mmi < mi && mi < icyCurve->w - 1) {
      Img imgA = {}, imgB = {};
      imgCropTo(&imgA, icyCurve, 0, 0, mi, icyCurve->h);
      filterResampleCubic(&imgA, mmi, icyCurve->h);
      imgInit(&imgB, icyCurve->w - mi + mmi + 1, icyCurve->h);
      imgCopyTo(&imgB, &imgA, 1, 0, 0, 0, imgA.w, imgA.h);
      imgCopyTo(&imgB, icyCurve, mmi + 1, 0, mi, 0, icyCurve->w - mi, icyCurve->h);
      filterFillCh(&imgB, 3, 1);
      filterCurveByCh(img, &imgB, 0);
      imgDestroy(&imgA);
      imgDestroy(&imgB);
    } else {
      filterCurveByCh(img, icyCurve, 0);
    }
  }

  clmMulColor(&m, optBright1);
  filterMatrix(img, &m);

  if (withWind) {
    Img wind = {};
    imgCopy(&wind, img);

    Img pat = {};
    imgInit(&pat, img->w, 1);
    double clOne[] = {1,1,1,1};
    filterFill(&pat, clOne);
    if (optWindWidth0) filterMulNoiseGray(&pat, img->w/optWindWidth0, 1, 1-optWindNoise0, 1);
    if (optWindWidth1) filterMulNoiseGray(&pat, img->w/optWindWidth1, 1, 1-optWindNoise1, 1);
    filterWind(&wind, &pat, optWindAtt);
    imgDestroy(&pat);

    filterBlend(&wind, img, &bfuncSum, -1);
    filterBlend(img, &wind, &bfuncSum, optWind);
    imgDestroy(&wind);
  }

  if (icyColor)
    filterCurveByCh(img, icyColor, 0);

  //clmScreenToCompositeYUV(&m);
  //filterMatrix(img, &m);
  filterScreenToCompositeHSV(img);
}


int icyGenerate(Img *img, int argc, char **argv) {
  if (img) imgDestroy(img);

  char *inFile = "", *outFile = "";
  char *curveFile = "data/icy-curve.tga", *colorFile = "data/icy-color.tga";
  double size = 4;
  int withWind = TRUE;
  int withoutWind = FALSE;
  ArgDesc descs[] = {
    { 'i', &inFile, &pargString, "path to input image" },
    { 'o', &outFile, &pargString, "path to output image" },
    { 'c', &curveFile, &pargString, "path to image with crystal curve" },
    { 'l', &colorFile, &pargString, "path to image with color curve" },
    { 's', &size, &pargDouble, "effect size" },
    { 'w', &withWind, NULL, "add icicles (default)" },
    { 'n', &withoutWind, NULL, "no icicles" },
    {}
  };

  if (!parseArgs(descs, argc, argv) || !inFile[0] || !outFile[0]) {
    printUsage(descs);
    return FALSE;
  }

  if (withoutWind) withWind = FALSE;

  Img imgC = {};
  Img imgCurve = {};
  Img imgColor = {};
  if (!imgLoad(&imgC, inFile))
    return FALSE;

  imgLoad(&imgCurve, curveFile);
  imgLoad(&imgColor, colorFile);
  filterIcy(&imgC, &imgCurve, &imgColor, size, withWind);

  if (!imgSave(&imgC, outFile))
    imgDestroy(&imgC);
  int success = !!imgC.data;

  if (img) imgSwap(img, &imgC);
  imgDestroy(&imgCurve);
  imgDestroy(&imgCurve);
  imgDestroy(&imgC);

  return success;
}