histogram.go raw

   1  package imaging
   2  
   3  import (
   4  	"image"
   5  	"sync"
   6  )
   7  
   8  // Histogram returns a normalized histogram of an image.
   9  //
  10  // Resulting histogram is represented as an array of 256 floats, where
  11  // histogram[i] is a probability of a pixel being of a particular luminance i.
  12  func Histogram(img image.Image) [256]float64 {
  13  	var mu sync.Mutex
  14  	var histogram [256]float64
  15  	var total float64
  16  
  17  	src := newScanner(img)
  18  	if src.w == 0 || src.h == 0 {
  19  		return histogram
  20  	}
  21  
  22  	parallel(0, src.h, func(ys <-chan int) {
  23  		var tmpHistogram [256]float64
  24  		var tmpTotal float64
  25  		scanLine := make([]uint8, src.w*4)
  26  		for y := range ys {
  27  			src.scan(0, y, src.w, y+1, scanLine)
  28  			i := 0
  29  			for x := 0; x < src.w; x++ {
  30  				s := scanLine[i : i+3 : i+3]
  31  				r := s[0]
  32  				g := s[1]
  33  				b := s[2]
  34  				y := 0.299*float32(r) + 0.587*float32(g) + 0.114*float32(b)
  35  				tmpHistogram[int(y+0.5)]++
  36  				tmpTotal++
  37  				i += 4
  38  			}
  39  		}
  40  		mu.Lock()
  41  		for i := 0; i < 256; i++ {
  42  			histogram[i] += tmpHistogram[i]
  43  		}
  44  		total += tmpTotal
  45  		mu.Unlock()
  46  	})
  47  
  48  	for i := 0; i < 256; i++ {
  49  		histogram[i] = histogram[i] / total
  50  	}
  51  	return histogram
  52  }
  53