s-bear / image-hash

Perceptual Image Hashing Utility
MIT License
2 stars 1 forks source link

Unsupported file format #3

Open hafedh-trimeche opened 1 year ago

hafedh-trimeche commented 1 year ago

Hi,

Please note that the command line (jpg,jpeg,png) always reports an error: Unsupported file format imghash.exe -d2 LeftIndex.jpeg LeftIndex.zip

Best regards.

s-bear commented 1 year ago

Hey mate, I took a look and I think you built the tool without libjpeg or libpng. I haven't had the time to write detailed build instructions, so I've uploaded pre-built static binaries: https://github.com/s-bear/image-hash/releases/tag/v0.1.1 I also added a CMakePresets.json file which may make building from an IDE easier. You'll want to set up vcpkg (https://vcpkg.io/en/) to fetch the jpeg and png libraries. I hope this works for you! Cheers, Sam

hafedh-trimeche commented 1 year ago

Hello,

Please note these Errors & Warnings:

1>------ Rebuild All started: Project: ZERO_CHECK, Configuration: Release x64 ------
1>Checking Build System
2>------ Rebuild All started: Project: imghash, Configuration: Release x64 ------
2>Building Custom Rule D:/DevStudio/image-hash/CMakeLists.txt
2>main.cpp
2>imghash.cpp
2>jpeg.cpp
2>png.cpp
2>mvptable.cpp
2>db.cpp
2>Generating Code...
2>SQLiteCpp.lib(Statement.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in main.obj
2>SQLiteCpp.lib(Column.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in main.obj
2>SQLiteCpp.lib(Database.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in main.obj
2>SQLiteCpp.lib(Exception.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in main.obj
2>SQLiteCpp.lib(Backup.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in main.obj
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "public: __cdecl std::_Lockit::_Lockit(int)" (??0_Lockit@std@@QEAA@H@Z) already defined in libcpmt.lib(xlock.obj)
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "public: __cdecl std::_Lockit::~_Lockit(void)" (??1_Lockit@std@@QEAA@XZ) already defined in libcpmt.lib(xlock.obj)
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "public: __cdecl std::locale::id::operator unsigned __int64(void)" (??Bid@locale@std@@QEAA_KXZ) already defined in libcpmt.lib(cout.obj)
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "public: bool __cdecl std::codecvt_base::always_noconv(void)const " (?always_noconv@codecvt_base@std@@QEBA_NXZ) already defined in libcpmt.lib(cout.obj)
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "public: int __cdecl std::codecvt<char,char,struct _Mbstatet>::in(struct _Mbstatet &,char const *,char const *,char const * &,char *,char *,char * &)const " (?in@?$codecvt@DDU_Mbstatet@@@std@@QEBAHAEAU_Mbstatet@@PEBD1AEAPEBDPEAD3AEAPEAD@Z) already defined in libcpmt.lib(cout.obj)
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "public: int __cdecl std::codecvt<char,char,struct _Mbstatet>::out(struct _Mbstatet &,char const *,char const *,char const * &,char *,char *,char * &)const " (?out@?$codecvt@DDU_Mbstatet@@@std@@QEBAHAEAU_Mbstatet@@PEBD1AEAPEBDPEAD3AEAPEAD@Z) already defined in libcpmt.lib(cout.obj)
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "public: int __cdecl std::codecvt<char,char,struct _Mbstatet>::unshift(struct _Mbstatet &,char *,char *,char * &)const " (?unshift@?$codecvt@DDU_Mbstatet@@@std@@QEBAHAEAU_Mbstatet@@PEAD1AEAPEAD@Z) already defined in libcpmt.lib(cout.obj)
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "public: static unsigned __int64 __cdecl std::codecvt<char,char,struct _Mbstatet>::_Getcat(class std::locale::facet const * *,class std::locale const *)" (?_Getcat@?$codecvt@DDU_Mbstatet@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z) already defined in imghash.obj
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "protected: __cdecl std::basic_streambuf<char,struct std::char_traits<char> >::basic_streambuf<char,struct std::char_traits<char> >(void)" (??0?$basic_streambuf@DU?$char_traits@D@std@@@std@@IEAA@XZ) already defined in imghash.obj
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "public: virtual __cdecl std::basic_streambuf<char,struct std::char_traits<char> >::~basic_streambuf<char,struct std::char_traits<char> >(void)" (??1?$basic_streambuf@DU?$char_traits@D@std@@@std@@UEAA@XZ) already defined in main.obj
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "protected: char * __cdecl std::basic_streambuf<char,struct std::char_traits<char> >::_Pninc(void)" (?_Pninc@?$basic_streambuf@DU?$char_traits@D@std@@@std@@IEAAPEADXZ) already defined in libcpmt.lib(cout.obj)
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "protected: void __cdecl std::basic_streambuf<char,struct std::char_traits<char> >::_Init(void)" (?_Init@?$basic_streambuf@DU?$char_traits@D@std@@@std@@IEAAXXZ) already defined in libcpmt.lib(cout.obj)
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "protected: virtual __int64 __cdecl std::basic_streambuf<char,struct std::char_traits<char> >::xsgetn(char *,__int64)" (?xsgetn@?$basic_streambuf@DU?$char_traits@D@std@@@std@@MEAA_JPEAD_J@Z) already defined in main.obj
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "protected: virtual __int64 __cdecl std::basic_streambuf<char,struct std::char_traits<char> >::xsputn(char const *,__int64)" (?xsputn@?$basic_streambuf@DU?$char_traits@D@std@@@std@@MEAA_JPEBD_J@Z) already defined in main.obj
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "public: virtual __cdecl std::basic_ios<char,struct std::char_traits<char> >::~basic_ios<char,struct std::char_traits<char> >(void)" (??1?$basic_ios@DU?$char_traits@D@std@@@std@@UEAA@XZ) already defined in main.obj
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "public: void __cdecl std::basic_ios<char,struct std::char_traits<char> >::setstate(int,bool)" (?setstate@?$basic_ios@DU?$char_traits@D@std@@@std@@QEAAXH_N@Z) already defined in libcpmt.lib(cout.obj)
2>msvcprt.lib(MSVCP140.dll) : error LNK2005: "protected: __cdecl std::basic_ios<char,struct std::char_traits<char> >::basic_ios<char,struct std::char_traits<char> >(void)" (??0?$basic_ios@DU?$char_traits@D@std@@@std@@IEAA@XZ) already defined in libcpmt.lib(cout.obj)
2>LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library
2>LINK : warning LNK4217: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'SQLiteCpp.lib(Statement.cpp.obj)' in function '"void * __cdecl std::_Allocate<16,struct std::_Default_allocate_traits,0>(unsigned __int64)" (??$_Allocate@$0BA@U_Default_allocate_traits@std@@$0A@@std@@YAPEAX_K@Z)'
2>LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'SQLiteCpp.lib(Column.cpp.obj)'
2>LINK : warning LNK4286: symbol '_invalid_parameter_noinfo_noreturn' defined in 'libucrt.lib(invalid_parameter.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)'
2>LINK : warning LNK4217: symbol '_get_stream_buffer_pointers' defined in 'libucrt.lib(_file.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"public: __cdecl std::basic_ifstream<char,struct std::char_traits<char> >::basic_ifstream<char,struct std::char_traits<char> >(char const *,int,int)" (??0?$basic_ifstream@DU?$char_traits@D@std@@@std@@QEAA@PEBDHH@Z)'
2>LINK : warning LNK4217: symbol 'fclose' defined in 'libucrt.lib(fclose.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"public: class std::basic_filebuf<char,struct std::char_traits<char> > * __cdecl std::basic_filebuf<char,struct std::char_traits<char> >::close(void)" (?close@?$basic_filebuf@DU?$char_traits@D@std@@@std@@QEAAPEAV12@XZ)'
2>LINK : warning LNK4217: symbol 'fflush' defined in 'libucrt.lib(fflush.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"protected: virtual int __cdecl std::basic_filebuf<char,struct std::char_traits<char> >::sync(void)" (?sync@?$basic_filebuf@DU?$char_traits@D@std@@@std@@MEAAHXZ)'
2>LINK : warning LNK4217: symbol 'fgetc' defined in 'libucrt.lib(fgetc.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"bool __cdecl std::_Fgetc<char>(char &,struct _iobuf *)" (??$_Fgetc@D@std@@YA_NAEADPEAU_iobuf@@@Z)'
2>LINK : warning LNK4217: symbol 'fgetpos' defined in 'libucrt.lib(fgetpos.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"protected: virtual class std::fpos<struct _Mbstatet> __cdecl std::basic_filebuf<char,struct std::char_traits<char> >::seekoff(__int64,int,int)" (?seekoff@?$basic_filebuf@DU?$char_traits@D@std@@@std@@MEAA?AV?$fpos@U_Mbstatet@@@2@_JHH@Z)'
2>LINK : warning LNK4217: symbol 'fputc' defined in 'libucrt.lib(fputc.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"bool __cdecl std::_Fputc<char>(char,struct _iobuf *)" (??$_Fputc@D@std@@YA_NDPEAU_iobuf@@@Z)'
2>LINK : warning LNK4217: symbol 'fread' defined in 'libucrt.lib(fread.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"protected: virtual __int64 __cdecl std::basic_filebuf<char,struct std::char_traits<char> >::xsgetn(char *,__int64)" (?xsgetn@?$basic_filebuf@DU?$char_traits@D@std@@@std@@MEAA_JPEAD_J@Z)'
2>LINK : warning LNK4217: symbol 'fsetpos' defined in 'libucrt.lib(fsetpos.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"protected: virtual class std::fpos<struct _Mbstatet> __cdecl std::basic_filebuf<char,struct std::char_traits<char> >::seekpos(class std::fpos<struct _Mbstatet>,int)" (?seekpos@?$basic_filebuf@DU?$char_traits@D@std@@@std@@MEAA?AV?$fpos@U_Mbstatet@@@2@V32@H@Z)'
2>LINK : warning LNK4217: symbol '_fseeki64' defined in 'libucrt.lib(fseek.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"protected: virtual class std::fpos<struct _Mbstatet> __cdecl std::basic_filebuf<char,struct std::char_traits<char> >::seekoff(__int64,int,int)" (?seekoff@?$basic_filebuf@DU?$char_traits@D@std@@@std@@MEAA?AV?$fpos@U_Mbstatet@@@2@_JHH@Z)'
2>LINK : warning LNK4217: symbol 'fwrite' defined in 'libucrt.lib(fwrite.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"protected: bool __cdecl std::basic_filebuf<char,struct std::char_traits<char> >::_Endwrite(void)" (?_Endwrite@?$basic_filebuf@DU?$char_traits@D@std@@@std@@IEAA_NXZ)'
2>LINK : warning LNK4217: symbol 'setvbuf' defined in 'libucrt.lib(setvbuf.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"protected: virtual class std::basic_streambuf<char,struct std::char_traits<char> > * __cdecl std::basic_filebuf<char,struct std::char_traits<char> >::setbuf(char *,__int64)" (?setbuf@?$basic_filebuf@DU?$char_traits@D@std@@@std@@MEAAPEAV?$basic_streambuf@DU?$char_traits@D@std@@@2@PEAD_J@Z)'
2>LINK : warning LNK4217: symbol 'ungetc' defined in 'libucrt.lib(ungetc.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"bool __cdecl std::_Ungetc<char>(char const &,struct _iobuf *)" (??$_Ungetc@D@std@@YA_NAEBDPEAU_iobuf@@@Z)'
2>LINK : warning LNK4217: symbol '_lock_file' defined in 'libucrt.lib(_file.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"public: virtual void __cdecl std::basic_filebuf<char,struct std::char_traits<char> >::_Lock(void)" (?_Lock@?$basic_filebuf@DU?$char_traits@D@std@@@std@@UEAAXXZ)'
2>LINK : warning LNK4217: symbol '_unlock_file' defined in 'libucrt.lib(_file.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"public: virtual void __cdecl std::basic_filebuf<char,struct std::char_traits<char> >::_Unlock(void)" (?_Unlock@?$basic_filebuf@DU?$char_traits@D@std@@@std@@UEAAXXZ)'
2>LINK : warning LNK4217: symbol 'strncmp' defined in 'libucrt.lib(strncmp.obj)' is imported by 'SQLiteCpp.lib(Database.cpp.obj)' in function '"public: static struct SQLite::Header __cdecl SQLite::Database::getHeaderInfo(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?getHeaderInfo@Database@SQLite@@SA?AUHeader@2@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)'
2>D:\DevStudio\image-hash\build-64\Release\imghash.exe : fatal error LNK1169: one or more multiply defined symbols found
2>Done building project "imghash.vcxproj" -- FAILED.
3>------ Rebuild All started: Project: ALL_BUILD, Configuration: Release x64 ------
3>Building Custom Rule D:/DevStudio/image-hash/CMakeLists.txt
4>------ Skipped Rebuild All: Project: PACKAGE, Configuration: Release x64 ------
4>Project not selected to build for this solution configuration 
5>------ Skipped Rebuild All: Project: INSTALL, Configuration: Release x64 ------
5>Project not selected to build for this solution configuration 
========== Rebuild All: 2 succeeded, 1 failed, 2 skipped ==========
===

Best regards.

s-bear commented 1 year ago

That first error, error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in main.obj, means that the linker is expecting static libraries but you've specified the dynamic version of SQLiteCpp.

The CMakeLists.txt and CMakePresets.json don't specify static or dynamic libraries, so it's unclear how that happened. I have build the project successfully using both static and dynamic configurations with the same CMake* files.

I would recommend cleaning the project, reconfiguring your cmake cache, and rebuilding. You might be having trouble configuring if you're launching cmake from within the visual studio IDE ... it doesn't support CMakePresets.json version 6. Try downgrading the file to 5 or 3 (at the beginning of CMakePresets.json) and see if that helps you build.

Do the prebuilt binaries work for you?

hafedh-trimeche commented 1 year ago

Hi,

Thank you for prompt response.

CMake 3.26.3 is used (Visual Studio 2022). cmake-gui_K5OJtj4Fh6

The prebuilt version worked well but 32 bit version also needed.

Best regards.

s-bear commented 1 year ago

I see. I haven't tested 32-bit builds at all! I'll give it a go

s-bear commented 1 year ago

Well, that was mildly embarassing... I was asking cmake to link it with static libraries on windows -- that's the set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") line. I just didn't remember what it did! I've updated CMakeLists with a switch for that line, and added explicit vcpkg triplets in CMakePresets.json to enable static linking for windows release builds. I prefer the static linkage because you don't have to include all of the DLLs with the executable, so that's the default, but it shouldn't be too hard (or mysterious) to move back to dynamic libs.

It was working on my machine because I had previously manually installed both dynamic and static 64-bit libraries, so there were no issues when vcpkg went to fetch the wrong versions of the libraries 🤦‍♂️

Anyway, I think it's all good now! Let me know how you get on and I'll close the issue if it's working.

Cheers, Sam

hafedh-trimeche commented 1 year ago

Hello,

The 2 builds are OK but dynamically linked:

imghash.exe
jpeg62.dll
libpng16.dll
sqlite3.dll
zlib1.dll

Would the hash function be exported as DLL ImageHash(JPEG/PNG/PPM Blob) or ImageHash(RawGrayImage,Width,Height)?

Regards.

s-bear commented 1 year ago

Ah, I'm afraid the hash functions are not exported at all... C++ code is unfortunately annoying to make (safely) exportable and the way I wrote this (using templates and exceptions) would make it a bit too much work for me to tackle it in my spare time. That being said, imghash.h and imghash.cpp contain the hashing functions (see BlockHasher::apply and DCTHasher::apply). You're certainly welcome to copy & modify the code to embed them in another application as long as you keep the attribution to me as per the license.

If you want to use it as part of a larger workflow/application/script without digging into the code---which I've done a few times for my own work---you can launch the program as a subprocess (popen or CreateProcess or whatever) without specifying a filename (e.g. imghash -d2 -q) and pipe image data to it via stdin in the ppm format. With -q the tool will output just the hash data over stdout so you don't have to parse anything and will process multiple images until you close the pipe.