[Forensics-changes] [SCM] debian-forensics/libphash branch, upstream, updated. upstream/0.7.2-2-gc0fab35

Tiago Bortoletto Vaz tiago at debian.org
Mon Feb 1 00:51:36 UTC 2010


The following commit has been merged in the upstream branch:
commit c0fab354496d5f588bfef49952fe3394295d5b3a
Author: Tiago Bortoletto Vaz <tiago at debian.org>
Date:   Mon Feb 1 00:49:33 2010 +0000

    Adding upstream version 0.8.1.

diff --git a/ChangeLog b/ChangeLog
index 7be0a89..3f8bb33 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+0.8.1
+---
+01.28.2010 minor bug fix for mh image hash and compilation fix for older gcc versions
+
+
+0.8.0
+---
+01.18.2010 change example files build_mvptree.cpp, add_mvptree.cpp, query_mvptree.cpp
+	   to use the new mh image hash
+01.17.2010 add new image hash based on mexican hat/marr wavelet together with distance func
+	   ph_mhimagehash() and ph_bitcount8() and ph_hammingdistance2() functions
+
 0.7.1
 ---
 12.22.2009 put code in cimgffmpeg.h header into own .cpp file
diff --git a/Makefile.in b/Makefile.in
index baecff0..e3a6d56 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -199,6 +199,7 @@ abs_top_srcdir = @abs_top_srcdir@
 ac_ct_CC = @ac_ct_CC@
 ac_ct_CXX = @ac_ct_CXX@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_GCJ = @ac_ct_GCJ@
 am__include = @am__include@
 am__leading_dot = @am__leading_dot@
 am__quote = @am__quote@
@@ -344,7 +345,7 @@ uninstall-pkgconfigDATA:
 #     (which will cause the Makefiles to be regenerated when you run `make');
 # (2) otherwise, pass the desired values on the `make' command line.
 $(RECURSIVE_TARGETS):
-	@failcom='exit 1'; \
+	@fail= failcom='exit 1'; \
 	for f in x $$MAKEFLAGS; do \
 	  case $$f in \
 	    *=* | --[!k]*);; \
@@ -369,7 +370,7 @@ $(RECURSIVE_TARGETS):
 	fi; test -z "$$fail"
 
 $(RECURSIVE_CLEAN_TARGETS):
-	@failcom='exit 1'; \
+	@fail= failcom='exit 1'; \
 	for f in x $$MAKEFLAGS; do \
 	  case $$f in \
 	    *=* | --[!k]*);; \
@@ -533,7 +534,8 @@ distdir: $(DISTFILES)
 	  fi; \
 	done
 	-test -n "$(am__skip_mode_fix)" \
-	|| find "$(distdir)" -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+	|| find "$(distdir)" -type d ! -perm -755 \
+		-exec chmod u+rwx,go+rx {} \; -o \
 	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
 	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
 	  ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
@@ -577,17 +579,17 @@ dist dist-all: distdir
 distcheck: dist
 	case '$(DIST_ARCHIVES)' in \
 	*.tar.gz*) \
-	  GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+	  GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
 	*.tar.bz2*) \
-	  bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+	  bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
 	*.tar.lzma*) \
-	  unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
+	  lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
 	*.tar.xz*) \
 	  xz -dc $(distdir).tar.xz | $(am__untar) ;;\
 	*.tar.Z*) \
 	  uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
 	*.shar.gz*) \
-	  GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+	  GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
 	*.zip*) \
 	  unzip $(distdir).zip ;;\
 	esac
diff --git a/aclocal.m4 b/aclocal.m4
index fbb4be9..6bf14e8 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.11 -*- Autoconf -*-
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
 
 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 # 2005, 2006, 2007, 2008, 2009  Free Software Foundation, Inc.
@@ -7862,15 +7862,15 @@ m4_define([lt_dict_filter],
 
 # Generated from ltversion.in.
 
-# serial 3012 ltversion.m4
+# serial 3017 ltversion.m4
 # This file is part of GNU Libtool
 
-m4_define([LT_PACKAGE_VERSION], [2.2.6])
-m4_define([LT_PACKAGE_REVISION], [1.3012])
+m4_define([LT_PACKAGE_VERSION], [2.2.6b])
+m4_define([LT_PACKAGE_REVISION], [1.3017])
 
 AC_DEFUN([LTVERSION_VERSION],
-[macro_version='2.2.6'
-macro_revision='1.3012'
+[macro_version='2.2.6b'
+macro_revision='1.3017'
 _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
 _LT_DECL(, macro_revision, 0)
 ])
@@ -7983,7 +7983,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
 [am__api_version='1.11'
 dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
 dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.11], [],
+m4_if([$1], [1.11.1], [],
       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
 ])
 
@@ -7999,7 +7999,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
 # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
 # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.11])dnl
+[AM_AUTOMAKE_VERSION([1.11.1])dnl
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
@@ -8358,14 +8358,14 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
 # Check for Java compiler.                                  -*- Autoconf -*-
 # For now we only handle the GNU compiler.
 
-# Copyright (C) 1999, 2000, 2003, 2005  Free Software Foundation, Inc.
+# Copyright (C) 1999, 2000, 2003, 2005, 2009  Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
 AC_DEFUN([AM_PROG_GCJ],[
-AC_CHECK_PROGS(GCJ, gcj, gcj)
+AC_CHECK_TOOLS(GCJ, gcj, gcj)
 test -z "$GCJ" && AC_MSG_ERROR([no acceptable gcj found in \$PATH])
 if test "x${GCJFLAGS-unset}" = xunset; then
    GCJFLAGS="-g -O2"
diff --git a/bindings/Makefile.in b/bindings/Makefile.in
index a788223..1305c7d 100644
--- a/bindings/Makefile.in
+++ b/bindings/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -159,6 +159,7 @@ abs_top_srcdir = @abs_top_srcdir@
 ac_ct_CC = @ac_ct_CC@
 ac_ct_CXX = @ac_ct_CXX@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_GCJ = @ac_ct_GCJ@
 am__include = @am__include@
 am__leading_dot = @am__leading_dot@
 am__quote = @am__quote@
@@ -253,7 +254,7 @@ clean-libtool:
 #     (which will cause the Makefiles to be regenerated when you run `make');
 # (2) otherwise, pass the desired values on the `make' command line.
 $(RECURSIVE_TARGETS):
-	@failcom='exit 1'; \
+	@fail= failcom='exit 1'; \
 	for f in x $$MAKEFLAGS; do \
 	  case $$f in \
 	    *=* | --[!k]*);; \
@@ -278,7 +279,7 @@ $(RECURSIVE_TARGETS):
 	fi; test -z "$$fail"
 
 $(RECURSIVE_CLEAN_TARGETS):
-	@failcom='exit 1'; \
+	@fail= failcom='exit 1'; \
 	for f in x $$MAKEFLAGS; do \
 	  case $$f in \
 	    *=* | --[!k]*);; \
diff --git a/bindings/java/AudioHash.java b/bindings/java/AudioHash.java
new file mode 100644
index 0000000..c109215
--- /dev/null
+++ b/bindings/java/AudioHash.java
@@ -0,0 +1,4 @@
+public class AudioHash extends Hash
+{
+	int[] hash;	
+}
diff --git a/bindings/java/DCTImageHash.java b/bindings/java/DCTImageHash.java
new file mode 100644
index 0000000..c0afc79
--- /dev/null
+++ b/bindings/java/DCTImageHash.java
@@ -0,0 +1,4 @@
+public class DCTImageHash extends ImageHash
+{
+	long hash;
+}
diff --git a/bindings/java/Hash.java b/bindings/java/Hash.java
new file mode 100644
index 0000000..01ee502
--- /dev/null
+++ b/bindings/java/Hash.java
@@ -0,0 +1,4 @@
+abstract class Hash
+{
+	String filename;
+}
diff --git a/bindings/java/ImageHash.java b/bindings/java/ImageHash.java
new file mode 100644
index 0000000..6379b06
--- /dev/null
+++ b/bindings/java/ImageHash.java
@@ -0,0 +1,3 @@
+abstract class ImageHash extends Hash
+{
+}
diff --git a/bindings/java/MHImageHash.java b/bindings/java/MHImageHash.java
new file mode 100644
index 0000000..25c6c60
--- /dev/null
+++ b/bindings/java/MHImageHash.java
@@ -0,0 +1,4 @@
+public class MHImageHash extends ImageHash
+{
+	byte[] hash;
+}
diff --git a/bindings/java/MVPTree.java b/bindings/java/MVPTree.java
new file mode 100644
index 0000000..e18ce59
--- /dev/null
+++ b/bindings/java/MVPTree.java
@@ -0,0 +1,9 @@
+public class MVPTree
+{
+String mvpFile;
+MVPTree(String filename) { mvpFile = filename; }
+public native boolean create(Hash[] hashes);
+public native Hash[] query(Hash hash, float radius, int maxResults);
+public native boolean add(Hash[] hashes);
+}
+
diff --git a/bindings/java/Makefile.am b/bindings/java/Makefile.am
index 224dd0f..97cf225 100644
--- a/bindings/java/Makefile.am
+++ b/bindings/java/Makefile.am
@@ -2,7 +2,7 @@ INCLUDES = -I$(top_srcdir)/src
 lib_LTLIBRARIES = libpHash-jni.la
 libpHash_jni_la_SOURCES = pHash-jni.cpp
 include_HEADERS = pHash-jni.h pHash_MVPTree.h
-EXTRA_DIST = pHash.java
+EXTRA_DIST = *.java README
 
 libpHash_jni_la_LIBADD = $(top_srcdir)/src/libpHash.la
 
diff --git a/bindings/java/Makefile.in b/bindings/java/Makefile.in
index 2c785fa..a0eeb7b 100644
--- a/bindings/java/Makefile.in
+++ b/bindings/java/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -36,7 +36,7 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 subdir = bindings/java
-DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
+DIST_COMMON = README $(include_HEADERS) $(srcdir)/Makefile.am \
 	$(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/configure.ac
@@ -164,6 +164,7 @@ abs_top_srcdir = @abs_top_srcdir@
 ac_ct_CC = @ac_ct_CC@
 ac_ct_CXX = @ac_ct_CXX@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_GCJ = @ac_ct_GCJ@
 am__include = @am__include@
 am__leading_dot = @am__leading_dot@
 am__quote = @am__quote@
@@ -214,7 +215,7 @@ INCLUDES = -I$(top_srcdir)/src
 lib_LTLIBRARIES = libpHash-jni.la
 libpHash_jni_la_SOURCES = pHash-jni.cpp
 include_HEADERS = pHash-jni.h pHash_MVPTree.h
-EXTRA_DIST = pHash.java
+EXTRA_DIST = *.java README
 libpHash_jni_la_LIBADD = $(top_srcdir)/src/libpHash.la
 all: all-am
 
diff --git a/bindings/java/README b/bindings/java/README
new file mode 100644
index 0000000..8391c89
--- /dev/null
+++ b/bindings/java/README
@@ -0,0 +1,11 @@
+How to use Java bindings:
+1) Configure pHash with Java support (--enable-java)
+2) Build pHash
+3) Compile Java classes if not done already: javac *.java
+4) Install pHash (make install)
+5) java -Djava.library.path=/usr/local/lib pHash -mh img1.jpg img2.jpg
+	See pHash.java for additional options
+
+	Note: When using the MVP storage functions, the number of hashes needed to create the tree is the leaf 
+	capacity + 3 (28 by default).
+
diff --git a/bindings/java/TextHash.java b/bindings/java/TextHash.java
new file mode 100644
index 0000000..90bde44
--- /dev/null
+++ b/bindings/java/TextHash.java
@@ -0,0 +1,4 @@
+public class TextHash extends Hash
+{
+	String[] hash;
+}
diff --git a/bindings/java/VideoHash.java b/bindings/java/VideoHash.java
new file mode 100644
index 0000000..efa3be3
--- /dev/null
+++ b/bindings/java/VideoHash.java
@@ -0,0 +1,4 @@
+public class VideoHash extends Hash
+{
+	long[] hash;
+}
diff --git a/bindings/java/pHash-jni.cpp b/bindings/java/pHash-jni.cpp
index 035f2c4..747ee84 100644
--- a/bindings/java/pHash-jni.cpp
+++ b/bindings/java/pHash-jni.cpp
@@ -1,3 +1,27 @@
+/*
+
+    pHash, the open source perceptual hash library
+    Copyright (C) 2010 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 <http://www.gnu.org/licenses/>.
+
+    Evan Klinger - eklinger at phash.org
+    David Starkweather - dstarkweather at phash.org
+
+*/
+
 #include "config.h"
 #include <jni.h>
 #include "pHash-jni.h"
@@ -8,17 +32,20 @@
 #include "audiophash.h"
 #endif
  
-jfieldID imHash_hash = NULL; 
+jfieldID dctImHash_hash = NULL; 
+jfieldID mhImHash_hash = NULL; 
 jfieldID vidHash_hash = NULL; 
 jfieldID audioHash_hash = NULL; 
 
 jfieldID hash_filename = NULL; 
 
-jclass imClass = NULL;
+jclass dctImClass = NULL;
+jclass mhImClass = NULL;
 jclass vidClass = NULL;
 jclass audioClass = NULL;
 
-jmethodID imCtor = NULL;
+jmethodID dctImCtor = NULL;
+jmethodID mhImCtor = NULL;
 jmethodID vidCtor = NULL;
 jmethodID audioCtor = NULL;
 
@@ -32,36 +59,37 @@ typedef enum ph_jni_hash_types
 
 typedef struct ph_jni_hash_classes
 {
-	jclass cl;
+	jclass *cl;
 	HashType hashType;
 	hash_compareCB callback;
 	jniHashType kind;
-	jmethodID ctor;
-	jfieldID hashID;
+	jmethodID *ctor;
+	jfieldID *hashID;
 } jniHashes;
 
 float video_distance(DP *a, DP *b)
 {
-ulong64 *hash1 = (ulong64 *)a->hash;
-ulong64 *hash2 = (ulong64 *)b->hash;
-double sim = ph_dct_videohash_dist(hash1, a->hash_length, hash2, b->hash_length, 21);
-return (float)sim;
+	ulong64 *hash1 = (ulong64 *)a->hash;
+	ulong64 *hash2 = (ulong64 *)b->hash;
+	double sim = ph_dct_videohash_dist(hash1, a->hash_length, hash2, b->hash_length, 21);
+	return (float)sim;
 }
 
-float image_distance(DP *pntA, DP *pntB)
+float dctImage_distance(DP *pntA, DP *pntB)
 {
-	uint8_t htypeA = pntA->hash_type;
-	uint8_t htypeB = pntB->hash_type;
-	if (htypeA != htypeB)
-        	return -1.0;
-	if (htypeA != UINT64ARRAY)
-        	return -1.0;
-    	if ((pntA->hash_length > 1) || (pntB->hash_length > 1))
-        	return -1.0;
-    	ulong64 *hashA = (ulong64*)pntA->hash;
-    	ulong64 *hashB = (ulong64*)pntB->hash;
-    	int res = ph_hamming_distance(*hashA, *hashB);
-    	return (float)res;
+	
+	ulong64 *hashA = (ulong64*)pntA->hash;
+	ulong64 *hashB = (ulong64*)pntB->hash;
+	float res = ph_hamming_distance(*hashA, *hashB);
+	return res;
+}
+
+float mhImage_distance(DP *a, DP *b)
+{
+	uint8_t *hashA = (uint8_t*)a->hash;
+	uint8_t *hashB = (uint8_t*)b->hash;
+	float res = ph_hammingdistance2(hashA,a->hash_length,hashB,b->hash_length)*10;
+    	return exp(res);
 }
 
 float audio_distance(DP *dpA, DP *dpB)
@@ -88,31 +116,32 @@ float audio_distance(DP *dpA, DP *dpB)
 }
 
 
-static jniHashes hashes[] = 
+const static jniHashes hashes[] = 
 			{ 	
-				{imClass, UINT64ARRAY, image_distance, IMAGE_HASH, imCtor, imHash_hash}, 
-				{vidClass, UINT64ARRAY, video_distance, VIDEO_HASH, vidCtor, vidHash_hash}, 
-				{audioClass, UINT32ARRAY, audio_distance, AUDIO_HASH, audioCtor, audioHash_hash},
+				{&mhImClass, BYTEARRAY, mhImage_distance, IMAGE_HASH, &mhImCtor, &mhImHash_hash}, 
+				{&dctImClass, UINT64ARRAY, dctImage_distance, IMAGE_HASH, &dctImCtor, &dctImHash_hash},
+				{&vidClass, UINT64ARRAY, video_distance, VIDEO_HASH, &vidCtor, &vidHash_hash}, 
+				{&audioClass, UINT32ARRAY, audio_distance, AUDIO_HASH, &audioCtor, &audioHash_hash},
 			};
 
-JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_create
+JNIEXPORT jboolean JNICALL Java_MVPTree_create
   (JNIEnv *e, jobject ob, jobjectArray hashArray)
 {
 	jint hashLen;
 	if(hashArray == NULL || (hashLen = e->GetArrayLength(hashArray)) == 0)
 		return JNI_FALSE;
 
-	jstring mvp = (jstring)e->GetObjectField(ob, e->GetFieldID(e->FindClass("pHash/MVPTree"), "mvpFile",
+	jstring mvp = (jstring)e->GetObjectField(ob, e->GetFieldID(e->FindClass("MVPTree"), "mvpFile",
 										"Ljava/lang/String;"));
 	
-
 	MVPFile mvpfile;
 	ph_mvp_init(&mvpfile);
 	mvpfile.filename = e->GetStringUTFChars(mvp, 0);
 	jniHashType type;
+	jobject htype = e->GetObjectArrayElement(hashArray, 0);
 	for(int i = 0; i < sizeof(hashes)/sizeof(hashes[0]); i++)
 	{
-		if(e->IsInstanceOf(hashArray, hashes[i].cl))
+		if(e->IsInstanceOf(htype, *hashes[i].cl))
 		{
 			mvpfile.hashdist = hashes[i].callback;
 			mvpfile.hash_type = hashes[i].hashType;
@@ -123,7 +152,6 @@ JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_create
 	
 
 	DP **hashlist = (DP **)malloc(hashLen*sizeof(DP*));
-
 	for(jsize i = 0; i < hashLen; i++)
 	{
 		jobject hashObj = e->GetObjectArrayElement(hashArray, i);
@@ -134,7 +162,7 @@ JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_create
 			free(hashlist);
 			e->ReleaseStringUTFChars(mvp, mvpfile.filename);
 			return JNI_FALSE;
-		}			
+		}
 		jstring fname = (jstring)e->GetObjectField(hashObj, hash_filename);
 
 		const char *path = e->GetStringUTFChars(fname, 0);
@@ -144,23 +172,23 @@ JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_create
 		switch(type)
 		{
 			case IMAGE_HASH:
-				ulong64 tmphash;
-				ph_dct_imagehash(path, tmphash);
-				hashlist[i]->hash = (ulong64 *)malloc(sizeof(ulong64));
-				if(!hashlist[i]->hash)
+				if(e->IsInstanceOf(hashObj, dctImClass))
 				{
-					for(int i = 0; i < hashLen; i++)
-					{
-						if(hashlist[i])
-							ph_free_datapoint(hashlist[i]);
-					}
-
-					free(hashlist);
-					e->ReleaseStringUTFChars(mvp, mvpfile.filename);
-					return JNI_FALSE;
+					ulong64 tmphash;
+					ph_dct_imagehash(path, tmphash);
+					hashlist[i]->hash = (ulong64 *)malloc(sizeof(ulong64));
+					*(ulong64 *)hashlist[i]->hash = tmphash;
+					hashlist[i]->hash_length = 1;
 				}
-				*(ulong64 *)hashlist[i]->hash = tmphash;
-				hashlist[i]->hash_length = 1;
+				else if(e->IsInstanceOf(hashObj, mhImClass))
+				{
+					int N;
+					uint8_t *hash = ph_mh_imagehash(path, N);
+					hashlist[i]->hash = hash;
+					hashlist[i]->hash_length = N;
+				}				
+
+
 				break;
 			case VIDEO_HASH:
 				{
@@ -198,12 +226,6 @@ JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_create
 				} 
 				else
 				{
-					for(int i = 0; i < hashLen; i++)
-					{
-						if(hashlist[i])
-							ph_free_datapoint(hashlist[i]);
-					}
-
 					free(hashlist);
 					e->ReleaseStringUTFChars(mvp, mvpfile.filename);
 					return JNI_FALSE;
@@ -214,6 +236,9 @@ JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_create
 		e->ReleaseStringUTFChars(fname, path);
 	}
 
+
+
+	MVPRetCode ret = ph_save_mvptree(&mvpfile, hashlist, hashLen);
 	for(int i = 0; i < hashLen; i++)
 	{
 		if(hashlist[i])
@@ -222,11 +247,10 @@ JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_create
 
 	free(hashlist);
 	e->ReleaseStringUTFChars(mvp, mvpfile.filename);
-	return JNI_TRUE;
-
+	return ret == 0 ? JNI_TRUE : JNI_FALSE;
 }
 
-JNIEXPORT jobjectArray JNICALL Java_pHash_00024MVPTree_query
+JNIEXPORT jobjectArray JNICALL Java_MVPTree_query
   (JNIEnv *e, jobject ob, jobject hashObj, jfloat radius, jint max)
 {
 
@@ -234,14 +258,14 @@ JNIEXPORT jobjectArray JNICALL Java_pHash_00024MVPTree_query
 	jniHashType type;	
 	ph_mvp_init(&mvpfile);
 	
-	jstring mvp = (jstring)e->GetObjectField(ob, e->GetFieldID(e->FindClass("pHash/MVPTree"), "mvpFile",
+	jstring mvp = (jstring)e->GetObjectField(ob, e->GetFieldID(e->FindClass("MVPTree"), "mvpFile",
 										"Ljava/lang/String;"));
 	
 	mvpfile.filename = e->GetStringUTFChars(mvp, 0);
 	int i;
 	for(i = 0; i < sizeof(hashes)/sizeof(hashes[0]); i++)
 	{
-		if(e->IsInstanceOf(hashObj, hashes[i].cl))
+		if(e->IsInstanceOf(hashObj, *hashes[i].cl))
 		{
 			mvpfile.hashdist = hashes[i].callback;
 			mvpfile.hash_type = hashes[i].hashType;
@@ -265,16 +289,27 @@ JNIEXPORT jobjectArray JNICALL Java_pHash_00024MVPTree_query
 	{
 		case IMAGE_HASH:
 		{	
-			query->hash_length = 1;
-			ulong64 hash = (ulong64)e->GetLongField(hashObj, imHash_hash);
-			query->hash = &hash;
+			if(e->IsInstanceOf(hashObj, dctImClass))
+			{
+				query->hash_length = 1;
+				ulong64 hash = (ulong64)e->GetLongField(hashObj, dctImHash_hash);
+				query->hash = &hash;
+			}
+			else if(e->IsInstanceOf(hashObj, mhImClass))
+			{
+				jbyteArray hash = (jbyteArray)e->GetObjectField(hashObj, mhImHash_hash);
+				query->hash_length = e->GetArrayLength(hash);
+				jbyte *hashes = e->GetByteArrayElements(hash, NULL);
+				query->hash = (uint8_t*)hashes;				
+			}
 			break;
 		}
 		case VIDEO_HASH:
 		{
-			query->hash_length = 1;
-			ulong64 hash = (ulong64)e->GetLongField(hashObj, vidHash_hash);
-                        query->hash = &hash;
+			jlongArray l = (jlongArray)e->GetObjectField(hashObj, vidHash_hash);
+			query->hash_length = e->GetArrayLength(l);
+			jlong *h = e->GetLongArrayElements(l, NULL);
+                        query->hash = (ulong64*)h;
 			break;
 		}
 		case AUDIO_HASH:
@@ -282,7 +317,7 @@ JNIEXPORT jobjectArray JNICALL Java_pHash_00024MVPTree_query
 			hashList = (jintArray)e->GetObjectField(hashObj, audioHash_hash);
 			query->hash_length = e->GetArrayLength(hashList);
 			hash_list = e->GetIntArrayElements(hashList, NULL);
-			query->hash = hash_list;
+			query->hash = (uint32_t*)hash_list;
 			break;
 		}
 	}
@@ -296,33 +331,44 @@ JNIEXPORT jobjectArray JNICALL Java_pHash_00024MVPTree_query
 	}
 	else
 	{
-		jobject obj = e->NewObject(hashes[i].cl, hashes[i].ctor);
-		ret = e->NewObjectArray(count, hashes[i].cl, obj);
+		jobject iobj = e->NewObject(*hashes[i].cl, *hashes[i].ctor);
+		ret = e->NewObjectArray(count, *hashes[i].cl, iobj);
 		for(int j = 0; j < count; j++)
 		{
-			obj = e->GetObjectArrayElement(ret, j);
+			jobject obj = e->NewObject(*hashes[i].cl, *hashes[i].ctor);
+
 			jstring id = e->NewStringUTF(results[j]->id);
 			e->SetObjectField(obj, hash_filename, id);
 			switch(type)
 			{
 				case IMAGE_HASH:
-					e->SetLongField(obj, hashes[i].hashID, *(jlong *)results[j]->hash);
-					break;
+					if(e->IsInstanceOf(obj, dctImClass))
+						e->SetLongField(obj, *hashes[i].hashID, *(jlong *)results[j]->hash);
+					else if(e->IsInstanceOf(obj, mhImClass))
+					{
+						jbyteArray hash = e->NewByteArray(results[j]->hash_length);
+						e->SetByteArrayRegion(hash, 0, results[j]->hash_length, (jbyte *)results[j]->hash);
+						e->SetObjectField(obj, *hashes[i].hashID, hash);
+					}	
+				break;
 				case VIDEO_HASH:
-					e->SetLongField(obj, hashes[i].hashID, *(jlong *)results[j]->hash);
+					e->SetLongField(obj, *hashes[i].hashID, *(jlong *)results[j]->hash);
 					break;
 				case AUDIO_HASH:
-					jintArray hashArray;
+					jintArray hashArray = e->NewIntArray(results[j]->hash_length);
 					e->SetIntArrayRegion(hashArray, 0, results[j]->hash_length, (jint *)results[j]->hash); 
-					e->SetObjectField(obj, hashes[i].hashID, hashArray);
+					e->SetObjectField(obj, *hashes[i].hashID, hashArray);
 					break;
 			}
+			e->SetObjectArrayElement(ret,j,obj);
+
 		}
+
 	}
 	e->ReleaseStringUTFChars(mvp, mvpfile.filename);
 	e->ReleaseStringUTFChars(hashStr, hash_file);
 	ph_free_datapoint(query);
-	for(int i = 0; i < max; i++)
+	for(int i = 0; i < count; i++)
 	{
 		if(results[i])
 			ph_free_datapoint(results[i]);
@@ -331,17 +377,18 @@ JNIEXPORT jobjectArray JNICALL Java_pHash_00024MVPTree_query
 	return ret;
 }
 
-JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_add
+JNIEXPORT jboolean JNICALL Java_MVPTree_add
   (JNIEnv *e, jobject ob, jobjectArray hashArray)
 {
 	MVPFile mvpfile;
 	jniHashType type;	
 	ph_mvp_init(&mvpfile);
+	jsize len;
 
-	if(hashArray == NULL)
+	if(hashArray == NULL || (len = e->GetArrayLength(hashArray)) == 0)
 		return JNI_FALSE;
 	
-	jstring mvp = (jstring)e->GetObjectField(ob, e->GetFieldID(e->FindClass("pHash/MVPTree"), "mvpFile",
+	jstring mvp = (jstring)e->GetObjectField(ob, e->GetFieldID(e->FindClass("MVPTree"), "mvpFile",
 										"Ljava/lang/String;"));
 	
 	mvpfile.filename = e->GetStringUTFChars(mvp, 0);
@@ -349,7 +396,7 @@ JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_add
 	jobject hashObj = e->GetObjectArrayElement(hashArray, 0);
 	for(i = 0; i < sizeof(hashes)/sizeof(hashes[0]); i++)
 	{
-		if(e->IsInstanceOf(hashObj, hashes[i].cl))
+		if(e->IsInstanceOf(hashObj, *hashes[i].cl))
 		{
 			mvpfile.hashdist = hashes[i].callback;
 			mvpfile.hash_type = hashes[i].hashType;
@@ -360,7 +407,6 @@ JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_add
 	
 	const char *hash_file = NULL;
 
-	jsize len = e->GetArrayLength(hashArray);
 
 	DP **newHashes = (DP **)malloc(len*sizeof(DP *));
 	jintArray hashList = NULL;
@@ -380,18 +426,30 @@ JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_add
 	{
 		case IMAGE_HASH:
 		{
+			
+			if(e->IsInstanceOf(hashObj, dctImClass))
+			{
 			newHashes[j]->hash_length = 1;
-			ulong64 hash = (ulong64)e->GetLongField(hashObj, imHash_hash);
+			ulong64 hash = (ulong64)e->GetLongField(hashObj, dctImHash_hash);
 			newHashes[j]->hash = (ulong64 *)malloc(sizeof(ulong64));
 			*(ulong64 *)newHashes[j]->hash = hash;
+			}
+			else if(e->IsInstanceOf(hashObj, mhImClass))
+			{
+			jbyteArray h = (jbyteArray)e->GetObjectField(hashObj, mhImHash_hash);
+			newHashes[j]->hash_length = e->GetArrayLength(h);
+			jbyte *hash = e->GetByteArrayElements(h, NULL);
+			newHashes[j]->hash = (uint8_t*)hash;
+			}
+
 			break;
 		}
 		case VIDEO_HASH:
 		{
-			newHashes[j]->hash_length = 1;
-			ulong64 hash = (ulong64)e->GetLongField(hashObj, vidHash_hash);
-                        newHashes[j]->hash = (ulong64 *)malloc(sizeof(ulong64));
-			*(ulong64 *)newHashes[j]->hash = hash;
+			jlongArray l = (jlongArray)e->GetObjectField(hashObj, vidHash_hash);
+			newHashes[j]->hash_length = e->GetArrayLength(l);
+			jlong *h = e->GetLongArrayElements(l, NULL);
+                        newHashes[j]->hash = (ulong64*)h;
 			break;
 		}
 		case AUDIO_HASH:
@@ -399,7 +457,7 @@ JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_add
 			hashList = (jintArray)e->GetObjectField(hashObj, audioHash_hash);
 			newHashes[j]->hash_length = e->GetArrayLength(hashList);
 			hash_list = e->GetIntArrayElements(hashList, NULL);
-			newHashes[j]->hash = hash_list;
+			newHashes[j]->hash = (uint32_t*)hash_list;
 			break;
 		}
 	}
@@ -430,16 +488,20 @@ JNIEXPORT void JNICALL Java_pHash_pHashInit
   (JNIEnv *e, jclass cl)
 {
 	
-	imClass = (jclass)e->NewGlobalRef(e->FindClass("ImageHash"));
+	dctImClass = (jclass)e->NewGlobalRef(e->FindClass("DCTImageHash"));
+	mhImClass = (jclass)e->NewGlobalRef(e->FindClass("MHImageHash"));
 	audioClass = (jclass)e->NewGlobalRef(e->FindClass("AudioHash"));
 	vidClass = (jclass)e->NewGlobalRef(e->FindClass("VideoHash"));
-        imHash_hash = e->GetFieldID(imClass, "hash", "J");
-        audioHash_hash = e->GetFieldID(audioClass, "hash", "[I");
-        vidHash_hash = e->GetFieldID(vidClass, "hash", "J");
-	
+
+        dctImHash_hash = e->GetFieldID(dctImClass, "hash", "J");
+	mhImHash_hash = e->GetFieldID(mhImClass, "hash", "[B");
+	audioHash_hash = e->GetFieldID(audioClass, "hash", "[I");
+	vidHash_hash = e->GetFieldID(vidClass, "hash", "[J");
+
 	hash_filename = e->GetFieldID(e->FindClass("Hash"), "filename", "Ljava/lang/String;");
 
-	imCtor = e->GetMethodID(imClass, "<init>", "()V");
+	dctImCtor = e->GetMethodID(dctImClass, "<init>", "()V");
+	mhImCtor = e->GetMethodID(mhImClass, "<init>", "()V");
 	vidCtor = e->GetMethodID(vidClass, "<init>", "()V");
 	audioCtor = e->GetMethodID(audioClass, "<init>", "()V");
 
@@ -447,20 +509,37 @@ JNIEXPORT void JNICALL Java_pHash_pHashInit
 JNIEXPORT void JNICALL Java_pHash_cleanup
   (JNIEnv *e, jclass cl)
 {
-	e->DeleteGlobalRef(imClass);
+	e->DeleteGlobalRef(mhImClass);
+	e->DeleteGlobalRef(dctImClass);
 	e->DeleteGlobalRef(vidClass);
 	e->DeleteGlobalRef(audioClass);
 
 }
-JNIEXPORT jint JNICALL Java_pHash_imageDistance
+JNIEXPORT jdouble JNICALL Java_pHash_imageDistance
   (JNIEnv *e, jclass cl, jobject hash1, jobject hash2)
 {
-	ulong64 imHash, imHash2;
-	imHash = (ulong64)e->GetLongField(hash1, imHash_hash);
-	imHash2 = (ulong64)e->GetLongField(hash2, imHash_hash);
+	if(e->IsInstanceOf(hash1, dctImClass) && e->IsInstanceOf(hash2, dctImClass))
+	{
+		ulong64 imHash, imHash2;
+		imHash = (ulong64)e->GetLongField(hash1, dctImHash_hash);
+		imHash2 = (ulong64)e->GetLongField(hash2, dctImHash_hash);
 
-	return ph_hamming_distance(imHash, imHash2);
-	
+		return ph_hamming_distance(imHash, imHash2);
+	}
+	else if(e->IsInstanceOf(hash1, mhImClass) && e->IsInstanceOf(hash2, mhImClass))
+	{
+		jbyteArray h = (jbyteArray)e->GetObjectField(hash1, mhImHash_hash);
+		jbyteArray h2 = (jbyteArray)e->GetObjectField(hash2, mhImHash_hash);
+		int N = e->GetArrayLength(h);
+		int N2 = e->GetArrayLength(h2);
+		jbyte *hash = e->GetByteArrayElements(h, NULL);
+		jbyte *hash2 = e->GetByteArrayElements(h2, NULL);
+		double hd = ph_hammingdistance2((uint8_t*)hash, N, (uint8_t*)hash2, N2);
+		e->ReleaseByteArrayElements(h, hash, 0);
+		e->ReleaseByteArrayElements(h2, hash2, 0);
+		return hd;	
+	}
+	return -1;
 }
 
 #ifdef HAVE_AUDIO_HASH
@@ -506,7 +585,7 @@ JNIEXPORT jdouble JNICALL Java_pHash_audioDistance
 }
 #endif
 
-JNIEXPORT jobject JNICALL Java_pHash_imageHash
+JNIEXPORT jobject JNICALL Java_pHash_dctImageHash
   (JNIEnv *e, jclass cl, jstring f)
 {
     
@@ -514,10 +593,35 @@ JNIEXPORT jobject JNICALL Java_pHash_imageHash
     
     	ulong64 hash;
     	ph_dct_imagehash(file, hash);
-	jobject imageHash = e->NewObject(imClass, imCtor);
+	jobject imageHash = e->NewObject(dctImClass, dctImCtor);
 	e->SetObjectField(imageHash, hash_filename, f);
 
-	e->SetLongField(imageHash, imHash_hash, (jlong)hash);
+	e->SetLongField(imageHash, dctImHash_hash, (jlong)hash);
+    	e->ReleaseStringUTFChars(f,file);
+	
+	return imageHash;
+	
+}
+
+JNIEXPORT jobject JNICALL Java_pHash_mhImageHash
+  (JNIEnv *e, jclass cl, jstring f)
+{
+    
+	const char *file = e->GetStringUTFChars(f,0);
+    
+	int N;
+    	uint8_t *hash = ph_mh_imagehash(file, N);
+	jobject imageHash = NULL;
+	if(hash && N > 0)
+	{
+		imageHash = e->NewObject(mhImClass, mhImCtor);
+		e->SetObjectField(imageHash, hash_filename, f);
+
+		jbyteArray hashVals = e->NewByteArray(N);
+		e->SetByteArrayRegion(hashVals, 0, N, (jbyte *)hash);
+		e->SetObjectField(imageHash, mhImHash_hash, hashVals);
+		free(hash);
+	}
     	e->ReleaseStringUTFChars(f,file);
 	
 	return imageHash;
@@ -564,9 +668,11 @@ JNIEXPORT jobject JNICALL Java_pHash_videoHash
 	jobject videoHash = e->NewObject(vidClass, vidCtor);
 	e->SetObjectField(videoHash, hash_filename, f);
 
-	jlongArray hashVals = (jlongArray)e->GetObjectField(videoHash, vidHash_hash);
-	
+	jlongArray hashVals = e->NewLongArray(len);
+
 	e->SetLongArrayRegion(hashVals, 0, len, (jlong *)hash);
+
+	e->SetObjectField(videoHash, vidHash_hash, hashVals);
 	free(hash);
     	e->ReleaseStringUTFChars(f,file);
 
@@ -604,9 +710,10 @@ JNIEXPORT jobject JNICALL Java_pHash_audioHash
 	e->SetObjectField(audioHash, hash_filename, f);
 	e->ReleaseStringUTFChars(f,file);
 
-	jintArray hashVals = (jintArray)e->GetObjectField(audioHash, audioHash_hash);
-	
+	jintArray hashVals = e->NewIntArray(nbframes);
+
 	e->SetIntArrayRegion(hashVals, 0, nbframes, (jint *)hash);
+	e->SetObjectField(audioHash, audioHash_hash, hashVals);
 	free(hash);
 
 	return audioHash;
diff --git a/bindings/java/pHash-jni.h b/bindings/java/pHash-jni.h
index 0980461..585f141 100644
--- a/bindings/java/pHash-jni.h
+++ b/bindings/java/pHash-jni.h
@@ -10,7 +10,7 @@ extern "C" {
 /*
  * Class:     pHash
  * Method:    videoHash
- * Signature: (Ljava/lang/String;)LpHash/VideoHash;
+ * Signature: (Ljava/lang/String;)LVideoHash;
  */
 JNIEXPORT jobject JNICALL Java_pHash_videoHash
   (JNIEnv *, jclass, jstring);
@@ -18,23 +18,31 @@ JNIEXPORT jobject JNICALL Java_pHash_videoHash
 /*
  * Class:     pHash
  * Method:    audioHash
- * Signature: (Ljava/lang/String;)LpHash/AudioHash;
+ * Signature: (Ljava/lang/String;)LAudioHash;
  */
 JNIEXPORT jobject JNICALL Java_pHash_audioHash
   (JNIEnv *, jclass, jstring);
 
 /*
  * Class:     pHash
- * Method:    imageHash
- * Signature: (Ljava/lang/String;)LpHash/ImageHash;
+ * Method:    dctImageHash
+ * Signature: (Ljava/lang/String;)LDCTImageHash;
  */
-JNIEXPORT jobject JNICALL Java_pHash_imageHash
+JNIEXPORT jobject JNICALL Java_pHash_dctImageHash
+  (JNIEnv *, jclass, jstring);
+
+/*
+ * Class:     pHash
+ * Method:    mhImageHash
+ * Signature: (Ljava/lang/String;)LMHImageHash;
+ */
+JNIEXPORT jobject JNICALL Java_pHash_mhImageHash
   (JNIEnv *, jclass, jstring);
 
 /*
  * Class:     pHash
  * Method:    textHash
- * Signature: (Ljava/lang/String;)LpHash/TextHash;
+ * Signature: (Ljava/lang/String;)LTextHash;
  */
 JNIEXPORT jobject JNICALL Java_pHash_textHash
   (JNIEnv *, jclass, jstring);
@@ -42,15 +50,15 @@ JNIEXPORT jobject JNICALL Java_pHash_textHash
 /*
  * Class:     pHash
  * Method:    imageDistance
- * Signature: (LpHash/ImageHash;LpHash/ImageHash;)I
+ * Signature: (LImageHash;LImageHash;)D
  */
-JNIEXPORT jint JNICALL Java_pHash_imageDistance
+JNIEXPORT jdouble JNICALL Java_pHash_imageDistance
   (JNIEnv *, jclass, jobject, jobject);
 
 /*
  * Class:     pHash
  * Method:    audioDistance
- * Signature: (LpHash/AudioHash;LpHash/AudioHash;)D
+ * Signature: (LAudioHash;LAudioHash;)D
  */
 JNIEXPORT jdouble JNICALL Java_pHash_audioDistance
   (JNIEnv *, jclass, jobject, jobject);
@@ -58,7 +66,7 @@ JNIEXPORT jdouble JNICALL Java_pHash_audioDistance
 /*
  * Class:     pHash
  * Method:    videoDistance
- * Signature: (LpHash/VideoHash;LpHash/VideoHash;)I
+ * Signature: (LVideoHash;LVideoHash;I)D
  */
 JNIEXPORT jdouble JNICALL Java_pHash_videoDistance
   (JNIEnv *, jclass, jobject, jobject, jint);
@@ -66,7 +74,7 @@ JNIEXPORT jdouble JNICALL Java_pHash_videoDistance
 /*
  * Class:     pHash
  * Method:    textDistance
- * Signature: (LpHash/TextHash;LpHash/TextHash;)I
+ * Signature: (LTextHash;LTextHash;)I
  */
 JNIEXPORT jint JNICALL Java_pHash_textDistance
   (JNIEnv *, jclass, jobject, jobject);
@@ -79,6 +87,11 @@ JNIEXPORT jint JNICALL Java_pHash_textDistance
 JNIEXPORT void JNICALL Java_pHash_pHashInit
   (JNIEnv *, jclass);
 
+/*
+ * Class:     pHash
+ * Method:    cleanup
+ * Signature: ()V
+ */
 JNIEXPORT void JNICALL Java_pHash_cleanup
   (JNIEnv *, jclass);
 
diff --git a/bindings/java/pHash.java b/bindings/java/pHash.java
index 757b9e1..3bc03ae 100644
--- a/bindings/java/pHash.java
+++ b/bindings/java/pHash.java
@@ -1,41 +1,14 @@
-	abstract class Hash
-	{
-		String filename;
-	}
-	class AudioHash extends Hash 
-	{
-		int[] hash;
-	}
-	class TextHash extends Hash 
-	{
-		String[] hash;
-	}
-	class VideoHash extends Hash 
-	{
-		long[] hash;
-	}
-	class ImageHash extends Hash 
-	{
-		long hash;
-	}
+import java.io.*;
 
-class pHash
+public class pHash
 {
-	class MVPTree
-	{
-		String mvpFile;
-
-		public MVPTree(String filename) { mvpFile = filename; }
-		public native boolean create(Hash[] hashes);
-		public native Hash[] query(Hash hash, float radius, int maxResults);
-		public native boolean add(Hash[] hashes);
-	}
 
 	native static VideoHash videoHash(String file);
 	native static AudioHash audioHash(String file);
-	native static ImageHash imageHash(String file);
+	native static DCTImageHash dctImageHash(String file);
+	native static MHImageHash mhImageHash(String file);
 	native static TextHash textHash(String file);
-	native static int imageDistance(ImageHash hash1, ImageHash hash2);
+	native static double imageDistance(ImageHash hash1, ImageHash hash2);
 	native static double audioDistance(AudioHash hash1, AudioHash hash2);
 	native static double videoDistance(VideoHash hash1, VideoHash hash2, int threshold);
 	native static int textDistance(TextHash txtHash1, TextHash txtHash2);
@@ -46,25 +19,85 @@ class pHash
 		pHashInit();
 	}
 
+	public static MHImageHash[] getMHImageHashes(String d)
+	{
+		File dir = new File(d);
+		MHImageHash[] hashes = null;
+		if(dir.isDirectory())
+		{
+			File[] files = dir.listFiles();
+			hashes = new MHImageHash[files.length];
+			for(int i = 0; i < files.length; ++i)
+			{
+				MHImageHash mh = mhImageHash(files[i].toString());
+				if(mh != null)
+					hashes[i] = mh;
+			}	
+
+		}
+		return hashes;
 
+	}
 	public static void main(String args[])
 	{
+			
 			int i = 0;
-			if(args[i].equals("-a"))
+			if(args[i].equals("-mvp"))
+			{
+					MVPTree mvp = new MVPTree("mvp");
+					MHImageHash[] hashes = getMHImageHashes(args[1]);
+					boolean result = mvp.create(hashes);
+					if(result)
+					{
+						System.out.println("Successfully created MVP tree");									
+						Hash[] results = mvp.query(hashes[0], 100, 20);
+						if(results != null && results.length > 0)
+						{
+						System.out.println("Query found " + results.length + " results");
+						for(int j = 0; j < results.length; ++j)
+							System.out.println("File: " + results[j].filename);
+						}
+
+						MHImageHash[] newHashes = getMHImageHashes(args[2]);
+
+						boolean added = mvp.add(newHashes);
+						if(added)
+						{
+							System.out.println("Hashes added successfully.");
+							Hash[] foundHashes = mvp.query(newHashes[0], 100, 20);
+							if(foundHashes != null && foundHashes.length > 0)
+							{
+								System.out.println("Found newly added hash.");
+							}
+						}
+					}
+				
+			}
+			else if(args[i].equals("-a"))
 			{
 				AudioHash audioHash1 = audioHash(args[1]);
 				AudioHash audioHash2 = audioHash(args[2]);
 				System.out.println("cs = " + audioDistance(audioHash1,audioHash2));
 			}
-			else if(args[i].equals("-i"))
+			else if(args[i].equals("-dct"))
 			{
-				ImageHash imHash = imageHash(args[1]);
-				ImageHash imHash2 = imageHash(args[2]);
+				DCTImageHash imHash = dctImageHash(args[1]);
+				DCTImageHash imHash2 = dctImageHash(args[2]);
 				System.out.println("File 1: " + imHash.filename);
 				System.out.println("File 2: " + imHash2.filename);
 
 				System.out.println(imageDistance(imHash,imHash2));
 			}
+			else if(args[i].equals("-mh"))
+			{
+				MHImageHash imHash = mhImageHash(args[1]);
+				MHImageHash imHash2 = mhImageHash(args[2]);
+				System.out.println("File 1: " + imHash.filename);
+				System.out.println("File 2: " + imHash2.filename);
+
+				System.out.println(imageDistance(imHash,imHash2));
+
+			}
 			else if(args[i].equals("-v"))
 			{
 				VideoHash vHash = videoHash(args[1]);
diff --git a/bindings/java/pHash_MVPTree.h b/bindings/java/pHash_MVPTree.h
index e619bdb..e96bfef 100644
--- a/bindings/java/pHash_MVPTree.h
+++ b/bindings/java/pHash_MVPTree.h
@@ -1,34 +1,34 @@
 /* DO NOT EDIT THIS FILE - it is machine generated */
 #include <jni.h>
-/* Header for class pHash_MVPTree */
+/* Header for class MVPTree */
 
-#ifndef _Included_pHash_MVPTree
-#define _Included_pHash_MVPTree
+#ifndef _Included_MVPTree
+#define _Included_MVPTree
 #ifdef __cplusplus
 extern "C" {
 #endif
 /*
- * Class:     pHash_MVPTree
+ * Class:     MVPTree
  * Method:    create
  * Signature: ([LHash;)Z
  */
-JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_create
+JNIEXPORT jboolean JNICALL Java_MVPTree_create
   (JNIEnv *, jobject, jobjectArray);
 
 /*
- * Class:     pHash_MVPTree
+ * Class:     MVPTree
  * Method:    query
  * Signature: (LHash;FI)[LHash;
  */
-JNIEXPORT jobjectArray JNICALL Java_pHash_00024MVPTree_query
+JNIEXPORT jobjectArray JNICALL Java_MVPTree_query
   (JNIEnv *, jobject, jobject, jfloat, jint);
 
 /*
- * Class:     pHash_MVPTree
+ * Class:     MVPTree
  * Method:    add
  * Signature: ([LHash;)Z
  */
-JNIEXPORT jboolean JNICALL Java_pHash_00024MVPTree_add
+JNIEXPORT jboolean JNICALL Java_MVPTree_add
   (JNIEnv *, jobject, jobjectArray);
 
 #ifdef __cplusplus
diff --git a/configure b/configure
index c81127c..4c5684f 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.63 for pHash 0.7.2.
+# Generated by GNU Autoconf 2.63 for pHash 0.8.1.
 #
 # Report bugs to <support at phash.org>.
 #
@@ -745,8 +745,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='pHash'
 PACKAGE_TARNAME='phash'
-PACKAGE_VERSION='0.7.2'
-PACKAGE_STRING='pHash 0.7.2'
+PACKAGE_VERSION='0.8.1'
+PACKAGE_STRING='pHash 0.8.1'
 PACKAGE_BUGREPORT='support at phash.org'
 
 ac_unique_file="src/pHash.cpp"
@@ -798,7 +798,6 @@ HAVE_IMAGE_HASH_FALSE
 HAVE_IMAGE_HASH_TRUE
 LIBTOOLS_DEPS
 CXXCPP
-CPP
 OTOOL64
 OTOOL
 LIPO
@@ -813,8 +812,6 @@ ac_ct_DUMPBIN
 DUMPBIN
 LD
 FGREP
-EGREP
-GREP
 SED
 host_os
 host_vendor
@@ -828,10 +825,14 @@ LIBTOOL
 LN_S
 WITH_JAVA_FALSE
 WITH_JAVA_TRUE
+EGREP
+GREP
+CPP
 am__fastdepGCJ_FALSE
 am__fastdepGCJ_TRUE
 GCJDEPMODE
 GCJFLAGS
+ac_ct_GCJ
 GCJ
 am__fastdepCC_FALSE
 am__fastdepCC_TRUE
@@ -1497,7 +1498,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures pHash 0.7.2 to adapt to many kinds of systems.
+\`configure' configures pHash 0.8.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1567,7 +1568,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of pHash 0.7.2:";;
+     short | recursive ) echo "Configuration of pHash 0.8.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1679,7 +1680,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-pHash configure 0.7.2
+pHash configure 0.8.1
 generated by GNU Autoconf 2.63
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1693,7 +1694,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by pHash $as_me 0.7.2, which was
+It was created by pHash $as_me 0.8.1, which was
 generated by GNU Autoconf 2.63.  Invocation command line was
 
   $ $0 $@
@@ -4209,10 +4210,11 @@ fi
 
 
 
-for ac_prog in gcj
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in gcj
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
 if test "${ac_cv_prog_GCJ+set}" = set; then
@@ -4228,7 +4230,7 @@ do
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
   if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_GCJ="$ac_prog"
+    ac_cv_prog_GCJ="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
@@ -4248,9 +4250,65 @@ $as_echo "no" >&6; }
 fi
 
 
-  test -n "$GCJ" && break
+    test -n "$GCJ" && break
+  done
+fi
+if test -z "$GCJ"; then
+  ac_ct_GCJ=$GCJ
+  for ac_prog in gcj
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_GCJ+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_GCJ"; then
+  ac_cv_prog_ac_ct_GCJ="$ac_ct_GCJ" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_GCJ="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_GCJ=$ac_cv_prog_ac_ct_GCJ
+if test -n "$ac_ct_GCJ"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_GCJ" >&5
+$as_echo "$ac_ct_GCJ" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_GCJ" && break
 done
-test -n "$GCJ" || GCJ="gcj"
+
+  if test "x$ac_ct_GCJ" = x; then
+    GCJ="gcj"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    GCJ=$ac_ct_GCJ
+  fi
+fi
 
 test -z "$GCJ" && { { $as_echo "$as_me:$LINENO: error: no acceptable gcj found in \$PATH" >&5
 $as_echo "$as_me: error: no acceptable gcj found in \$PATH" >&2;}
@@ -4429,6 +4487,803 @@ else
 fi
 
 
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:$LINENO: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    { { $as_echo "$as_me:$LINENO: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+$as_echo "$as_me: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:$LINENO: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    { { $as_echo "$as_me:$LINENO: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+$as_echo "$as_me: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_stdc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -rf conftest.dSYM
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+as_val=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+   if test "x$as_val" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+if test "$java" = "yes"; then
+
+	if test "${ac_cv_header_jni_h+set}" = set; then
+  { $as_echo "$as_me:$LINENO: checking for jni.h" >&5
+$as_echo_n "checking for jni.h... " >&6; }
+if test "${ac_cv_header_jni_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_jni_h" >&5
+$as_echo "$ac_cv_header_jni_h" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking jni.h usability" >&5
+$as_echo_n "checking jni.h usability... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <jni.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:$LINENO: checking jni.h presence" >&5
+$as_echo_n "checking jni.h presence... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <jni.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { $as_echo "$as_me:$LINENO: WARNING: jni.h: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: jni.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: jni.h: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: jni.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: jni.h: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: jni.h: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: jni.h:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: jni.h:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: jni.h: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: jni.h: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: jni.h:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: jni.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: jni.h: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: jni.h: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: jni.h: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: jni.h: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## -------------------------------- ##
+## Report this to support at phash.org ##
+## -------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ $as_echo "$as_me:$LINENO: checking for jni.h" >&5
+$as_echo_n "checking for jni.h... " >&6; }
+if test "${ac_cv_header_jni_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_header_jni_h=$ac_header_preproc
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_jni_h" >&5
+$as_echo "$ac_cv_header_jni_h" >&6; }
+
+fi
+if test "x$ac_cv_header_jni_h" = x""yes; then
+  found_jni="y"
+else
+  found_jni="n"
+fi
+
+
+
+if test x"$found_jni" = x"n"; then
+	{ $as_echo "$as_me:$LINENO: checking whether jni.h is in the current or src directory." >&5
+$as_echo_n "checking whether jni.h is in the current or src directory.... " >&6; }
+
+	if test `ls . src | grep "jni.h"` >/dev/null 2>&1; then
+		{ $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+		found_java="y"
+	else
+		{ $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+		{ $as_echo "$as_me:$LINENO: checking if jni.h is in other system directories." >&5
+$as_echo_n "checking if jni.h is in other system directories.... " >&6; }
+		jni_header=`locate jni.h|grep include/jni.h|head -n1`
+
+		if test x"$jni_header" != "x"; then
+			{ $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+			jni_header=`dirname $jni_header`
+			CPPFLAGS="$CPPFLAGS -I $jni_header"
+		else
+			{ $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+		fi
+	fi
+
+fi
+
+
+fi
+
+
  if test x$java != xno; then
   WITH_JAVA_TRUE=
   WITH_JAVA_FALSE='#'
@@ -4557,8 +5412,8 @@ esac
 
 
 
-macro_version='2.2.6'
-macro_revision='1.3012'
+macro_version='2.2.6b'
+macro_revision='1.3017'
 
 
 
@@ -4741,140 +5596,6 @@ Xsed="$SED -e 1s/^X//"
 
 
 
-{ $as_echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if test "${ac_cv_path_GREP+set}" = set; then
-  $as_echo_n "(cached) " >&6
-else
-  if test -z "$GREP"; then
-  ac_path_GREP_found=false
-  # Loop through the user's path and test for each of PROGNAME-LIST
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_prog in grep ggrep; do
-    for ac_exec_ext in '' $ac_executable_extensions; do
-      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
-# Check for GNU ac_path_GREP and select it if it is found.
-  # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
-  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
-  ac_count=0
-  $as_echo_n 0123456789 >"conftest.in"
-  while :
-  do
-    cat "conftest.in" "conftest.in" >"conftest.tmp"
-    mv "conftest.tmp" "conftest.in"
-    cp "conftest.in" "conftest.nl"
-    $as_echo 'GREP' >> "conftest.nl"
-    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
-    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
-    ac_count=`expr $ac_count + 1`
-    if test $ac_count -gt ${ac_path_GREP_max-0}; then
-      # Best one so far, save it but keep looking for a better one
-      ac_cv_path_GREP="$ac_path_GREP"
-      ac_path_GREP_max=$ac_count
-    fi
-    # 10*(2^10) chars as input seems more than enough
-    test $ac_count -gt 10 && break
-  done
-  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
-      $ac_path_GREP_found && break 3
-    done
-  done
-done
-IFS=$as_save_IFS
-  if test -z "$ac_cv_path_GREP"; then
-    { { $as_echo "$as_me:$LINENO: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-$as_echo "$as_me: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
-   { (exit 1); exit 1; }; }
-  fi
-else
-  ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:$LINENO: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if test "${ac_cv_path_EGREP+set}" = set; then
-  $as_echo_n "(cached) " >&6
-else
-  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
-   then ac_cv_path_EGREP="$GREP -E"
-   else
-     if test -z "$EGREP"; then
-  ac_path_EGREP_found=false
-  # Loop through the user's path and test for each of PROGNAME-LIST
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_prog in egrep; do
-    for ac_exec_ext in '' $ac_executable_extensions; do
-      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
-  # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
-  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
-  ac_count=0
-  $as_echo_n 0123456789 >"conftest.in"
-  while :
-  do
-    cat "conftest.in" "conftest.in" >"conftest.tmp"
-    mv "conftest.tmp" "conftest.in"
-    cp "conftest.in" "conftest.nl"
-    $as_echo 'EGREP' >> "conftest.nl"
-    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
-    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
-    ac_count=`expr $ac_count + 1`
-    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
-      # Best one so far, save it but keep looking for a better one
-      ac_cv_path_EGREP="$ac_path_EGREP"
-      ac_path_EGREP_max=$ac_count
-    fi
-    # 10*(2^10) chars as input seems more than enough
-    test $ac_count -gt 10 && break
-  done
-  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
-      $ac_path_EGREP_found && break 3
-    done
-  done
-done
-IFS=$as_save_IFS
-  if test -z "$ac_cv_path_EGREP"; then
-    { { $as_echo "$as_me:$LINENO: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-$as_echo "$as_me: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
-   { (exit 1); exit 1; }; }
-  fi
-else
-  ac_cv_path_EGREP=$EGREP
-fi
-
-   fi
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
 { $as_echo "$as_me:$LINENO: checking for fgrep" >&5
 $as_echo_n "checking for fgrep... " >&6; }
 if test "${ac_cv_path_FGREP+set}" = set; then
@@ -5251,13 +5972,13 @@ if test "${lt_cv_nm_interface+set}" = set; then
 else
   lt_cv_nm_interface="BSD nm"
   echo "int some_variable = 0;" > conftest.$ac_ext
-  (eval echo "\"\$as_me:5254: $ac_compile\"" >&5)
+  (eval echo "\"\$as_me:5975: $ac_compile\"" >&5)
   (eval "$ac_compile" 2>conftest.err)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:5257: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval echo "\"\$as_me:5978: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
   (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:5260: output\"" >&5)
+  (eval echo "\"\$as_me:5981: output\"" >&5)
   cat conftest.out >&5
   if $GREP 'External.*some_variable' conftest.out > /dev/null; then
     lt_cv_nm_interface="MS dumpbin"
@@ -6420,7 +7141,6 @@ fi
 
 
 
-
 # Check whether --enable-libtool-lock was given.
 if test "${enable_libtool_lock+set}" = set; then
   enableval=$enable_libtool_lock;
@@ -6452,7 +7172,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 6455 "configure"' > conftest.$ac_ext
+  echo '#line 7175 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -7257,494 +7977,6 @@ $as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
     ;;
   esac
 
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
-  CPP=
-fi
-if test -z "$CPP"; then
-  if test "${ac_cv_prog_CPP+set}" = set; then
-  $as_echo_n "(cached) " >&6
-else
-      # Double quotes because CPP needs to be expanded
-    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
-    do
-      ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-		     Syntax error
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  :
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Broken: fails on valid input.
-continue
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether nonexistent headers
-  # can be detected and how.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  # Broken: success on invalid input.
-continue
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
-  break
-fi
-
-    done
-    ac_cv_prog_CPP=$CPP
-
-fi
-  CPP=$ac_cv_prog_CPP
-else
-  ac_cv_prog_CPP=$CPP
-fi
-{ $as_echo "$as_me:$LINENO: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-		     Syntax error
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  :
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Broken: fails on valid input.
-continue
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether nonexistent headers
-  # can be detected and how.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  # Broken: success on invalid input.
-continue
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
-  :
-else
-  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ { $as_echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&5
-$as_echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-{ $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then
-  $as_echo_n "(cached) " >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_cv_header_stdc=yes
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_cv_header_stdc=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
-  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "memchr" >/dev/null 2>&1; then
-  :
-else
-  ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
-  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "free" >/dev/null 2>&1; then
-  :
-else
-  ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
-  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
-  if test "$cross_compiling" = yes; then
-  :
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
-		   (('a' <= (c) && (c) <= 'i') \
-		     || ('j' <= (c) && (c) <= 'r') \
-		     || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
-  int i;
-  for (i = 0; i < 256; i++)
-    if (XOR (islower (i), ISLOWER (i))
-	|| toupper (i) != TOUPPER (i))
-      return 2;
-  return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  :
-else
-  $as_echo "$as_me: program exited with status $ac_status" >&5
-$as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_header_stdc=no
-fi
-rm -rf conftest.dSYM
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define STDC_HEADERS 1
-_ACEOF
-
-fi
-
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-
-
-
-
-
-
-
-
-
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
-		  inttypes.h stdint.h unistd.h
-do
-as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
-$as_echo_n "checking for $ac_header... " >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  $as_echo_n "(cached) " >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  eval "$as_ac_Header=yes"
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	eval "$as_ac_Header=no"
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-ac_res=`eval 'as_val=${'$as_ac_Header'}
-		 $as_echo "$as_val"'`
-	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-as_val=`eval 'as_val=${'$as_ac_Header'}
-		 $as_echo "$as_val"'`
-   if test "x$as_val" = x""yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
 
 for ac_header in dlfcn.h
 do
@@ -8546,10 +8778,11 @@ fi
 
 
 
-for ac_prog in gcj
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in gcj
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
 if test "${ac_cv_prog_GCJ+set}" = set; then
@@ -8565,7 +8798,7 @@ do
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
   if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_GCJ="$ac_prog"
+    ac_cv_prog_GCJ="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
@@ -8585,9 +8818,65 @@ $as_echo "no" >&6; }
 fi
 
 
-  test -n "$GCJ" && break
+    test -n "$GCJ" && break
+  done
+fi
+if test -z "$GCJ"; then
+  ac_ct_GCJ=$GCJ
+  for ac_prog in gcj
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_GCJ+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_GCJ"; then
+  ac_cv_prog_ac_ct_GCJ="$ac_ct_GCJ" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_GCJ="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
 done
-test -n "$GCJ" || GCJ="gcj"
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_GCJ=$ac_cv_prog_ac_ct_GCJ
+if test -n "$ac_ct_GCJ"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_GCJ" >&5
+$as_echo "$ac_ct_GCJ" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_GCJ" && break
+done
+
+  if test "x$ac_ct_GCJ" = x; then
+    GCJ="gcj"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    GCJ=$ac_ct_GCJ
+  fi
+fi
 
 test -z "$GCJ" && { { $as_echo "$as_me:$LINENO: error: no acceptable gcj found in \$PATH" >&5
 $as_echo "$as_me: error: no acceptable gcj found in \$PATH" >&2;}
@@ -9221,11 +9510,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9224: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:9513: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:9228: \$? = $ac_status" >&5
+   echo "$as_me:9517: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -9560,11 +9849,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9563: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:9852: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:9567: \$? = $ac_status" >&5
+   echo "$as_me:9856: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -9665,11 +9954,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9668: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:9957: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:9672: \$? = $ac_status" >&5
+   echo "$as_me:9961: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -9720,11 +10009,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9723: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:10012: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:9727: \$? = $ac_status" >&5
+   echo "$as_me:10016: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -12523,7 +12812,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12526 "configure"
+#line 12815 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12619,7 +12908,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12622 "configure"
+#line 12911 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -14639,11 +14928,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14642: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14931: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:14646: \$? = $ac_status" >&5
+   echo "$as_me:14935: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -14738,11 +15027,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14741: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15030: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:14745: \$? = $ac_status" >&5
+   echo "$as_me:15034: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -14790,11 +15079,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14793: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15082: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:14797: \$? = $ac_status" >&5
+   echo "$as_me:15086: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -15858,11 +16147,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15861: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16150: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:15865: \$? = $ac_status" >&5
+   echo "$as_me:16154: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -16191,11 +16480,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:16194: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16483: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:16198: \$? = $ac_status" >&5
+   echo "$as_me:16487: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -16290,11 +16579,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:16293: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16582: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:16297: \$? = $ac_status" >&5
+   echo "$as_me:16586: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -16342,11 +16631,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:16345: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16634: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:16349: \$? = $ac_status" >&5
+   echo "$as_me:16638: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -20702,7 +20991,7 @@ exec 6>&1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by pHash $as_me 0.7.2, which was
+This file was extended by pHash $as_me 0.8.1, which was
 generated by GNU Autoconf 2.63.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -20765,7 +21054,7 @@ Report bugs to <bug-autoconf at gnu.org>."
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_version="\\
-pHash config.status 0.7.2
+pHash config.status 0.8.1
 configured by $0, generated by GNU Autoconf 2.63,
   with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
diff --git a/configure.ac b/configure.ac
index 00cfa19..60da316 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT([pHash],[0.7.2],[support at phash.org])
+AC_INIT([pHash],[0.8.1],[support at phash.org])
 AM_INIT_AUTOMAKE($PACKAGE_NAME,$PACKAGE_VERSION)
 AC_CONFIG_SRCDIR([src/pHash.cpp])
 AC_CONFIG_HEADERS([config.h])
@@ -37,6 +37,34 @@ AC_ARG_ENABLE(java, [AS_HELP_STRING([--enable-java],
 [compile java (JNI) binding for pHash @<:@default=no@:>@])], 
 java=yes, java=no)
 
+AS_IF([test "$java" = "yes"],
+[
+	AC_CHECK_HEADER([jni.h], [found_jni="y"], [found_jni="n"])
+
+if test x"$found_jni" = x"n"; then
+	AC_MSG_CHECKING([whether jni.h is in the current or src directory.])
+	
+	if [test `ls . src | grep "jni.h"` >/dev/null 2>&1]; then
+		AC_MSG_RESULT([yes])
+		found_java="y"
+	else
+		AC_MSG_RESULT([no])
+		AC_MSG_CHECKING([if jni.h is in other system directories.])
+		jni_header=`locate jni.h|grep include/jni.h|head -n1`
+		
+		if test x"$jni_header" != "x"; then
+			AC_MSG_RESULT([yes])
+			jni_header=`dirname $jni_header`
+			CPPFLAGS="$CPPFLAGS -I $jni_header"
+		else
+			AC_MSG_RESULT([no])
+		fi
+	fi
+	
+fi
+
+])
+
 AM_CONDITIONAL([WITH_JAVA], test x$java != xno)
 AC_PROG_INSTALL
 AC_LANG([C++])
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 22531dd..c8d6eaa 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -33,9 +33,12 @@ query_mvptree_audio_LDADD = $(top_srcdir)/src/libpHash.la
 endif
 
 if HAVE_IMAGE_HASH
-bin_PROGRAMS += test_image
+bin_PROGRAMS += test_image test_mhimagehash
 test_image_SOURCES = test_imagephash.cpp
 test_image_LDADD = $(top_srcdir)/src/libpHash.la
+
+test_mhimagehash_SOURCES = test_mhimagehash.cpp
+test_mhimagehash_LDADD = $(top_srcdir)/src/libpHash.la
 endif
 
 if HAVE_VIDEO_HASH
diff --git a/examples/Makefile.in b/examples/Makefile.in
index 1bc6466..ca55bb6 100644
--- a/examples/Makefile.in
+++ b/examples/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -39,7 +39,7 @@ bin_PROGRAMS = build_mvptree$(EXEEXT) add_mvptree$(EXEEXT) \
 	test_texthash2$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2) \
 	$(am__EXEEXT_3)
 @HAVE_AUDIO_HASH_TRUE at am__append_1 = test_audio build_mvptree_audio add_mvptree_audio query_mvptree_audio
- at HAVE_IMAGE_HASH_TRUE@am__append_2 = test_image
+ at HAVE_IMAGE_HASH_TRUE@am__append_2 = test_image test_mhimagehash
 @HAVE_VIDEO_HASH_TRUE at am__append_3 = test_video
 subdir = examples
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
@@ -55,7 +55,8 @@ CONFIG_CLEAN_VPATH_FILES =
 @HAVE_AUDIO_HASH_TRUE@	build_mvptree_audio$(EXEEXT) \
 @HAVE_AUDIO_HASH_TRUE@	add_mvptree_audio$(EXEEXT) \
 @HAVE_AUDIO_HASH_TRUE@	query_mvptree_audio$(EXEEXT)
- at HAVE_IMAGE_HASH_TRUE@am__EXEEXT_2 = test_image$(EXEEXT)
+ at HAVE_IMAGE_HASH_TRUE@am__EXEEXT_2 = test_image$(EXEEXT) \
+ at HAVE_IMAGE_HASH_TRUE@	test_mhimagehash$(EXEEXT)
 @HAVE_VIDEO_HASH_TRUE at am__EXEEXT_3 = test_video$(EXEEXT)
 am__installdirs = "$(DESTDIR)$(bindir)"
 PROGRAMS = $(bin_PROGRAMS)
@@ -98,6 +99,12 @@ am__test_image_SOURCES_DIST = test_imagephash.cpp
 test_image_OBJECTS = $(am_test_image_OBJECTS)
 @HAVE_IMAGE_HASH_TRUE at test_image_DEPENDENCIES =  \
 @HAVE_IMAGE_HASH_TRUE@	$(top_srcdir)/src/libpHash.la
+am__test_mhimagehash_SOURCES_DIST = test_mhimagehash.cpp
+ at HAVE_IMAGE_HASH_TRUE@am_test_mhimagehash_OBJECTS =  \
+ at HAVE_IMAGE_HASH_TRUE@	test_mhimagehash.$(OBJEXT)
+test_mhimagehash_OBJECTS = $(am_test_mhimagehash_OBJECTS)
+ at HAVE_IMAGE_HASH_TRUE@test_mhimagehash_DEPENDENCIES =  \
+ at HAVE_IMAGE_HASH_TRUE@	$(top_srcdir)/src/libpHash.la
 am_test_texthash_OBJECTS = test_texthash.$(OBJEXT)
 test_texthash_OBJECTS = $(am_test_texthash_OBJECTS)
 test_texthash_DEPENDENCIES = $(top_srcdir)/src/libpHash.la
@@ -127,16 +134,16 @@ SOURCES = $(add_mvptree_SOURCES) $(add_mvptree_audio_SOURCES) \
 	$(build_mvptree_SOURCES) $(build_mvptree_audio_SOURCES) \
 	$(query_mvptree_SOURCES) $(query_mvptree_audio_SOURCES) \
 	$(test_audio_SOURCES) $(test_image_SOURCES) \
-	$(test_texthash_SOURCES) $(test_texthash2_SOURCES) \
-	$(test_video_SOURCES)
+	$(test_mhimagehash_SOURCES) $(test_texthash_SOURCES) \
+	$(test_texthash2_SOURCES) $(test_video_SOURCES)
 DIST_SOURCES = $(add_mvptree_SOURCES) \
 	$(am__add_mvptree_audio_SOURCES_DIST) $(build_mvptree_SOURCES) \
 	$(am__build_mvptree_audio_SOURCES_DIST) \
 	$(query_mvptree_SOURCES) \
 	$(am__query_mvptree_audio_SOURCES_DIST) \
 	$(am__test_audio_SOURCES_DIST) $(am__test_image_SOURCES_DIST) \
-	$(test_texthash_SOURCES) $(test_texthash2_SOURCES) \
-	$(am__test_video_SOURCES_DIST)
+	$(am__test_mhimagehash_SOURCES_DIST) $(test_texthash_SOURCES) \
+	$(test_texthash2_SOURCES) $(am__test_video_SOURCES_DIST)
 ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -213,6 +220,7 @@ abs_top_srcdir = @abs_top_srcdir@
 ac_ct_CC = @ac_ct_CC@
 ac_ct_CXX = @ac_ct_CXX@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_GCJ = @ac_ct_GCJ@
 am__include = @am__include@
 am__leading_dot = @am__leading_dot@
 am__quote = @am__quote@
@@ -280,6 +288,8 @@ test_texthash2_LDADD = $(top_srcdir)/src/libpHash.la
 @HAVE_AUDIO_HASH_TRUE at query_mvptree_audio_LDADD = $(top_srcdir)/src/libpHash.la
 @HAVE_IMAGE_HASH_TRUE at test_image_SOURCES = test_imagephash.cpp
 @HAVE_IMAGE_HASH_TRUE at test_image_LDADD = $(top_srcdir)/src/libpHash.la
+ at HAVE_IMAGE_HASH_TRUE@test_mhimagehash_SOURCES = test_mhimagehash.cpp
+ at HAVE_IMAGE_HASH_TRUE@test_mhimagehash_LDADD = $(top_srcdir)/src/libpHash.la
 @HAVE_VIDEO_HASH_TRUE at test_video_SOURCES = test_dctvideohash.cpp
 @HAVE_VIDEO_HASH_TRUE at test_video_LDADD = $(top_srcdir)/src/libpHash.la
 all: all-am
@@ -383,6 +393,9 @@ test_audio$(EXEEXT): $(test_audio_OBJECTS) $(test_audio_DEPENDENCIES)
 test_image$(EXEEXT): $(test_image_OBJECTS) $(test_image_DEPENDENCIES) 
 	@rm -f test_image$(EXEEXT)
 	$(CXXLINK) $(test_image_OBJECTS) $(test_image_LDADD) $(LIBS)
+test_mhimagehash$(EXEEXT): $(test_mhimagehash_OBJECTS) $(test_mhimagehash_DEPENDENCIES) 
+	@rm -f test_mhimagehash$(EXEEXT)
+	$(CXXLINK) $(test_mhimagehash_OBJECTS) $(test_mhimagehash_LDADD) $(LIBS)
 test_texthash$(EXEEXT): $(test_texthash_OBJECTS) $(test_texthash_DEPENDENCIES) 
 	@rm -f test_texthash$(EXEEXT)
 	$(CXXLINK) $(test_texthash_OBJECTS) $(test_texthash_LDADD) $(LIBS)
@@ -408,6 +421,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/test_audiophash.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/test_dctvideohash.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/test_imagephash.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/test_mhimagehash.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/test_texthash.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/test_texthash2.Po at am__quote@
 
diff --git a/examples/add_mvptree.cpp b/examples/add_mvptree.cpp
index abf25c5..db8d1dd 100644
--- a/examples/add_mvptree.cpp
+++ b/examples/add_mvptree.cpp
@@ -23,23 +23,37 @@
 */
 
 #include <stdio.h>
-#include <dirent.h>
+#include <math.h>
 #include "pHash.h"
 
+
+float distancefunc(DP *pa, DP *pb){
+    uint8_t *hashA = (uint8_t*)pa->hash;
+    uint8_t *hashB = (uint8_t*)pb->hash;
+    float d = 10*ph_hammingdistance2(hashA,pa->hash_length, hashB, pb->hash_length);
+    float res = exp(d);
+    return res;
+}
+
 int main(int argc, char **argv){
- 
+    if (argc < 3){
+	printf("not enough input args\n");
+	return 1;
+    }
+
     const char *dir_name = argv[1];/* name of dir to retrieve image files */
     const char *filename = argv[2];/* name of file to save db */
 
+    int alpha = 2;
+    int lvl  = 2;
+
     MVPFile mvpfile;
     ph_mvp_init(&mvpfile);
     mvpfile.filename = strdup(filename);
-    mvpfile.hashdist = hammingdistance;
-    mvpfile.hash_type = UINT64ARRAY;
+    mvpfile.hashdist = distancefunc;
+    mvpfile.hash_type = BYTEARRAY;
    
 
-    ulong64 tmphash = 0;
-    
     int nbfiles = 0;
     printf("dir name: %s\n", dir_name);
     char **files = ph_readfilenames(dir_name,nbfiles);
@@ -53,32 +67,23 @@ int main(int argc, char **argv){
 	printf("mem alloc error\n");
 	exit(1);
     }
-
+    int hashlength;
     int count = 0;
     for (int i=0;i<nbfiles;i++){
-	printf("file[%d]: %s ", i, files[i]);
-	if (ph_dct_imagehash(files[i],tmphash) < 0){
-	    printf("could not get for file %s\n",files[i]);
-	    continue;
-	}
-	printf("hash = %llx\n", tmphash);
-
+	printf("file[%d]: %s\n", i, files[i]);
         hashlist[count] = ph_malloc_datapoint(mvpfile.hash_type,mvpfile.pathlength);
-        if (!hashlist[count]){
+	if (hashlist[count] == NULL){
 	    printf("mem alloc error\n");
-	    exit(1);
+	    continue;
+	}
+	hashlist[count]->id = files[i];
+	hashlist[count]->hash = ph_mh_imagehash(files[i],hashlength,alpha,lvl);
+	if (hashlist[count]->hash == NULL){
+	    printf("unable to get hash\n");
+	    continue;
 	}
-	hashlist[count]->id = strdup(files[i]);
-        void *ptr_hash = malloc(8);
-	if (!ptr_hash){
-            printf("unable to allocate mem\n");
-            exit(1);
-        }
-        hashlist[count]->hash = ptr_hash;
-	ulong64 *ptr = (ulong64*)hashlist[count]->hash;
-        *ptr = tmphash;
-	hashlist[count]->hash_length = 1;
-         count++;
+	hashlist[count]->hash_length = hashlength;
+        count++;
     }
 
     printf("add files to file %s\n", filename);
diff --git a/examples/build_mvptree.cpp b/examples/build_mvptree.cpp
index 29edb4f..e826cec 100644
--- a/examples/build_mvptree.cpp
+++ b/examples/build_mvptree.cpp
@@ -23,25 +23,41 @@
 */
 
 #include <stdio.h>
-#include <dirent.h>
+#include <math.h>
 #include "pHash.h"
 
 
+float distancefunc(DP *pa, DP *pb){
+    if ((!pa)||(!pb)){
+	printf("dp is null\n");
+	return -1.0;
+    }
+    uint8_t *hashA = (uint8_t*)pa->hash;
+    uint8_t *hashB = (uint8_t*)pb->hash;
+    float d = 10*ph_hammingdistance2(hashA,pa->hash_length,hashB,pb->hash_length);
+    float res = exp(d);
+    return res;
+}
 
 int main(int argc, char **argv){
+    if (argc < 3){
+	printf("not enough input args\n");
+	return 1;
+    }
  
     const char *dir_name = argv[1];/* name of dir to retrieve image files */
     const char *filename = argv[2];/* name of file to save db */
 
+    int alpha = 2;
+    int lvl = 2;
+
     MVPFile mvpfile;
     ph_mvp_init(&mvpfile);
     mvpfile.filename = strdup(filename);
-    mvpfile.hashdist = hammingdistance;
-    mvpfile.hash_type = UINT64ARRAY;
+    mvpfile.hashdist = distancefunc;
+    mvpfile.hash_type = BYTEARRAY;
 
 
-    ulong64 tmphash = 0;
-    
     int nbfiles = 0;
     printf("dir name: %s\n", dir_name);
     char **files = ph_readfilenames(dir_name,nbfiles);
@@ -55,34 +71,25 @@ int main(int argc, char **argv){
 	printf("mem alloc error\n");
 	exit(1);
     }
-
+    int hashlength;
     int count = 0;
     for (int i=0;i<nbfiles;i++){
-	printf("file[%d]: %s ", i, files[i]);
-	if (ph_dct_imagehash(files[i],tmphash) < 0){
-	    printf("could not get for file %s\n",files[i]);
-	    continue;
-	}
-	printf("hash = %llx\n", tmphash);
-
+	printf("file[%d]: %s\n", i, files[i]);
         hashlist[count] = ph_malloc_datapoint(mvpfile.hash_type,mvpfile.pathlength);
-        if (!hashlist[count]){
+	if (hashlist[count] == NULL){
 	    printf("mem alloc error\n");
 	    exit(1);
 	}
-	hashlist[count]->id = strdup(files[i]);
-        void *ptr_hash = malloc(8);
-	if (!ptr_hash){
-            printf("unable to allocate mem\n");
-            exit(1);
-        }
-        hashlist[count]->hash = ptr_hash;
-	ulong64 *ptr = (ulong64*)hashlist[count]->hash;
-        *ptr = tmphash;
-	hashlist[count]->hash_length = 1;
-         count++;
+	hashlist[count]->id = files[i];
+	hashlist[count]->hash = ph_mh_imagehash(files[i],hashlength, alpha, lvl);
+	if (hashlist[count]->hash == NULL){
+	    printf("unable to get hash\n");
+	    exit(1);
+	}
+	printf("len %d\n", hashlength);
+	hashlist[count]->hash_length = hashlength;
+        count++;
     }
-
  
 
     if (ph_save_mvptree(&mvpfile, hashlist, count) < 0){
diff --git a/examples/query_mvptree.cpp b/examples/query_mvptree.cpp
index 4da8283..09c5358 100644
--- a/examples/query_mvptree.cpp
+++ b/examples/query_mvptree.cpp
@@ -23,41 +23,41 @@
 */
 
 #include <stdio.h>
-#include <dirent.h>
+#include <math.h>
 #include "pHash.h"
 
 static int nb_calcs;
 
-float imagedistance(DP *pntA, DP *pntB){
+
+float distancefunc(DP *pa, DP *pb){
     nb_calcs++;
-    uint8_t htypeA = pntA->hash_type;
-    uint8_t htypeB = pntB->hash_type;
-    if (htypeA != htypeB)
-	return -1.0;
-    if (htypeA != UINT64ARRAY)
-	return -1.0;
-    if ((pntA->hash_length > 1) || (pntB->hash_length > 1))
-	return -1.0;
-    ulong64 *hashA = (ulong64*)pntA->hash;
-    ulong64 *hashB = (ulong64*)pntB->hash;
-    int res = ph_hamming_distance(*hashA, *hashB);
-    return (float) res;
+    uint8_t *hashA = (uint8_t*)pa->hash;
+    uint8_t *hashB = (uint8_t*)pb->hash;
+    float d = 10*ph_hammingdistance2(hashA, pa->hash_length, hashB, pb->hash_length);
+    float result = exp(d);
+    return result;
+
 }
 
+
 int main(int argc, char **argv){
- 
+    if (argc <= 3){
+	printf("not enough input args\n");
+	return 1;
+    }
+
     const char *dir_name = argv[1];/* name of files in directory of query images */
     const char *filename = argv[2];/* name of file to save db */
 
+    int alpha = 2;
+    int lvl = 2;
+
     MVPFile mvpfile;
     ph_mvp_init(&mvpfile);
     mvpfile.filename = strdup(filename);
-    mvpfile.hashdist = imagedistance;
-    mvpfile.hash_type = UINT64ARRAY;
-
-    ulong64 tmphash = 0;
+    mvpfile.hashdist = distancefunc;
+    mvpfile.hash_type = BYTEARRAY;
 
-   
     int nbfiles = 0;
     printf("using db %s\n", filename);
     printf("using dir %s for query files\n", dir_name);
@@ -69,35 +69,29 @@ int main(int argc, char **argv){
 
     printf("nb query files = %d\n", nbfiles);
 
-    DP *query = NULL;
-    float radius = 3.0;
+    DP *query = ph_malloc_datapoint(mvpfile.hash_type,mvpfile.pathlength);
+    
+    float radius;
+    if (argc <= 4){
+	char *radius_str = argv[3];
+	radius = atof(radius_str);
+    } else {
+	radius = 30.0f;
+    }
+    printf("radius = %f\n", radius);
+
     const int knearest = 20;
-    DP **results = (DP**)malloc(knearest * sizeof(DP**));
+    DP **results = (DP**)malloc(knearest*sizeof(DP**));
     int nbfound = 0, count = 0, sum_calcs = 0;
-
+    int hashlength;
     for (int i=0;i<nbfiles;i++){
-	printf("query[%d]: %s ", i, files[i]);
-	if (ph_dct_imagehash(files[i],tmphash) < 0){
-	    printf("could not get for file %s\n",files[i]);
-	    continue;
-	}
-	printf(" hash = %llx\n", tmphash);
-        query = ph_malloc_datapoint(mvpfile.hash_type,mvpfile.pathlength);
-        if (!query){
-	    printf("mem alloc error\n");
-	    continue;
-	}
-	query->id = strdup(files[i]);
-        void *ptr_hash = malloc(8);
-	if (!ptr_hash){
-            printf("unable to allocate mem\n");
-            continue;
-        }
-        query->hash = ptr_hash;
-	ulong64 *ptr = (ulong64*)query->hash;
-        *ptr = tmphash;
-	query->hash_length = 1;
-        count++;
+	printf("query[%d]: %s\n", i, files[i]);
+
+	query->id = files[i];
+	query->hash = ph_mh_imagehash(files[i],hashlength,alpha,lvl);
+	query->hash_length = hashlength;
+
+	printf("do query ...\n");
 	nb_calcs = 0;
 	nbfound = 0;
 	int res = ph_query_mvptree(&mvpfile,query,knearest,radius,results,&nbfound);
@@ -110,11 +104,10 @@ int main(int argc, char **argv){
 
 	printf(" %d files found\n", nbfound);
 	for (int i=0;i<nbfound;i++){
-	    ulong64 *ptrhash = (ulong64*)(results[i]->hash);
-	    printf(" %d %s %llx\n", i, results[i]->id, *ptrhash);
+	    printf(" %d  %s\n", i, results[i]->id);
 	}
 	printf("nb distance calcs: %d\n", nb_calcs);
-	free(query);
+	free(query->hash);
     } 
    float ave_calcs = (float)sum_calcs/(float)count;      
    printf("ave calcs/query: %f\n", ave_calcs);
diff --git a/examples/test_mhimagehash.cpp b/examples/test_mhimagehash.cpp
new file mode 100644
index 0000000..b1bc4d6
--- /dev/null
+++ b/examples/test_mhimagehash.cpp
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <stdint.h>
+#include "math.h"
+#include "pHash.h"
+
+using namespace cimg_library;
+
+
+void sort_names(char **names, int L1){
+
+    for (int i=0;i<L1;i++){
+	int min = i;
+	for (int j=i+1;j<L1;j++){
+	    if (strcmp(names[j], names[min]) <= 0)
+		min = j;
+	}
+	if (i != min){
+	    char *swap = names[i];
+	    names[i] = names[min];
+	    names[min] = swap;
+	}
+
+    }
+
+}
+
+int main(int argc, char **argv){
+
+    if (argc < 3){
+	printf(" not enough input args\n");
+	exit(1);
+    }
+
+    const char *dirname1 = argv[1];
+    const char *dirname2 = argv[2];
+
+    int alpha = 2;
+    int level = 1;
+
+    int nbfiles1;
+    char **files1 = ph_readfilenames(dirname1, nbfiles1);
+    sort_names(files1,nbfiles1);
+
+    int nbfiles2;
+    char **files2 = ph_readfilenames(dirname2, nbfiles2);
+    sort_names(files2,nbfiles2);
+
+    if (nbfiles1 != nbfiles2){
+	printf("number files in both directories not equal\n");
+	exit(1);
+    }
+
+    uint8_t **hash1 = (uint8_t**)malloc(nbfiles1*sizeof(uint8_t*));
+    uint8_t *hash2 = NULL;
+    int hashlen1=0, hashlen2=0;
+    double dist = 0;
+    printf("intra distances\n");
+    printf("***************\n");
+    for (int i=0;i<nbfiles1;i++){
+	printf("file1: %s\n", files1[i]);
+	hash1[i] = ph_mh_imagehash(files1[i], hashlen1, alpha, level);
+	if (hash1 == NULL)
+	    continue;
+	printf("file2: %s\n", files2[i]);
+	hash2 = ph_mh_imagehash(files2[i], hashlen2, alpha, level);
+	if (hash2 == NULL)
+	    continue;
+
+	dist = ph_hammingdistance2(hash1[i], hashlen1, hash2, hashlen2);
+	printf("distance = %f\n", dist);
+	printf("-------------\n");
+	free(hash2);
+    }
+    printf("\n\n");
+    printf("--hit any key--\n");
+    getchar();
+    printf("inter distances\n");
+    for (int i=0;i<nbfiles1;i++){
+	for (int j=i+1;j<nbfiles1;j++){
+	    dist = ph_hammingdistance2(hash1[i], hashlen1, hash1[j], hashlen1);
+	    printf(" %d %d dist = %f\n", i, j, dist);
+	    printf("----------------\n");
+	}
+    }
+    printf("done\n");
+
+    for(int i = 0; i < nbfiles1; ++i)
+    {
+	free(files1[i]);
+	free(files2[i]);
+	free(hash1[i]);
+    }
+    free(files1);
+    free(files2);
+    free(hash1);
+    return 0;
+}
diff --git a/libpHash.spec b/libpHash.spec
index 1b6d514..3349ca9 100644
--- a/libpHash.spec
+++ b/libpHash.spec
@@ -1,5 +1,5 @@
 Name:           pHash
-Version:        0.7.1
+Version:        0.7.2
 Release:        1%{?dist}
 Summary:        pHash, the open source perceptual hashing library
 
diff --git a/ltmain.sh b/ltmain.sh
index 6939dcc..a72f2fd 100755
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -1,6 +1,6 @@
 # Generated from ltmain.m4sh.
 
-# ltmain.sh (GNU libtool) 2.2.6
+# ltmain.sh (GNU libtool) 2.2.6b
 # Written by Gordon Matzigkeit <gord at gnu.ai.mit.edu>, 1996
 
 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc.
@@ -65,7 +65,7 @@
 #       compiler:		$LTCC
 #       compiler flags:		$LTCFLAGS
 #       linker:		$LD (gnu? $with_gnu_ld)
-#       $progname:		(GNU libtool) 2.2.6
+#       $progname:		(GNU libtool) 2.2.6b
 #       automake:		$automake_version
 #       autoconf:		$autoconf_version
 #
@@ -73,9 +73,9 @@
 
 PROGRAM=ltmain.sh
 PACKAGE=libtool
-VERSION=2.2.6
+VERSION=2.2.6b
 TIMESTAMP=""
-package_revision=1.3012
+package_revision=1.3017
 
 # Be Bourne compatible
 if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
diff --git a/src/Makefile.am b/src/Makefile.am
index 2ef5daa..f54036d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,11 +1,11 @@
 lib_LTLIBRARIES = libpHash.la
-libpHash_la_SOURCES = pHash.cpp ph_fft.c ph_fft.h
+libpHash_la_SOURCES = pHash.cpp
 libpHash_la_LDFLAGS = -no-undefined
 include_HEADERS = pHash.h
 
 if HAVE_AUDIO_HASH
-libpHash_la_SOURCES += audiophash.cpp
-include_HEADERS += audiophash.h
+libpHash_la_SOURCES += audiophash.cpp ph_fft.c
+include_HEADERS += audiophash.h ph_fft.h
 endif
 
 if HAVE_VIDEO_HASH
diff --git a/src/Makefile.in b/src/Makefile.in
index 4adbcb6..ad18687 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -35,8 +35,8 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
- at HAVE_AUDIO_HASH_TRUE@am__append_1 = audiophash.cpp
- at HAVE_AUDIO_HASH_TRUE@am__append_2 = audiophash.h
+ at HAVE_AUDIO_HASH_TRUE@am__append_1 = audiophash.cpp ph_fft.c
+ at HAVE_AUDIO_HASH_TRUE@am__append_2 = audiophash.h ph_fft.h
 @HAVE_VIDEO_HASH_TRUE at am__append_3 = cimgffmpeg.cpp cimgffmpeg.h
 subdir = src
 DIST_COMMON = $(am__include_HEADERS_DIST) $(srcdir)/Makefile.am \
@@ -73,12 +73,11 @@ am__base_list = \
 am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
 LTLIBRARIES = $(lib_LTLIBRARIES)
 libpHash_la_LIBADD =
-am__libpHash_la_SOURCES_DIST = pHash.cpp ph_fft.c ph_fft.h \
-	audiophash.cpp cimgffmpeg.cpp cimgffmpeg.h
- at HAVE_AUDIO_HASH_TRUE@am__objects_1 = audiophash.lo
+am__libpHash_la_SOURCES_DIST = pHash.cpp audiophash.cpp ph_fft.c \
+	cimgffmpeg.cpp cimgffmpeg.h
+ at HAVE_AUDIO_HASH_TRUE@am__objects_1 = audiophash.lo ph_fft.lo
 @HAVE_VIDEO_HASH_TRUE at am__objects_2 = cimgffmpeg.lo
-am_libpHash_la_OBJECTS = pHash.lo ph_fft.lo $(am__objects_1) \
-	$(am__objects_2)
+am_libpHash_la_OBJECTS = pHash.lo $(am__objects_1) $(am__objects_2)
 libpHash_la_OBJECTS = $(am_libpHash_la_OBJECTS)
 libpHash_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
@@ -107,7 +106,7 @@ CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
 	$(LDFLAGS) -o $@
 SOURCES = $(libpHash_la_SOURCES)
 DIST_SOURCES = $(am__libpHash_la_SOURCES_DIST)
-am__include_HEADERS_DIST = pHash.h audiophash.h
+am__include_HEADERS_DIST = pHash.h audiophash.h ph_fft.h
 HEADERS = $(include_HEADERS)
 ETAGS = etags
 CTAGS = ctags
@@ -185,6 +184,7 @@ abs_top_srcdir = @abs_top_srcdir@
 ac_ct_CC = @ac_ct_CC@
 ac_ct_CXX = @ac_ct_CXX@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_GCJ = @ac_ct_GCJ@
 am__include = @am__include@
 am__leading_dot = @am__leading_dot@
 am__quote = @am__quote@
@@ -232,8 +232,7 @@ top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 lib_LTLIBRARIES = libpHash.la
-libpHash_la_SOURCES = pHash.cpp ph_fft.c ph_fft.h $(am__append_1) \
-	$(am__append_3)
+libpHash_la_SOURCES = pHash.cpp $(am__append_1) $(am__append_3)
 libpHash_la_LDFLAGS = -no-undefined
 include_HEADERS = pHash.h $(am__append_2)
 all: all-am
diff --git a/src/pHash.cpp b/src/pHash.cpp
index 23211ff..6c95f63 100644
--- a/src/pHash.cpp
+++ b/src/pHash.cpp
@@ -28,7 +28,7 @@
 #include "cimgffmpeg.h"
 #endif
 
-const char phash_project[] = "%s. Copyright 2008-2009 Aetilius, Inc.";
+const char phash_project[] = "%s. Copyright 2008-2010 Aetilius, Inc.";
 char phash_version[255] = {0};
 const char* ph_about(){
 	if(phash_version[0] != 0)
@@ -267,13 +267,17 @@ cleanup:
 int ph_image_digest(const char *file, double sigma, double gamma, Digest &digest, int N){
     
     CImg<uint8_t> *src = new CImg<uint8_t>(file);
-    int result = ph_image_digest(*src,sigma,gamma,digest,N);
-    delete src;
-    return result;
-
+	int res = -1;
+	if(src)
+	{
+    		int result = ph_image_digest(*src,sigma,gamma,digest,N);
+		delete src;
+    		res = result;
+	}
+	return res;
 }
 
-int ph_compare_images(const CImg<uint8_t> &imA,const CImg<uint8_t> &imB,double &pcc, double sigma, double gamma,int N,double threshold){
+int _ph_compare_images(const CImg<uint8_t> &imA,const CImg<uint8_t> &imB,double &pcc, double sigma, double gamma,int N,double threshold){
 
     int result = 0;
     Digest digestA;
@@ -304,7 +308,7 @@ int ph_compare_images(const char *file1, const char *file2,double &pcc, double s
     CImg<uint8_t> *imA = new CImg<uint8_t>(file1);
     CImg<uint8_t> *imB = new CImg<uint8_t>(file2);
     
-    int res = ph_compare_images(*imA,*imB,pcc,sigma,gamma,N,threshold);
+    int res = _ph_compare_images(*imA,*imB,pcc,sigma,gamma,N,threshold);
 
     return res;
 }
@@ -736,6 +740,124 @@ char** ph_readfilenames(const char *dirname,int &count){
 }
 
 
+uint8_t* ph_mh_imagehash(const char *filename, int &N,int alpha, int lvl){
+    if (filename == NULL){
+	return NULL;
+    }
+    uint8_t *hash = (unsigned char*)malloc(72*sizeof(uint8_t));
+    N = 72;
+
+    CImg<uint8_t> src(filename);
+    CImg<uint8_t> img;
+    if (img.spectrum() == 3){
+	img = src.get_RGBtoYCbCr().channel(0).blur(1.5,1.5,1.5).resize(512,512,1,1,5).get_equalize(256);
+    } else{
+	img = src.get_blur(1.5,1.5,1.5).resize(512,512,1,1,5);
+    }
+    src.clear();
+    int sigma = (int)(4*pow((float)alpha,(float)lvl));
+    float xpos, ypos, A;
+    CImg<float> MHKernel(2*sigma+1,2*sigma+1,1,1,0);
+    cimg_forXY(MHKernel,X,Y){
+	xpos = pow((float)alpha,-lvl)*(X - sigma);
+        ypos = pow((float)alpha,-lvl)*(Y - sigma);
+	A = xpos*xpos + ypos*ypos;
+	MHKernel(X,Y) = (2-A)*exp(-A/2);
+    }
+    
+    CImg<float> fresp =  img.get_correlate(MHKernel);
+    img.clear();
+    fresp.normalize(0,1.0);
+    CImg<float> blocks(31,31,1,1,0);
+    for (int rindex=0;rindex < 31;rindex++){
+	for (int cindex=0;cindex < 31;cindex++){
+	    blocks(rindex,cindex) = fresp.get_crop(rindex*16,cindex*16,rindex*16+16-1,cindex*16+16-1).sum();
+	}
+    }
+ 
+    int hash_index;
+    int nb_ones = 0, nb_zeros = 0;
+    int bit_index = 0;
+    unsigned char hashbyte = 0;
+    for (int rindex=0;rindex < 31-2;rindex+=4){
+	CImg<float> subsec;
+	for (int cindex=0;cindex < 31-2;cindex+=4){
+	    subsec = blocks.get_crop(cindex,rindex, cindex+2, rindex+2).unroll('x');
+	    float ave = subsec.mean();
+	    cimg_forX(subsec, I){
+		hashbyte <<= 1;
+		if (subsec(I) > ave){
+		    hashbyte |= 0x01;
+		    nb_ones++;
+		} else {
+		    nb_zeros++;
+		}
+		bit_index++;
+		if ((bit_index%8) == 0){
+		    hash_index = (int)(bit_index/8) - 1; 
+		    hash[hash_index] = hashbyte;
+		    hashbyte = 0x00;
+		}
+	    }
+	}
+    }
+
+    return hash;
+}
+
+
+int ph_bitcount8(uint8_t val){
+    int num = 0;
+    while (val){
+	++num;
+	val &= val - 1;
+    }
+    return num;
+}
+
+
+
+double ph_hammingdistance2(uint8_t *hashA, int lenA, uint8_t *hashB, int lenB){
+    if (lenA != lenB){
+	return -1.0;
+    }
+    if ((hashA == NULL) || (hashB == NULL) || (lenA <= 0)){
+	return -1.0;
+    }
+    double dist = 0;
+    uint8_t D = 0;
+    for (int i=0;i<lenA;i++){
+	D = hashA[i]^hashB[i];
+	dist = dist + (double)ph_bitcount8(D);
+    }
+    double bits = (double)lenA*8;
+    return dist/bits;
+
+}
+
+int ph_selectvantagepoints(MVPFile *m, DP **points, int N, int &sv1_pos, int &sv2_pos, float &maxdist, float &mindist){
+    sv1_pos = 0;
+    sv2_pos = 0;
+    maxdist = 0.0;
+    mindist = INT_MAX;
+    float d;
+    for (int i=0;i<N;i++){ /* find 2 points furthest apart */
+	for (int j=i+1;j<N;j++){
+	    d = m->hashdist(points[i],points[j]);
+	    if (d > maxdist){
+		maxdist = d;
+		sv1_pos = i;
+		sv2_pos = j;
+		
+	    }
+	    if (m->hashdist(points[i],points[j]) < mindist){
+		mindist = d;
+	    }
+	}
+    }
+    return 0;
+}
+
 DP* ph_read_datapoint(MVPFile *m){
     DP *dp = NULL;
     uint8_t active;
@@ -916,7 +1038,7 @@ float hammingdistance(DP *pntA, DP *pntB){
 }
 
 
-MVPRetCode ph_query_mvptree(MVPFile *m, DP *query, int knearest, float radius, 
+MVPRetCode _ph_query_mvptree(MVPFile *m, DP *query, int knearest, float radius, 
                                               DP **results, int *count, int level){
     int BranchFactor = m->branchfactor;
     int LengthM1 = BranchFactor-1;
@@ -1086,7 +1208,7 @@ MVPRetCode ph_query_mvptree(MVPFile *m, DP *query, int knearest, float radius,
 			orig_pos = m->file_pos;
 			MVPFile *m2 = _ph_map_mvpfile(filenumber,child_pos, m);
 			if (m2){
-			   ret = ph_query_mvptree(m2,query,knearest,radius,results,count,level+2);
+			   ret = _ph_query_mvptree(m2,query,knearest,radius,results,count,level+2);
 			}
 
 			/* unmap and remap to the origional file/posion */
@@ -1110,7 +1232,7 @@ MVPRetCode ph_query_mvptree(MVPFile *m, DP *query, int knearest, float radius,
 
 		    MVPFile *m2 = _ph_map_mvpfile(filenumber, child_pos,m); 
 		    if (m2){
-			ret = ph_query_mvptree(m2,query,knearest,radius,results,count,level+2);
+			ret = _ph_query_mvptree(m2,query,knearest,radius,results,count,level+2);
 		    }
 		    /*unmap and remap to original file/position  */
 		    _ph_unmap_mvpfile(filenumber, orig_pos, m, m2);
@@ -1136,7 +1258,7 @@ MVPRetCode ph_query_mvptree(MVPFile *m, DP *query, int knearest, float radius,
 		    orig_pos = m->file_pos;
 		    MVPFile *m2 = _ph_map_mvpfile(filenumber, child_pos, m);
 		    if (m2){
-			ret = ph_query_mvptree(m2,query,knearest,radius,results,count,level+2);
+			ret = _ph_query_mvptree(m2,query,knearest,radius,results,count,level+2);
 		    }
 		    /* unmap/remap to original filenumber/position */
 		    _ph_unmap_mvpfile(filenumber, orig_pos, m, m2);
@@ -1158,7 +1280,7 @@ MVPRetCode ph_query_mvptree(MVPFile *m, DP *query, int knearest, float radius,
 		orig_pos = m->file_pos;
 		MVPFile *m2 = _ph_map_mvpfile(filenumber, child_pos, m);
 		if (m2){
-		    ret = ph_query_mvptree(m2,query,knearest,radius,results,count,level+2);
+		    ret = _ph_query_mvptree(m2,query,knearest,radius,results,count,level+2);
 		}
 		/* return to original and remap to original filenumber/position */
 		_ph_unmap_mvpfile(filenumber, orig_pos, m, m2);
@@ -1233,7 +1355,7 @@ MVPRetCode ph_query_mvptree(MVPFile *m, DP *query, int knearest, float radius,
 
     /* finish the query by calling the recursive auxiliary function */
     *count = 0;
-    MVPRetCode res = ph_query_mvptree(m,query,knearest,radius,results,count,0);
+    MVPRetCode res = _ph_query_mvptree(m,query,knearest,radius,results,count,0);
 
     munmap(m->buf, m->pgsize);
     m->buf = NULL;
@@ -1245,7 +1367,7 @@ MVPRetCode ph_query_mvptree(MVPFile *m, DP *query, int knearest, float radius,
     return res;
 }
 
-FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_flag, int level){
+FileIndex* _ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_flag, int level){
     int Np = (nbpoints >= 2) ? nbpoints - 2 : 0; 
     int BranchFactor = m->branchfactor;
     int PathLength = m->pathlength;
@@ -1255,15 +1377,15 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
     int Fanout = BranchFactor*BranchFactor;
 
     if ((!m) || (!points) || (nbpoints <= 0))
-	return NULL;
+	return (FileIndex*)PH_ERRARG;
     FileIndex *pOffset = (FileIndex*)malloc(sizeof(FileIndex));
     if (!pOffset){
-	return NULL;
+	return (FileIndex*)PH_ERRMEM;
     }
     hash_compareCB hashdist = m->hashdist;
     if (hashdist == NULL){
 	free(pOffset);
-	return NULL;
+	return (FileIndex*)PH_ERRARG;
     }
 
     off_t offset_mask = m->pgsize - 1;
@@ -1275,12 +1397,13 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	m2.leafcapacity = m->leafcapacity;
 	m2.pathlength = m->pathlength;
 	m2.pgsize = m->pgsize;
+	m2.hashdist = hashdist;
 
 	/* open new file */
 	char extfile[256];
 	snprintf(extfile, sizeof(extfile),"%s%d.mvp", m->filename, m->nbdbfiles);
 	
-	m2.fd = open(extfile, O_CREAT|O_RDWR|O_APPEND, 00777);
+	m2.fd = open(extfile, O_CREAT|O_RDWR|O_APPEND, 00755);
 	if (m2.fd < 0){
 	    free(pOffset);
 	    return NULL;
@@ -1296,7 +1419,7 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	    m->nbdbfiles++;
 	    snprintf(extfile, sizeof(extfile),"%s%d.mvp", m->filename, m->nbdbfiles);
 	    
-	    m2.fd = open(extfile,O_CREAT|O_RDWR|O_APPEND, 00777);
+	    m2.fd = open(extfile,O_CREAT|O_RDWR|O_APPEND, 00755);
 	    if (m2.fd < 0){
 		free(pOffset);
 		return NULL;
@@ -1331,31 +1454,21 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	m2.file_pos++;
 
 	/* find vantage points, sv1 and sv2 */
-	DP *sv1 = points[0];
-	DP *sv2 = NULL;
-	float d, max_dist = 0;
-	int max_pos = 0;
-	for (int i=1; i< nbpoints;i++){
-	    d = hashdist(sv1, points[i]);
-	    if (d > max_dist){
-		max_dist = d;
-		max_pos = i;
-	    }
-	}
-	
-	if (max_pos > 0){
-	    sv2 = points[max_pos]; /* sv2 is furthest point from sv1 */
-	}
+	int sv1_pos, sv2_pos;
+	float max_distance, min_distance;
+	ph_selectvantagepoints(&m2, points, nbpoints, sv1_pos, sv2_pos,max_distance, min_distance);
+	DP *sv1 = points[sv1_pos];
+	DP *sv2 = points[sv2_pos];
 
 	/* if file pos is beyond pg size*/
 	if ((m->file_pos & offset_mask) + ph_sizeof_dp(sv1,&m2) > m->pgsize)
-	    return NULL;
+	    return (FileIndex*)PH_ERRPGSIZE;
 
 	ph_save_datapoint(sv1, &m2);
 
 	/*if file pos is beyond pg size */
 	if ((m->file_pos & offset_mask) + ph_sizeof_dp(sv1,&m2) > m->pgsize)
-	    return NULL;
+	    return (FileIndex*)PH_ERRPGSIZE;
 
 	ph_save_datapoint(sv2, &m2);
 
@@ -1367,8 +1480,8 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	off_t curr_pos = m2.file_pos;
 	off_t last_pos = curr_pos + LeafCapacity*(2*sizeof(float) + sizeof(off_t));
 	off_t dp_pos;
-	for (int i=1;i<nbpoints;i++){
-	    if (i==max_pos) /* skip sv2 */
+	for (int i=0;i<nbpoints;i++){
+	    if ((i==sv1_pos)||(i==sv2_pos)) /* skip sv1 and sv2 */
 		continue;
 	    /* write d1, d2 */
 	    d1 = hashdist(sv1, points[i]);
@@ -1384,7 +1497,7 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 
 	    /* if file pos is beyond pg size */
 	    if ((m->file_pos & offset_mask) + ph_sizeof_dp(sv1,&m2) > m->pgsize)
-		return NULL;
+		return (FileIndex*)PH_ERRPGSIZE;
 	    
 	    dp_pos = ph_save_datapoint(points[i], &m2);
 	    last_pos = m2.file_pos;
@@ -1446,58 +1559,45 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	memcpy(&m->buf[m->file_pos++ & offset_mask],  &ntype, sizeof(uint8_t));
 	
 	/* choose vantage points, sv1, sv2 */
-	DP *sv1 = points[0]; 
-	DP *sv2 = NULL;
-	float max_dist = 0.0, min_dist = INT_MAX;
-	float *dist = (float*)malloc(nbpoints*sizeof(float));
-	if (!dist){
-	    free(pOffset);
-	    return NULL;
-	}
-	int max_pos = 0;
-	for (int i=0;i<nbpoints;i++){
-	    dist[i] = hashdist(sv1, points[i]);
-	    if (dist[i] > max_dist){
-		max_pos = i;
-		max_dist = dist[i];
-	    }
-	    if ((dist[i] < min_dist) && (dist[i] != 0)){
-		min_dist = dist[i];
-	    }
-            if (level <= PathLength)
-		points[i]->path[level] = dist[i];
-	}
-	sv2 = points[max_pos]; /* sv2 is furthest away from sv1 */
+	int sv1_pos, sv2_pos;
+	float max_distance, min_distance;
+	ph_selectvantagepoints(m, points, nbpoints, sv1_pos, sv2_pos, max_distance, min_distance);
+
+	DP *sv1 = points[sv1_pos]; 
+	DP *sv2 = points[sv2_pos];
 
 	/* save sv1, sv2 */
 	
 	/* check that file_pos does not exceed pgsize */
 	if ((m->file_pos & offset_mask) + ph_sizeof_dp(sv1,m) > m->pgsize)
-	    return NULL;
+	    return (FileIndex*)PH_ERRPGSIZE;
 
 	ph_save_datapoint(sv1, m);
 
 	/* check the file_os does not exceed pgsize */
 	if ((m->file_pos & offset_mask) + ph_sizeof_dp(sv1,m) > m->pgsize)
-	    return NULL;
+	    return (FileIndex*)PH_ERRPGSIZE;
 
 	ph_save_datapoint(sv2, m);
 
 	/* 1st tier pivots, M1, derived from the distance of each point from sv1*/
-	float step = (max_dist - min_dist)/BranchFactor;
+	float step = (max_distance - min_distance)/BranchFactor;
+	if (step <= 0.5){
+	    return (FileIndex*)PH_ERRDIST;
+	}
+
         float incr = step;
 
 	float *M1 = (float*)malloc(LengthM1*sizeof(float));
 	float *M2 = (float*)malloc(LengthM2*sizeof(float));
 	if (!M1 || !M2){
 	    free(pOffset);
-	    free(dist);
 	    return NULL;
 	}
 
 
 	for (int i=0;i<LengthM1;i++){
-	    M1[i] = min_dist + incr;
+	    M1[i] = min_distance + incr;
 	    incr += step;
 	    memcpy(&(m->buf[m->file_pos & offset_mask]),&M1[i], sizeof(float));
 	    m->file_pos += sizeof(float);
@@ -1508,7 +1608,6 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	DP ***bins = (DP***)malloc(BranchFactor*sizeof(DP***));
 	if (!bins){
 	    free(pOffset);
-	    free(dist);
 	    free(M1);
 	    free(M2);
 	    return NULL;
@@ -1516,7 +1615,6 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	int *mlens = (int*)calloc(BranchFactor, sizeof(int)); /*no. points in each bin */
 	if (!mlens){
 	    free(pOffset);
-	    free(dist);
 	    free(M1);
 	    free(M2);
 	    free(bins);
@@ -1527,7 +1625,6 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	    bins[i] = (DP**)malloc(Np*sizeof(DP**)); /*Np should be more than enough */            
 	    if (!bins[i]){
 		free(pOffset);
-		free(dist);
 		free(M1);
 		free(M2);
 		free(bins);
@@ -1537,10 +1634,13 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	}
 
 	/* sort points into bins (except sv1 and sv2 )*/
-	for (int i=1;i<nbpoints;i++){
-	    if (i == max_pos)
+	for (int i=0;i<nbpoints;i++){
+	    if ((i == sv1_pos)||(i==sv2_pos))
 		continue;
-	    float cur_dist = dist[i];
+	    float cur_dist = m->hashdist(sv1, points[i]);
+	    if (level < PathLength){
+		points[i]->path[level] = cur_dist;
+	    }
 	    /* check if <= M1[i] */
 	    for (int j=0;j < LengthM1;j++){
 		if (cur_dist <= M1[j]){
@@ -1570,7 +1670,6 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	DP ***bins2 = (DP***)malloc(BranchFactor*sizeof(DP***));
 	if (!bins2){
 	    free(pOffset);
-	    free(dist);
 	    free(M1);
 	    free(M2);
 	    free(bins);
@@ -1580,7 +1679,6 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	int *mlens2 = (int*)calloc(BranchFactor, sizeof(int)); /*number points in each bin */
 	if (!mlens2){
 	    free(pOffset);
-	    free(dist);
 	    free(M1);
 	    free(M2);
 	    free(bins);
@@ -1593,7 +1691,6 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	    bins2[i] = (DP**)malloc(Np*sizeof(DP**)); /* Np is more than enough */
 	    if (!bins2[i]){
 		free(pOffset);
-		free(dist);
 		free(M1);
 		free(M2);
 		free(bins);
@@ -1609,17 +1706,16 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	off_t child_pos = m2_pos + LengthM2*sizeof(float); /*pos where child offsets are written*/
 	off_t last_pos = child_pos + Fanout*(sizeof(uint8_t) + sizeof(off_t)); /* last pos in
                                                                       in internal node */
-
+	float *distance_vector = NULL;
 	/* for each row of bin, sort the row into bins2 */
 	for (int i=0;i < BranchFactor;i++){
 	    int row_len = mlens[i]; /* length of current row, bins[i] */
 	    for (int j=0;j < BranchFactor;j++){ /* reset the lengths to 0 */
 		mlens2[j] = 0;
 	    }
-	    float *dist2 = (float*)realloc(dist,row_len*sizeof(float));
-	    if (!dist2){
+	    float *dist_temp = (float*)realloc(distance_vector, row_len*sizeof(float));
+	    if (!dist_temp){
 		free(pOffset);
-		free(dist);
 		free(M1);
 		free(M2);
 		free(bins);
@@ -1628,27 +1724,27 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 		free(mlens2);
 		return NULL;
 	    }
-	    dist = dist2;
+	    distance_vector = dist_temp;
 
 	    /* 2nd tier pivots M2[], for row */
-	    max_dist = 0;
-	    min_dist = INT_MAX;
+	    max_distance = 0;
+	    min_distance = INT_MAX;
 	    for (int j=0;j<row_len;j++){
-		dist[j] = hashdist(sv2, bins[i][j]);
-		if ( dist[j] > max_dist)
-		    max_dist = dist[j];
-		if (dist[j] < min_dist)
-		    min_dist = dist[j];
-		if (level < PathLength){
-		    bins[i][j]->path[level+1] = dist[j];
+		distance_vector[j] = hashdist(sv2, bins[i][j]);
+		if ( distance_vector[j] > max_distance)
+		    max_distance = distance_vector[j];
+		if (distance_vector[j] < min_distance)
+		    min_distance = distance_vector[j];
+		if (level+1 < PathLength){
+		    bins[i][j]->path[level+1] = distance_vector[j];
 		}
 	    }
 
-	    step = (max_dist - min_dist)/BranchFactor;
+	    step = (max_distance - min_distance)/BranchFactor;
 	    incr = step;
 	    
 	    for (int j=0;j < LengthM1;j++){
-		M2[j+i*LengthM1] = min_dist + incr;
+		M2[j+i*LengthM1] = min_distance + incr;
 		memcpy(&(m->buf[m2_pos & offset_mask]),&M2[j+i*LengthM1],sizeof(float));
 		incr += step;
 		m2_pos += sizeof(float);
@@ -1659,14 +1755,14 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 		DP *current = bins[i][j];
 		/*check <= each M2 pivot  */
 		for (int k=0;k<LengthM1;k++){
-		    if (dist[j] <= M2[k+i*LengthM1]){
+		    if (distance_vector[j] <= M2[k+i*LengthM1]){
 			bins2[k][mlens2[k]] = current;
 			mlens2[k]++;
 			break;
 		    }
 		}
 		/* check > last M2 pivot  */
-		if (dist[j] > M2[LengthM1-1 + i*LengthM1]){
+		if (distance_vector[j] > M2[LengthM1-1 + i*LengthM1]){
 		    bins2[BranchFactor-1][mlens2[BranchFactor-1]] = current;
 		    mlens2[BranchFactor-1]++;
 		}
@@ -1680,11 +1776,12 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 		}
 	    }
 	    */
+
 	    /* save child nodes */
 	    FileIndex *pChild = NULL;
 	    for (int j=0;j<BranchFactor;j++){
 		m->file_pos = last_pos;
-		pChild = ph_save_mvptree(m, bins2[j], mlens2[j], saveall_flag, level+2);
+		pChild = _ph_save_mvptree(m, bins2[j], mlens2[j], saveall_flag, level+2);
 		if (pChild){ /* write filenumber and offset of child node */
 		    last_pos = m->file_pos;
 		    m->file_pos = child_pos;
@@ -1727,11 +1824,11 @@ FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_fl
 	}
 	/* cleanup */
 cleanup:
+	free(distance_vector);
 	free(bins);
 	free(bins2);
 	free(mlens);
 	free(mlens2);
-	free(dist);
 	free(M1);
 	free(M2);
     }
@@ -1743,21 +1840,24 @@ MVPRetCode ph_save_mvptree(MVPFile *m, DP **points, int nbpoints){
 
     if (m->pgsize == 0) /*use host pg size as default */
 	m->pgsize = sysconf(_SC_PAGE_SIZE);
-
+   
     /* check to see that the pg sizes are at least the size of host page size */
     off_t host_pgsize = sysconf(_SC_PAGE_SIZE);
     if (m->pgsize < host_pgsize){
 	return PH_ERRPGSIZE;
     }
-
+    
     /* pg sizes must be a power of 2 */
     if ((m->pgsize) & (m->pgsize - 1))
 	return PH_ERRPGSIZE;
+    if (nbpoints < m->leafcapacity + 2){
+	return PH_ERRARG;
+    }
 
     /* open main file */
     char mainfile[256];
     snprintf(mainfile, sizeof(mainfile),"%s.mvp", m->filename);
-    m->fd = open(mainfile, O_CREAT|O_RDWR|O_TRUNC, 00777);
+    m->fd = open(mainfile, O_CREAT|O_RDWR|O_TRUNC, 00755);
     if (m->fd < 0){
 	return PH_ERRFILE;
     }
@@ -1806,7 +1906,7 @@ MVPRetCode ph_save_mvptree(MVPFile *m, DP **points, int nbpoints){
 
     m->file_pos = HeaderSize;
 
-    if (ph_save_mvptree(m, points, nbpoints, 1, 0) == NULL){
+    if (_ph_save_mvptree(m, points, nbpoints, 1, 0) == NULL){
 	return PH_ERRSAVEMVP;
     }
 
@@ -1825,7 +1925,7 @@ MVPRetCode ph_save_mvptree(MVPFile *m, DP **points, int nbpoints){
 }
 
 
-MVPRetCode ph_add_mvptree(MVPFile *m, DP *new_dp, int level){
+MVPRetCode _ph_add_mvptree(MVPFile *m, DP *new_dp, int level){
 
     uint8_t ntype;
     off_t offset_mask, page_mask;
@@ -1842,8 +1942,8 @@ MVPRetCode ph_add_mvptree(MVPFile *m, DP *new_dp, int level){
     page_mask = ~(m->pgsize - 1);
 
     off_t start_pos = m->file_pos;
-
     memcpy(&ntype, &m->buf[m->file_pos++ & offset_mask], sizeof(uint8_t));
+
     if (ntype == 0){
 	uint8_t Np = 0;
 	DP *sv1 = ph_read_datapoint(m);
@@ -1853,7 +1953,7 @@ MVPRetCode ph_add_mvptree(MVPFile *m, DP *new_dp, int level){
 		off_t Np_pos = m->file_pos;
 		memcpy(&Np,&m->buf[m->file_pos & offset_mask], sizeof(uint8_t));
 		m->file_pos++;
-
+		
 		off_t offset_start = m->file_pos;
 
 		float d1 = hashdist(sv1,new_dp);
@@ -1929,7 +2029,7 @@ MVPRetCode ph_add_mvptree(MVPFile *m, DP *new_dp, int level){
 		    }
 		    points[Np+2] = new_dp;
 		    m->file_pos = start_pos;
-		    if (!ph_save_mvptree(m, points, Np+3, 0, level+2)){
+		    if (!_ph_save_mvptree(m, points, Np+3, 0, level+2)){
 			free(points);
 			free(sv1);
 			free(sv2);
@@ -1957,9 +2057,17 @@ MVPRetCode ph_add_mvptree(MVPFile *m, DP *new_dp, int level){
 		memcpy(&m->buf[m->file_pos & offset_mask], &Np, sizeof(uint8_t));
 		m->file_pos++;
 	    }
+            ph_free_datapoint(sv1);
 	    ph_free_datapoint(sv2);
 	}
-	ph_free_datapoint(sv1);
+        else {
+            m->file_pos = start_pos;
+	    ntype = 0;
+	    memcpy(&m->buf[m->file_pos & offset_mask], &ntype, sizeof(uint8_t));
+	    m->file_pos++;
+	    ph_save_datapoint(new_dp, m);
+	    ph_save_datapoint(NULL, m);
+	}
     } else if (ntype == 1){
 	int LengthM1 = m->branchfactor - 1;
 	int LengthM2 = (m->branchfactor)*LengthM1;
@@ -2003,6 +2111,7 @@ MVPRetCode ph_add_mvptree(MVPFile *m, DP *new_dp, int level){
 	for (pivot1=0;pivot1 < LengthM1;pivot1++){
 	    if (d1 <= M1[pivot1]){
 		/* check <= each M2 pivot */
+
 		for (pivot2 = 0; pivot2 < LengthM1;pivot2++){
 		    if (d2 <= M2[pivot2+pivot1*LengthM1]){
 			/* determine pos from which to read filenumber and offset */
@@ -2017,7 +2126,7 @@ MVPRetCode ph_add_mvptree(MVPFile *m, DP *new_dp, int level){
 			orig_pos = m->file_pos;
 			MVPFile *m2 = _ph_map_mvpfile(filenumber,child_pos,m);
 			if (m2){
-			    retcode = ph_add_mvptree(m2, new_dp, level+2);
+			    retcode = _ph_add_mvptree(m2, new_dp, level+2);
 			    if (retcode != PH_SUCCESS){
 				return retcode;
 			    }
@@ -2038,7 +2147,7 @@ MVPRetCode ph_add_mvptree(MVPFile *m, DP *new_dp, int level){
 		    orig_pos = m->file_pos;
 		    MVPFile *m2 = _ph_map_mvpfile(filenumber, child_pos, m);
 		    if (m2){
-			retcode = ph_add_mvptree(m2, new_dp, level+2);
+			retcode = _ph_add_mvptree(m2, new_dp, level+2);
 			if (retcode != PH_SUCCESS){
 			    return retcode;
 			}
@@ -2063,7 +2172,7 @@ MVPRetCode ph_add_mvptree(MVPFile *m, DP *new_dp, int level){
 		    orig_pos = m->file_pos;
 		    MVPFile *m2 = _ph_map_mvpfile(filenumber,child_pos,m);
 		    if (m2){
-			retcode = ph_add_mvptree(m2,new_dp,level+2);
+			retcode = _ph_add_mvptree(m2,new_dp,level+2);
 			if (retcode != PH_SUCCESS){
 			    return retcode;
 			}
@@ -2084,7 +2193,7 @@ MVPRetCode ph_add_mvptree(MVPFile *m, DP *new_dp, int level){
 		orig_pos = m->file_pos;
 		MVPFile *m2 = _ph_map_mvpfile(filenumber, child_pos, m);
 		if (m2){
-		    retcode = ph_add_mvptree(m2, new_dp, level+2);
+		    retcode = _ph_add_mvptree(m2, new_dp, level+2);
 		    if (retcode != PH_SUCCESS){
 			return retcode;
 		    }
@@ -2170,9 +2279,11 @@ int ph_add_mvptree(MVPFile *m, DP **points, int nbpoints){
     }
 
     int nbsaved = 0;
+    int retval;
     for (int i=0;i<nbpoints;i++){
         m->file_pos = HeaderSize;
-	if (ph_add_mvptree(m, points[i], 0) != PH_SUCCESS){
+	retval = _ph_add_mvptree(m, points[i], 0);
+	if (retval != 0){
 	    continue;
 	}
 	nbsaved++;
@@ -2215,7 +2326,7 @@ TxtHashPoint* ph_texthash(const char *filename,int *nbpoints){
 	return NULL;
     }
     *nbpoints=0;
-    int i, first=0;
+    int i, first=0, last=KgramLength-1;
     int text_index = 0;
     int win_index = 0;
     for (i=0;i < KgramLength;i++){    /* calc first kgram */
@@ -2232,8 +2343,8 @@ TxtHashPoint* ph_texthash(const char *filename,int *nbpoints){
 	    d = d + 32;
       
 	kgram[i] = (char)d;
-        hashword = ROTATELEFT(hashword, delta);
-        hashword = hashword^textkeys[d];
+        hashword = hashword << delta;   /* rotate left or shift left ??? */
+        hashword = hashword^textkeys[d];/* right now, rotate breaks it */
     }
 
     WinHash[win_index].hash = hashword;
@@ -2257,13 +2368,18 @@ TxtHashPoint* ph_texthash(const char *filename,int *nbpoints){
 	    continue;
 	if ((d >= 65)&&(d<=90))       /*convert upper to lower case */
 	    d = d + 32;
-	hashword = hashword << delta;
-	hashword = hashword^((ulong64)d);
-	ulong64 oldsym = (ulong64)kgram[first%KgramLength];
+
+	ulong64 oldsym = textkeys[kgram[first%KgramLength]];
+
+	/* rotate or left shift ??? */
+	/* right now, rotate breaks it */
 	oldsym = oldsym << delta*KgramLength;
+	hashword = hashword << delta;
+	hashword = hashword^textkeys[d];
 	hashword = hashword^oldsym;
-	kgram[first%KgramLength] = (char)d;
+	kgram[last%KgramLength] = (char)d;
 	first++;
+	last++;
 
         WinHash[win_index%WindowLength].hash = hashword;
 	WinHash[win_index%WindowLength].index = text_index;
diff --git a/src/pHash.h b/src/pHash.h
index cbbe4dd..dfdfd96 100644
--- a/src/pHash.h
+++ b/src/pHash.h
@@ -60,11 +60,15 @@ typedef unsigned long long ulong64;
 typedef signed long long long64;
 #endif
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 const int MaxFileSize = (1<<30); /* 1GB file size limit (for mvp files) */
 const off_t HeaderSize = 64;     /* header size for mvp file */
 
 
-const char *mvptag = "pHashMVPfile2009";
+const char mvptag[] = "pHashMVPfile2009";
 
 typedef enum ph_mvp_retcode {
     PH_SUCCESS = 0,   /* success */
@@ -79,6 +83,7 @@ typedef enum ph_mvp_retcode {
     PH_ERRNTYPE,      /* unrecognized node type */
     PH_ERRCAP,     /* more results found than can be supported in ret array */
     PH_ERRFILETYPE,  /*unrecognized file type  */
+    PH_ERRDIST,      /*not enough variance in distances */
 }MVPRetCode;
 
 
@@ -138,7 +143,7 @@ typedef struct ph_mvp_file {
 void ph_mvp_init(MVPFile *m){
     m->branchfactor = 2;
     m->pathlength = 5;
-    m->leafcapacity = 25;
+    m->leafcapacity = 23;
     m->pgsize = sysconf(_SC_PAGE_SIZE);     /* use host page size */
     return;
 }
@@ -189,7 +194,7 @@ typedef struct ph_match{
 /* /brief alloc a single data point
  *  allocates path array, does nto set id or path
  */
-DP* ph_malloc_datapoint(int hashtype, int pathlength);
+ DP* ph_malloc_datapoint(int hashtype, int pathlength);
 
 /** /brief free a datapoint and its path
  *
@@ -247,7 +252,7 @@ int ph_crosscorr(const Digest &x,const Digest &y,double &pcc, double threshold =
  *  /param N      - int value for the number of angles to consider. 
  *  /return       - less than 0 for error
  */
-int ph_image_digest(const CImg<uint8_t> &img,double sigma, double gamma,Digest &digest,int N=180);
+int _ph_image_digest(const CImg<uint8_t> &img,double sigma, double gamma,Digest &digest,int N=180);
 
 /*! /brief image digest
  *  Compute the image digest given the file name.
@@ -270,7 +275,7 @@ int ph_image_digest(const char *file, double sigma, double gamma, Digest &digest
  *  /param theshold - double value for the threshold
  *  /return int 0 (false) for different images, 1 (true) for same image, less than 0 for error
  */
-int ph_compare_images(const CImg<uint8_t> &imA,const CImg<uint8_t> &imB,double &pcc, double sigma = 3.5, double gamma = 1.0,int N=180,double threshold=0.90);
+int _ph_compare_images(const CImg<uint8_t> &imA,const CImg<uint8_t> &imB,double &pcc, double sigma = 3.5, double gamma = 1.0,int N=180,double threshold=0.90);
 
 /*! /brief compare 2 images
  *  Compare 2 images given the file names
@@ -289,7 +294,7 @@ int ph_compare_images(const char *file1, const char *file2,double &pcc, double s
  *  /param N - int denoting the size of the square matrix to create.
  *  /return CImg<double> size NxN containing the dct matrix
  */
-CImg<float>* ph_dct_matrix(const int N);
+static CImg<float>* ph_dct_matrix(const int N);
 
 /*! /brief compute dct robust image hash
  *  /param file string variable for name of file
@@ -299,7 +304,7 @@ CImg<float>* ph_dct_matrix(const int N);
 int ph_dct_imagehash(const char* file,ulong64 &hash);
 
 
-CImgList<uint8_t>* ph_getKeyFramesFromVideo(const char *filename);
+static CImgList<uint8_t>* ph_getKeyFramesFromVideo(const char *filename);
 
 ulong64* ph_dct_videohash(const char *filename, int &Lenght);
 
@@ -322,12 +327,37 @@ int ph_hamming_distance(const ulong64 hash1,const ulong64 hash2);
 
 DP** ph_read_imagehashes(const char *dirname,int capacity, int &count);
 
+/** /brief create MH image hash for filename image
+*   /param filename - string name of image file
+*   /param N - (out) int value for length of image hash returned
+*   /param alpha - int scale factor for marr wavelet (default=2)
+*   /param lvl   - int level of scale factor (default = 1)
+*   /return uint8_t array
+**/
+uint8_t* ph_mh_imagehash(const char *filename, int &N, int alpha=2, int lvl = 1);
+
+/** /brief count number bits set in given byte
+*   /param val - uint8_t byte value
+*   /return int value for number of bits set
+**/
+int ph_bitcount8(uint8_t val);
+
+/** /brief compute hamming distance between two byte arrays
+ *  /param hashA - byte array for first hash
+ *  /param lenA - int length of hashA 
+ *  /param hashB - byte array for second hash
+ *  /param lenB - int length of hashB
+ *  /return double value for normalized hamming distance
+ **/
+double ph_hammingdistance2(uint8_t *hashA, int lenA, uint8_t *hashB, int lenB);
+
 /** /brief get all the filenames in specified directory
  *  /param dirname - string value for path and filename
  *  /param cap - int value for upper limit to number of files
  *  /param count - int value for number of file names returned
  *  /return array of pointers to string file names (NULL for error)
  **/
+
 char** ph_readfilenames(const char *dirname,int &count);
 
 /** /brief read a datapoint (aux function)
@@ -380,7 +410,7 @@ float hammingdistance(DP *pntA, DP *pntB);
  *  /param level - int value to track recursion depth.
  *  /return MVPRetCode
 **/
-MVPRetCode ph_query_mvptree(MVPFile *m, DP *query, int knearest, float radius,
+static MVPRetCode _ph_query_mvptree(MVPFile *m, DP *query, int knearest, float radius,
 			    DP **results, int *count, int level);
 
 /**  /brief query mvptree function
@@ -402,7 +432,7 @@ MVPRetCode ph_query_mvptree(MVPFile *m, DP *query, int knearest, float radius,
  *  /param level - int track recursion level
  *  /return FileIndex* - fileno and offset into file.
 **/
-FileIndex* ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_flag, int level);
+static FileIndex* _ph_save_mvptree(MVPFile *m, DP **points, int nbpoints, int saveall_flag, int level);
 
 /** /brief save points to mvp file 
  *  /param m - MVPFile state info of file
@@ -419,7 +449,7 @@ MVPRetCode ph_save_mvptree(MVPFile *m, DP **points, int nbpoints);
  *   /param level - int track recursion level
  *   /return MVPRetCode
  **/
-MVPRetCode ph_add_mvptree(MVPFile *m, DP *new_dp, int level);
+static MVPRetCode _ph_add_mvptree(MVPFile *m, DP *new_dp, int level);
 
 /** /brief add a list of points to mvp file
     /param m - MVPFile state information of file.
@@ -448,7 +478,7 @@ TxtMatch* ph_compare_text_hashes(TxtHashPoint *hash1, int N1, TxtHashPoint *hash
 
 /* random char mapping for textual hash */
 
-ulong64 textkeys[256] = {
+static const ulong64 textkeys[256] = {
     15498727785010036736LLU,
     7275080914684608512LLU,
     14445630958268841984LLU,
@@ -707,5 +737,7 @@ ulong64 textkeys[256] = {
     11569021017716162560LLU
 };
 
-
+#ifdef __cplusplus
+}
+#endif
 #endif

-- 
debian-forensics/libphash



More information about the forensics-changes mailing list