A Rust library for calculating perceptual hash values of images

Overview

img_hash Build Status Crates.io shield

Now builds on stable Rust! (But needs nightly to bench.)

A library for getting perceptual hash values of images.

Thanks to Dr. Neal Krawetz for the outlines of the Mean (aHash), Gradient (dHash), and DCT (pHash) perceptual hash algorithms:
http://www.hackerfactor.com/blog/?/archives/432-Looks-Like-It.html (Accessed August 2014)

Also provides an implementation of the Blockhash.io algorithm.

This crate can operate directly on buffers from the PistonDevelopers/image crate.

Usage

Documentation

Add img_hash to your Cargo.toml:

[dependencies.img_hash]
version = "3.0"

Example program:

 extern crate image;
 extern crate img_hash;
 
 use img_hash::{HasherConfig, HashAlg};

 fn main() {
     let image1 = image::open("image1.png").unwrap();
     let image2 = image::open("image2.png").unwrap();
     
     let hasher = HasherConfig::new().to_hasher();

     let hash1 = hasher.hash_image(&image1);
     let hash2 = hasher.hash_image(&image2);
     
     println!("Image1 hash: {}", hash1.to_base64());
     println!("Image2 hash: {}", hash2.to_base64());
     
     println!("Hamming Distance: {}", hash1.dist(&hash2));
 }

Benchmarking

In order to build and test on Rust stable, the benchmarks have to be placed behind a feature gate. If you have Rust nightly installed and want to run benchmarks, use the following command:

