/
dhash.go
109 lines (85 loc) · 3.24 KB
/
dhash.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
package imagehash
import (
"image"
"./bitarray"
"github.com/disintegration/imaging"
)
func Dhash(img image.Image, hashLen int) ([]byte, error) {
imgGray := imaging.Grayscale(img) // Grayscale image first for performance
// Calculate both horizontal and vertical gradients
horiz, err1 := horizontalGradient(imgGray, hashLen)
vert, err2 := verticalGradient(imgGray, hashLen)
if err1 != nil {
return nil, err1
} else if err2 != nil {
return nil, err2
}
// Return the horizontal hash with the vertical one appended
return append(horiz, vert...), nil
}
func DhashHorizontal(img image.Image, hashLen int) ([]byte, error) {
imgGray := imaging.Grayscale(img) // Grayscale image first
horiz, err := horizontalGradient(imgGray, hashLen) // horizontal diff gradient
return horiz, err
}
func DhashVertical(img image.Image, hashLen int) ([]byte, error) {
imgGray := imaging.Grayscale(img) // Grayscale image first
horiz, err := verticalGradient(imgGray, hashLen) // horizontal diff gradient
return horiz, err
}
func horizontalGradient(img image.Image, hashLen int) ([]byte, error) {
// Width and height of the scaled-down image
width, height := hashLen + 1, hashLen
// Downscale the image by 'hashLen' amount for a horizonal diff.
res := imaging.Resize(img, width, height, imaging.Lanczos)
// Create a new bitArray
bitArray,err := bitarray.NewBitArray(hashLen * hashLen)
if err != nil { return nil, err }
var prev uint32 // Variable to store the previous pixel value
// Calculate the horizonal gradient difference
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
// Since the image is grayscaled, r = g = b
r,_,_,_ := res.At(x,y).RGBA() // Get the pixel at (x,y)
// If this is not the first value of the current row, then
// compare the gradient difference from the previous one
if x > 0 {
if prev < r {
bitArray.AppendBit(1) // if it's smaller, append '1'
} else {
bitArray.AppendBit(0) // else append '0'
}
}
prev = r // Set this current pixel value as the previous one
}
}
return bitArray.GetArray(), nil
}
func verticalGradient(img image.Image, hashLen int) ([]byte, error) {
// Width and height of the scaled-down image
width, height := hashLen, hashLen + 1
// Downscale the image by 'hashLen' amount for a horizonal diff.
res := imaging.Resize(img, width, height, imaging.Lanczos)
// Create a new bitArray
bitArray,err := bitarray.NewBitArray(hashLen * hashLen)
if err != nil { return nil, err }
var prev uint32 // Variable to store the previous pixel value
// Calculate the horizonal gradient difference
for x := 0; x < width; x++ {
for y := 0; y < height; y++ {
// Since the image is grayscaled, r = g = b
r,_,_,_ := res.At(x,y).RGBA() // Get the pixel at (x,y)
// If this is not the first value of the current row, then
// compare the gradient difference from the previous one
if y > 0 {
if prev < r {
bitArray.AppendBit(1) // if it's smaller, append '1'
} else {
bitArray.AppendBit(0) // else append '0'
}
}
prev = r // Set this current pixel value as the previous one
}
}
return bitArray.GetArray(), nil
}