pub fn phash(img: &Image<Luma<f32>>) -> PHash {
    const N: u32 = 8;
    const HASH_FACTOR: u32 = 4;
    let img = imageops::resize(
        img,
        HASH_FACTOR * N,
        HASH_FACTOR * N,
        imageops::FilterType::Lanczos3,
    );
    let dct = signals::dct2d(Cow::Owned(img));
    let topleft = Rect {
        x: 1,
        y: 1,
        width: N,
        height: N,
    };
    let topleft_dct = crate::compose::crop(&dct, topleft);
    debug_assert_eq!(topleft_dct.dimensions(), (N, N));
    assert_eq!(topleft_dct.len(), (N * N) as usize);
    let mean =
        topleft_dct.iter().copied().reduce(|a, b| a + b).unwrap() / (topleft_dct.len() as f32);
    let bits = topleft_dct.iter().map(|&x| x > mean);
    PHash(Bits64::new(bits))
}
Compute the [pHash] using [DCT].

# Example

```no_run
use imageproc::image_hash;

# fn main() {
let img1 = image::open("first.png").unwrap().to_luma32f();
let img2 = image::open("second.png").unwrap().to_luma32f();
let hash1 = image_hash::phash(&img1);
let hash2 = image_hash::phash(&img2);
dbg!(hash1.hamming_distance(hash2));
# }
```

[pHash]: https://phash.org/docs/pubs/thesis_zauner.pdf
[DCT]: https://en.wikipedia.org/wiki/Discrete_cosine_transform
src/image_hash/phash.rs