git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/imaging/histogram.go (about)

     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  }