AverageHash.php 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. <?php
  2. namespace Grafika\Gd\ImageHash;
  3. use Grafika\Gd\Editor;
  4. use Grafika\Gd\Image;
  5. /**
  6. * AverageHash
  7. *
  8. * Algorithm:
  9. * Reduce size. Remove high frequencies and detail by shrinking to 8x8 so that there are 64 total pixels.
  10. * Reduce color. The tiny 8x8 picture is converted to a grayscale.
  11. * Average the colors. Compute the mean value of the 64 colors.
  12. * Compute the bits. Each bit is simply set based on whether the color value is above or below the mean.
  13. * Construct the hash. Set the 64 bits into a 64-bit integer. The order does not matter, just as long as you are consistent.
  14. *
  15. * http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html
  16. *
  17. * @package Grafika\Gd\ImageHash
  18. */
  19. class AverageHash
  20. {
  21. /**
  22. * Generate and get the average hash of the image.
  23. *
  24. * @param Image $image
  25. *
  26. * @param Editor $editor
  27. *
  28. * @return string
  29. */
  30. public function hash($image, $editor)
  31. {
  32. // Resize the image.
  33. $width = 8;
  34. $height = 8;
  35. $image = clone $image; // Make sure we are working on the clone if Image is passed
  36. $editor->resizeExact($image, $width, $height); // Resize to exactly 8x8
  37. $gd = $image->getCore();
  38. // Create an array of greyscale pixel values.
  39. $pixels = array();
  40. for ($y = 0; $y < $height; $y++) {
  41. for ($x = 0; $x < $width; $x++) {
  42. $rgba = imagecolorat($gd, $x, $y);
  43. $r = ($rgba >> 16) & 0xFF;
  44. $g = ($rgba >> 8) & 0xFF;
  45. $b = $rgba & 0xFF;
  46. $pixels[] = floor(($r + $g + $b) / 3); // Gray
  47. }
  48. }
  49. // Get the average pixel value.
  50. $average = floor(array_sum($pixels) / count($pixels));
  51. // Each hash bit is set based on whether the current pixels value is above or below the average.
  52. $hash = '';
  53. foreach ($pixels as $pixel) {
  54. if ($pixel > $average) {
  55. $hash .= '1';
  56. } else {
  57. $hash .= '0';
  58. }
  59. }
  60. return $hash;
  61. }
  62. }