|
|
608c44 |
|
|
|
608c44 |
|
|
|
608c44 |
void filterIcy(Img *img, double size, int withWind) {
|
|
|
608c44 |
if (!img->data) return;
|
|
|
608c44 |
size = fabs(size);
|
|
|
608c44 |
if (!(size > IMG_PRECISION)) withWind = FALSE;
|
|
|
608c44 |
|
|
|
608c44 |
const int optNoiseWidth0 = (int)round(size/4);
|
|
|
608c44 |
const int optNoiseWidth1 = (int)round(size);
|
|
|
608c44 |
const double optNoise0 = 1;
|
|
|
608c44 |
const double optNoise1 = 0.75;
|
|
|
608c44 |
const double optBright0 = 1.1;
|
|
|
608c44 |
const double optBright1 = 1.4;
|
|
|
608c44 |
|
|
|
608c44 |
const double optWind = 0.75;
|
|
|
608c44 |
const int optWindWidth0 = (int)round(size/4);
|
|
|
608c44 |
const int optWindWidth1 = (int)round(size/2);
|
|
|
608c44 |
const double optWindNoise0 = 0.5;
|
|
|
608c44 |
const double optWindNoise1 = 0.75;
|
|
|
608c44 |
const double optWindAtt = withWind ? pow(0.95, 4/size) : 0;
|
|
|
608c44 |
|
|
|
608c44 |
double curve[][3] = {
|
|
|
608c44 |
{ 0 , 0 , 0 },
|
|
|
608c44 |
{ 0.15, 0.65, 0 },
|
|
|
608c44 |
{ 0.35, 0.15, 0 },
|
|
|
608c44 |
{ 0.65, 0.85, 0 },
|
|
|
608c44 |
{ 0.85, 0.35, 0 },
|
|
|
608c44 |
{ 1 , 1 , 0 } };
|
|
|
608c44 |
double curveColor[][5] = {
|
|
|
608c44 |
{ 0 , 0 , 0 , 0 , 1 },
|
|
|
608c44 |
{ 0.6, 0.4, 0.4, 0.6, 1 },
|
|
|
608c44 |
{ 1 , 1 , 1 , 1 , 1 } };
|
|
|
608c44 |
|
|
|
608c44 |
|
|
|
608c44 |
double blurSize = size/2;
|
|
|
608c44 |
if (optNoiseWidth0) filterMulNoiseGray(img, img->w/optNoiseWidth0, img->h/optNoiseWidth0, 1-optNoise0, 1);
|
|
|
608c44 |
if (optNoiseWidth1) filterMulNoiseGray(img, img->w/optNoiseWidth1, img->h/optNoiseWidth1, 1-optNoise1, 1);
|
|
|
608c44 |
filterFillCh(img, 3, 1);
|
|
|
608c44 |
filterBlurGauss(img, blurSize, blurSize);
|
|
|
608c44 |
|
|
|
608c44 |
ClMat m;
|
|
|
608c44 |
clmMulColor(&m, optBright0);
|
|
|
608c44 |
filterMatrix(img, &m);
|
|
|
608c44 |
|
|
|
608c44 |
Img imgC = {};
|
|
|
608c44 |
imgInit(&imgC, 512, 1);
|
|
|
608c44 |
|
|
|
608c44 |
curve[0][0] = curve[1][0]*(1 - 4/size);
|
|
|
608c44 |
filterRasterizeTCurve(&imgC, curve[0], sizeof(curve)/sizeof(*curve), curve[0][0], 1);
|
|
|
608c44 |
filterFillCh(&imgC, 3, 1);
|
|
|
608c44 |
filterCurveByCh(img, &imgC, 0);
|
|
|
608c44 |
|
|
|
608c44 |
clmMulColor(&m, optBright1);
|
|
|
608c44 |
filterMatrix(img, &m);
|
|
|
608c44 |
|
|
|
608c44 |
if (withWind) {
|
|
|
608c44 |
Img wind = {};
|
|
|
608c44 |
imgCopy(&wind, img);
|
|
|
608c44 |
|
|
|
608c44 |
Img pat = {};
|
|
|
608c44 |
imgInit(&pat, img->w, 1);
|
|
|
608c44 |
double clOne[] = {1,1,1,1};
|
|
|
608c44 |
filterFill(&pat, clOne);
|
|
|
608c44 |
if (optWindWidth0) filterMulNoiseGray(&pat, img->w/optWindWidth0, 1, 1-optWindNoise0, 1);
|
|
|
608c44 |
if (optWindWidth1) filterMulNoiseGray(&pat, img->w/optWindWidth1, 1, 1-optWindNoise1, 1);
|
|
|
608c44 |
filterWind(&wind, &pat, optWindAtt);
|
|
|
608c44 |
imgDestroy(&pat);
|
|
|
608c44 |
|
|
|
608c44 |
filterBlend(&wind, img, &bfuncSum, -1);
|
|
|
608c44 |
filterBlend(img, &wind, &bfuncSum, optWind);
|
|
|
608c44 |
imgDestroy(&wind);
|
|
|
608c44 |
}
|
|
|
608c44 |
|
|
|
608c44 |
filterRasterizeCurveColor(&imgC, curveColor[0], sizeof(curveColor)/sizeof(*curveColor), 0, 1);
|
|
|
608c44 |
filterCurveByCh(img, &imgC, 0);
|
|
|
608c44 |
imgDestroy(&imgC);
|
|
|
608c44 |
|
|
|
608c44 |
//clmScreenToCompositeYUV(&m);
|
|
|
608c44 |
//filterMatrix(img, &m);
|
|
|
608c44 |
filterScreenToCompositeHSV(img);
|
|
|
608c44 |
}
|
|
|
608c44 |
|
|
|
608c44 |
|
|
|
608c44 |
int icyGenerate(Img *img, int argc, char **argv) {
|
|
|
608c44 |
if (img) imgDestroy(img);
|
|
|
608c44 |
|
|
|
608c44 |
char *inFile = "", *outFile = "";
|
|
|
608c44 |
double size = 4;
|
|
|
608c44 |
int withWind = TRUE;
|
|
|
608c44 |
int withoutWind = FALSE;
|
|
|
608c44 |
ArgDesc descs[] = {
|
|
|
608c44 |
{ 'i', &inFile, &pargString, "path to input image" },
|
|
|
608c44 |
{ 'o', &outFile, &pargString, "path to output image" },
|
|
|
608c44 |
{ 's', &size, &pargDouble, "effect size" },
|
|
|
608c44 |
{ 'w', &withWind, NULL, "add icicles (default)" },
|
|
|
608c44 |
{ 'n', &withoutWind, NULL, "no icicles" },
|
|
|
608c44 |
{}
|
|
|
608c44 |
};
|
|
|
608c44 |
|
|
|
608c44 |
if (!parseArgs(descs, argc, argv) || !inFile[0] || !outFile[0]) {
|
|
|
608c44 |
printUsage(descs);
|
|
|
608c44 |
return FALSE;
|
|
|
608c44 |
}
|
|
|
608c44 |
|
|
|
608c44 |
if (withoutWind) withWind = FALSE;
|
|
|
608c44 |
|
|
|
608c44 |
Img imgC = {};
|
|
|
608c44 |
if (!imgLoad(&imgC, inFile))
|
|
|
608c44 |
return FALSE;
|
|
|
608c44 |
|
|
|
608c44 |
filterIcy(&imgC, size, withWind);
|
|
|
608c44 |
|
|
|
608c44 |
if (!imgSave(&imgC, outFile))
|
|
|
608c44 |
imgDestroy(&imgC);
|
|
|
608c44 |
int success = !!imgC.data;
|
|
|
608c44 |
|
|
|
608c44 |
if (img) imgSwap(img, &imgC);
|
|
|
608c44 |
imgDestroy(&imgC);
|
|
|
608c44 |
|
|
|
608c44 |
return success;
|
|
|
608c44 |
}
|
|
|
608c44 |
|
|
|
608c44 |
|