DifferenceHash.php 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. <?php
  2. namespace Grafika\Gd\ImageHash;
  3. use Grafika\Gd\Editor;
  4. use Grafika\Gd\Image;
  5. /**
  6. * DifferenceHash
  7. *
  8. * Algorithm:
  9. * Reduce size. The fastest way to remove high frequencies and detail is to shrink the image. In this case, shrink it to 9x8 so that there are 72 total pixels.
  10. * Reduce color. Convert the image to a grayscale picture. This changes the hash from 72 pixels to a total of 72 colors.
  11. * Compute the difference. The algorithm works on the difference between adjacent pixels. This identifies the relative gradient direction. In this case, the 9 pixels per row yields 8 differences between adjacent pixels. Eight rows of eight differences becomes 64 bits.
  12. * Assign bits. Each bit is simply set based on whether the left pixel is brighter than the right pixel.
  13. *
  14. * http://www.hackerfactor.com/blog/index.php?/archives/529-Kind-of-Like-That.html
  15. *
  16. * @package Grafika\Gd\ImageHash
  17. */
  18. class DifferenceHash
  19. {
  20. /**
  21. * Generate and get the difference hash of image.
  22. *
  23. * @param Image $image
  24. *
  25. * @param Editor $editor
  26. *
  27. * @return string
  28. */
  29. public function hash($image, $editor)
  30. {
  31. $width = 9;
  32. $height = 8;
  33. $image = clone $image; // Make sure we are working on the clone if Image is passed
  34. $editor->resizeExact($image, $width, $height); // Resize to exactly 9x8
  35. $gd = $image->getCore();
  36. // Build hash
  37. $hash = '';
  38. for ($y = 0; $y < $height; $y++) {
  39. // Get the pixel value for the leftmost pixel.
  40. $rgba = imagecolorat($gd, 0, $y);
  41. $r = ($rgba >> 16) & 0xFF;
  42. $g = ($rgba >> 8) & 0xFF;
  43. $b = $rgba & 0xFF;
  44. $left = floor(($r + $g + $b) / 3);
  45. for ($x = 1; $x < $width; $x++) {
  46. // Get the pixel value for each pixel starting from position 1.
  47. $rgba = imagecolorat($gd, $x, $y);
  48. $r = ($rgba >> 16) & 0xFF;
  49. $g = ($rgba >> 8) & 0xFF;
  50. $b = $rgba & 0xFF;
  51. $right = floor(($r + $g + $b) / 3);
  52. // Each hash bit is set based on whether the left pixel is brighter than the right pixel.
  53. if ($left > $right) {
  54. $hash .= '1';
  55. } else {
  56. $hash .= '0';
  57. }
  58. // Prepare the next loop.
  59. $left = $right;
  60. }
  61. }
  62. $editor->free( $image );
  63. return $hash;
  64. }
  65. }