/**
 * Computes the standard deviations of the intensities of all blocks and
 * the minimum standard deviation
 */
func computeStdevs(blocks []image.Image) (float64, []float64) {
	stdevs := make([]float64, len(blocks), len(blocks))
	minStdev := math.Inf(1)
	ch := make(chan indexValuePair)
	for i, block := range blocks {
		go func(i int, block image.Image) {
			variance, mean := 0.0, 0.0
			minX, minY := block.Bounds().Min.X, block.Bounds().Min.Y
			maxX, maxY := block.Bounds().Max.X, block.Bounds().Max.Y
			total := float64((maxX - minX) * (maxY - minY))
			for i := minX; i < maxX; i++ {
				for j := minY; j < maxY; j++ {
					mean += utils.Intensity(block.At(i, j))
				}
			}
			mean /= total
			for i := minX; i < maxX; i++ {
				for j := minY; j < maxY; j++ {
					variance += math.Pow(utils.Intensity(block.At(i, j))-mean, 2)
				}
			}
			ch <- indexValuePair{i: i, value: math.Sqrt(variance / total)}
		}(i, block)
	}
	for i := 0; i < len(blocks); i++ {
		pair := <-ch
		stdevs[pair.i] = pair.value
		minStdev = utils.MinF(pair.value, minStdev)
	}
	close(ch)
	return minStdev, stdevs
}
/**
 * Returns the differences between the intensities between each original block and
 * the filtered one. Also return the mean of those differences.
 */
func diffsAndMeanDiff(origBlocks, filtBlocks []image.Image) ([]float64, float64) {
	total := float64(len(origBlocks) * BLOCK_WIDTH * BLOCK_HEIGHT)
	diffs := make([]float64, int(total), int(total))
	mean := 0.0
	for b := 0; b < len(origBlocks); b++ {
		minX, minY := origBlocks[b].Bounds().Min.X, origBlocks[b].Bounds().Min.Y
		maxX, maxY := origBlocks[b].Bounds().Max.X, origBlocks[b].Bounds().Max.Y
		for i := minX; i < maxX; i++ {
			for j := minY; j < maxY; j++ {
				intensityFiltered := utils.Intensity(filtBlocks[b].At(i-minX, j-minY))
				intensityOriginal := utils.Intensity(origBlocks[b].At(i, j))
				diffs[b] = math.Abs(intensityFiltered - intensityOriginal)
				mean += diffs[b] / total
			}
		}
	}
	return diffs, mean
}
/**
 * Computes the absolute difference between the two pixels intensities.
 */
func IntensityDifference(p1 graph.Pixel, p2 graph.Pixel) float64 {
	return math.Abs(utils.Intensity(p2.Color) - utils.Intensity(p1.Color))
}