From 7350b6047d23be154d308ee82a61213c47e749dc Mon Sep 17 00:00:00 2001 From: klementyev Date: Thu, 20 Apr 2017 21:01:27 +0300 Subject: [PATCH 1/3] Fix hexadecimal to decimal conversion for negative hashes --- src/ImageHash.php | 19 +++++++++++++++++-- tests/ImageHashTest.php | 10 ++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/ImageHash.php b/src/ImageHash.php index 55ea5f8..fcd6799 100644 --- a/src/ImageHash.php +++ b/src/ImageHash.php @@ -113,8 +113,8 @@ public function distance($hash1, $hash2) } } else { if ($this->mode === self::HEXADECIMAL) { - $hash1 = hexdec($hash1); - $hash2 = hexdec($hash2); + $hash1 = $this->hexdec($hash1); + $hash2 = $this->hexdec($hash2); } $dh = 0; @@ -179,4 +179,19 @@ protected function formatHash($hash) { return $this->mode === static::HEXADECIMAL ? dechex($hash) : $hash; } + + /** + * Convert hexadecimal to signed decimal. + * + * @param string $hex + * @return int + */ + protected function hexdec($hex) + { + if (strlen($hex) == 16 && hexdec($hex[0]) > 8) { + return unpack('J', hex2bin($hex))[1]; + } + + return hexdec($hex); + } } diff --git a/tests/ImageHashTest.php b/tests/ImageHashTest.php index 140eee6..ffefecb 100644 --- a/tests/ImageHashTest.php +++ b/tests/ImageHashTest.php @@ -31,4 +31,14 @@ public function testHashStringSameAsFile() $this->assertSame($this->imageHash->hash($path), $this->imageHash->hashFromString(file_get_contents($path))); } + + public function testDistanceOfNegativeHashes() + { + $imageHash = new ImageHash(null, ImageHash::HEXADECIMAL); + $hash1 = 'ffffffffffffffff'; // -1 + $hash2 = 'fffffffffffffff0'; // -16 + + $distance = $imageHash->distance($hash1, $hash2); + $this->assertEquals(4, $distance); + } } From b6d7b81f335b68dee37831788d6a42e3cadb3779 Mon Sep 17 00:00:00 2001 From: klementyev Date: Thu, 20 Apr 2017 21:51:35 +0300 Subject: [PATCH 2/3] add test --- src/ImageHash.php | 30 +++++++++++++++--------------- tests/ImageHashTest.php | 12 ++++++++++++ 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/ImageHash.php b/src/ImageHash.php index fcd6799..849c1a5 100644 --- a/src/ImageHash.php +++ b/src/ImageHash.php @@ -129,6 +129,21 @@ public function distance($hash1, $hash2) return $dh; } + /** + * Convert hexadecimal to signed decimal. + * + * @param string $hex + * @return int + */ + public function hexdec($hex) + { + if (strlen($hex) == 16 && hexdec($hex[0]) > 8) { + return unpack('J', hex2bin($hex))[1]; + } + + return hexdec($hex); + } + /** * Get a GD2 resource from file. * @@ -179,19 +194,4 @@ protected function formatHash($hash) { return $this->mode === static::HEXADECIMAL ? dechex($hash) : $hash; } - - /** - * Convert hexadecimal to signed decimal. - * - * @param string $hex - * @return int - */ - protected function hexdec($hex) - { - if (strlen($hex) == 16 && hexdec($hex[0]) > 8) { - return unpack('J', hex2bin($hex))[1]; - } - - return hexdec($hex); - } } diff --git a/tests/ImageHashTest.php b/tests/ImageHashTest.php index ffefecb..784f8ae 100644 --- a/tests/ImageHashTest.php +++ b/tests/ImageHashTest.php @@ -32,6 +32,18 @@ public function testHashStringSameAsFile() $this->assertSame($this->imageHash->hash($path), $this->imageHash->hashFromString(file_get_contents($path))); } + public function testHexdecForNegativeIntegers() + { + // native hexdec dechex conversion working for positive integers + $this->assertEquals(1, hexdec(dechex(1))); + // but not working for negative + $this->assertNotEquals(-1, hexdec(dechex(-1))); + + // custom hexdec implementation works for both + $this->assertEquals(1, $this->imageHash->hexdec(dechex(1))); + $this->assertEquals(-1, $this->imageHash->hexdec(dechex(-1))); + } + public function testDistanceOfNegativeHashes() { $imageHash = new ImageHash(null, ImageHash::HEXADECIMAL); From 337bc08b7cb0a16b54fc81af49351b4d4728932b Mon Sep 17 00:00:00 2001 From: klementyev Date: Thu, 20 Apr 2017 22:07:41 +0300 Subject: [PATCH 3/3] use fallback for php <= 5.5 --- src/ImageHash.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ImageHash.php b/src/ImageHash.php index 849c1a5..1bed620 100644 --- a/src/ImageHash.php +++ b/src/ImageHash.php @@ -138,7 +138,8 @@ public function distance($hash1, $hash2) public function hexdec($hex) { if (strlen($hex) == 16 && hexdec($hex[0]) > 8) { - return unpack('J', hex2bin($hex))[1]; + list($higher, $lower) = array_values(unpack('N2', hex2bin($hex))); + return $higher << 32 | $lower; } return hexdec($hex);