// Copyright 2017 The goimagehash Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package goimagehash import ( "image" "image/jpeg" "os" "testing" ) func TestHashCompute(t *testing.T) { for _, tt := range []struct { img1 string img2 string method func(img image.Image) (*ImageHash, error) name string distance int }{ {"_examples/sample1.jpg", "_examples/sample1.jpg", AverageHash, "AverageHash", 0}, {"_examples/sample2.jpg", "_examples/sample2.jpg", AverageHash, "AverageHash", 0}, {"_examples/sample3.jpg", "_examples/sample3.jpg", AverageHash, "AverageHash", 0}, {"_examples/sample4.jpg", "_examples/sample4.jpg", AverageHash, "AverageHash", 0}, {"_examples/sample1.jpg", "_examples/sample2.jpg", AverageHash, "AverageHash", 40}, {"_examples/sample1.jpg", "_examples/sample3.jpg", AverageHash, "AverageHash", 0}, {"_examples/sample1.jpg", "_examples/sample4.jpg", AverageHash, "AverageHash", 34}, {"_examples/sample2.jpg", "_examples/sample3.jpg", AverageHash, "AverageHash", 40}, {"_examples/sample2.jpg", "_examples/sample4.jpg", AverageHash, "AverageHash", 6}, {"_examples/sample1.jpg", "_examples/sample1.jpg", DifferenceHash, "DifferenceHash", 0}, {"_examples/sample2.jpg", "_examples/sample2.jpg", DifferenceHash, "DifferenceHash", 0}, {"_examples/sample3.jpg", "_examples/sample3.jpg", DifferenceHash, "DifferenceHash", 0}, {"_examples/sample4.jpg", "_examples/sample4.jpg", DifferenceHash, "DifferenceHash", 0}, {"_examples/sample1.jpg", "_examples/sample2.jpg", DifferenceHash, "DifferenceHash", 40}, {"_examples/sample1.jpg", "_examples/sample3.jpg", DifferenceHash, "DifferenceHash", 2}, {"_examples/sample1.jpg", "_examples/sample4.jpg", DifferenceHash, "DifferenceHash", 38}, {"_examples/sample2.jpg", "_examples/sample3.jpg", DifferenceHash, "DifferenceHash", 42}, {"_examples/sample2.jpg", "_examples/sample4.jpg", DifferenceHash, "DifferenceHash", 20}, {"_examples/sample1.jpg", "_examples/sample1.jpg", PerceptionHash, "PerceptionHash", 0}, {"_examples/sample2.jpg", "_examples/sample2.jpg", PerceptionHash, "PerceptionHash", 0}, {"_examples/sample3.jpg", "_examples/sample3.jpg", PerceptionHash, "PerceptionHash", 0}, {"_examples/sample4.jpg", "_examples/sample4.jpg", PerceptionHash, "PerceptionHash", 0}, {"_examples/sample1.jpg", "_examples/sample2.jpg", PerceptionHash, "PerceptionHash", 34}, {"_examples/sample1.jpg", "_examples/sample3.jpg", PerceptionHash, "PerceptionHash", 0}, {"_examples/sample1.jpg", "_examples/sample4.jpg", PerceptionHash, "PerceptionHash", 30}, {"_examples/sample2.jpg", "_examples/sample3.jpg", PerceptionHash, "PerceptionHash", 34}, {"_examples/sample2.jpg", "_examples/sample4.jpg", PerceptionHash, "PerceptionHash", 20}, } { file1, err := os.Open(tt.img1) if err != nil { } defer file1.Close() file2, err := os.Open(tt.img2) if err != nil { t.Errorf("%s", err) } defer file2.Close() img1, err := jpeg.Decode(file1) if err != nil { t.Errorf("%s", err) } img2, err := jpeg.Decode(file2) if err != nil { t.Errorf("%s", err) } hash1, err := tt.method(img1) if err != nil { t.Errorf("%s", err) } hash2, err := tt.method(img2) if err != nil { t.Errorf("%s", err) } dis1, err := hash1.Distance(hash2) if err != nil { t.Errorf("%s", err) } dis2, err := hash2.Distance(hash1) if err != nil { t.Errorf("%s", err) } if dis1 != dis2 { t.Errorf("Distance should be identical %v vs %v", dis1, dis2) } if dis1 != tt.distance { t.Errorf("%s: Distance between %v and %v is expected %v but got %v", tt.name, tt.img1, tt.img2, tt.distance, dis1) } } } func TestNilHashCompute(t *testing.T) { hash, err := AverageHash(nil) if err == nil { t.Errorf("Error should be got.") } if hash != nil { t.Errorf("Nil hash should be got. but got %v", hash) } hash, err = DifferenceHash(nil) if err == nil { t.Errorf("Error should be got.") } if hash != nil { t.Errorf("Nil hash should be got. but got %v", hash) } hash, err = PerceptionHash(nil) if err == nil { t.Errorf("Error should be got.") } if hash != nil { t.Errorf("Nil hash should be got. but got %v", hash) } } func TestExtendHashCompute(t *testing.T) { file, err := os.Open("_examples/sample1.jpg") if err != nil { t.Errorf("%s", err) } defer file.Close() img, err := jpeg.Decode(file) if err != nil { t.Errorf("%s", err) } hash, err := ExtPerceptionHash(img, 0, 8) if err == nil { t.Errorf("Error should be got.") } if hash != nil { t.Errorf("Nil hash should be got. but got %v", hash) } hash, err = ExtPerceptionHash(img, 16, 2) if err != nil { t.Errorf("%s", err) } if hash == nil { t.Errorf("Hash should be got.") } } // func TestNilExtendHashCompute(t *testing.T) { // hash, err := ExtAverageHash(nil, 8, 8) // if err == nil { // t.Errorf("Error should be got.") // } // if hash != nil { // t.Errorf("Nil hash should be got. but got %v", hash) // } // hash, err = ExtDifferenceHash(nil, 8, 8) // if err == nil { // t.Errorf("Error should be got.") // } // if hash != nil { // t.Errorf("Nil hash should be got. but got %v", hash) // } // hash, err = ExtPerceptionHash(nil, 8, 8) // if err == nil { // t.Errorf("Error should be got.") // } // if hash != nil { // t.Errorf("Nil hash should be got. but got %v", hash) // } // hash, err = ExtPerceptionHash(nil, 8, 9) // if err == nil { // t.Errorf("Error should be got.") // } // if hash != nil { // t.Errorf("Nil hash should be got. but got %v", hash) // } // } func BenchmarkDistanceIdentical(b *testing.B) { h1 := &ImageHash{hash: 0xe48ae53c05e502f7} h2 := &ImageHash{hash: 0xe48ae53c05e502f7} for i := 0; i < b.N; i++ { h1.Distance(h2) } } func BenchmarkDistanceDifferent(b *testing.B) { h1 := &ImageHash{hash: 0xe48ae53c05e502f7} h2 := &ImageHash{hash: 0x678be53815e510f7} // 8 bits flipped for i := 0; i < b.N; i++ { h1.Distance(h2) } } // func TestExtImageHashCompute(t *testing.T) { // for _, tt := range []struct { // img1 string // img2 string // width int // height int // method func(img image.Image, width, height int) (*ExtImageHash, error) // name string // distance int // }{ // {"_examples/sample1.jpg", "_examples/sample1.jpg", 8, 8, ExtAverageHash, "ExtAverageHash", 0}, // {"_examples/sample2.jpg", "_examples/sample2.jpg", 8, 8, ExtAverageHash, "ExtAverageHash", 0}, // {"_examples/sample3.jpg", "_examples/sample3.jpg", 8, 8, ExtAverageHash, "ExtAverageHash", 0}, // {"_examples/sample4.jpg", "_examples/sample4.jpg", 8, 8, ExtAverageHash, "ExtAverageHash", 0}, // {"_examples/sample1.jpg", "_examples/sample2.jpg", 8, 8, ExtAverageHash, "ExtAverageHash", 40}, // {"_examples/sample1.jpg", "_examples/sample3.jpg", 8, 8, ExtAverageHash, "ExtAverageHash", 0}, // {"_examples/sample1.jpg", "_examples/sample4.jpg", 8, 8, ExtAverageHash, "ExtAverageHash", 34}, // {"_examples/sample2.jpg", "_examples/sample3.jpg", 8, 8, ExtAverageHash, "ExtAverageHash", 40}, // {"_examples/sample2.jpg", "_examples/sample4.jpg", 8, 8, ExtAverageHash, "ExtAverageHash", 6}, // {"_examples/sample1.jpg", "_examples/sample1.jpg", 16, 16, ExtAverageHash, "ExtAverageHash", 0}, // {"_examples/sample2.jpg", "_examples/sample2.jpg", 16, 16, ExtAverageHash, "ExtAverageHash", 0}, // {"_examples/sample3.jpg", "_examples/sample3.jpg", 16, 16, ExtAverageHash, "ExtAverageHash", 0}, // {"_examples/sample4.jpg", "_examples/sample4.jpg", 16, 16, ExtAverageHash, "ExtAverageHash", 0}, // {"_examples/sample1.jpg", "_examples/sample2.jpg", 16, 16, ExtAverageHash, "ExtAverageHash", 143}, // {"_examples/sample1.jpg", "_examples/sample3.jpg", 16, 16, ExtAverageHash, "ExtAverageHash", 3}, // {"_examples/sample1.jpg", "_examples/sample4.jpg", 16, 16, ExtAverageHash, "ExtAverageHash", 148}, // {"_examples/sample2.jpg", "_examples/sample3.jpg", 16, 16, ExtAverageHash, "ExtAverageHash", 146}, // {"_examples/sample2.jpg", "_examples/sample4.jpg", 16, 16, ExtAverageHash, "ExtAverageHash", 31}, // {"_examples/sample1.jpg", "_examples/sample1.jpg", 17, 17, ExtAverageHash, "ExtAverageHash", 0}, // {"_examples/sample2.jpg", "_examples/sample2.jpg", 17, 17, ExtAverageHash, "ExtAverageHash", 0}, // {"_examples/sample3.jpg", "_examples/sample3.jpg", 17, 17, ExtAverageHash, "ExtAverageHash", 0}, // {"_examples/sample4.jpg", "_examples/sample4.jpg", 17, 17, ExtAverageHash, "ExtAverageHash", 0}, // {"_examples/sample1.jpg", "_examples/sample1.jpg", 8, 4, ExtPerceptionHash, "ExtPerceptionHash", 0}, // {"_examples/sample2.jpg", "_examples/sample2.jpg", 8, 4, ExtPerceptionHash, "ExtPerceptionHash", 0}, // {"_examples/sample3.jpg", "_examples/sample3.jpg", 8, 4, ExtPerceptionHash, "ExtPerceptionHash", 0}, // {"_examples/sample4.jpg", "_examples/sample4.jpg", 8, 4, ExtPerceptionHash, "ExtPerceptionHash", 0}, // {"_examples/sample1.jpg", "_examples/sample2.jpg", 8, 4, ExtPerceptionHash, "ExtPerceptionHash", 32}, // {"_examples/sample1.jpg", "_examples/sample3.jpg", 8, 4, ExtPerceptionHash, "ExtPerceptionHash", 2}, // {"_examples/sample1.jpg", "_examples/sample4.jpg", 8, 4, ExtPerceptionHash, "ExtPerceptionHash", 30}, // {"_examples/sample2.jpg", "_examples/sample3.jpg", 8, 4, ExtPerceptionHash, "ExtPerceptionHash", 34}, // {"_examples/sample2.jpg", "_examples/sample4.jpg", 8, 4, ExtPerceptionHash, "ExtPerceptionHash", 20}, // {"_examples/sample1.jpg", "_examples/sample1.jpg", 16, 4, ExtPerceptionHash, "ExtPerceptionHash", 0}, // {"_examples/sample2.jpg", "_examples/sample2.jpg", 16, 4, ExtPerceptionHash, "ExtPerceptionHash", 0}, // {"_examples/sample3.jpg", "_examples/sample3.jpg", 16, 4, ExtPerceptionHash, "ExtPerceptionHash", 0}, // {"_examples/sample4.jpg", "_examples/sample4.jpg", 16, 4, ExtPerceptionHash, "ExtPerceptionHash", 0}, // {"_examples/sample1.jpg", "_examples/sample2.jpg", 16, 4, ExtPerceptionHash, "ExtPerceptionHash", 124}, // {"_examples/sample1.jpg", "_examples/sample3.jpg", 16, 4, ExtPerceptionHash, "ExtPerceptionHash", 14}, // {"_examples/sample1.jpg", "_examples/sample4.jpg", 16, 4, ExtPerceptionHash, "ExtPerceptionHash", 122}, // {"_examples/sample2.jpg", "_examples/sample3.jpg", 16, 4, ExtPerceptionHash, "ExtPerceptionHash", 120}, // {"_examples/sample2.jpg", "_examples/sample4.jpg", 16, 4, ExtPerceptionHash, "ExtPerceptionHash", 102}, // {"_examples/sample1.jpg", "_examples/sample1.jpg", 8, 8, ExtDifferenceHash, "ExtDifferenceHash", 0}, // {"_examples/sample2.jpg", "_examples/sample2.jpg", 8, 8, ExtDifferenceHash, "ExtDifferenceHash", 0}, // {"_examples/sample3.jpg", "_examples/sample3.jpg", 8, 8, ExtDifferenceHash, "ExtDifferenceHash", 0}, // {"_examples/sample4.jpg", "_examples/sample4.jpg", 8, 8, ExtDifferenceHash, "ExtDifferenceHash", 0}, // {"_examples/sample1.jpg", "_examples/sample2.jpg", 8, 8, ExtDifferenceHash, "ExtDifferenceHash", 40}, // {"_examples/sample1.jpg", "_examples/sample3.jpg", 8, 8, ExtDifferenceHash, "ExtDifferenceHash", 2}, // {"_examples/sample1.jpg", "_examples/sample4.jpg", 8, 8, ExtDifferenceHash, "ExtDifferenceHash", 38}, // {"_examples/sample2.jpg", "_examples/sample3.jpg", 8, 8, ExtDifferenceHash, "ExtDifferenceHash", 42}, // {"_examples/sample2.jpg", "_examples/sample4.jpg", 8, 8, ExtDifferenceHash, "ExtDifferenceHash", 20}, // {"_examples/sample1.jpg", "_examples/sample1.jpg", 16, 16, ExtDifferenceHash, "ExtDifferenceHash", 0}, // {"_examples/sample2.jpg", "_examples/sample2.jpg", 16, 16, ExtDifferenceHash, "ExtDifferenceHash", 0}, // {"_examples/sample3.jpg", "_examples/sample3.jpg", 16, 16, ExtDifferenceHash, "ExtDifferenceHash", 0}, // {"_examples/sample4.jpg", "_examples/sample4.jpg", 16, 16, ExtDifferenceHash, "ExtDifferenceHash", 0}, // {"_examples/sample1.jpg", "_examples/sample2.jpg", 16, 16, ExtDifferenceHash, "ExtDifferenceHash", 137}, // {"_examples/sample1.jpg", "_examples/sample3.jpg", 16, 16, ExtDifferenceHash, "ExtDifferenceHash", 13}, // {"_examples/sample1.jpg", "_examples/sample4.jpg", 16, 16, ExtDifferenceHash, "ExtDifferenceHash", 124}, // {"_examples/sample2.jpg", "_examples/sample3.jpg", 16, 16, ExtDifferenceHash, "ExtDifferenceHash", 140}, // {"_examples/sample2.jpg", "_examples/sample4.jpg", 16, 16, ExtDifferenceHash, "ExtDifferenceHash", 109}, // {"_examples/sample1.jpg", "_examples/sample1.jpg", 17, 17, ExtDifferenceHash, "ExtDifferenceHash", 0}, // {"_examples/sample2.jpg", "_examples/sample2.jpg", 17, 17, ExtDifferenceHash, "ExtDifferenceHash", 0}, // {"_examples/sample3.jpg", "_examples/sample3.jpg", 17, 17, ExtDifferenceHash, "ExtDifferenceHash", 0}, // {"_examples/sample4.jpg", "_examples/sample4.jpg", 17, 17, ExtDifferenceHash, "ExtDifferenceHash", 0}, // } { // file1, err := os.Open(tt.img1) // if err != nil { // t.Errorf("%s", err) // } // defer file1.Close() // file2, err := os.Open(tt.img2) // if err != nil { // t.Errorf("%s", err) // } // defer file2.Close() // img1, err := jpeg.Decode(file1) // if err != nil { // t.Errorf("%s", err) // } // img2, err := jpeg.Decode(file2) // if err != nil { // t.Errorf("%s", err) // } // hash1, err := tt.method(img1, tt.width, tt.height) // if err != nil { // t.Errorf("%s", err) // } // hash2, err := tt.method(img2, tt.width, tt.height) // if err != nil { // t.Errorf("%s", err) // } // dis1, err := hash1.Distance(hash2) // if err != nil { // t.Errorf("%s", err) // } // dis2, err := hash2.Distance(hash1) // if err != nil { // t.Errorf("%s", err) // } // if dis1 != dis2 { // t.Errorf("Distance should be identical %v vs %v", dis1, dis2) // } // if dis1 != tt.distance { // t.Errorf("%s: Distance between %v and %v is expected %v but got %v: %v %v", tt.name, tt.img1, tt.img2, tt.distance, dis1, hash1, hash2) // } // } // } func BenchmarkExtImageHashDistanceDifferent(b *testing.B) { h1 := &ExtImageHash{hash: []uint64{0xe48ae53c05e502f7}} h2 := &ExtImageHash{hash: []uint64{0x678be53815e510f7}} // 8 bits flipped for i := 0; i < b.N; i++ { _, err := h1.Distance(h2) if err != nil { b.Errorf("%s", err) } } } func BenchmarkPerceptionHash(b *testing.B) { file1, err := os.Open("_examples/sample3.jpg") if err != nil { b.Errorf("%s", err) } defer file1.Close() img1, err := jpeg.Decode(file1) if err != nil { b.Errorf("%s", err) } for i := 0; i < b.N; i++ { _, err := ExtPerceptionHash(img1, 8, 8) if err != nil { b.Errorf("%s", err) } } } // func BenchmarkAverageHash(b *testing.B) { // file1, err := os.Open("_examples/sample3.jpg") // if err != nil { // b.Errorf("%s", err) // } // defer file1.Close() // img1, err := jpeg.Decode(file1) // if err != nil { // b.Errorf("%s", err) // } // for i := 0; i < b.N; i++ { // _, err := ExtAverageHash(img1, 8, 8) // if err != nil { // b.Errorf("%s", err) // } // } // } // func BenchmarkDifferenceHash(b *testing.B) { // file1, err := os.Open("_examples/sample3.jpg") // if err != nil { // b.Errorf("%s", err) // } // defer file1.Close() // img1, err := jpeg.Decode(file1) // if err != nil { // b.Errorf("%s", err) // } // for i := 0; i < b.N; i++ { // _, err := ExtDifferenceHash(img1, 8, 8) // if err != nil { // b.Errorf("%s", err) // } // } // }