imagehash: Add new serialization API dump/load. (#24)
Create a new APIs for serializing purpose which can use standard io.Reader/io.Writer APIs. ToString() API will be remain for debugging purpose and ExtImageHashFromString, ImageHashFromString will be removed after next version. - New APIs are added: LoadExtImageHash, LoadImageHash, xxxHash.Dump - These APIs are deprecated: ExtImageHashFromString, ImageHashFromString
This commit is contained in:
parent
7558e00b90
commit
84eb1859d0
@ -45,8 +45,8 @@ func main() {
|
|||||||
## Release Note
|
## Release Note
|
||||||
|
|
||||||
### v0.4.0(TBA)
|
### v0.4.0(TBA)
|
||||||
- **IMPORTANT** goimagehash does not have compatible with the before version
|
- **IMPORTANT** goimagehash v0.0.4 does not have compatible with the before
|
||||||
when it comes to the serialization based on string. bit set order is changed.
|
version when it comes to the serialization.
|
||||||
|
|
||||||
### v0.3.0
|
### v0.3.0
|
||||||
- Support DifferenceHashExtend.
|
- Support DifferenceHashExtend.
|
||||||
|
43
_examples/load_and_dump.go
Normal file
43
_examples/load_and_dump.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"github.com/corona10/goimagehash"
|
||||||
|
"image/jpeg"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
file1, _ := os.Open("sample1.jpg")
|
||||||
|
file2, _ := os.Open("sample2.jpg")
|
||||||
|
defer file1.Close()
|
||||||
|
defer file2.Close()
|
||||||
|
var b bytes.Buffer
|
||||||
|
foo := bufio.NewWriter(&b)
|
||||||
|
img1, _ := jpeg.Decode(file1)
|
||||||
|
img2, _ := jpeg.Decode(file2)
|
||||||
|
hash1, _ := goimagehash.AverageHashExtend(img1, 15)
|
||||||
|
hash2, _ := goimagehash.AverageHashExtend(img2, 15)
|
||||||
|
distance, _ := hash1.Distance(hash2)
|
||||||
|
fmt.Printf("Distance between images: %v\n", distance)
|
||||||
|
|
||||||
|
err := hash1.Dump(foo)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
foo.Flush()
|
||||||
|
bar := bufio.NewReader(&b)
|
||||||
|
hash3, err := goimagehash.LoadImageHashExtend(bar)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
distance, _ = hash1.Distance(hash3)
|
||||||
|
fmt.Printf("Distance between hash1 and hash3: %v\n", distance)
|
||||||
|
distance, _ = hash2.Distance(hash3)
|
||||||
|
fmt.Printf("Distance between hash2 and hash3: %v\n", distance)
|
||||||
|
fmt.Println(hash1.ToString())
|
||||||
|
fmt.Println(hash2.ToString())
|
||||||
|
fmt.Println(hash3.ToString())
|
||||||
|
}
|
64
imagehash.go
64
imagehash.go
@ -6,9 +6,11 @@ package goimagehash
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"encoding/gob"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Kind describes the kinds of hash.
|
// Kind describes the kinds of hash.
|
||||||
@ -73,7 +75,38 @@ func (h *ImageHash) leftShiftSet(idx int) {
|
|||||||
|
|
||||||
const strFmt = "%1s:%016x"
|
const strFmt = "%1s:%016x"
|
||||||
|
|
||||||
|
// Dump method writes a binary serialization into w io.Writer.
|
||||||
|
func (h *ImageHash) Dump(w io.Writer) error {
|
||||||
|
type D struct {
|
||||||
|
Hash uint64
|
||||||
|
Kind Kind
|
||||||
|
}
|
||||||
|
enc := gob.NewEncoder(w)
|
||||||
|
err := enc.Encode(D{Hash: h.hash, Kind: h.kind})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadImageHash method loads a ExtImageHash from io.Reader.
|
||||||
|
func LoadImageHash(b io.Reader) (*ImageHash, error) {
|
||||||
|
type E struct {
|
||||||
|
Hash uint64
|
||||||
|
Kind Kind
|
||||||
|
}
|
||||||
|
var e E
|
||||||
|
dec := gob.NewDecoder(b)
|
||||||
|
err := dec.Decode(&e)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &ImageHash{hash: e.Hash, kind: e.Kind}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ImageHashFromString returns an image hash from a hex representation
|
// ImageHashFromString returns an image hash from a hex representation
|
||||||
|
//
|
||||||
|
// Deprecated: Use goimagehash.LoadImageHash instead.
|
||||||
func ImageHashFromString(s string) (*ImageHash, error) {
|
func ImageHashFromString(s string) (*ImageHash, error) {
|
||||||
var kindStr string
|
var kindStr string
|
||||||
var hash uint64
|
var hash uint64
|
||||||
@ -148,9 +181,40 @@ func (h *ExtImageHash) GetKind() Kind {
|
|||||||
return h.kind
|
return h.kind
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dump method writes a binary serialization into w io.Writer.
|
||||||
|
func (h *ExtImageHash) Dump(w io.Writer) error {
|
||||||
|
type D struct {
|
||||||
|
Hash []uint64
|
||||||
|
Kind Kind
|
||||||
|
}
|
||||||
|
enc := gob.NewEncoder(w)
|
||||||
|
err := enc.Encode(D{Hash: h.hash, Kind: h.kind})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadImageHashExtend method loads a ExtImageHash from io.Reader.
|
||||||
|
func LoadImageHashExtend(b io.Reader) (*ExtImageHash, error) {
|
||||||
|
type E struct {
|
||||||
|
Hash []uint64
|
||||||
|
Kind Kind
|
||||||
|
}
|
||||||
|
var e E
|
||||||
|
dec := gob.NewDecoder(b)
|
||||||
|
err := dec.Decode(&e)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &ExtImageHash{hash: e.Hash, kind: e.Kind}, nil
|
||||||
|
}
|
||||||
|
|
||||||
const extStrFmt = "%1s:%s"
|
const extStrFmt = "%1s:%s"
|
||||||
|
|
||||||
// ExtImageHashFromString returns a big hash from a hex representation
|
// ExtImageHashFromString returns a big hash from a hex representation
|
||||||
|
//
|
||||||
|
// Deprecated: Use goimagehash.LoadImageHashExtend instead.
|
||||||
func ExtImageHashFromString(s string) (*ExtImageHash, error) {
|
func ExtImageHashFromString(s string) (*ExtImageHash, error) {
|
||||||
var kindStr string
|
var kindStr string
|
||||||
var hashStr string
|
var hashStr string
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
package goimagehash
|
package goimagehash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"image"
|
"image"
|
||||||
_ "image/jpeg"
|
_ "image/jpeg"
|
||||||
@ -124,3 +126,76 @@ func TestSerialization(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDumpAndLoad(t *testing.T) {
|
||||||
|
checkErr := func(err error) {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
methods := []func(img image.Image) (*ImageHash, error){
|
||||||
|
AverageHash, PerceptionHash, DifferenceHash,
|
||||||
|
}
|
||||||
|
examples := []string{
|
||||||
|
"_examples/sample1.jpg", "_examples/sample2.jpg", "_examples/sample3.jpg", "_examples/sample4.jpg",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ex := range examples {
|
||||||
|
file, err := os.Open(ex)
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
img, _, err := image.Decode(file)
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
|
for _, method := range methods {
|
||||||
|
hash, err := method(img)
|
||||||
|
checkErr(err)
|
||||||
|
var b bytes.Buffer
|
||||||
|
foo := bufio.NewWriter(&b)
|
||||||
|
err = hash.Dump(foo)
|
||||||
|
checkErr(err)
|
||||||
|
foo.Flush()
|
||||||
|
bar := bufio.NewReader(&b)
|
||||||
|
reHash, err := LoadImageHash(bar)
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
|
distance, err := hash.Distance(reHash)
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
|
if distance != 0 {
|
||||||
|
t.Errorf("Original and unserialized objects should be identical, got distance=%v", distance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for ExtIExtImageHash
|
||||||
|
extMethods := []func(img image.Image, hashSize int) (*ExtImageHash, error){
|
||||||
|
AverageHashExtend, PerceptionHashExtend, DifferenceHashExtend,
|
||||||
|
}
|
||||||
|
|
||||||
|
hashSizeList := []int{8, 16}
|
||||||
|
for _, hashSize := range hashSizeList {
|
||||||
|
for _, method := range extMethods {
|
||||||
|
hash, err := method(img, hashSize)
|
||||||
|
checkErr(err)
|
||||||
|
var b bytes.Buffer
|
||||||
|
foo := bufio.NewWriter(&b)
|
||||||
|
err = hash.Dump(foo)
|
||||||
|
checkErr(err)
|
||||||
|
foo.Flush()
|
||||||
|
bar := bufio.NewReader(&b)
|
||||||
|
reHash, err := LoadImageHashExtend(bar)
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
|
distance, err := hash.Distance(reHash)
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
|
if distance != 0 {
|
||||||
|
t.Errorf("Original and unserialized objects should be identical, got distance=%v", distance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user