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.

138 lines
4.1 KiB

8 years ago
  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. extern crate docopt;
  6. extern crate pihash;
  7. extern crate rustc_serialize;
  8. #[macro_use]
  9. extern crate serde_derive;
  10. use docopt::Docopt;
  11. use std::path::Path;
  12. // Getting the version information from cargo during compile time
  13. const VERSION: &'static str = env!("CARGO_PKG_VERSION");
  14. // The usage description
  15. const USAGE: &'static str = "
  16. Perceptual Image Hashing (pihash)
  17. Calculate the perceptual hash values for an input or compare the
  18. input file to a set of other images and return a list of the similar
  19. images.
  20. Usage:
  21. pihash [options] <path> [<comparison>...]
  22. pihash (--help | --version)
  23. Options:
  24. -h, --help Show this screen.
  25. -V, --version Print version.
  26. -a, --ahash Include an ahash calculation.
  27. -d, --dhash Include an dhash calculation.
  28. -p, --phash Include an phash calculation.
  29. ";
  30. #[derive(Debug, Deserialize)]
  31. struct Args {
  32. flag_version: bool,
  33. flag_ahash: bool,
  34. flag_dhash: bool,
  35. flag_phash: bool,
  36. arg_path: String,
  37. arg_comparison: Vec<String>,
  38. }
  39. fn main() {
  40. let args: Args = Docopt::new(USAGE)
  41. .and_then(|d| d.deserialize())
  42. .unwrap_or_else(|e| e.exit());
  43. // Print version information and exit
  44. if args.flag_version {
  45. println!("Perceptual Image Hashing: v{}", VERSION);
  46. std::process::exit(0);
  47. }
  48. // Init the hashing library
  49. let lib = pihash::PIHash::new(Some(pihash::cache::DEFAULT_CACHE_DIR));
  50. // println!("{:?}", args);
  51. if args.arg_comparison.len() > 0 {
  52. let base_image_path = Path::new(&args.arg_path);
  53. let base_hash = get_requested_perceptual_hashes(&lib, &base_image_path, &args);
  54. let mut comparison_hashes: Vec<pihash::hash::PerceptualHashes> = Vec::new();
  55. for index in 0..args.arg_comparison.len() {
  56. comparison_hashes
  57. .push(get_requested_perceptual_hashes(&lib,
  58. &Path::new(&args.arg_comparison[index]),
  59. &args));
  60. }
  61. let mut similar_images: Vec<&str> = Vec::new();
  62. for comparison_hash in comparison_hashes {
  63. if base_hash.similar(&comparison_hash) {
  64. similar_images.push(&comparison_hash.orig_path);
  65. }
  66. }
  67. println!("Base Image:");
  68. println!("{}", base_image_path.to_str().unwrap());
  69. println!("Similar Images:");
  70. for similar_image in similar_images {
  71. println!("{}", similar_image);
  72. }
  73. } else {
  74. let image_path = Path::new(&args.arg_path);
  75. let hashes = get_requested_perceptual_hashes(&lib, &image_path, &args);
  76. let hash_result = format!(
  77. r#"
  78. file: {}
  79. ahash: {}
  80. dhash: {}
  81. phash: {}
  82. "#,
  83. hashes.orig_path,
  84. hashes.ahash,
  85. hashes.dhash,
  86. hashes.phash);
  87. println!("{}", hash_result);
  88. }
  89. }
  90. fn flags_get_all_perceptual_hashes(args: &Args) -> bool {
  91. (args.flag_ahash && args.flag_dhash && args.flag_phash) ||
  92. (!args.flag_ahash && !args.flag_dhash && !args.flag_phash)
  93. }
  94. fn get_requested_perceptual_hashes<'a>(lib: &pihash::PIHash,
  95. image_path: &'a Path,
  96. args: &Args)
  97. -> pihash::hash::PerceptualHashes<'a> {
  98. let ahash = if args.flag_ahash || flags_get_all_perceptual_hashes(&args) {
  99. lib.get_ahash(&image_path)
  100. } else {
  101. 0u64
  102. };
  103. let dhash = if args.flag_dhash || flags_get_all_perceptual_hashes(&args) {
  104. lib.get_dhash(&image_path)
  105. } else {
  106. 0u64
  107. };
  108. let phash = if args.flag_phash || flags_get_all_perceptual_hashes(&args) {
  109. lib.get_phash(&image_path)
  110. } else {
  111. 0u64
  112. };
  113. pihash::hash::PerceptualHashes {
  114. orig_path: image_path.to_str().unwrap(),
  115. ahash: ahash,
  116. dhash: dhash,
  117. phash: phash,
  118. }
  119. }