void	ImageMean<T>::compute(int x, int y, T darkvalue) {
	// if the dark value is invalid, then the computed value
	// is also invalid
	if (darkvalue != darkvalue) {
		image->pixel(x, y) = darkvalue;
		var->pixel(x, y) = darkvalue;
		return;
	}

	// perform mean (and possibly variance) computation in the
	// case where 
	//T	m;
	T	X = 0, X2 = 0;
	typename std::vector<PV>::const_iterator j;
	unsigned int	counter = 0;
	for (j = pvs.begin(); j != pvs.end(); j++) {
		T	v = j->pixelvalue(x, y);
		// skip this value if it is a NaN
		if (v != v)
			continue;
		if (v < darkvalue) {
			v = 0;
		} else {
			v = v - darkvalue;
		}
		X += v;
		if (enableVariance) {
			X2 += v * v;
		}
		counter++;
	}
	if (counter != pvs.size()) {
		debug(LOG_DEBUG, DEBUG_LOG, 0, "bad pixel values at (%d, %d): %d", x, y, counter);
	}
	T	EX = X / counter;
	T	EX2 = 0;
	if (enableVariance) {
		EX2 = X2 / counter;
	}

	// if we don't have the variance, we leave it at that
	if (!enableVariance) {
		image->pixel(x, y) = EX;
		return;
	}

	// if the variance is enabled, then we can do the computation
	// again, and ignore not only the bad values, but also the
	// ones that are more then 3 standard deviations away from 
	// the mean
	X = 0, X2 = 0;
	counter = 0;
	T	stddevk = k * sqrt(EX2 - EX * EX);
	if (stddevk < 1) {
		stddevk = std::numeric_limits<T>::infinity();
	}
	for (j = pvs.begin(); j != pvs.end(); j++) {
		T	v = j->pixelvalue(x, y);
		// skip NaNs
		if (v != v)
			continue;
		if (v < darkvalue) {
			v = 0;
		} else {
			v = v - darkvalue;
		}
		// skip values that are too far off
		if (fabs(v - EX) > stddevk) {
			continue;
		}
		X += v;
		X2 += v * v;
		counter++;
	}

	if (0 == counter) {
		image->pixel(x, y) = std::numeric_limits<T>::quiet_NaN();
		var->pixel(x, y) = std::numeric_limits<T>::quiet_NaN();
		return;
	}
	EX = X / counter;
	EX2 = X2 / counter;
	image->pixel(x, y) = EX;
	var->pixel(x, y) = EX2 - EX * EX;
}