/*
pHash, the open source perceptual hash library
Copyright (C) 2009 Aetilius, Inc.
All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Evan Klinger - eklinger@phash.org
David Starkweather - dstarkweather@phash.org
*/
#include
#include
#include
#include
#include
#include
#include "pHash.h"
using namespace std;
#define TRUE 1
#define FALSE 0
// data structure for a hash and id
struct ph_imagepoint {
ulong64 hash;
char *id;
};
// aux function to create imagepoint data struct
struct ph_imagepoint *ph_malloc_imagepoint() {
return (struct ph_imagepoint *)malloc(sizeof(struct ph_imagepoint));
}
// auxiliary function for sorting list of hashes
bool cmp_lt_imp(struct ph_imagepoint dpa, struct ph_imagepoint dpb) {
int result = strcmp(dpa.id, dpb.id);
if (result < 0) return TRUE;
return FALSE;
}
/** TEST for image DCT hash function
* The program reads all images from the two directories given on the command
*line. The program expects the same number of image files in each directory.
*Each image should be perceptually similar to a corresponding file in the other
*directory and have the same exact name. For example, one directory could
*contain the originals, and the other directory blurred counterparts. The
*program calculates the hashes. First, the hamming distances are calculated
*between all similar image hashes (-i.e. the intra compares), and then hamming
*distances for different images hashes (-i.e. the inter compares).
**/
int main(int argc, char **argv) {
const char *msg = ph_about();
printf(" %s\n", msg);
if (argc < 3) {
printf("no input args\n");
printf("expected: \"test_imagephash [dir name] [dir_name]\"\n");
exit(1);
}
const char *dir_name = argv[1];
const char *dir_name2 = argv[2];
struct dirent *dir_entry;
vector hashlist1; // for hashes in first directory
vector hashlist2; // for hashes in second directory
ph_imagepoint *dp = NULL;
// first directory
DIR *dir = opendir(dir_name);
if (!dir) {
printf("unable to open directory\n");
exit(1);
}
errno = 0;
int i = 0;
ulong64 tmphash;
char path[100];
path[0] = '\0';
while ((dir_entry = readdir(dir)) != 0) {
if (strcmp(dir_entry->d_name, ".") && strcmp(dir_entry->d_name, "..")) {
strcat(path, dir_name);
strcat(path, "/");
strcat(path, dir_entry->d_name);
if (ph_dct_imagehash(path, tmphash) < 0) // calculate the hash
continue;
dp = ph_malloc_imagepoint(); // store in structure with file name
dp->id = dir_entry->d_name;
dp->hash = tmphash;
hashlist1.push_back(*dp);
i++;
}
errno = 0;
path[0] = '\0';
}
if (errno) {
printf("error reading directory\n");
exit(1);
}
sort(hashlist1.begin(), hashlist1.end(), cmp_lt_imp);
// second directory
dir_entry = NULL;
DIR *dir2 = opendir(dir_name2);
if (!dir) {
printf("unable to open directory\n");
exit(1);
}
errno = 0;
path[0] = '\0';
i = 0;
while ((dir_entry = readdir(dir2)) != 0) {
if (strcmp(dir_entry->d_name, ".") && strcmp(dir_entry->d_name, "..")) {
strcat(path, dir_name2);
strcat(path, "/");
strcat(path, dir_entry->d_name);
if (ph_dct_imagehash(path, tmphash) < 0) // calculate the hash
continue;
dp = ph_malloc_imagepoint(); // store in structure with filename
dp->id = dir_entry->d_name;
dp->hash = tmphash;
std::cout << "HASH " << tmphash << std::endl;
hashlist2.push_back(*dp);
i++;
}
errno = 0;
path[0] = '\0';
}
if (errno) {
printf("error reading directory\n");
exit(1);
}
sort(hashlist2.begin(), hashlist2.end(), cmp_lt_imp);
int nbfiles1 = hashlist1.size();
int nbfiles2 = hashlist2.size();
int nbfiles = nbfiles1;
if (nbfiles1 != nbfiles2) {
nbfiles = (nbfiles2 > nbfiles1) ? nbfiles2 : nbfiles1;
}
int distance = -1;
printf("**************************\n");
printf("intra distance comparisons\n");
printf("**************************\n");
for (i = 0; i < nbfiles; i++) {
printf(" %d %s %s ", i, hashlist1[i].id, hashlist2[i].id);
// calculate distance
distance = ph_hamming_distance(hashlist1[i].hash, hashlist2[i].hash);
printf(" dist = %d\n", distance);
}
printf("**************************\n");
printf("inter distance comparisons\n");
printf("**************************\n");
for (i = 0; i < nbfiles1; i++) {
for (int j = i + 1; j < nbfiles1; j++) {
printf(" %s %s ", hashlist1[i].id, hashlist1[j].id);
// calculate distance
distance =
ph_hamming_distance(hashlist1[i].hash, hashlist1[j].hash);
printf(" dist = %d\n", distance);
}
}
printf("**************************\n");
return 0;
}