From 759ce9fffee107ba41967cbc2e4398e16e163b30 Mon Sep 17 00:00:00 2001 From: clanmills Date: Fri, 1 May 2020 16:18:01 +0100 Subject: [PATCH 01/19] fix_1046_sample_geotag Take advantage of fix to #1046 in samples/geotag.cpp --- samples/geotag.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/geotag.cpp b/samples/geotag.cpp index 84061f5278..cbcdc40dc8 100644 --- a/samples/geotag.cpp +++ b/samples/geotag.cpp @@ -906,7 +906,7 @@ int main(int argc,const char* argv[]) image->readMetadata(); Exiv2::ExifData& exifData = image->exifData(); if ( pPos ) { - exifData["Exif.GPSInfo.GPSProcessingMethod" ] = "65 83 67 73 73 0 0 0 72 89 66 82 73 68 45 70 73 88"; // ASCII HYBRID-FIX + exifData["Exif.GPSInfo.GPSProcessingMethod" ] = "charset=Ascii HYBRID-FIX"; exifData["Exif.GPSInfo.GPSVersionID" ] = "2 2 0 0"; exifData["Exif.GPSInfo.GPSMapDatum" ] = "WGS-84"; From d994161e804412a925fb8b7073f1d8128682c4fb Mon Sep 17 00:00:00 2001 From: clanmills Date: Fri, 1 May 2020 17:40:20 +0100 Subject: [PATCH 02/19] Added option -remove to samples/geotag.cpp --- README-SAMPLES.md | 5 +++-- samples/geotag.cpp | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/README-SAMPLES.md b/README-SAMPLES.md index 99391f42ae..7b50d3de17 100644 --- a/README-SAMPLES.md +++ b/README-SAMPLES.md @@ -195,7 +195,7 @@ $ #### geotag ``` -Usage: geotag {-help|-version|-dst|-dryrun|-ascii|-verbose|-adjust value|-tz value|-delta value}+ path+ +Usage: geotag {-help|-version|-dst|-dryrun|-ascii|-remove|-verbose|-adjust value|-tz value|-delta value}+ path+ ``` Geotag reads one or more GPX files and adds GPS Tages to images. _Code: [geotag.cpp](samples/geotag.cpp)_ @@ -208,6 +208,7 @@ If the path is a directory, geotag will read all the files in the directory. It | -dst | Apply 1 hour adjustment for daylight saving time. | | -dryrun | Read arguments and print report. Does not modify images. | | -verbose | Report progress. | +| -remove | Removes GPS tags from images. | | -adjust value | Add/subtract time from image data. | | -tz value | Specify time zone. For example PST = -8:00 | | -delta value | Correction between Image DataTime and GPS time. | @@ -643,4 +644,4 @@ Read an XMP packet from a file, parse and re-serialize it. Robin Mills
robin@clanmills.com
-Revised: 2019-06-20 \ No newline at end of file +Revised: 2020-05-01 \ No newline at end of file diff --git a/samples/geotag.cpp b/samples/geotag.cpp index cbcdc40dc8..0e806d3554 100644 --- a/samples/geotag.cpp +++ b/samples/geotag.cpp @@ -87,6 +87,7 @@ class Options { bool dst; bool dryrun; bool ascii; + bool remove; Options() { @@ -96,6 +97,7 @@ class Options { dst = false; dryrun = false; ascii = false; + remove = false; } virtual ~Options() {} ; @@ -113,6 +115,7 @@ enum // keyword indices , kwDST , kwDRYRUN , kwASCII +, kwREMOVE , kwVERBOSE , kwADJUST , kwTZ @@ -790,6 +793,7 @@ int main(int argc,const char* argv[]) keywords[kwADJUST ] = "adjust"; keywords[kwTZ ] = "tz"; keywords[kwDELTA ] = "delta"; + keywords[kwREMOVE ] = "remove"; map shorts; shorts["-?"] = "-help"; @@ -803,6 +807,7 @@ int main(int argc,const char* argv[]) shorts["-s"] = "-delta"; shorts["-X"] = "-dryrun"; shorts["-a"] = "-ascii"; + shorts["-r"] = "-remove"; Options options ; options.help = sina(keywords[kwHELP ],argv) || argc < 2; @@ -811,6 +816,7 @@ int main(int argc,const char* argv[]) options.version = sina(keywords[kwVERSION],argv); options.dst = sina(keywords[kwDST ],argv); options.ascii = sina(keywords[kwASCII ],argv); + options.remove = sina(keywords[kwASCII ],argv); for ( int i = 1 ; !result && i < argc ; i++ ) { const char* arg = argv[i++]; @@ -831,6 +837,7 @@ int main(int argc,const char* argv[]) case kwDRYRUN : options.dryrun = true ; break; case kwVERBOSE : options.verbose = true ; break; case kwASCII : options.ascii = true ; break; + case kwREMOVE : options.remove = true ; break; case kwTZ : Position::tz_ = parseTZ(value);break; case kwADJUST : Position::adjust_ = ivalue;break; case kwDELTA : Position::deltaMax_ = ivalue;break; @@ -881,8 +888,8 @@ int main(int argc,const char* argv[]) s-= m*60 ; printf("tz,dst,adjust = %d,%d,%d total = %dsecs (= %d:%d:%d)\n",t,d,a,A,h,m,s); } -/* - if ( options.verbose ) { + + if ( options.verbose && gTimeDict.size() ) { printf("Time Dictionary\n"); for ( TimeDict_i it = gTimeDict.begin() ; it != gTimeDict.end() ; it++ ) { std::string sTime = getExifTime(it->first); @@ -894,7 +901,10 @@ int main(int argc,const char* argv[]) printf("%s %s\n",sTime.c_str(), sPos.c_str()); } } -*/ + + if ( !gTimeDict.size() && gFiles.size() && !options.remove ) { + printf("nothing in time dictionary!\n"); + } for ( size_t p = 0 ; p < gFiles.size() ; p++ ) { std::string path = gFiles[p] ; std::string stamp ; @@ -905,6 +915,20 @@ int main(int argc,const char* argv[]) if ( image.get() ) { image->readMetadata(); Exiv2::ExifData& exifData = image->exifData(); + + // if asked to remove, cycle the metadata and remove GPSInfo + // you can remove and geotag in the same run + // this is very useful when the TZ is incorrectly set to "clean" GPS before writing new data + if ( options.remove ) { + for (Exiv2::ExifData::iterator pos = exifData.begin(); pos != exifData.end(); ++pos) { + if ( pos->groupName() == "GPSInfo" ) { + if ( options.verbose ) { + std::cout << "remove: " << pos->key() << std::endl; + } + if ( !options.dryrun ) exifData.erase(pos); + } + } + } if ( pPos ) { exifData["Exif.GPSInfo.GPSProcessingMethod" ] = "charset=Ascii HYBRID-FIX"; exifData["Exif.GPSInfo.GPSVersionID" ] = "2 2 0 0"; @@ -924,7 +948,9 @@ int main(int argc,const char* argv[]) printf("%s %s % 2d\n",path.c_str(),pPos->toString().c_str(),pPos->delta()); } else { - printf("%s *** not in time dict ***\n",path.c_str()); + if ( gTimeDict.size() ) { + printf("%s *** not in time dict ***\n",path.c_str()); + } } if ( !options.dryrun ) image->writeMetadata(); } From 4da0a57ec00ddf2c8e045def1ba14af49821b5cf Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 12:17:04 +0100 Subject: [PATCH 03/19] Fixing reference output from test/geotag-test.sh --- test/data/geotag-test.out | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/data/geotag-test.out b/test/data/geotag-test.out index 0d49855cbc..56af4b3978 100644 --- a/test/data/geotag-test.out +++ b/test/data/geotag-test.out @@ -23,5 +23,5 @@ Exif.GPSInfo.GPSAltitudeRef Byte 1 Below sea level Exif.GPSInfo.GPSAltitude Rational 1 14.3 m Exif.GPSInfo.GPSTimeStamp Rational 3 09:54:28 Exif.GPSInfo.GPSMapDatum Ascii 7 WGS-84 -Exif.GPSInfo.GPSProcessingMethod Undefined 58 65 83 67 73 73 0 0 0 72 89 66 82 73 68 45 70 73 88 +Exif.GPSInfo.GPSProcessingMethod Undefined 18 HYBRID-FIX Exif.GPSInfo.GPSDateStamp Ascii 20 2008:05:08 09:54:28 From 63a13e8620feb8831a016beff1ac9e9b825ae4f1 Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 12:21:21 +0100 Subject: [PATCH 04/19] Adding option -DEXIV2_BUILD_USE_C++11 --- CMakeLists.txt | 4 ++-- cmake/compilerFlags.cmake | 13 ++++++++----- cmake/printSummary.cmake | 3 +++ include/exiv2/config.h | 10 ++++++++++ samples/CMakeLists.txt | 1 - src/CMakeLists.txt | 4 ---- src/basicio.cpp | 1 - unitTests/CMakeLists.txt | 1 - 8 files changed, 23 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f8cb8a4e39..99e694a473 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,6 @@ project(exiv2 # use TWEAK to categorize the build # 0.27.3.19 = RC1 Not for release LANGUAGES CXX C ) - include(cmake/mainSetup.cmake REQUIRED) # options and their default values @@ -29,8 +28,9 @@ option( EXIV2_ENABLE_SSH "USE Libssh for SshIo (WEBREADY)" option( EXIV2_BUILD_SAMPLES "Build sample applications" ON ) option( EXIV2_BUILD_EXIV2_COMMAND "Build exiv2 command-line executable" ON ) -option( EXIV2_BUILD_UNIT_TESTS "Build unit tests" OFF ) +option( EXIV2_BUILD_UNIT_TESTS "Build unit tests" ON ) option( EXIV2_BUILD_DOC "Add 'doc' target to generate documentation" OFF ) +option( EXIV2_BUILD_USE_C++11 "Use the C++11 compiler" OFF ) # Only intended to be used by Exiv2 developers/contributors option( EXIV2_TEAM_EXTRA_WARNINGS "Add more sanity checks using compiler flags" OFF ) diff --git a/cmake/compilerFlags.cmake b/cmake/compilerFlags.cmake index e2a15abb0e..9a0f4565e9 100644 --- a/cmake/compilerFlags.cmake +++ b/cmake/compilerFlags.cmake @@ -1,5 +1,9 @@ # These flags applies to exiv2lib, the applications, and to the xmp code +if ( EXIV2_BUILD_USE_C++11 ) + set(CMAKE_CXX_STANDARD 11) +endif() + if ( MINGW OR UNIX OR MSYS ) # MINGW, Linux, APPLE, CYGWIN if (${CMAKE_CXX_COMPILER_ID} STREQUAL GNU) set(COMPILER_IS_GCC ON) @@ -22,10 +26,6 @@ if ( MINGW OR UNIX OR MSYS ) # MINGW, Linux, APPLE, CYGWIN if (COMPILER_IS_GCC OR COMPILER_IS_CLANG) - # On Solaris target_compile_features(${application} PRIVATE cxx_std_98) fails to set this flag - if ( CMAKE_HOST_SOLARIS ) - add_compile_options(-std=gnu++98) - endif() # This fails under Fedora, MinGW GCC 8.3.0 and CYGWIN/MSYS 9.3.0 if (NOT (MINGW OR CMAKE_HOST_SOLARIS OR CYGWIN OR MSYS) ) @@ -58,7 +58,6 @@ if ( MINGW OR UNIX OR MSYS ) # MINGW, Linux, APPLE, CYGWIN # This seems to be causing issues in the Fedora_MinGW GitLab job #add_compile_options(-fasynchronous-unwind-tables) - if ( EXIV2_TEAM_USE_SANITIZERS ) # ASAN is available in gcc from 4.8 and UBSAN from 4.9 # ASAN is available in clang from 3.1 and UBSAN from 3.3 @@ -90,6 +89,10 @@ if ( MINGW OR UNIX OR MSYS ) # MINGW, Linux, APPLE, CYGWIN endif() endif() endif() + if ( EXIV2_BUILD_USE_C++11 ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated") + endif() endif () # http://stackoverflow.com/questions/10113017/setting-the-msvc-runtime-in-cmake diff --git a/cmake/printSummary.cmake b/cmake/printSummary.cmake index fefd709bcc..b3e804bd56 100644 --- a/cmake/printSummary.cmake +++ b/cmake/printSummary.cmake @@ -49,6 +49,9 @@ if ( EXIV2_ENABLE_EXTERNAL_XMP ) else() OptionOutput( "XMP metadata support: " EXIV2_ENABLE_XMP ) endif() +if ( EXIV2_BUILD_USE_C++11 ) + OptionOutput("Use C++11: " EXIV2_BUILD_USE_C++11 ) +endif() OptionOutput( "Native language support: " EXIV2_ENABLE_NLS ) OptionOutput( "Conversion of Windows XP tags: " EXIV2_ENABLE_PRINTUCS2 ) OptionOutput( "Nikon lens database: " EXIV2_ENABLE_LENSDATA ) diff --git a/include/exiv2/config.h b/include/exiv2/config.h index b31ceb1f26..f98896d359 100644 --- a/include/exiv2/config.h +++ b/include/exiv2/config.h @@ -93,5 +93,15 @@ typedef int pid_t; #endif ////////////////////////////////////// +// https://softwareengineering.stackexchange.com/questions/291141/how-to-handle-design-changes-for-auto-ptr-deprecation-in-c11 +#if __cplusplus >= 201103L + #include + #include + #include + template + using auto_ptr = std::unique_ptr; +#else + using std::auto_ptr; +#endif #endif // _CONFIG_H_ diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index f7c3e2a33b..7628110dc6 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -120,7 +120,6 @@ list(APPEND APPLICATIONS remotetest) # ****************************************************************************** foreach(application ${APPLICATIONS}) target_link_libraries(${application} PRIVATE exiv2lib) - target_compile_features(${application} PRIVATE cxx_std_98) if( EXIV2_ENABLE_PNG ) target_link_libraries( ${application} PRIVATE ${ZLIB_LIBRARIES} ) endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 29bbf50ead..279b22a729 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -91,10 +91,6 @@ generate_export_header(exiv2lib STATIC_DEFINE exiv2lib_STATIC ) -target_compile_features(exiv2lib_int PRIVATE cxx_std_98) -target_compile_features(exiv2lib PRIVATE cxx_std_98) - - # Conditional addition of sources to library targets # --------------------------------------------------------- diff --git a/src/basicio.cpp b/src/basicio.cpp index f4223f74ea..bd6dba0055 100644 --- a/src/basicio.cpp +++ b/src/basicio.cpp @@ -80,7 +80,6 @@ typedef short nlink_t; // ***************************************************************************** // class member definitions namespace Exiv2 { - BasicIo::~BasicIo() { } diff --git a/unitTests/CMakeLists.txt b/unitTests/CMakeLists.txt index 7e246a446e..5c74100b6b 100644 --- a/unitTests/CMakeLists.txt +++ b/unitTests/CMakeLists.txt @@ -42,7 +42,6 @@ target_compile_definitions(unit_tests exiv2lib_STATIC TESTDATA_PATH="${PROJECT_SOURCE_DIR}/test/data" ) -target_compile_features(unit_tests PRIVATE cxx_std_98) if (exiv2lib_COMPILE_DEFINITIONS) target_compile_definitions(unit_tests PRIVATE ${exiv2lib_COMPILE_DEFINITIONS}) From cd5c3e4ff9d157ea3d34f65e7279cba2b38698ee Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 12:47:24 +0100 Subject: [PATCH 05/19] Remove target_compile_features(exiv2 PRIVATE cxx_std_98) from src/exiv2 --- src/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 279b22a729..7809863ed0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -252,7 +252,6 @@ if(EXIV2_BUILD_EXIV2_COMMAND) getopt.cpp getopt.hpp utils.cpp utils.hpp ) - target_compile_features(exiv2 PRIVATE cxx_std_98) set_target_properties( exiv2 PROPERTIES COMPILE_FLAGS ${EXTRA_COMPILE_FLAGS} From e0f65f7e759a4cdb5d6d3db13a466106157a8c79 Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 13:06:19 +0100 Subject: [PATCH 06/19] Always include before discussing auto_ptr --- include/exiv2/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/exiv2/config.h b/include/exiv2/config.h index f98896d359..3255d3d5f7 100644 --- a/include/exiv2/config.h +++ b/include/exiv2/config.h @@ -94,8 +94,8 @@ typedef int pid_t; ////////////////////////////////////// // https://softwareengineering.stackexchange.com/questions/291141/how-to-handle-design-changes-for-auto-ptr-deprecation-in-c11 +#include #if __cplusplus >= 201103L - #include #include #include template From 65dde52cf963538ae94a554983ccb894db140962 Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 14:22:44 +0100 Subject: [PATCH 07/19] Updated documentation. Removed -DEXIV2_BUILD_USE_C++11 --- README.md | 21 ++++++++++++++++++++- cmake/compilerFlags.cmake | 13 +++++-------- cmake/printSummary.cmake | 3 --- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c9676ac802..ad6f9bf070 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ 14. [Thread Safety](#2-14) 15. [Library Initialisation and Cleanup](#2-15) 16. [Cross Platform Build and Test on Linux for MinGW](#2-16) + 17. [Building with C++11 and other compilers](#2-17) 3. [License and Support](#3) 1. [License](#3-1) 2. [Support](#3-2) @@ -696,6 +697,24 @@ You will find that 3 tests fail at the end of the test suite. It is safe to ign [TOC](#TOC) +
+ +### 2.17 Building with C++11 and other compilers + +Exiv2 uses the default compiler for your system. Exiv2 v0.27 was written to the C++ 1998 standard and will compile with C++11 and C++14. As auto_ptr support is no longer in C++17, you cannot build with that system. Exiv2 v0.28 and later do not use auto_ptr and are fully supported with all compilers. + +To generate a build with C++11: + +```bash +$ cd +$ mkdir build ; cd build +$ cmake .. -DCMAKE_CXX_STANDARD=11 -DCMAKE_CXX_FLAGS=-Wno-deprecated +``` + +The option -DCMAKE\_CXX\_FLAGS=-Wno-deprecated suppresses warnings from C++11 concerning auto_ptr which is deprecated. + +[TOC](#TOC) +
## 3 License and Support @@ -1167,4 +1186,4 @@ $ sudo pkg install developer/gcc-7 [TOC](#TOC) -Written by Robin Mills
robin@clanmills.com
Updated: 2020-04-21 +Written by Robin Mills
robin@clanmills.com
Updated: 2020-05-02 diff --git a/cmake/compilerFlags.cmake b/cmake/compilerFlags.cmake index 9a0f4565e9..e2a15abb0e 100644 --- a/cmake/compilerFlags.cmake +++ b/cmake/compilerFlags.cmake @@ -1,9 +1,5 @@ # These flags applies to exiv2lib, the applications, and to the xmp code -if ( EXIV2_BUILD_USE_C++11 ) - set(CMAKE_CXX_STANDARD 11) -endif() - if ( MINGW OR UNIX OR MSYS ) # MINGW, Linux, APPLE, CYGWIN if (${CMAKE_CXX_COMPILER_ID} STREQUAL GNU) set(COMPILER_IS_GCC ON) @@ -26,6 +22,10 @@ if ( MINGW OR UNIX OR MSYS ) # MINGW, Linux, APPLE, CYGWIN if (COMPILER_IS_GCC OR COMPILER_IS_CLANG) + # On Solaris target_compile_features(${application} PRIVATE cxx_std_98) fails to set this flag + if ( CMAKE_HOST_SOLARIS ) + add_compile_options(-std=gnu++98) + endif() # This fails under Fedora, MinGW GCC 8.3.0 and CYGWIN/MSYS 9.3.0 if (NOT (MINGW OR CMAKE_HOST_SOLARIS OR CYGWIN OR MSYS) ) @@ -58,6 +58,7 @@ if ( MINGW OR UNIX OR MSYS ) # MINGW, Linux, APPLE, CYGWIN # This seems to be causing issues in the Fedora_MinGW GitLab job #add_compile_options(-fasynchronous-unwind-tables) + if ( EXIV2_TEAM_USE_SANITIZERS ) # ASAN is available in gcc from 4.8 and UBSAN from 4.9 # ASAN is available in clang from 3.1 and UBSAN from 3.3 @@ -89,10 +90,6 @@ if ( MINGW OR UNIX OR MSYS ) # MINGW, Linux, APPLE, CYGWIN endif() endif() endif() - if ( EXIV2_BUILD_USE_C++11 ) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated") - endif() endif () # http://stackoverflow.com/questions/10113017/setting-the-msvc-runtime-in-cmake diff --git a/cmake/printSummary.cmake b/cmake/printSummary.cmake index b3e804bd56..fefd709bcc 100644 --- a/cmake/printSummary.cmake +++ b/cmake/printSummary.cmake @@ -49,9 +49,6 @@ if ( EXIV2_ENABLE_EXTERNAL_XMP ) else() OptionOutput( "XMP metadata support: " EXIV2_ENABLE_XMP ) endif() -if ( EXIV2_BUILD_USE_C++11 ) - OptionOutput("Use C++11: " EXIV2_BUILD_USE_C++11 ) -endif() OptionOutput( "Native language support: " EXIV2_ENABLE_NLS ) OptionOutput( "Conversion of Windows XP tags: " EXIV2_ENABLE_PRINTUCS2 ) OptionOutput( "Nikon lens database: " EXIV2_ENABLE_LENSDATA ) From c423b91b9228e42d95f0715a89b0a097f660ce04 Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 14:41:03 +0100 Subject: [PATCH 08/19] Change config.h to compile isatty() and getpid() on macOS when -DCMAKE_CXX_STANDARD=98 --- include/exiv2/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/exiv2/config.h b/include/exiv2/config.h index 3255d3d5f7..6d861e8f0b 100644 --- a/include/exiv2/config.h +++ b/include/exiv2/config.h @@ -95,9 +95,9 @@ typedef int pid_t; // https://softwareengineering.stackexchange.com/questions/291141/how-to-handle-design-changes-for-auto-ptr-deprecation-in-c11 #include +#include +#include #if __cplusplus >= 201103L - #include - #include template using auto_ptr = std::unique_ptr; #else From 3ebfee1c397e924f52d19f3994d553e684635ca9 Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 14:48:22 +0100 Subject: [PATCH 09/19] Fix auto_ptr to auto\_ptr --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ad6f9bf070..6e9c8a88e5 100644 --- a/README.md +++ b/README.md @@ -701,7 +701,7 @@ You will find that 3 tests fail at the end of the test suite. It is safe to ign ### 2.17 Building with C++11 and other compilers -Exiv2 uses the default compiler for your system. Exiv2 v0.27 was written to the C++ 1998 standard and will compile with C++11 and C++14. As auto_ptr support is no longer in C++17, you cannot build with that system. Exiv2 v0.28 and later do not use auto_ptr and are fully supported with all compilers. +Exiv2 uses the default compiler for your system. Exiv2 v0.27 was written to the C++ 1998 standard and will compile with C++11 and C++14. As _auto\_ptr support is no longer in C++17, you cannot build with that system._ Exiv2 v0.28 and later do not use auto\_ptr and are fully supported with all compilers. To generate a build with C++11: @@ -709,9 +709,10 @@ To generate a build with C++11: $ cd $ mkdir build ; cd build $ cmake .. -DCMAKE_CXX_STANDARD=11 -DCMAKE_CXX_FLAGS=-Wno-deprecated +$ make ``` -The option -DCMAKE\_CXX\_FLAGS=-Wno-deprecated suppresses warnings from C++11 concerning auto_ptr which is deprecated. +The option -DCMAKE\_CXX\_FLAGS=-Wno-deprecated suppresses warnings from C++11 concerning auto\_ptr which is deprecated. [TOC](#TOC) From b22d1de8b19660e66f8e792eee018ff0723638ea Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 15:11:30 +0100 Subject: [PATCH 10/19] Remove add_compile_options(-std=gnu++98) --- cmake/compilerFlags.cmake | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmake/compilerFlags.cmake b/cmake/compilerFlags.cmake index e2a15abb0e..f20187812c 100644 --- a/cmake/compilerFlags.cmake +++ b/cmake/compilerFlags.cmake @@ -22,10 +22,6 @@ if ( MINGW OR UNIX OR MSYS ) # MINGW, Linux, APPLE, CYGWIN if (COMPILER_IS_GCC OR COMPILER_IS_CLANG) - # On Solaris target_compile_features(${application} PRIVATE cxx_std_98) fails to set this flag - if ( CMAKE_HOST_SOLARIS ) - add_compile_options(-std=gnu++98) - endif() # This fails under Fedora, MinGW GCC 8.3.0 and CYGWIN/MSYS 9.3.0 if (NOT (MINGW OR CMAKE_HOST_SOLARIS OR CYGWIN OR MSYS) ) From 7928c637962b684cdbee45afa19cf2d0dfeecaeb Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 16:48:21 +0100 Subject: [PATCH 11/19] Documentation polishing. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6e9c8a88e5..d8dbb5c6e0 100644 --- a/README.md +++ b/README.md @@ -701,7 +701,7 @@ You will find that 3 tests fail at the end of the test suite. It is safe to ign ### 2.17 Building with C++11 and other compilers -Exiv2 uses the default compiler for your system. Exiv2 v0.27 was written to the C++ 1998 standard and will compile with C++11 and C++14. As _auto\_ptr support is no longer in C++17, you cannot build with that system._ Exiv2 v0.28 and later do not use auto\_ptr and are fully supported with all compilers. +Exiv2 uses the default compiler for your system. Exiv2 v0.27 was written to the C++ 1998 standard and uses auto\_ptr. The C++11 and C++14 compilers will issue deprecation warnings about auto\_ptr. As _auto\_ptr support has been removed from C++17, you cannot build Exiv2 v0.27 build with C++17 or later compilers._ Exiv2 v0.28 and later do not use auto\_ptr and will build with all compilers. To generate a build with C++11: @@ -712,7 +712,7 @@ $ cmake .. -DCMAKE_CXX_STANDARD=11 -DCMAKE_CXX_FLAGS=-Wno-deprecated $ make ``` -The option -DCMAKE\_CXX\_FLAGS=-Wno-deprecated suppresses warnings from C++11 concerning auto\_ptr which is deprecated. +The option -DCMAKE\_CXX\_FLAGS=-Wno-deprecated suppresses warnings from C++11 concerning auto\_ptr and other deprecated features. [TOC](#TOC) From 0a06dc9ee4e67654fda973760c9e04a6f34369ea Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 16:50:21 +0100 Subject: [PATCH 12/19] Issue identified in #1101 master/MinGW/Qt. Apply the change here (although this is working on 0.27-maintenance) --- src/futils.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/futils.cpp b/src/futils.cpp index 5da1a0b10a..67c910acef 100644 --- a/src/futils.cpp +++ b/src/futils.cpp @@ -62,6 +62,9 @@ #include #endif +#ifndef _MAX_PATH +#define _MAX_PATH 1024 +#endif namespace Exiv2 { const char* ENVARDEF[] = {"/exiv2.php", "40"}; //!< @brief default URL for http exiv2 handler and time-out From 40602989eb6df716ef3683101651eed31442ee65 Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 17:15:24 +0100 Subject: [PATCH 13/19] Print summary to report compiler and c++ standard. --- cmake/printSummary.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/printSummary.cmake b/cmake/printSummary.cmake index fefd709bcc..0e98fccd2a 100644 --- a/cmake/printSummary.cmake +++ b/cmake/printSummary.cmake @@ -21,6 +21,8 @@ message( STATUS "--------------------------------------------------------------- message( STATUS "CMake Generator: ${CMAKE_GENERATOR}" ) message( STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}" ) message( STATUS "Compiler info: ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) ; version: ${CMAKE_CXX_COMPILER_VERSION}") +message( STATUS "CMAKE_CXX_COMPILER:${CMAKE_CXX_COMPILER}" ) +message( STATUS "CMAKE_CXX_STANDARD:${CMAKE_CXX_STANDARD}" ) message( STATUS " --- Compiler flags --- ") message( STATUS "General: ${CMAKE_CXX_FLAGS}" ) printList("${COMPILER_OPTIONS}") From da91f04692565044f71b0552d2e9c4993ef1f08e Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 17:32:01 +0100 Subject: [PATCH 14/19] Don't report CMAKE_CXX_COMPILER - it's on the previous line of output. --- cmake/printSummary.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/printSummary.cmake b/cmake/printSummary.cmake index 0e98fccd2a..15d8a1b93b 100644 --- a/cmake/printSummary.cmake +++ b/cmake/printSummary.cmake @@ -21,7 +21,6 @@ message( STATUS "--------------------------------------------------------------- message( STATUS "CMake Generator: ${CMAKE_GENERATOR}" ) message( STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}" ) message( STATUS "Compiler info: ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) ; version: ${CMAKE_CXX_COMPILER_VERSION}") -message( STATUS "CMAKE_CXX_COMPILER:${CMAKE_CXX_COMPILER}" ) message( STATUS "CMAKE_CXX_STANDARD:${CMAKE_CXX_STANDARD}" ) message( STATUS " --- Compiler flags --- ") message( STATUS "General: ${CMAKE_CXX_FLAGS}" ) From f1182b8d73acfc187a483e7d5375bd1b5341c99b Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 17:37:03 +0100 Subject: [PATCH 15/19] Only #include when C++ >= C++11 --- include/exiv2/config.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/include/exiv2/config.h b/include/exiv2/config.h index 6d861e8f0b..2dddcae875 100644 --- a/include/exiv2/config.h +++ b/include/exiv2/config.h @@ -94,14 +94,12 @@ typedef int pid_t; ////////////////////////////////////// // https://softwareengineering.stackexchange.com/questions/291141/how-to-handle-design-changes-for-auto-ptr-deprecation-in-c11 -#include -#include -#include #if __cplusplus >= 201103L + #include + #include + #include template using auto_ptr = std::unique_ptr; -#else - using std::auto_ptr; #endif #endif // _CONFIG_H_ From 9b3f47f9a9027f504b4a184abd841e6dde095ff9 Mon Sep 17 00:00:00 2001 From: clanmills Date: Sat, 2 May 2020 18:29:52 +0100 Subject: [PATCH 16/19] Fixing a typo in the documentation. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d8dbb5c6e0..874c0eee88 100644 --- a/README.md +++ b/README.md @@ -701,7 +701,7 @@ You will find that 3 tests fail at the end of the test suite. It is safe to ign ### 2.17 Building with C++11 and other compilers -Exiv2 uses the default compiler for your system. Exiv2 v0.27 was written to the C++ 1998 standard and uses auto\_ptr. The C++11 and C++14 compilers will issue deprecation warnings about auto\_ptr. As _auto\_ptr support has been removed from C++17, you cannot build Exiv2 v0.27 build with C++17 or later compilers._ Exiv2 v0.28 and later do not use auto\_ptr and will build with all compilers. +Exiv2 uses the default compiler for your system. Exiv2 v0.27 was written to the C++ 1998 standard and uses auto\_ptr. The C++11 and C++14 compilers will issue deprecation warnings about auto\_ptr. As _auto\_ptr support has been removed from C++17, you cannot build Exiv2 v0.27 with C++17 or later compilers._ Exiv2 v0.28 and later do not use auto\_ptr and will build with all compilers. To generate a build with C++11: From f775676e00bd2384a9906aa26fa087e3cf2267e0 Mon Sep 17 00:00:00 2001 From: Robin Mills Date: Sat, 2 May 2020 18:32:29 +0100 Subject: [PATCH 17/19] Delete geotag-test.out --- test/data/geotag-test.out | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 test/data/geotag-test.out diff --git a/test/data/geotag-test.out b/test/data/geotag-test.out deleted file mode 100644 index 56af4b3978..0000000000 --- a/test/data/geotag-test.out +++ /dev/null @@ -1,27 +0,0 @@ ---- show GPSInfo tags --- -Exif.GPSInfo.GPSVersionID Byte 4 2.2.0.0 -Exif.GPSInfo.GPSLatitudeRef Ascii 2 North -Exif.GPSInfo.GPSLatitude Rational 3 36deg 26' 54" -Exif.GPSInfo.GPSLongitudeRef Ascii 2 West -Exif.GPSInfo.GPSLongitude Rational 3 116deg 51' 18" -Exif.GPSInfo.GPSAltitudeRef Byte 1 Below sea level -Exif.GPSInfo.GPSAltitude Rational 1 14.3 m -Exif.GPSInfo.GPSTimeStamp Rational 3 09:54:28 -Exif.GPSInfo.GPSMapDatum Ascii 7 WGS-84 -Exif.GPSInfo.GPSProcessingMethod Undefined 18 HYBRID-FIX -Exif.GPSInfo.GPSDateStamp Ascii 20 2008:05:08 09:54:28 ---- deleting the GPSInfo tags ---- run geotag --- -116deg51'18"W 036deg26'54"N -14.282 -3 ---- show GPSInfo tags --- -Exif.GPSInfo.GPSVersionID Byte 4 2.2.0.0 -Exif.GPSInfo.GPSLatitudeRef Ascii 2 North -Exif.GPSInfo.GPSLatitude Rational 3 36deg 26' 54" -Exif.GPSInfo.GPSLongitudeRef Ascii 2 West -Exif.GPSInfo.GPSLongitude Rational 3 116deg 51' 18" -Exif.GPSInfo.GPSAltitudeRef Byte 1 Below sea level -Exif.GPSInfo.GPSAltitude Rational 1 14.3 m -Exif.GPSInfo.GPSTimeStamp Rational 3 09:54:28 -Exif.GPSInfo.GPSMapDatum Ascii 7 WGS-84 -Exif.GPSInfo.GPSProcessingMethod Undefined 18 HYBRID-FIX -Exif.GPSInfo.GPSDateStamp Ascii 20 2008:05:08 09:54:28 From cd9ee99567a6458cd6b5bb250dd180edde9504ca Mon Sep 17 00:00:00 2001 From: Robin Mills Date: Sat, 2 May 2020 18:33:10 +0100 Subject: [PATCH 18/19] Delete geotag.cpp --- samples/geotag.cpp | 965 --------------------------------------------- 1 file changed, 965 deletions(-) delete mode 100644 samples/geotag.cpp diff --git a/samples/geotag.cpp b/samples/geotag.cpp deleted file mode 100644 index 0e806d3554..0000000000 --- a/samples/geotag.cpp +++ /dev/null @@ -1,965 +0,0 @@ -// ***************************************************************** -*- C++ -*- -// geotag.cpp -// Sample program to read gpx files and update images with GPS tags - -// g++ geotag.cpp -o geotag -lexiv2 -lexpat - -#include -#include "unused.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#if defined(__MINGW32__) || defined(__MINGW64__) -# ifndef __MINGW__ -# define __MINGW__ -# endif -#endif - -using namespace std; - -#ifndef lengthof -#define lengthof(x) (sizeof(*x)/sizeof(x)) -#endif - -#if defined(_MSC_VER) || defined(__MINGW__) -#include -char* realpath(const char* file,char* path); -#define lstat _stat -#define stat _stat -#if _MSC_VER < 1400 -#define strcpy_s(d,l,s) strcpy(d,s) -#define strcat_s(d,l,s) strcat(d,s) -#endif -#endif - -#if ! defined(_MSC_VER) -#include -#include -#include -#define stricmp strcasecmp -#endif - -#ifndef _MAX_PATH -#define _MAX_PATH 1024 -#endif - -// prototypes -class Options; -int getFileType(const char* path ,Options& options); -int getFileType(std::string& path,Options& options); - -string getExifTime(const time_t t); -time_t parseTime(const char* ,bool bAdjust=false); -int timeZoneAdjust(); - -// platform specific code -#if defined(_MSC_VER) || defined(__MINGW__) -char* realpath(const char* file,char* path) -{ - char* result = (char*) malloc(_MAX_PATH); - if (result) GetFullPathName(file,_MAX_PATH,result,NULL); - return result ; - UNUSED(path); -} -#endif - -// Command-line parser -class Options { -public: - bool verbose; - bool help; - bool version; - bool dst; - bool dryrun; - bool ascii; - bool remove; - - Options() - { - verbose = false; - help = false; - version = false; - dst = false; - dryrun = false; - ascii = false; - remove = false; - } - - virtual ~Options() {} ; -} ; - -enum -{ resultOK=0 -, resultSyntaxError -, resultSelectFailed -}; - -enum // keyword indices -{ kwHELP = 0 -, kwVERSION -, kwDST -, kwDRYRUN -, kwASCII -, kwREMOVE -, kwVERBOSE -, kwADJUST -, kwTZ -, kwDELTA -, kwMAX // manages keyword array -, kwNEEDVALUE // bogus keywords for error reporting -, kwSYNTAX // -- ditto -- -, kwNOVALUE = -kwVERBOSE // keywords <= kwNOVALUE are flags (no value needed) -}; - -// file types supported -enum -{ typeUnknown = 0 -, typeDirectory = 1 -, typeImage = 2 -, typeXML = 3 -, typeFile = 4 -, typeDoc = 5 -, typeCode = 6 -, typeMax = 7 -}; - -// forward declaration -class Position; - -// globals -typedef std::map TimeDict_t; -typedef std::map::iterator TimeDict_i; -typedef std::vector strings_t; -const char* gDeg = NULL ; // string "°" or "deg" -TimeDict_t gTimeDict ; -strings_t gFiles; - -// Position (from gpx file) -class Position -{ -public: - Position(time_t time, double lat, double lon, double ele) : - time_(time) - , lon_(lon) - , lat_(lat) - , ele_(ele) - , delta_(0) - {} - - Position(): - time_(0) - , lon_(0.0) - , lat_(0.0) - , ele_(0.0) - , delta_(0) - { } - - virtual ~Position() {} -// copy constructor - Position(const Position& o) : - time_(o.time_) - , lon_(o.lon_) - , lat_(o.lat_) - , ele_(o.ele_) - , delta_(o.delta_) - {} - -// instance methods - bool good() { return time_ || lon_ || lat_ || ele_ ; } - std::string getTimeString() { if ( times_.empty() ) times_ = getExifTime(time_) ; return times_; } - time_t getTime() { return time_ ; } - std::string toString(); - -// getters/setters - double lat() {return lat_ ;} - double lon() {return lon_ ;} - double ele() {return ele_ ;} - int delta() {return delta_ ;} - void delta(int delta) {delta_=delta ;} - -// data -private: - time_t time_; - double lon_ ; - double lat_ ; - double ele_ ; - std::string times_; - int delta_; - -// public static data -public: - static int adjust_ ; - static int tz_ ; - static int dst_ ; - static time_t deltaMax_; - -// public static member functions -public: - static int Adjust() {return Position::adjust_ + Position::tz_ + Position::dst_ ;} - static int tz() {return tz_ ;} - static int dst() {return dst_ ;} - static int adjust() {return adjust_;} - - static std::string toExifString(double d,bool bRational,bool bLat); - static std::string toExifString(double d); - static std::string toExifTimeStamp(std::string& t); -}; - -std::string Position::toExifTimeStamp(std::string& t) -{ - char result[200]; - const char* arg = t.c_str(); - int HH = 0 ; - int mm = 0 ; - int SS1 = 0 ; - if ( strstr(arg,":") || strstr(arg,"-") ) { - int YY,MM,DD ; - char a,b,c,d,e ; - sscanf(arg,"%d%c%d%c%d%c%d%c%d%c%d",&YY,&a,&MM,&b,&DD,&c,&HH,&d,&mm,&e,&SS1); - } - sprintf(result,"%d/1 %d/1 %d/1",HH,mm,SS1); - return std::string(result); -} - -std::string Position::toExifString(double d) -{ - char result[200]; - d *= 100; - sprintf(result,"%d/100",abs((int)d)); - return std::string(result); -} - -std::string Position::toExifString(double d,bool bRational,bool bLat) -{ - const char* NS = d>=0.0?"N":"S"; - const char* EW = d>=0.0?"E":"W"; - const char* NSEW = bLat ? NS: EW; - if ( d < 0 ) d = -d; - int deg = (int) d; - d -= deg; - d *= 60; - int min = (int) d ; - d -= min; - d *= 60; - int sec = (int)d; - char result[200]; - if ( bRational ) - sprintf(result,"%d/1 %d/1 %d/1" ,deg,min,sec); - else - sprintf(result,"%03d%s%02d'%02d\"%s" ,deg,gDeg,min,sec,NSEW); - return std::string(result); -} - -std::string Position::toString() -{ - char result[200]; - std::string sLat = Position::toExifString(lat_,false,true ); - std::string sLon = Position::toExifString(lon_,false,false); - sprintf(result,"%s %s %-8.3f",sLon.c_str(),sLat.c_str(),ele_); - return std::string(result); -} - -// defaults -int Position::adjust_ = 0; -int Position::tz_ = timeZoneAdjust(); -int Position::dst_ = 0; -time_t Position::deltaMax_ = 60 ; - -/////////////////////////////////////////////////////////// -// UserData - used by XML Parser -class UserData -{ -public: - explicit UserData(Options& options): - indent(0) - , count(0) - , nTrkpt(0) - , bTime(false) - , bEle(false) - , ele(0.0) - , lat(0.0) - , lon(0.0) - , options_(options) - {} - virtual ~UserData() {} - -// public data members - int indent; - size_t count ; - Position now ; - Position prev; - int nTrkpt; - bool bTime ; - bool bEle ; - double ele; - double lat; - double lon; - std::string xmlt; - std::string exift; - time_t time; - Options& options_; -// static public data memembers -}; - -// XML Parser Callbacks -static void startElement(void* userData, const char* name, const char** atts ) -{ - UserData* me = (UserData*) userData; - //for ( int i = 0 ; i < me->indent ; i++ ) printf(" "); - //printf("begin %s\n",name); - me->bTime = strcmp(name,"time")==0; - me->bEle = strcmp(name,"ele")==0; - - if ( strcmp(name,"trkpt")==0 ) { - me->nTrkpt++; - while ( *atts ) { - const char* a=atts[0]; - const char* v=atts[1]; - if ( !strcmp(a,"lat") ) me->lat = atof(v); - if ( !strcmp(a,"lon") ) me->lon = atof(v); - atts += 2 ; - } - } - me->count++ ; - me->indent++ ; -} - -static void endElement(void* userData, const char* name) -{ - UserData* me = (UserData*) userData; - me->indent-- ; - if ( strcmp(name,"trkpt")==0 ) { - - me->nTrkpt--; - me->now = Position(me->time,me->lat,me->lon,me->ele) ; - - if ( !me->prev.good() && me->options_.verbose ) { - printf("trkseg %s begin ",me->now.getTimeString().c_str()); - } - - // remember our location and put it in gTimeDict - gTimeDict[me->time] = me->now ; - me->prev = me->now ; - } - if ( strcmp(name,"trkseg")==0 && me->options_.verbose ) { - printf("%s end\n",me->now.getTimeString().c_str()); - } -} - -void charHandler(void* userData,const char* s,int len) -{ - UserData* me = (UserData*) userData; - - if ( me->nTrkpt == 1 ) { - char buffer[100]; - int l_max = 98 ; // lengthof(buffer) -2 ; - - if ( me->bTime && len > 5 ) { - if ( len < l_max ) { - memcpy(buffer,s,len); - buffer[len]=0; - char* b = buffer ; - while ( *b == ' ' && b < buffer+len ) b++ ; - me->xmlt = b ; - me->time = parseTime(me->xmlt.c_str()); - me->exift = getExifTime(me->time); - } - me->bTime=false; - } - if ( me->bEle && len > 2 ) { - if ( len < l_max ) { - memcpy(buffer,s,len); - buffer[len]=0; - char* b = buffer ; - while ( *b == ' ' && b < buffer+len ) b++ ; - me->ele = atof(b); - } - me->bEle=false; - } - } -} - -/////////////////////////////////////////////////////////// -// Time Functions -time_t parseTime(const char* arg,bool bAdjust) -{ - time_t result = 0 ; - try { - //559 rmills@rmills-imac:~/bin $ exiv2 -pa ~/R.jpg | grep -i date - //Exif.Image.DateTime Ascii 20 2009:08:03 08:58:57 - //Exif.Photo.DateTimeOriginal Ascii 20 2009:08:03 08:58:57 - //Exif.Photo.DateTimeDigitized Ascii 20 2009:08:03 08:58:57 - //Exif.GPSInfo.GPSDateStamp Ascii 21 2009-08-03T15:58:57Z - - // - - if ( strstr(arg,":") || strstr(arg,"-") ) { - int YY,MM,DD,HH,mm,SS1 ; - char a,b,c,d,e ; - sscanf(arg,"%d%c%d%c%d%c%d%c%d%c%d",&YY,&a,&MM,&b,&DD,&c,&HH,&d,&mm,&e,&SS1); - - struct tm T; - memset(&T,0,sizeof(T)); - T.tm_min = mm ; - T.tm_hour = HH ; - T.tm_sec = SS1 ; - if ( bAdjust ) T.tm_sec -= Position::Adjust(); - T.tm_year = YY -1900 ; - T.tm_mon = MM -1 ; - T.tm_mday = DD ; - T.tm_isdst = -1 ; // determine value automatically (otherwise hour may shift) - result = mktime(&T); - } - } catch ( ... ) {}; - return result ; -} - -// West of GMT is negative (PDT = Pacific Daylight = -07:00 == -25200 seconds -int timeZoneAdjust() -{ - time_t now = time(NULL); - int offset; - -#if defined(_MSC_VER) || defined(__MINGW__) - TIME_ZONE_INFORMATION TimeZoneInfo; - GetTimeZoneInformation( &TimeZoneInfo ); - offset = - (((int)TimeZoneInfo.Bias + (int)TimeZoneInfo.DaylightBias) * 60); - UNUSED(now); -#elif defined(__CYGWIN__) - struct tm lcopy = *localtime(&now); - time_t gmt = timegm(&lcopy) ; // timegm modifies lcopy - offset = (int) ( ((long signed int) gmt) - ((long signed int) now) ) ; -#elif defined(OS_SOLARIS) || defined(__sun__) - struct tm local = *localtime(&now) ; - time_t local_tt = (int) mktime(&local); - time_t time_gmt = (int) mktime(gmtime(&now)); - offset = time_gmt - local_tt; -#else - struct tm local = *localtime(&now) ; - offset = local.tm_gmtoff ; - -#if EXIV2_DEBUG_MESSAGES - struct tm utc = *gmtime(&now); - printf("utc : offset = %6d dst = %d time = %s", 0 ,utc .tm_isdst, asctime(&utc )); - printf("local: offset = %6d dst = %d time = %s", offset,local.tm_isdst, asctime(&local)); - printf("timeZoneAdjust = %6d\n",offset); -#endif -#endif - return offset ; -} - -string getExifTime(const time_t t) -{ - static char result[100]; - strftime(result,sizeof(result),"%Y-%m-%d %H:%M:%S",localtime(&t)); - return result ; -} - -std::string makePath(const std::string& dir, const std::string& file) -{ - return dir + std::string(EXV_SEPARATOR_STR) + file ; -} - -const char* makePath(const char* dir,const char* file) -{ - static char result[_MAX_PATH] ; - std::string r = makePath(std::string(dir),std::string(file)); - strcpy(result,r.c_str()); - return result; -} - -// file utilities -bool readDir(const char* path,Options& options) -{ - bool bResult = false; - -#ifdef _MSC_VER - DWORD attrs = GetFileAttributes(path); - bool bOKAttrs = attrs != INVALID_FILE_ATTRIBUTES; - bool bIsDir = (attrs & FILE_ATTRIBUTE_DIRECTORY) ? true : false ; - - if( bOKAttrs && bIsDir ) { - bResult = true ; - - char search[_MAX_PATH+10]; - strcpy_s(search,_MAX_PATH,path); - strcat_s(search,_MAX_PATH,"\\*"); - - WIN32_FIND_DATA ffd; - HANDLE hFind = FindFirstFile(search, &ffd); - BOOL bGo = hFind != INVALID_HANDLE_VALUE; - - if ( bGo ) { - while ( bGo ) { - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - // _tprintf(TEXT(" %s \n"), ffd.cFileName); - } - else - { - std::string pathName = makePath(path,std::string(ffd.cFileName)); - if ( getFileType(pathName,options) == typeImage ) { - gFiles.push_back( pathName ); - } - } - bGo = FindNextFile(hFind, &ffd) != 0; - } - // CloseHandle(hFind); - } - } -#else - DIR* dir = opendir (path); - if (dir != NULL) - { - bResult = true; - struct dirent* ent; - - // print all the files and directories within directory - while ((ent = readdir (dir)) != NULL) - { - std::string pathName = makePath(path,ent->d_name); - struct stat buf ; - lstat(path, &buf ); - if ( ent->d_name[0] != '.' ) { - - // printf("reading %s => %s\n",ent->d_name,pathName.c_str()); - if ( getFileType(pathName,options) == typeImage ) { - gFiles.push_back( pathName ); - } - } - } - closedir (dir); - } -#endif - return bResult ; -} - -inline size_t sip(FILE* f,char* buffer,size_t max_len,size_t len) -{ - while ( !feof(f) && len < max_len && buffer[len-1] != '>') - buffer[len++] = fgetc(f); - return len; -} - -bool readXML(const char* path,Options& options) -{ - FILE* f = fopen(path,"r"); - XML_Parser parser = XML_ParserCreate(NULL); - bool bResult = f && parser ; - if ( bResult ) { - char buffer[8*1024]; - UserData me(options) ; - - XML_SetUserData (parser, &me); - XML_SetElementHandler (parser, startElement, endElement); - XML_SetCharacterDataHandler(parser,charHandler); - - // a little sip at the data - size_t len = fread(buffer,1,sizeof(buffer)-100,f); - const char* lead = "readMetadata(); - ExifData &exifData = image->exifData(); - bResult = !exifData.empty(); - } - } catch ( ... ) {}; - return bResult ; -} - -time_t readImageTime(const std::string& path,std::string* pS=NULL) -{ - using namespace Exiv2; - - time_t result = 0 ; - - const char* dateStrings[] = - { "Exif.Photo.DateTimeOriginal" - , "Exif.Photo.DateTimeDigitized" - , "Exif.Image.DateTime" - , NULL - }; - const char* dateString = dateStrings[0] ; - - do { - try { - Image::AutoPtr image = ImageFactory::open(path); - if ( image.get() ) { - image->readMetadata(); - ExifData &exifData = image->exifData(); - // printf("%s => %s\n",dateString, exifData[dateString].toString().c_str()); - result = parseTime(exifData[dateString].toString().c_str(),true); - if ( result && pS ) *pS = exifData[dateString].toString(); - } - } catch ( ... ) {}; - } while ( !result && ++dateString ); - - return result ; -} - -bool sina(const char* s,const char** a) -{ - bool bResult = false ; - int i = 0 ; - while ( *s == '-' ) s++; - while ( !bResult && a[i]) { - const char* A = a[i] ; - while ( *A == '-' ) A++ ; - bResult = stricmp(s,A)==0; - i++; - } - return bResult; -} - -int readFile(const char* path,Options /* options */) -{ - FILE* f = fopen(path,"r"); - int nResult = f ? typeFile : typeUnknown; - if ( f ) { - const char* ext = strstr(path,"."); - if ( ext ) { - const char* docs[] = { ".doc",".txt", NULL }; - const char* code[] = { ".cpp",".h" ,".pl" ,".py" ,".pyc", NULL }; - if ( sina(ext,docs) ) - nResult = typeDoc; - if ( sina(ext,code) ) - nResult = typeCode; - } - } - if ( f ) fclose(f) ; - - return nResult ; -} - -Position* searchTimeDict(TimeDict_t& td, const time_t& time,long long delta) -{ - Position* result = NULL; - for ( int t = 0 ; !result && t < delta ; t++ ) { - for ( int x = 0 ; !result && x < 2 ; x++ ) { - int T = t * ((x==0)?-1:1); - if ( td.count(time+T) ) { - result = &td[time+T]; - result->delta(T); - } - } - } - return result; -} - -int getFileType(std::string& path,Options& options) { return getFileType(path.c_str(),options); } -int getFileType(const char* path,Options& options) -{ - return readXML (path,options) ? typeXML - : readDir (path,options) ? typeDirectory - : readImage(path,options) ? typeImage - : readFile (path,options) - ; -} - -int version(const char* program) -{ - printf("%s: %s %s\n",program,__DATE__,__TIME__); - return 0; -} - -int help(const char* program,char const* words[],int nWords,bool /*bVerbose*/) -{ - printf("usage: %s ",program); - for ( int i = 0 ; i < nWords ; i++ ) { - if ( words[i] ) - printf("%c-%s%s",i?'|':'{',words[i],i>(-kwNOVALUE)?" value":""); - } - printf("}+ path+\n"); - return 0; -} - -int compare(const char* a,const char* b) -{ - int result=*a && *b; - while ( result && *a && *b) { - char A=*a++; - char B=*b++; - result=tolower(A)==tolower(B); - } - return result; -} - -int find(const char* arg,char const* words[],int nWords) -{ - if ( arg[0] != '-' ) return kwSYNTAX; - - int result=0; - int count =0; - - for ( int i = 0 ; i < nWords ; i++) { - int j = 0 ; - while ( arg[j] == '-' ) j++; - if ( ::compare(arg+j,words[i]) ) { - result = i ; - count++; - } - } - - return count==1?result:kwSYNTAX; -} - -int parseTZ(const char* adjust) -{ - int h=0; - int m=0; - char c ; - try { - sscanf(adjust,"%d%c%d",&h,&c,&m); - } catch ( ... ) {} ; - - return (3600*h)+(60*m); -} - -bool mySort(const std::string& a, const std::string& b) -{ - time_t A = readImageTime(a); - time_t B = readImageTime(b); - return (A shorts; - shorts["-?"] = "-help"; - shorts["-h"] = "-help"; - shorts["-v"] = "-verbose"; - shorts["-V"] = "-version"; - shorts["-d"] = "-dst"; - shorts["-a"] = "-adjust"; - shorts["-t"] = "-tz"; - shorts["-D"] = "-delta"; - shorts["-s"] = "-delta"; - shorts["-X"] = "-dryrun"; - shorts["-a"] = "-ascii"; - shorts["-r"] = "-remove"; - - Options options ; - options.help = sina(keywords[kwHELP ],argv) || argc < 2; - options.verbose = sina(keywords[kwVERBOSE],argv); - options.dryrun = sina(keywords[kwDRYRUN ],argv); - options.version = sina(keywords[kwVERSION],argv); - options.dst = sina(keywords[kwDST ],argv); - options.ascii = sina(keywords[kwASCII ],argv); - options.remove = sina(keywords[kwASCII ],argv); - - for ( int i = 1 ; !result && i < argc ; i++ ) { - const char* arg = argv[i++]; - if ( shorts.count(arg) ) arg = shorts[arg].c_str(); - - const char* value = argv[i ]; - int ivalue = ::atoi(value?value:"0"); - int key = ::find(arg,keywords,kwMAX); - int needv = key < kwMAX && key > (-kwNOVALUE); - - if (!needv ) i--; - if ( needv && !value) key = kwNEEDVALUE; - - switch ( key ) { - case kwDST : options.dst = true ; break; - case kwHELP : options.help = true ; break; - case kwVERSION : options.version = true ; break; - case kwDRYRUN : options.dryrun = true ; break; - case kwVERBOSE : options.verbose = true ; break; - case kwASCII : options.ascii = true ; break; - case kwREMOVE : options.remove = true ; break; - case kwTZ : Position::tz_ = parseTZ(value);break; - case kwADJUST : Position::adjust_ = ivalue;break; - case kwDELTA : Position::deltaMax_ = ivalue;break; - case kwNEEDVALUE: fprintf(stderr,"error: %s requires a value\n",arg); result = resultSyntaxError ; break ; - case kwSYNTAX : default: - { - int type = getFileType(arg,options) ; - if ( options.verbose ) printf("%s %s ",arg,types[type]) ; - if ( type == typeImage ) { - time_t t = readImageTime(std::string(arg)) ; -#ifdef __APPLE__ - char buffer[1024]; -#else - char* buffer = NULL; -#endif - char* path = realpath(arg,buffer); - if ( t && path ) { - if ( options.verbose) printf("%s %ld %s",path,(long int)t,asctime(localtime(&t))); - gFiles.push_back(path); - } - if ( path && path != buffer ) ::free((void*) path); - } - if ( type == typeUnknown ) { - fprintf(stderr,"error: illegal syntax %s\n",arg); - result = resultSyntaxError ; - } - } break; - } - } - - if ( options.help ) ::help(program,keywords,kwMAX,options.verbose); - if ( options.version ) ::version(program); - gDeg = options.ascii ? "deg" : "°"; - - if ( !result ) { - sort(gFiles.begin(),gFiles.end(),mySort); - if ( options.dst ) Position::dst_ = 3600; - if ( options.verbose ) { - int t = Position::tz(); - int d = Position::dst(); - int a = Position::adjust(); - int A = Position::Adjust(); - int s = A ; - int h = s/3600; - s-= h*3600; - s = abs(s); - int m = s/60 ; - s-= m*60 ; - printf("tz,dst,adjust = %d,%d,%d total = %dsecs (= %d:%d:%d)\n",t,d,a,A,h,m,s); - } - - if ( options.verbose && gTimeDict.size() ) { - printf("Time Dictionary\n"); - for ( TimeDict_i it = gTimeDict.begin() ; it != gTimeDict.end() ; it++ ) { - std::string sTime = getExifTime(it->first); - Position* pPos = &it->second; - std::string sPos = Position::toExifString(pPos->lat(),false,true) - + " " - + Position::toExifString(pPos->lon(),false,true) - ; - printf("%s %s\n",sTime.c_str(), sPos.c_str()); - } - } - - if ( !gTimeDict.size() && gFiles.size() && !options.remove ) { - printf("nothing in time dictionary!\n"); - } - for ( size_t p = 0 ; p < gFiles.size() ; p++ ) { - std::string path = gFiles[p] ; - std::string stamp ; - try { - time_t t = readImageTime(path,&stamp) ; - Position* pPos = searchTimeDict(gTimeDict,t,Position::deltaMax_); - Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path); - if ( image.get() ) { - image->readMetadata(); - Exiv2::ExifData& exifData = image->exifData(); - - // if asked to remove, cycle the metadata and remove GPSInfo - // you can remove and geotag in the same run - // this is very useful when the TZ is incorrectly set to "clean" GPS before writing new data - if ( options.remove ) { - for (Exiv2::ExifData::iterator pos = exifData.begin(); pos != exifData.end(); ++pos) { - if ( pos->groupName() == "GPSInfo" ) { - if ( options.verbose ) { - std::cout << "remove: " << pos->key() << std::endl; - } - if ( !options.dryrun ) exifData.erase(pos); - } - } - } - if ( pPos ) { - exifData["Exif.GPSInfo.GPSProcessingMethod" ] = "charset=Ascii HYBRID-FIX"; - exifData["Exif.GPSInfo.GPSVersionID" ] = "2 2 0 0"; - exifData["Exif.GPSInfo.GPSMapDatum" ] = "WGS-84"; - - exifData["Exif.GPSInfo.GPSLatitude" ] = Position::toExifString(pPos->lat(),true,true); - exifData["Exif.GPSInfo.GPSLongitude" ] = Position::toExifString(pPos->lon(),true,false); - exifData["Exif.GPSInfo.GPSAltitude" ] = Position::toExifString(pPos->ele()); - - exifData["Exif.GPSInfo.GPSAltitudeRef" ] = pPos->ele()<0.0?"1":"0"; - exifData["Exif.GPSInfo.GPSLatitudeRef" ] = pPos->lat()>0?"N":"S"; - exifData["Exif.GPSInfo.GPSLongitudeRef" ] = pPos->lon()>0?"E":"W"; - - exifData["Exif.GPSInfo.GPSDateStamp" ] = stamp; - exifData["Exif.GPSInfo.GPSTimeStamp" ] = Position::toExifTimeStamp(stamp); - exifData["Exif.Image.GPSTag" ] = 4908; - - printf("%s %s % 2d\n",path.c_str(),pPos->toString().c_str(),pPos->delta()); - } else { - if ( gTimeDict.size() ) { - printf("%s *** not in time dict ***\n",path.c_str()); - } - } - if ( !options.dryrun ) image->writeMetadata(); - } - } catch ( ... ) {}; - } - } - - return result ; -} - -// That's all Folks! -//// From 9b6b4036d840d812a5d60a5e0bb91a2a79fe3a52 Mon Sep 17 00:00:00 2001 From: Robin Mills Date: Sat, 2 May 2020 18:33:51 +0100 Subject: [PATCH 19/19] Delete README-SAMPLES.md --- README-SAMPLES.md | 647 ---------------------------------------------- 1 file changed, 647 deletions(-) delete mode 100644 README-SAMPLES.md diff --git a/README-SAMPLES.md b/README-SAMPLES.md deleted file mode 100644 index 7b50d3de17..0000000000 --- a/README-SAMPLES.md +++ /dev/null @@ -1,647 +0,0 @@ -![Exiv2](exiv2.png) - -# Exiv2 Sample Applications - -Exiv2 is a C++ library and a command line utility to read, write, delete and modify Exif, IPTC, XMP and ICC image metadata. Exiv2 also features a collection of sample and test command-line programs. Please be aware that while the program _**exiv2**_ enjoys full support from Team Exiv2, the other programs have been written for test, documentation or development purposes. You are expected to read the code to discover the specification of programs other than _**exiv2**_. - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -### Sample Programs - -| Name | Purpose | More information | Code | -|:--- |:--- |:--- |:-- | -| _**addmoddel**_ | Demonstrates Exiv2 library APIs to add, modify or delete metadata | [addmoddel](#addmoddel) | [addmoddel.cpp](samples/addmoddel.cpp) | -| _**exifcomment**_ | Set Exif.Photo.UserComment in an image | [exifcomment](#exifcomment) | [exifcomment.cpp](samples/exifcomment.cpp) | -| _**exifdata**_ | Prints _**Exif**_ metadata in different formats in an image | [exifdata](#exifdata) | [exifdata.cpp](samples/exifdata.cpp) | -| _**exifprint**_ | Print _**Exif**_ metadata in images
Miscelleous other features | [exifprint](#exifprint)| [exifprint.cpp](samples/exifprint.cpp) | -| _**exifvalue**_ | Prints the value of a single _**Exif**_ tag in a file | [exifvalue](#exifvalue) | [exifvalue.cpp](samples/exifvalue.cpp) | -| _**exiv2**_ | Command line utility to read, write, delete and modify Exif, IPTC, XMP and ICC image metadata.
This is the primary test tool used by Team Exiv2 and can exercise almost all code in the library. Due to the extensive capability of this utility, the APIs used are usually less obvious for casual code inspection. | [https://exiv2.org/manpage.html](https://exiv2.org/manpage.html)
[https://exiv2.org/sample.html](https://exiv2.org/sample.html) | | -| _**exiv2json**_ | Extracts data from image in JSON format.
This program also contains a parser to recursively parse Xmp metadata into vectors and objects. | [exiv2json](#exiv2json) | [exiv2json.cpp](samples/exiv2json.cpp) | -| _**geotag**_ | Reads GPX data and updates images with GPS Tags | [geotag](#geotag) | [geotag.cpp](samples/geotag.cpp) | -| _**iptceasy**_ | Demonstrates read, set or modify IPTC metadata | [iptceasy](#iptceasy) | [iptceasy.cpp](samples/iptceasy.cpp) | -| _**iptcprint**_ | Demonstrates Exiv2 library APIs to print Iptc data | [iptceasy](#iptceasy) | [iptcprint.cpp](samples/iptcprint.cpp) | -| _**metacopy**_ | Demonstrates copying metadata from one image to another | [metacopy](#metacopy) | [metacopy.cpp](samples/metacopy.cpp) | -| _**mrwthumb**_ | Sample program to extract a Minolta thumbnail from the makernote | [mrwthumb](#mrwthumb) | [mrwthumb.cpp](samples/mrwthumb.cpp) | -| _**xmpparse**_ | Read an XMP packet from a file, parse it and print all (known) properties. | [xmpparse](#xmpparse) | [xmpparse.cpp](samples/xmpparse.cpp) | -| _**xmpprint**_ | Read an XMP from a file, parse it and print all (known) properties.. | [xmpprint](#xmpprint) | [xmpprint.cpp](samples/xmpprint.cpp) | -| _**xmpsample**_ | Demonstrates Exiv2 library high level XMP classes | [xmpsample](#xmpsample) | [xmpsample.cpp](samples/exmpsample.cpp) | - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -### Test Programs - -As Exiv2 is open source, we publish all our materials. Some of the following programs are actively used in our test harness. Some of the following programs were written during the development of features and their on-going use may be limited, or even obsolete. In general these programs are published as source and Team Exiv2 will not provide support to users. - -| Name | Kind | More information | -|:--- |:--- |:--- | -| _**conntest**_ | Test http/https/ftp/ssh/sftp connection | [conntest](#conntest) | -| _**convert-test**_ | Conversion test driver | [convert-test](#convert-test) | -| _**easyaccess-test**_ | Sample program using high-level metadata access functions | [easyaccess-test](#easyaccess-test) | -| _**getopt-test**_ | Sample program to test getopt() | [getopt-test](#getopt-test) | -| _**ini-test**_ | Shows simple usage of the INIReader class | [ini-test](#ini-test) | -| _**iotest**_ | Test programs for BasicIo functions. | [iotest](#iotest) | -| _**iptctest**_ | Sample program test Iptc reading and writing. | [iptctest](#iptctest) | -| _**key-test**_ | Key unit tests | [key-test](#key-test) | -| _**largeiptc-test**_ | Test for large (>65535 bytes) IPTC buffer | [largeiptc-test](#largeiptc-test) | -| _**mmap-test**_ | Simple mmap tests | [mmap-test](#mmap-test) | -| _**path-test**_ | Test path IO | [path-test](#path-test) | -| _**prevtest**_ | Test access to preview images | [prevtest](#prevtest) | -| _**remotetest**_ | Tester application for testing remote i/o. | [remotetest](#remotetest) | -| _**stringto-test**_ | Test conversions from string to long, float and Rational types. | [stringto-test](#stringto-test) | -| _**taglist**_ | Print a simple comma separated list of tags defined in Exiv2 | [taglist](#taglist) | -| _**tiff-test**_ | Simple TIFF write test | [tiff-test](#tiff-test) | -| _**werror-test**_ | Simple tests for the wide-string error class WError | [werror-test](#werror-test) | -| _**write-test**_ | ExifData write unit tests | [write-test](#write-test) | -| _**write2-test**_ | ExifData write unit tests for Exif data created from scratch | [write2-test](#write2-test) | -| _**xmpdump**_ | Sample program to dump the XMP packet of an image | [xmpdump](#xmpdump) | -| _**xmpparser-test**_ | Read an XMP packet from a file, parse and re-serialize it. | [xmpparser-test](#xmpparser-test) | - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -## 2 Sample Program Descriptions - -
- -#### addmoddel - -``` -Usage: addmoddel file -``` - -Demonstrates Exiv2 library APIs to add, modify or delete metadata. _Code: [addmoddel.cpp](samples/addmoddel.cpp)_ - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### exifcomment - -``` -Usage: exifcomment file -``` - -This is a simple program that demonstrates how to set _**Exif.Photo.UserComment**_ in an image. _Code: [exifcomment.cpp](samples/exifcomment.cpp)_ - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -### exifdata - -``` -Usage: exifdata file format -formats: csv | json | wolf | xml -``` - -This is a simple program to demonstrate dumping _**Exif**_ metadata in common formats. _Code: [exifdata.cpp](samples/exifdata.cpp)_ - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### exifprint - -``` -Usage: exifprint [ file | --version | --version-test ] -``` - -| Arguments | Description | -|:-- |:--- | -| file | Path to image | -| --version | Print version information from build | -| --version-test | Tests Exiv2 VERSION API | - -This program demonstrates how to print _**Exif**_ metadata in an image. This program is also discussed in the platform ReadMe.txt file included in a build bundle. The option **--version** was added enable the user to build a test application which dumps the build information. The option **--version-test** was added to test the macro EXIV2\_TEST\_VERSION() in **include/exiv2/version.hpp**. - -There is one other unique feature of this program. It is the only test/sample program which can use the EXV\_UNICODE\_PATH build feature of Exiv2 on Windows. - -_Code: [exifprint.cpp](samples/exifprint.cpp)_ - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### exifvalue - -``` -Usage: exifvalue file tag -``` -Prints the value of a single _**Exif**_ tag in a file. _Code: [exifvalue.cpp](samples/exifvalue.cpp)_ - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### exiv2json - -``` -Usage: exiv2json [-option] file -Option: all | exif | iptc | xmp | filesystem -``` -| Arguments | Description | -|:-- |:--- | -| all | All metadata | -| filesystem | Filesystem metadata | -| exif | Exif metadata | -| iptc | Iptc metadata | -| xmp | Xmp metadata | -| file | path to image | - -This program dumps metadata from an image in JSON format. _Code: [exiv2json.cpp](samples/exiv2json.cpp)_ - -exiv2json has a recursive parser to encode XMP into Vectors and Objects. XMP data is XMP and can contain XMP `Bag` and `Seq` which are converted to JSON Objects and Arrays. Exiv2 presents data in the format: Family.Group.Tag. For XMP, results in "flat" output such such as: - -``` -$ exiv2 -px ~/Stonehenge.jpg -Xmp.xmp.Rating XmpText 1 0 -Xmp.xmp.ModifyDate XmpText 25 2015-07-16T20:25:28+01:00 -Xmp.dc.description LangAlt 1 lang="x-default" Classic View -``` - -exiv2json parses the Exiv2 'Family.Group.Tag' data and restores the structure of the original data in JSON. _Code: [exiv2json.cpp](samples/exiv2json.cpp)_ - -``` -$ exiv2json -xmp http://clanmills.com/Stonehenge.jpg -{ - "Xmp": { - "xmp": { - "Rating": "0", - "ModifyDate": "2015-07-16T20:25:28+01:00" - }, - "dc": { - "description": { - "lang": { - "x-default": "Classic View" - } - } - }, - "xmlns": { - "dc": "http:\/\/purl.org\/dc\/elements\/1.1\/", - "xmp": "http:\/\/ns.adobe.com\/xap\/1.0\/" - } - } -} -$ -``` - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### geotag - -``` -Usage: geotag {-help|-version|-dst|-dryrun|-ascii|-remove|-verbose|-adjust value|-tz value|-delta value}+ path+ -``` - -Geotag reads one or more GPX files and adds GPS Tages to images. _Code: [geotag.cpp](samples/geotag.cpp)_ - -If the path is a directory, geotag will read all the files in the directory. It constructs a time dictionary of position data, then updates every image with GPS Tags. - -| Arguments | Description | -|:-- |:--- | -| -ascii | Output in ascii (not UTF8). Prints `deg` instead of °. | -| -dst | Apply 1 hour adjustment for daylight saving time. | -| -dryrun | Read arguments and print report. Does not modify images. | -| -verbose | Report progress. | -| -remove | Removes GPS tags from images. | -| -adjust value | Add/subtract time from image data. | -| -tz value | Specify time zone. For example PST = -8:00 | -| -delta value | Correction between Image DataTime and GPS time. | - -I use this program frequently. I have a little Canon camera which I take when I run. My Samsung Galaxy Watch uploads my runs to Strava and I download the GPX. If I'm in another time-zone and have forgotten to change the time setting in the camera, I use `-adjust` to alter the images. The GPX time is always correct, however the camera is normally off by seconds or minutes. This option enables you to correct for inaccuracy in the setting of the camera time. - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### iptceasy - -``` -Usage: iptceasy file -Reads and writes raw metadata. Use -h option for help. -``` - -Demonstrates read, set or modify IPTC metadata. _Code: [iptceasy.cpp](samples/iptceasy.cpp)_ - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### iptcprint - -``` -Usage: iptcprint file -Reads and writes raw metadata. Use -h option for help. -``` - -Demonstrates Exiv2 library APIs to print Iptc data. _Code: [iptcprint.cpp](samples/iptcprint.cpp)_ - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### metacopy - -``` -Usage: metacopy [-iecaph] readfile writefile -Reads and writes raw metadata. Use -h option for help. -``` - -Metacopy is used to copy a complete metadata block from one file to another. _Code: [metacopy.cpp](samples/metacopy.cpp)_ - -Please note that some metadata such as Exif.Photo.PixelXDimension is considered to be part of the image and will not be copied. - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### mrwthumb - -``` -Usage: mrwthumb file -``` - -Sample program to extract a Minolta thumbnail from the makernote. _Code: [mrwthumb.cpp](samples/mrwthumb.cpp)_ - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### xmpparse - -``` -Usage: xmpparse file -``` - -Read an XMP packet from a file, parse it and print all (known) properties. _Code: [xmpparse.cpp](samples/xmpparse.cpp)_ - - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### xmpprint - -``` -Usage: xmpprint file -``` - -Read an XMP from a file, parse it and print all (known) properties. _Code: [xmpprint.cpp](samples/xmpprint.cpp)_ - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### xmpsample - -``` -Usage: xmpsample file -``` - -Demonstrates Exiv2 library high level XMP classes. _Code: [xmpsample.cpp](samples/xmpsample.cpp)_ - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -## 3 Test Program Descriptions - -
- -#### conntest - -``` -Usage: conntest url {-http1_0} -``` - -Test http/https/ftp/ssh/sftp connection - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### convert-test - -``` -Usage: convert-test file -``` - -Conversion test driver - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### easyaccess-test - -``` -Usage: easyaccess-test file -``` - -Sample program using high-level metadata access functions - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### getopt-test - -``` -Usage: getopt-test -``` -This program is used to test the function **getopt()**. Prior to Exiv2 v0.27, the sample programs used the platform's C Runtime Library function **getopt()**. Visual Studio builds used code in src/getopt.cpp. Due to differences in the platform **getopt()**, the code in src/getopt.cpp was modified and adopted on every platforms. This test program was added for test and debug purpose. Please note that src/getopt.cpp is compiled and linked into the sample application and is not part of the Exiv2 library. - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### ini-test - -``` -Usage: ini-test -``` - -This program is used to test reading the file ini-test. This program was added in Exiv2 v0.26 when the ~/.exiv2 file was added to the Exiv2 architecture. - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### iotest - -``` -Usage: iotest filein fileout1 fileout2 -fileouts are overwritten and should match filein exactly -``` - -Test programs for BasicIo functions. - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### iptctest - -``` -Usage: iptctest image -Commands read from stdin. -``` - -Sample program test Iptc reading and writing. - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### key-test - -``` -Usage: key-test -``` - -Key unit tests - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### largeiptc-test - -``` -Usage: largeiptc-test image datafile -``` - -Test for large (>65535 bytes) IPTC buffer - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### mmap-test - -``` -Usage: mmap-test file -``` - -Simple mmap tests - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### path-test - -``` -Usage: path-test file -``` - -Test path IO - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### prevtest - -``` -Usage: prevtest file -``` - -Test access to preview images - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### remotetest - -``` -Usage: remotetest remotetest file {--nocurl | --curl} -``` - -Tester application for testing remote i/o. - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### stringto-test - -``` -Usage: stringto-test -``` - -Test conversions from string to long, float and Rational types. - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### taglist - -``` -$ taglist --help -Usage: taglist [--help] - [--group name| - Groups|Exif|Canon|CanonCs|CanonSi|CanonCf|Fujifilm|Minolta|Nikon1|Nikon2|Nikon3|Olympus| - Panasonic|Pentax|Sigma|Sony|Iptc| - dc|xmp|xmpRights|xmpMM|xmpBJ|xmpTPg|xmpDM|pdf|photoshop|crs|tiff|exif|aux|iptc|all|ALL - ] -Print Exif tags, MakerNote tags, or Iptc datasets -``` - -Print a simple comma separated list of tags defined in Exiv2 - -This program encodes the library's tag definitions in ascii. -The data from this program is formatted as HTML on the web-site. https://exiv2.org/metadata.html - -For example, to show the binary definition of Group `Nikon3`: - -``` -$ taglist Nikon3 -Version, 1, 0x0001, Nikon3, Exif.Nikon3.Version, Undefined, Nikon Makernote version -ISOSpeed, 2, 0x0002, Nikon3, Exif.Nikon3.ISOSpeed, Short, ISO speed setting -ColorMode, 3, 0x0003, Nikon3, Exif.Nikon3.ColorMode, Ascii, Color mode -Quality, 4, 0x0004, Nikon3, Exif.Nikon3.Quality, Ascii, Image quality setting -WhiteBalance, 5, 0x0005, Nikon3, Exif.Nikon3.WhiteBalance, Ascii, White balance -Sharpening, 6, 0x0006, Nikon3, Exif.Nikon3.Sharpening, Ascii, Image sharpening setting -Focus, 7, 0x0007, Nikon3, Exif.Nikon3.Focus, Ascii, Focus mode -FlashSetting, 8, 0x0008, Nikon3, Exif.Nikon3.FlashSetting, Ascii, Flash setting -FlashDevice, 9, 0x0009, Nikon3, Exif.Nikon3.FlashDevice, Ascii, Flash device -... -``` - -We can see those tags being used: - -``` -$ exiv2 -pa --grep Nikon3 http://clanmills.com/Stonehenge.jpg -Exif.Nikon3.Version Undefined 4 2.11 -Exif.Nikon3.ISOSpeed Short 2 200 -... -``` - -This information is formatted (search Nikon (format 3) MakerNote Tags): [https://exiv2.org/tags-nikon.html](https://exiv2.org/tags-nikon.html) - -#### taglist all - -These options are provided to list every Exif tag known to Exiv2. The option `all` prints Group.Name for every tag. The option `ALL` print Group.Name followed by the TagInfo for that tag. For example: - -```bash -$ taglist all | grep ISOSpeed$ -Photo.ISOSpeed -PanasonicRaw.ISOSpeed -CanonCs.ISOSpeed -CanonSi.ISOSpeed -Casio2.ISOSpeed -MinoltaCs5D.ISOSpeed -MinoltaCs7D.ISOSpeed -Nikon1.ISOSpeed -Nikon2.ISOSpeed -Nikon3.ISOSpeed -Olympus.ISOSpeed -Olympus2.ISOSpeed -``` - -```bash -$ taglist ALL | grep ISOSpeed, -Photo.ISOSpeed, 34867, 0x8833, Photo, Exif.Photo.ISOSpeed, Long, This tag indicates the ISO speed value of a camera or input device that is defined in ISO 12232. When recording this tag, the PhotographicSensitivity and SensitivityType tags shall also be recorded. -PanasonicRaw.ISOSpeed, 23, 0x0017, PanasonicRaw, Exif.PanasonicRaw.ISOSpeed, Short, ISO speed setting -CanonCs.ISOSpeed, 16, 0x0010, CanonCs, Exif.CanonCs.ISOSpeed, SShort, ISO speed setting -CanonSi.ISOSpeed, 2, 0x0002, CanonSi, Exif.CanonSi.ISOSpeed, Short, ISO speed used -Casio2.ISOSpeed, 20, 0x0014, Casio2, Exif.Casio2.ISOSpeed, Short, ISO Speed -MinoltaCs5D.ISOSpeed, 38, 0x0026, MinoltaCs5D, Exif.MinoltaCs5D.ISOSpeed, Short, ISO speed setting -MinoltaCs7D.ISOSpeed, 28, 0x001c, MinoltaCs7D, Exif.MinoltaCs7D.ISOSpeed, Short, ISO speed setting -Nikon1.ISOSpeed, 2, 0x0002, Nikon1, Exif.Nikon1.ISOSpeed, Short, ISO speed setting -Nikon2.ISOSpeed, 6, 0x0006, Nikon2, Exif.Nikon2.ISOSpeed, Short, ISO speed setting -Nikon3.ISOSpeed, 2, 0x0002, Nikon3, Exif.Nikon3.ISOSpeed, Short, ISO speed setting -Olympus.ISOSpeed, 4097, 0x1001, Olympus, Exif.Olympus.ISOSpeed, SRational, ISO speed value -Olympus2.ISOSpeed, 4097, 0x1001, Olympus, Exif.Olympus.ISOSpeed, SRational, ISO speed value -Sony1MltCs7D.ISOSpeed, 28, 0x001c, MinoltaCs7D, Exif.MinoltaCs7D.ISOSpeed, Short, ISO speed setting -``` - - - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### tiff-test - -``` -Usage: tiff-test file -``` - -Simple TIFF write test - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - - -
- -#### werror-test - -``` -Usage: werror-test -``` - -Simple tests for the wide-string error class WError - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### write-test - -``` -Usage: write-test file case -where case is an integer between 1 and 11 -``` - -ExifData write unit tests - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### write2-test - -``` -Usage: write2-test file -``` - -ExifData write unit tests for Exif data created from scratch - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### xmpdump - -``` -Usage: xmpdump file -``` - -Sample program to dump the XMP packet of an image - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - -
- -#### xmpparser-test - -``` -Usage: xmpparser-test file -``` - -Read an XMP packet from a file, parse and re-serialize it. - -[Sample](#TOC1) Programs [Test](#TOC2) Programs - - - -Robin Mills
-robin@clanmills.com
-Revised: 2020-05-01 \ No newline at end of file