/
histogram.go
110 lines (105 loc) · 2.41 KB
/
histogram.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package imagex
import (
"image"
"image/color"
)
func Histogram(img image.Image, rect image.Rectangle) ([]int, string) {
var hist []int
var pix []uint8
var colormodel string
var bounds image.Rectangle
stride := 0
n := 0
switch img := img.(type) {
case *image.RGBA:
colormodel = "rgba"
img = img.SubImage(rect).(*image.RGBA)
pix = img.Pix
n = 4
stride = img.Stride
bounds = img.Bounds()
case *image.NRGBA:
colormodel = "rgba"
img = img.SubImage(rect).(*image.NRGBA)
pix = img.Pix
n = 4
stride = img.Stride
bounds = img.Bounds()
// case *image.RGBA64: -- 16-bit values
case *image.Gray:
colormodel = "gray"
img = img.SubImage(rect).(*image.Gray)
pix = img.Pix
n = 1
stride = img.Stride
bounds = img.Bounds()
// case *image.Gray16: -- 16-bit values
case *image.YCbCr:
colormodel = "ycbcr"
hist = HistogramYCbCr(img, rect, false)
if hist != nil {
return hist, colormodel
}
default:
colormodel = "other"
}
if n > 0 {
hist = make([]int, n*256)
for y, o := bounds.Min.Y, 0; y < bounds.Max.Y; y, o = y+1, o+stride {
for x := 0; x < n*bounds.Dx(); x += n {
for i := 0; i < n; i++ {
hist[int(pix[o+x+i])+i*256] += 1
}
}
}
} else {
colormodel = "rgb"
hist = make([]int, 3*256)
for y := rect.Min.Y; y < rect.Max.Y; y += 1 {
for x := rect.Min.X; x < rect.Max.X; x += 1 {
color := img.At(x, y)
r, g, b, _ := color.RGBA()
hist[r>>8] += 1
hist[(g>>8)+256] += 1
hist[(b>>8)+512] += 1
}
}
}
return hist, colormodel
}
func HistogramYCbCr(img *image.YCbCr, rect image.Rectangle, rgb bool) []int {
var verticalRes int
var horizontalRes int
switch img.SubsampleRatio {
case image.YCbCrSubsampleRatio420:
verticalRes = 2
horizontalRes = 2
case image.YCbCrSubsampleRatio422:
verticalRes = 1
horizontalRes = 2
case image.YCbCrSubsampleRatio444:
verticalRes = 1
horizontalRes = 1
default:
return nil
}
hist := make([]int, 256*3)
for y := rect.Min.Y; y < rect.Max.Y; y++ {
Y := img.Y[y*img.YStride:]
Cb := img.Cb[y/verticalRes*img.CStride:]
Cr := img.Cr[y/verticalRes*img.CStride:]
for x := rect.Min.X; x < rect.Max.X; x++ {
if rgb {
r, g, b := color.YCbCrToRGB(Y[x], Cb[x/horizontalRes], Cr[x/horizontalRes])
hist[r] += 1
hist[int(g)+256] += 1
hist[int(b)+512] += 1
} else {
hist[Y[x]] += 1
hist[int(Cb[x/horizontalRes])+256] += 1
hist[int(Cr[x/horizontalRes])+512] += 1
}
}
}
return hist
}