You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
2.2 KiB

  1. // Copyright 2015 Drew Short <drew@sothr.com>.
  2. //
  3. // Licensed under the MIT license<LICENSE-MIT or http://opensource.org/licenses/MIT>.
  4. // This file may not be copied, modified, or distributed except according to those terms.
  5. // Pull in the image processing crate
  6. extern crate image;
  7. use std::path::Path;
  8. use self::image::{
  9. GenericImage,
  10. Pixel
  11. };
  12. pub struct PreparedImage<'a> {
  13. orig_path: &'a str,
  14. grey_image: image::ImageBuffer<image::Luma<u8>,Vec<u8>>
  15. }
  16. pub fn prepare_image(path: &Path) -> PreparedImage {
  17. let grey_img = image::open(path).unwrap().to_luma();
  18. let image_path = path.to_str().unwrap();
  19. PreparedImage { orig_path: &*image_path, grey_image: grey_img }
  20. }
  21. /*
  22. * Calculate the number of bits different between two hashes
  23. */
  24. pub fn calculate_hamming_distance(hash1: u64, hash2: u64) -> u64 {
  25. // The binary xor of the two hashes should give us a number representing
  26. // the differences between the two hashes. All that's left is to count
  27. // the number of 1's in the difference to determine the hamming distance
  28. let bin_diff = hash1 ^ hash2;
  29. let bin_diff_str = format!("{:b}", bin_diff);
  30. let mut hamming = 0u64;
  31. for bit in bin_diff_str.chars() {
  32. match bit {
  33. '1' => hamming+=1,
  34. _ => continue
  35. }
  36. }
  37. hamming
  38. }
  39. /**
  40. * Calculate the ahash of an image provided at the indicated path.
  41. *
  42. * # Arguments
  43. *
  44. * * 'path' - The path to the image file to create a hash from.
  45. *
  46. * Returns a u64 representing the value of the hash
  47. */
  48. pub fn get_ahash(prepared_image: PreparedImage) -> u64 {
  49. let img = prepared_image.grey_image;
  50. let (width, height) = img.dimensions();
  51. // calculating the average pixel value
  52. let mut total = 0u64;
  53. for pixel in img.pixels() {
  54. let channels = pixel.channels();
  55. total += channels[0] as u64;
  56. }
  57. let mean = total / (width*height) as u64;
  58. // Calculating a hash based on the mean
  59. let mut hash = 0u64;
  60. for pixel in img.pixels() {
  61. let channels = pixel.channels();
  62. let pixel_sum = channels[0] as u64;
  63. hash <<= 1;
  64. if pixel_sum >= mean {
  65. hash |= 1;
  66. } else {
  67. hash |= 0;
  68. }
  69. }
  70. return hash;
  71. }