package ihash import ( "encoding/binary" "fmt" "image" "github.com/corona10/goimagehash" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/bsontype" ) type IHash struct { pHash, dHash, aHash *goimagehash.ImageHash } func (h IHash) Compare(other IHash) uint64 { pd, _ := h.pHash.Distance(other.pHash) dd, _ := h.dHash.Distance(other.dHash) ad, _ := h.aHash.Distance(other.aHash) return uint64(pd + dd + ad) } func GenerateIHash(img image.Image) (IHash, error) { hash := IHash{} var err error hash.pHash, err = goimagehash.PerceptionHash(img) if err != nil { return hash, fmt.Errorf("perception hash error: %s", err.Error()) } hash.dHash, err = goimagehash.DifferenceHash(img) if err != nil { return hash, fmt.Errorf("difference hash error: %s", err.Error()) } hash.aHash, err = goimagehash.AverageHash(img) if err != nil { return hash, fmt.Errorf("average hash error: %s", err.Error()) } return hash, nil } func (h IHash) MarshalBSONValue() (bsontype.Type, []byte, error) { b := make([]byte, 0, 8*3) b = binary.LittleEndian.AppendUint64(b, h.pHash.GetHash()) b = binary.LittleEndian.AppendUint64(b, h.dHash.GetHash()) b = binary.LittleEndian.AppendUint64(b, h.aHash.GetHash()) return bson.MarshalValue(b) } // UnmarshalBSONValue implements bson.ValueUnmarshaler interface. func (h *IHash) UnmarshalBSONValue(t bsontype.Type, data []byte) error { if h == nil { return bson.ErrDecodeToNil } h.pHash = goimagehash.NewImageHash(binary.LittleEndian.Uint64(data[0:8]), goimagehash.PHash) h.dHash = goimagehash.NewImageHash(binary.LittleEndian.Uint64(data[8:16]), goimagehash.DHash) h.aHash = goimagehash.NewImageHash(binary.LittleEndian.Uint64(data[16:24]), goimagehash.PHash) return nil }