Exemple #1
0
static void tonemap(NodeTonemap* ntm, CompBuf* dst, CompBuf* src)
{
	int x, y;
	float dr, dg, db, al, igm = (ntm->gamma==0.f) ? 1 : (1.f / ntm->gamma);
	float auto_key, Lav, Cav[3] = {0, 0, 0};

	al = avgLogLum(src, &auto_key, &Lav, Cav);
	al = (al == 0.f) ? 0.f : (ntm->key / al);

	if (ntm->type == 1) {
		// Reinhard/Devlin photoreceptor
		const float f = exp((double)-ntm->f);
		const float m = (ntm->m > 0.f) ? ntm->m : (0.3f + 0.7f*pow((double)auto_key, 1.4));
		const float ic = 1.f - ntm->c, ia = 1.f - ntm->a;
		if (ntm->m == 0.f) printf("tonemap node, M: %g\n", m); 
		for (y=0; y<src->y; ++y) {
			fRGB* sp = (fRGB*)&src->rect[y*src->x*src->type];
			fRGB* dp = (fRGB*)&dst->rect[y*src->x*src->type];
			for (x=0; x<src->x; ++x) {
				const float L = 0.212671f*sp[x][0] + 0.71516f*sp[x][1] + 0.072169f*sp[x][2];
				float I_l = sp[x][0] + ic*(L - sp[x][0]);
				float I_g = Cav[0] + ic*(Lav - Cav[0]);
				float I_a = I_l + ia*(I_g - I_l);
				dp[x][0] /= (dp[x][0] + pow((double)f*I_a, (double)m));
				I_l = sp[x][1] + ic*(L - sp[x][1]);
				I_g = Cav[1] + ic*(Lav - Cav[1]);
				I_a = I_l + ia*(I_g - I_l);
				dp[x][1] /= (dp[x][1] + pow((double)f*I_a,(double)m));
				I_l = sp[x][2] + ic*(L - sp[x][2]);
				I_g = Cav[2] + ic*(Lav - Cav[2]);
				I_a = I_l + ia*(I_g - I_l);
				dp[x][2] /= (dp[x][2] + pow((double)f*I_a, (double)m));
			}
		}
		return;
	}

	// Reinhard simple photographic tm (simplest, not using whitepoint var)
	for (y=0; y<src->y; y++) {
		fRGB* sp = (fRGB*)&src->rect[y*src->x*src->type];
		fRGB* dp = (fRGB*)&dst->rect[y*src->x*src->type];
		for (x=0; x<src->x; x++) {
			fRGB_copy(dp[x], sp[x]);
			fRGB_mult(dp[x], al);
			dr = dp[x][0] + ntm->offset;
			dg = dp[x][1] + ntm->offset;
			db = dp[x][2] + ntm->offset;
			dp[x][0] /= ((dr == 0.f) ? 1.f : dr);
			dp[x][1] /= ((dg == 0.f) ? 1.f : dg);
			dp[x][2] /= ((db == 0.f) ? 1.f : db);
			if (igm != 0.f) {
				dp[x][0] = pow((double)MAX2(dp[x][0], 0.), igm);
				dp[x][1] = pow((double)MAX2(dp[x][1], 0.), igm);
				dp[x][2] = pow((double)MAX2(dp[x][2], 0.), igm);
			}
		}
	}
}
Exemple #2
0
// mix two images, src buffer does not have to be same size,
static void mixImages(CompBuf *dst, CompBuf *src, float mix)
{
	int x, y;
	fRGB c1, c2, *dcolp, *scolp;
	const float mf = 2.f - 2.f*fabsf(mix - 0.5f);
	if ((dst->x == src->x) && (dst->y == src->y)) {
		for (y=0; y<dst->y; y++) {
			dcolp = (fRGB*)&dst->rect[y*dst->x*dst->type];
			scolp = (fRGB*)&src->rect[y*dst->x*dst->type];
			for (x=0; x<dst->x; x++) {
				fRGB_copy(c1, dcolp[x]);
				fRGB_copy(c2, scolp[x]);
				c1[0] += mix*(c2[0] - c1[0]);
				c1[1] += mix*(c2[1] - c1[1]);
				c1[2] += mix*(c2[2] - c1[2]);
				if (c1[0] < 0.f) c1[0] = 0.f;
				if (c1[1] < 0.f) c1[1] = 0.f;
				if (c1[2] < 0.f) c1[2] = 0.f;
				fRGB_mult(c1, mf);
				fRGB_copy(dcolp[x], c1);
			}
		}
	}
	else {
		float xr = src->x / (float)dst->x;
		float yr = src->y / (float)dst->y;
		for (y=0; y<dst->y; y++) {
			dcolp = (fRGB*)&dst->rect[y*dst->x*dst->type];
			for (x=0; x<dst->x; x++) {
				fRGB_copy(c1, dcolp[x]);
				qd_getPixelLerp(src, (x + 0.5f)*xr - 0.5f, (y + 0.5f)*yr - 0.5f, c2);
				c1[0] += mix*(c2[0] - c1[0]);
				c1[1] += mix*(c2[1] - c1[1]);
				c1[2] += mix*(c2[2] - c1[2]);
				if (c1[0] < 0.f) c1[0] = 0.f;
				if (c1[1] < 0.f) c1[1] = 0.f;
				if (c1[2] < 0.f) c1[2] = 0.f;
				fRGB_mult(c1, mf);
				fRGB_copy(dcolp[x], c1);
			}
		}
	}
}
Exemple #3
0
static float avgLogLum(CompBuf *src, float* auto_key, float* Lav, float* Cav)
{
	float lsum = 0;
	int p = src->x*src->y;
	fRGB* bc = (fRGB*)src->rect;
	float avl, maxl = -1e10f, minl = 1e10f;
	const float sc = 1.f/(src->x*src->y);
	*Lav = 0.f;
	while (p--) {
		float L = 0.212671f*bc[0][0] + 0.71516f*bc[0][1] + 0.072169f*bc[0][2];
		*Lav += L;
		fRGB_add(Cav, bc[0]);
		lsum += (float)log((double)MAX2(L, 0.0) + 1e-5);
		maxl = (L > maxl) ? L : maxl;
		minl = (L < minl) ? L : minl;
		bc++;
	}
	*Lav *= sc;
	fRGB_mult(Cav, sc);
	maxl = log((double)maxl + 1e-5); minl = log((double)minl + 1e-5f); avl = lsum*sc;
	*auto_key = (maxl > minl) ? ((maxl - avl) / (maxl - minl)) : 1.f;
	return exp((double)avl);
}
Exemple #4
0
static void fglow(NodeGlare* ndg, CompBuf* dst, CompBuf* src)
{
	int x, y;
	float scale, u, v, r, w, d;
	fRGB fcol;
	CompBuf *tsrc, *ckrn;
	unsigned int sz = 1 << ndg->size;
	const float cs_r = 1.f, cs_g = 1.f, cs_b = 1.f;

	// temp. src image
	tsrc = BTP(src, ndg->threshold, 1 << ndg->quality);
	// make the convolution kernel
	ckrn = alloc_compbuf(sz, sz, CB_RGBA, 1);

	scale = 0.25f*sqrtf(sz*sz);

	for (y=0; y<sz; ++y) {
		v = 2.f*(y / (float)sz) - 1.f;
		for (x=0; x<sz; ++x) {
			u = 2.f*(x / (float)sz) - 1.f;
			r = (u*u + v*v)*scale;
			d = -sqrtf(sqrtf(sqrtf(r)))*9.f;
			fcol[0] = expf(d*cs_r), fcol[1] = expf(d*cs_g), fcol[2] = expf(d*cs_b);
			// linear window good enough here, visual result counts, not scientific analysis
			//w = (1.f-fabs(u))*(1.f-fabs(v));
			// actually, Hanning window is ok, cos^2 for some reason is slower
			w = (0.5f + 0.5f*cos((double)u*M_PI))*(0.5f + 0.5f*cos((double)v*M_PI));
			fRGB_mult(fcol, w);
			qd_setPixel(ckrn, x, y, fcol);
		}
	}

	convolve(tsrc, tsrc, ckrn);
	free_compbuf(ckrn);
	mixImages(dst, tsrc, 0.5f + 0.5f*ndg->mix);
	free_compbuf(tsrc);
}
Exemple #5
0
static void ghosts(NodeGlare* ndg, CompBuf* dst, CompBuf* src)
{
	// colormodulation and scale factors (cm & scalef) for 16 passes max: 64
	int x, y, n, p, np;
	fRGB c, tc, cm[64];
	float sc, isc, u, v, sm, s, t, ofs, scalef[64];
	CompBuf *tbuf1, *tbuf2, *gbuf;
	const float cmo = 1.f - ndg->colmod;
	const int qt = 1 << ndg->quality;
	const float s1 = 4.f/(float)qt, s2 = 2.f*s1;

	gbuf = BTP(src, ndg->threshold, qt);
	tbuf1 = dupalloc_compbuf(gbuf);
	IIR_gauss(tbuf1, s1, 0, 3);
	IIR_gauss(tbuf1, s1, 1, 3);
	IIR_gauss(tbuf1, s1, 2, 3);
	tbuf2 = dupalloc_compbuf(tbuf1);
	IIR_gauss(tbuf2, s2, 0, 3);
	IIR_gauss(tbuf2, s2, 1, 3);
	IIR_gauss(tbuf2, s2, 2, 3);

	if (ndg->iter & 1) ofs = 0.5f; else ofs = 0.f;
	for (x=0; x<(ndg->iter*4); x++) {
		y = x & 3;
		cm[x][0] = cm[x][1] = cm[x][2] = 1;
		if (y==1) fRGB_rgbmult(cm[x], 1.f, cmo, cmo);
		if (y==2) fRGB_rgbmult(cm[x], cmo, cmo, 1.f);
		if (y==3) fRGB_rgbmult(cm[x], cmo, 1.f, cmo);
		scalef[x] = 2.1f*(1.f-(x+ofs)/(float)(ndg->iter*4));
		if (x & 1) scalef[x] = -0.99f/scalef[x];
	}

	sc = 2.13;
	isc = -0.97;
	for (y=0; y<gbuf->y; y++) {
		v = (float)(y+0.5f) / (float)gbuf->y;
		for (x=0; x<gbuf->x; x++) {
			u = (float)(x+0.5f) / (float)gbuf->x;
			s = (u-0.5f)*sc + 0.5f, t = (v-0.5f)*sc + 0.5f;
			qd_getPixelLerp(tbuf1, s*gbuf->x, t*gbuf->y, c);
			sm = smoothMask(s, t);
			fRGB_mult(c, sm);
			s = (u-0.5f)*isc + 0.5f, t = (v-0.5f)*isc + 0.5f;
			qd_getPixelLerp(tbuf2, s*gbuf->x - 0.5f, t*gbuf->y - 0.5f, tc);
			sm = smoothMask(s, t);
			fRGB_madd(c, tc, sm);
			qd_setPixel(gbuf, x, y, c);
		}
	}

	memset(tbuf1->rect, 0, tbuf1->x*tbuf1->y*tbuf1->type*sizeof(float));
	for (n=1; n<ndg->iter; n++) {
		for (y=0; y<gbuf->y; y++) {
			v = (float)(y+0.5f) / (float)gbuf->y;
			for (x=0; x<gbuf->x; x++) {
				u = (float)(x+0.5f) / (float)gbuf->x;
				tc[0] = tc[1] = tc[2] = 0.f;
				for (p=0;p<4;p++) {
					np = (n<<2) + p;
					s = (u-0.5f)*scalef[np] + 0.5f;
					t = (v-0.5f)*scalef[np] + 0.5f;
					qd_getPixelLerp(gbuf, s*gbuf->x - 0.5f, t*gbuf->y - 0.5f, c);
					fRGB_colormult(c, cm[np]);
					sm = smoothMask(s, t)*0.25f;
					fRGB_madd(tc, c, sm);
				}
				p = (x + y*tbuf1->x)*tbuf1->type;
				tbuf1->rect[p] += tc[0];
				tbuf1->rect[p+1] += tc[1];
				tbuf1->rect[p+2] += tc[2];
			}
		}
		memcpy(gbuf->rect, tbuf1->rect, tbuf1->x*tbuf1->y*tbuf1->type*sizeof(float));
	}

	free_compbuf(tbuf1);
	free_compbuf(tbuf2);

	mixImages(dst, gbuf, 0.5f + 0.5f*ndg->mix);
	free_compbuf(gbuf);
}
Exemple #6
0
static void star4(NodeGlare* ndg, CompBuf* dst, CompBuf* src)
{
	int x, y, i, xm, xp, ym, yp;
	float c[4] = {0,0,0,0}, tc[4] = {0,0,0,0};
	CompBuf *tbuf1, *tbuf2, *tsrc;
	const float f1 = 1.f - ndg->fade, f2 = (1.f - f1)*0.5f;
	//const float t3 = ndg->threshold*3.f;
	const float sc = (float)(1 << ndg->quality);
	const float isc = 1.f/sc;

	tsrc = BTP(src, ndg->threshold, (int)sc);

	tbuf1 = dupalloc_compbuf(tsrc);
	tbuf2 = dupalloc_compbuf(tsrc);

	for (i=0; i<ndg->iter; i++) {
		// (x || x-1, y-1) to (x || x+1, y+1)
		// F
		for (y=0; y<tbuf1->y; y++) {
			ym = y - i;
			yp = y + i;
			for (x=0; x<tbuf1->x; x++) {
				xm = x - i;
				xp = x + i;
				qd_getPixel(tbuf1, x, y, c);
				fRGB_mult(c, f1);
				qd_getPixel(tbuf1, (ndg->angle ? xm : x), ym, tc);
				fRGB_madd(c, tc, f2);
				qd_getPixel(tbuf1, (ndg->angle ? xp : x), yp, tc);
				fRGB_madd(c, tc, f2);
				qd_setPixel(tbuf1, x, y, c);
			}
		}
		// B
		for (y=tbuf1->y-1; y>=0; y--) {
			ym = y - i;
			yp = y + i;
			for (x=tbuf1->x-1; x>=0; x--) {
				xm = x - i;
				xp = x + i;
				qd_getPixel(tbuf1, x, y, c);
				fRGB_mult(c, f1);
				qd_getPixel(tbuf1, (ndg->angle ? xm : x), ym, tc);
				fRGB_madd(c, tc, f2);
				qd_getPixel(tbuf1, (ndg->angle ? xp : x), yp, tc);
				fRGB_madd(c, tc, f2);
				qd_setPixel(tbuf1, x, y, c);
			}
		}
		// (x-1, y || y+1) to (x+1, y || y-1)
		// F
		for (y=0; y<tbuf2->y; y++) {
			ym = y - i;
			yp = y + i;
			for (x=0; x<tbuf2->x; x++) {
				xm = x - i;
				xp = x + i;
				qd_getPixel(tbuf2, x, y, c);
				fRGB_mult(c, f1);
				qd_getPixel(tbuf2, xm, (ndg->angle ? yp : y), tc);
				fRGB_madd(c, tc, f2);
				qd_getPixel(tbuf2, xp, (ndg->angle ? ym : y), tc);
				fRGB_madd(c, tc, f2);
				qd_setPixel(tbuf2, x, y, c);
			}
		}
		// B
		for (y=tbuf2->y-1; y>=0; y--) {
			ym = y - i;
			yp = y + i;
			for (x=tbuf2->x-1; x>=0; x--) {
				xm = x - i;
				xp = x + i;
				qd_getPixel(tbuf2, x, y, c);
				fRGB_mult(c, f1);
				qd_getPixel(tbuf2, xm, (ndg->angle ? yp : y), tc);
				fRGB_madd(c, tc, f2);
				qd_getPixel(tbuf2, xp, (ndg->angle ? ym : y), tc);
				fRGB_madd(c, tc, f2);
				qd_setPixel(tbuf2, x, y, c);
			}
		}
	}

	for (y=0; y<tbuf1->y; ++y)
		for (x=0; x<tbuf1->x; ++x) {
			unsigned int p = (x + y*tbuf1->x)*tbuf1->type;
			tbuf1->rect[p] += tbuf2->rect[p];
			tbuf1->rect[p+1] += tbuf2->rect[p+1];
			tbuf1->rect[p+2] += tbuf2->rect[p+2];
		}

	for (y=0; y<dst->y; ++y) {
		const float m = 0.5f + 0.5f*ndg->mix;
		for (x=0; x<dst->x; ++x) {
			unsigned int p = (x + y*dst->x)*dst->type;
			qd_getPixelLerp(tbuf1, x*isc, y*isc, tc);
			dst->rect[p] = src->rect[p] + m*(tc[0] - src->rect[p]);
			dst->rect[p+1] = src->rect[p+1] + m*(tc[1] - src->rect[p+1]);
			dst->rect[p+2] = src->rect[p+2] + m*(tc[2] - src->rect[p+2]);
		}
	}

	free_compbuf(tbuf1);
	free_compbuf(tbuf2);
	free_compbuf(tsrc);
}