cargo bench --features bench

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Comments
  • Optimized DCT Implementation

    Optimized DCT Implementation

    Seeking an optimized DCT implementation with a compatible license.

    Options:

    • RustDCT Needs benchmarking as current API supports 1D slices only so it needs a transpose step that the in-tree impl doesn't. (ejmahler/rust_dct#2)

    Dubious:

    • FFTW; licensed under GPL, not compatible with MIT Can provide interface to link in like old UserDCT implementation but composable with the new 3.0-alpha API.

    cc @ejmahler

    enhancement help wanted 
    opened by abonander 12
  • Don't try and hash if the data is empty

    Don't try and hash if the data is empty

    I ran into a situation where I tried to push in a hash of a zero-length value, and instead of erroring, it paniced! This PR fixes the problem, but my Rust is still not very good so I haven't figured out how to write the test correctly. If anyone has any thoughts about how to fix the commented out code, that'd be much appreciated.

    opened by palfrey 10
  • Remove unnecessary indirect dependencies

    Remove unnecessary indirect dependencies

    This deactivates all unnecessary features of the image dependency. The image dependency usually pulls in a lot of indirect dependencies that you possibly don't want.

    In particular this causes issues in my case, because it pulls in rayon, which doesn't work in WebAssembly.

    opened by CryZe 7
  • Port to image 0.21

    Port to image 0.21

    This allows img_hash to be used by projects that depend on image 0.21. Sadly 0.20 is breaking so this change isn't reverse compatible and would require a semver bump.

    This patch is relevant for me because I depend on another crate that requires image 0.21 and as far as I can tell this is the only way to use both at once.

    Thanks!

    opened by kpcyrd 6
  • Thread panic when using Blockhash, but not with DCT

    Thread panic when using Blockhash, but not with DCT

    works:

    let img = image::load_from_memory(&mut buf).unwrap();
    let hash = ImageHash::hash(&img, 8, HashType::DCT);
    

    doesn't work:

    let img = image::load_from_memory(&mut buf).unwrap();
    let hash = ImageHash::hash(&img, 8, HashType::Block);
    

    thread 'main' panicked at 'index out of bounds: the len is 64 but the index is 64', /checkout/src/libcore/slice/mod.rs:2085:14

    versions: rustc: 1.28-nightly image = "0.13" # had to peg this to an older version to get it to work

    [dependencies.img_hash] version = "^2.0.1" features = ["rust-image"]

    stack trace:

    thread 'main' panicked at 'index out of bounds: the len is 64 but the index is 64', /checkout/src/libcore/slice/mod.rs:2085:14
    stack backtrace:
       0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
                 at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
       1: std::sys_common::backtrace::print
                 at libstd/sys_common/backtrace.rs:71
                 at libstd/sys_common/backtrace.rs:59
       2: std::panicking::default_hook::{{closure}}
                 at libstd/panicking.rs:211
       3: std::panicking::default_hook
                 at libstd/panicking.rs:227
       4: std::panicking::rust_panic_with_hook
                 at libstd/panicking.rs:511
       5: std::panicking::continue_panic_fmt
                 at libstd/panicking.rs:426
       6: rust_begin_unwind
                 at libstd/panicking.rs:337
       7: core::panicking::panic_fmt
                 at libcore/panicking.rs:92
       8: core::panicking::panic_bounds_check
                 at libcore/panicking.rs:60
       9: <usize as core::slice::SliceIndex<[T]>>::index_mut
                 at /checkout/src/libcore/slice/mod.rs:2085
      10: core::slice::<impl core::ops::index::IndexMut<I> for [T]>::index_mut
                 at /checkout/src/libcore/slice/mod.rs:1958
      11: <alloc::vec::Vec<T> as core::ops::index::IndexMut<I>>::index_mut
                 at /checkout/src/liballoc/vec.rs:1717
      12: img_hash::block::blockhash_slow::{{closure}}
                 at /home/~/img_hash-2.0.1/src/block.rs:99
      13: img_hash::rust_image::<impl img_hash::HashImage for image::dynimage::DynamicImage>::foreach_pixel
                 at /home/~/img_hash-2.0.1/src/rust_image.rs:89
      14: img_hash::block::blockhash_slow
                 at /home/~/img_hash-2.0.1/src/block.rs:72
      15: img_hash::block::blockhash
                 at /home/~/img_hash-2.0.1/src/block.rs:29
      16: img_hash::HashType::hash
                 at /home/~/img_hash-2.0.1/src/lib.rs:279
      17: img_hash::ImageHash::hash
                 at /home/~/img_hash-2.0.1/src/lib.rs:85
      18: app::event
                 at src/main.rs:63
      19: nannou::run_loop::process_and_emit_glutin_event
                 at /home/~/nannou-0.6.0/src/lib.rs:368
      20: nannou::run_loop
                 at /home/~/nannou-0.6.0/src/lib.rs:412
      21: <nannou::Builder<M, E>>::run
                 at /home/~/nannou-0.6.0/src/lib.rs:147
      22: app::main
                 at src/main.rs:14
      23: std::rt::lang_start::{{closure}}
                 at /checkout/src/libstd/rt.rs:74
      24: std::panicking::try::do_call
                 at libstd/rt.rs:59
                 at libstd/panicking.rs:310
      25: __rust_maybe_catch_panic
                 at libpanic_unwind/lib.rs:105
      26: std::rt::lang_start_internal
                 at libstd/panicking.rs:289
                 at libstd/panic.rs:392
                 at libstd/rt.rs:58
      27: std::rt::lang_start
                 at /checkout/src/libstd/rt.rs:74
      28: main
      29: __libc_start_main
      30: _start
    
    opened by cryptoquick 6
  • Example code in documentation not running

    Example code in documentation not running

    I'm trying to run the example code and was unable to circumvent this error: "the trait img_hash::HashImage is not implemented for image::DynamicImage". Could you look into this??

    screen shot 2017-08-22 at 11 40 44 am

    opened by ndortega 6
  • Produced gradient hash has an invalid size

    Produced gradient hash has an invalid size

    I've been testing this library with this simple script, but I can't figure out why the produced hash has an invalid size (here 56 instead of 64 bits). The size is also incorrect for DoubleGradient with 135 instead of 128 bits. When using the Mean, Block or DCT hashtype, the resulting hash has the correct length (64 bits). (I'm a novice in Rust, so I might have done something wrong.)

    extern crate image;
    extern crate img_hash;
    
    use std::path::Path;
    use img_hash::{ImageHash, HashType};
    
    fn main() {
        let img = image::open(&Path::new("00002701.jpg")).unwrap();
        let hash = ImageHash::hash(&img, 8, HashType::Gradient);
        println!("{:?}", hash.bitv);
        println!("{}", hash.size());
    }
    

    (The image is just a random picture, I am only looking at the hash size here.)

    opened by ksesong 5
  • Relicense under dual MIT/Apache-2.0

    Relicense under dual MIT/Apache-2.0

    This issue was automatically generated. Feel free to close without ceremony if you do not agree with re-licensing or if it is not possible for other reasons. Respond to @cmr with any questions or concerns, or pop over to #rust-offtopic on IRC to discuss.

    You're receiving this because someone (perhaps the project maintainer) published a crates.io package with the license as "MIT" xor "Apache-2.0" and the repository field pointing here.

    TL;DR the Rust ecosystem is largely Apache-2.0. Being available under that license is good for interoperation. The MIT license as an add-on can be nice for GPLv2 projects to use your code.

    Why?

    The MIT license requires reproducing countless copies of the same copyright header with different names in the copyright field, for every MIT library in use. The Apache license does not have this drawback. However, this is not the primary motivation for me creating these issues. The Apache license also has protections from patent trolls and an explicit contribution licensing clause. However, the Apache license is incompatible with GPLv2. This is why Rust is dual-licensed as MIT/Apache (the "primary" license being Apache, MIT only for GPLv2 compat), and doing so would be wise for this project. This also makes this crate suitable for inclusion and unrestricted sharing in the Rust standard distribution and other projects using dual MIT/Apache, such as my personal ulterior motive, the Robigalia project.

    Some ask, "Does this really apply to binary redistributions? Does MIT really require reproducing the whole thing?" I'm not a lawyer, and I can't give legal advice, but some Google Android apps include open source attributions using this interpretation. Others also agree with it. But, again, the copyright notice redistribution is not the primary motivation for the dual-licensing. It's stronger protections to licensees and better interoperation with the wider Rust ecosystem.

    How?

    To do this, get explicit approval from each contributor of copyrightable work (as not all contributions qualify for copyright, due to not being a "creative work", e.g. a typo fix) and then add the following to your README:

    ## License
    
    Licensed under either of
    
     * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
     * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
    
    at your option.
    
    ### Contribution
    
    Unless you explicitly state otherwise, any contribution intentionally submitted
    for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
    additional terms or conditions.
    

    and in your license headers, if you have them, use the following boilerplate (based on that used in Rust):

    // Copyright 2016 img_hash developers
    //
    // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
    // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
    // option. This file may not be copied, modified, or distributed
    // except according to those terms.
    

    It's commonly asked whether license headers are required. I'm not comfortable making an official recommendation either way, but the Apache license recommends it in their appendix on how to use the license.

    Be sure to add the relevant LICENSE-{MIT,APACHE} files. You can copy these from the Rust repo for a plain-text version.

    And don't forget to update the license metadata in your Cargo.toml to:

    license = "MIT/Apache-2.0"
    

    I'll be going through projects which agree to be relicensed and have approval by the necessary contributors and doing this changes, so feel free to leave the heavy lifting to me!

    Contributor checkoff

    To agree to relicensing, comment with :

    I license past and future contributions under the dual MIT/Apache-2.0 license, allowing licensees to chose either at their option.
    

    Or, if you're a contributor, you can check the box in this repo next to your name. My scripts will pick this exact phrase up and check your checkbox, but I'll come through and manually review this issue later as well.

    • [x] @cybergeek94
    • [x] @forgemo
    • [x] @talevy
    • [x] @palfrey
    opened by emberian 5
  • introduced from_base64(), replaced size and hash_size() by size(), replaced all uint by usize

    introduced from_base64(), replaced size and hash_size() by size(), replaced all uint by usize

    • Introduced method 'from_base64(...)' for deserialization
    • Removed the field 'size' from ImageHash
    • Renamed hash_size() to size()
    • Replaced all occurences of uint with usize (uint has become deprecated)
    opened by forgemo 5
  • 3.0.0 Release

    3.0.0 Release

    The crate has been completely revamped with a new, much more Rust-y API.

    New Features

    • Serde support (finally)
    • Support for inline storage for hashes with generic arrays
    • DCT and Difference-of-Gaussians preprocessing for all hash types
    • Hash sizes are rectangular now to allow capturing more detail in one dimension or the other

    Additionally, DCT is implemented by the RustDCT crate now which enables the following:

    • Precomputing of DCT coefficients is now automatic and per-instance of HasherConfig instead of user-configured per-thread
    • DCT is implemented in terms of FFTs now and receives roughly an order of magnitude speedup (need to add benches back to show this)

    Breaking Changes

    • The old API is completely gone
    • Requirement for the image crate now starts at 0.21 (might be able to loosen this)
    • Minimum supported Rust version is increased to at least 1.26 (need to establish this exactly)
    opened by abonander 3
  • Point to the PistonDevelopers image in Cargo.toml?

    Point to the PistonDevelopers image in Cargo.toml?

    Getting error:

    warning: using multiple versions of crate `image`
    src/lib.rs:11:1: 11:27 note: used here
    src/lib.rs:11 extern crate gfx_graphics;
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~
    note: crate name: image
    src/lib.rs:37:1: 37:41 note: used here
    src/lib.rs:37 extern crate "img_hash" as img_hash_lib;
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    note: crate name: image
    
    opened by bvssvni 3
  • Add support for `image-rs 0.24`

    Add support for `image-rs 0.24`

    Since the latest version of image-rs library require Rust 1.56.0, I think that img_hash also should use Rust 2021 edition and bump minimal requirements.

    For now I can't use image-rs 0.24.0, because img_hash crate cannot interoperate with this version and I have such errors(this works with 0.23)

    error[E0277]: the trait bound `image::DynamicImage: Image` is not satisfied
       --> czkawka_core/src/similar_images.rs:606:50
        |
    606 |                     let hash = hasher.hash_image(&image);
        |                                       ---------- ^^^^^^ the trait `Image` is not implemented for `image::DynamicImage`
        |                                       |
        |                                       required by a bound introduced by this call
    
    opened by qarmin 4
  • ImageHash should be serializable

    ImageHash should be serializable

    Since it is fairly costly to calculate a hash, it makes sense to serialize an deserialize the ImageHash struct. To do this, the struct should derive Serialize and Deserialize from the serde crate.

    opened by Futsch1 0
  • Replace HashBytes manual array impl with min_const_generics

    Replace HashBytes manual array impl with min_const_generics

    When going for a 128 byte image hash, I noticed that the size wasn't actually implemented, even though the doc comment said as such. So, instead of just adding more lengths I tried to just switch it to min_const_generics instead since its been on stable for a while now.

    If you prefer not to make the MSRV so high I can drop this commit and just add the extra array implementations.

    opened by BlackHoleFox 0
  • Update to 2018

    Update to 2018

    I noticed some of these libraries are pretty old, and so I set out to update them (and, you know, migrate to the 2018 edition). In so doing, I also realized that the rustdct library kind of changed its API on you, apparently just to make life a little more fun. As such, my most important changes (read: the ones I understand the least) are in dct_2d(), on line 44 of dct.rs. The rest of this is pretty much 100% just me screwing with formatting and implementing advice from cargo clippy.

    Anyway, here it is if you want it.

    A note: at least after I did this, I did not notice any major difference in performance between dct and non-dct hashes (at least in my tiny use case). Of course, I didn't check to see what difference there was beforehand, and I don't know if the code even works correctly (although it seems to be producing valid hashes for me). There's no telling what, if anything, that indicates. That said, I did completely remove use of transpose from that code path. /shrug

    opened by archer884 4
Owner
Austin Bonander
Austin Bonander
Zero dependency images (of chaos) in Rust

bifurcate-rs Zero dependency images (of chaos) in Rust To run: time cargo run --release > img.pgm To convert from PGM to PNG using Image Magick: conve

Stephen Merity 32 Nov 17, 2021
tai (Terminal Ascii Image) tool to convert images to ascii written in Rust

TAI Terminal Ascii Image A tool to convert images to ascii art written in Rust ?? Notes This tool is still in development stage. Contributions All Con

Mustafa Salih 258 Dec 5, 2022
Encoding and decoding images in Rust

Image Maintainers: @HeroicKatora, @fintelia How to contribute An Image Processing Library This crate provides basic image processing functions and met

image-rs 3.5k Jan 2, 2023
Converts images into textual line art.

img2utf Transform images to textual line art! Images require pre-processing to come out nice. It's expected that users will do the following: Apply ga

Lee 149 Dec 10, 2022
Automated image compression for efficiently distributing images on the web.

Imager Apparently this project made it into the GitHub Archive Program. About Imager is a tool for automated image compression, and can competitively

Imager IO 487 Dec 25, 2022
Convert Sketchbook Tiff Files to Open Raster Images

SketchbookTiffConverter Convert Sketchbook Tiff Files to Open Raster Images and retain layer information. This is a command line program that will con

Phil Spindler 3 Nov 2, 2021
Fetch original quality URLs for images posted to a Twitter account

twitter-images Fetches the last tweets of a given account, then prints original quality URLs for all image tweets. Useful for archiving image content

Harsh Shandilya 6 Dec 23, 2022
Simple CLI program to generate zoomable tiled images

zoomtiler Simple CLI program to generate deepzoom zoomable tiled images. The input can either be a single image or multiple images of the same height,

Matthieu Pizenberg 3 Mar 14, 2022
Takes a folder of images (as a palette), and an image, and figures out how to tile the palette to resemble the image!

Takes a folder of images (as a palette), and an image, and figures out how to tile the palette to resemble the image!

Jacob 258 Dec 30, 2022
CLI and utilities for converting media files (images/videos) to ascii outputs (output media file or print to console)

CLI and utilities for converting media files (images/videos) to ascii outputs (output media file or print to console). Supports most standard image formats, and some video formats.

Michael 30 Jan 1, 2023
A simple steganography library written in rust

steganography A stable steganography library written in rust Crates.io Usage Add the following to the Cargo.toml in your project: [dependencies] stega

Teodor Voinea 79 Dec 9, 2022
Face detection library for the Rust programming language

Rustface SeetaFace detection library for the Rust programming language Example of demo program output SEETAFACE C++ – Github repository for the origin

Andrei Tomashpolskiy 323 Dec 27, 2022
A Simple-to-use, cross-platform Rust Webcam Capture Library

Cross Platform Rust Library for powerful Webcam Capture and Virtual Webcams

null 246 Jan 8, 2023
😱 Dead fast thumbnail library for browser and NodeJs! Built with Rust 🦀 and WebAssembly 🕸

thumbo-core ?? Dead fast thumbnail library for browser and NodeJs Built with Rust ?? & WebAssembly ?? ?? About thumbo-core is a thubnail library for b

Victor Aremu 12 Dec 2, 2022
Rust library for fast image resizing with using of SIMD instructions.

fast_image_resize Rust library for fast image resizing with using of SIMD instructions. CHANGELOG Supported pixel formats and available optimisations:

Kirill Kuzminykh 115 Jan 5, 2023
PNG decoding and encoding library in pure Rust

PNG Decoder/Encoder PNG decoder/encoder in pure Rust. It contains all features required to handle the entirety of the PngSuite by Willem van Schack. p

image-rs 247 Dec 25, 2022
An advanced image processing library for Rust.

ImageProc Maintainers: @chyh1990 Note: this project is under active depvelopment, API may change! imageproc is a advanced image proccessing library fo

Chen Yuheng 97 Oct 18, 2022
Rust library to get image size and format without loading/decoding

imageinfo-rs Rust library to get image size and format without loading/decoding. The imageinfo don't get image format by file ext name, but infer by f

xiaozhuai, Weihang Ding 47 Dec 30, 2022
Image operation rust library

Image operation rust library

LongYinan 166 Dec 20, 2022