diff --git a/README-SAMPLES.md b/README-SAMPLES.md
index eea883f3..28a5e6f1 100644
--- a/README-SAMPLES.md
+++ b/README-SAMPLES.md
@@ -112,18 +112,21 @@ This is a simple program to demonstrate dumping _**Exif**_ metadata in common fo
#### exifprint
```
-Usage: exifprint [ path | --version | --version-test ]
+Usage: exifprint [ [--lint] path | --version | --version-test ]
```
| Arguments | Description |
|:-- |:--- |
| path | Path to image |
+| --lint path | Path to image. Type metadata test |
| --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 to 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.
+You can process the metadata in two different ways. The default prints the metadata. The option --lint instructs exifprint to compare the type of the metadata to the standard.
+
+There is another 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)_
@@ -656,4 +659,4 @@ Read an XMP packet from a file, parse and re-serialize it.
Robin Mills
robin@clanmills.com
-Revised: 2020-11-20
\ No newline at end of file
+Revised: 2021-06-23
\ No newline at end of file
diff --git a/README.md b/README.md
index 46ace875..aa4dbe64 100644
--- a/README.md
+++ b/README.md
@@ -490,7 +490,7 @@ Those blocks of code are not compiled unless you define `EXIV2_DEBUG_MESSAGES`.
```bash
$ cd
$ touch src/webpimage.cpp
-$ make CXXFLAGS=-DEXIV2_DEBUG_MESSAGES
+$ make CXX_FLAGS=-DEXIV2_DEBUG_MESSAGES
$ bin/exiv2 ...
-- or --
$ sudo make install
diff --git a/cmake/compilerFlags.cmake b/cmake/compilerFlags.cmake
index a8e81327..c8a85c59 100644
--- a/cmake/compilerFlags.cmake
+++ b/cmake/compilerFlags.cmake
@@ -33,7 +33,9 @@ if ( MINGW OR UNIX OR MSYS ) # MINGW, Linux, APPLE, CYGWIN
if (COMPILER_IS_GCC OR COMPILER_IS_CLANG)
# This fails under Fedora - MinGW - Gcc 8.3
if (NOT (MINGW OR CYGWIN OR CMAKE_HOST_SOLARIS))
+ if (NOT APPLE) # Don't know why this isn't working correctly on Apple with M1 processor
check_cxx_compiler_flag(-fstack-clash-protection HAS_FSTACK_CLASH_PROTECTION)
+ endif()
check_cxx_compiler_flag(-fcf-protection HAS_FCF_PROTECTION)
check_cxx_compiler_flag(-fstack-protector-strong HAS_FSTACK_PROTECTOR_STRONG)
if(HAS_FSTACK_CLASH_PROTECTION)
diff --git a/samples/exifprint.cpp b/samples/exifprint.cpp
index 43dff727..02015672 100644
--- a/samples/exifprint.cpp
+++ b/samples/exifprint.cpp
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
#include
// https://github.com/Exiv2/exiv2/issues/468
@@ -42,6 +43,14 @@
#define _tmain main
#endif
+// copied from src/tiffvisitor_int.cpp
+static const Exiv2::TagInfo* findTag(const Exiv2::TagInfo* pList,uint16_t tag)
+{
+ while ( pList->tag_ != 0xffff && pList->tag_ != tag ) pList++;
+ return pList->tag_ != 0xffff ? pList : NULL;
+}
+
+
int _tmain(int argc, _tchar* const argv[])
try {
Exiv2::XmpParser::initialize();
@@ -51,19 +60,22 @@ try {
#endif
const _tchar* prog = argv[0];
- const _tchar* file = argv[1];
-
- if (argc != 2) {
- std::_tcout << _t("Usage: ") << prog << _t(" [ path | --version | --version-test ]") << std::endl;
+ if (argc == 1) {
+ std::_tcout << _t("Usage: ") << prog << _t(" [ [--lint] path | --version | --version-test ]") << std::endl;
return 1;
}
+ int rc = 0 ;
+ const _tchar* file = argv[1];
+ bool bLint = _tstrcmp(file,_t("--lint")) == 0 && argc == 3;
+ if ( bLint ) file= argv[2];
+
+
if ( _tstrcmp(file,_t("--version")) == 0 ) {
exv_grep_keys_t keys;
Exiv2::dumpLibraryInfo(std::cout,keys);
- return 0;
- }
- if (_tstrcmp(file, _t("--version-test")) == 0) {
+ return rc;
+ } else if ( _tstrcmp(file,_t("--version-test")) == 0 ) {
// verifies/test macro EXIV2_TEST_VERSION
// described in include/exiv2/version.hpp
std::cout << "EXV_PACKAGE_VERSION " << EXV_PACKAGE_VERSION << std::endl
@@ -86,7 +98,7 @@ try {
#else
std::cout << "Compile-time Exiv2 version doesn't have Exiv2::testVersion()\n";
#endif
- return 0;
+ return rc;
}
Exiv2::Image::UniquePtr image = Exiv2::ImageFactory::open(file);
@@ -98,24 +110,50 @@ try {
std::string error("No Exif data found in file");
throw Exiv2::Error(Exiv2::kerErrorMessage, error);
}
+
+ std::set shortLong;
+ shortLong.insert("Exif.Photo.PixelXDimension");
+ shortLong.insert("Exif.Photo.PixelYDimension");
+ shortLong.insert("Exif.Photo.ImageLength");
+ shortLong.insert("Exif.Photo.ImageWidth");
+ shortLong.insert("Exif.Photo.RowsPerStrip");
+ shortLong.insert("Exif.Photo.StripOffsets");
+ shortLong.insert("Exif.Photo.StripByteCounts");
auto end = exifData.end();
for (auto i = exifData.begin(); i != end; ++i) {
- const char* tn = i->typeName();
- std::cout << std::setw(44) << std::setfill(' ') << std::left
- << i->key() << " "
- << "0x" << std::setw(4) << std::setfill('0') << std::right
- << std::hex << i->tag() << " "
- << std::setw(9) << std::setfill(' ') << std::left
- << (tn ? tn : "Unknown") << " "
- << std::dec << std::setw(3)
- << std::setfill(' ') << std::right
- << i->count() << " "
- << std::dec << i->toString()
- << "\n";
+ if ( ! bLint ) {
+ const char* tn = i->typeName();
+ std::cout << std::setw(44) << std::setfill(' ') << std::left
+ << i->key() << " "
+ << "0x" << std::setw(4) << std::setfill('0') << std::right
+ << std::hex << i->tag() << " "
+ << std::setw(9) << std::setfill(' ') << std::left
+ << (tn ? tn : "Unknown") << " "
+ << std::dec << std::setw(3)
+ << std::setfill(' ') << std::right
+ << i->count() << " "
+ << std::dec << i->toString()
+ << "\n";
+ } else {
+ const Exiv2::TagInfo* tagInfo = findTag( Exiv2::ExifTags::tagList(i->groupName()),i->tag() );
+ if ( tagInfo ) {
+ Exiv2::TypeId type = i->typeId();
+ if ( type!= tagInfo-> typeId_
+ &&!(tagInfo->typeId_ == Exiv2::comment && type == Exiv2::undefined) // comment is stored as undefined
+ &&!(shortLong.find(i->key())!=shortLong.end() &&(type == Exiv2::unsignedShort||type==Exiv2::unsignedLong)) // can be short or long!
+ ) {
+ std::cerr << i->key()
+ << " type " << i->typeName() << " (" << type << ")"
+ << " expected " << Exiv2::TypeInfo::typeName(tagInfo-> typeId_) << " (" << tagInfo-> typeId_ << ")"
+ << std::endl;
+ rc=2;
+ }
+ }
+ }
}
- return 0;
+ return rc;
}
//catch (std::exception& e) {
//catch (Exiv2::AnyError& e) {
diff --git a/tests/bugfixes/github/test_exifprint_lint.py b/tests/bugfixes/github/test_exifprint_lint.py
new file mode 100644
index 00000000..9873df63
--- /dev/null
+++ b/tests/bugfixes/github/test_exifprint_lint.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+
+from system_tests import CaseMeta, CopyTmpFiles, path
+@CopyTmpFiles("$data_path/Stonehenge.exv")
+
+class test_exifprint_lint(metaclass=CaseMeta):
+ url = "https://github.com/Exiv2/exiv2/pull/1738"
+ filename = path("$tmp_path/Stonehenge.exv")
+ commands = [ "$exifprint --lint $filename"
+ , '$exiv2 -M"set Exif.Image.ImageDescription Short 3" $filename'
+ , "$exifprint --lint $filename"
+ ]
+ stderr = ["""Exif.Nikon3.ExposureTuning type Undefined (7) expected Short (3)
+""","","""Exif.Image.ImageDescription type Short (3) expected Ascii (2)
+Exif.Nikon3.ExposureTuning type Undefined (7) expected Short (3)
+"""
+]
+ stdout = [""]*len(commands)
+ retval = [2,0,2]
diff --git a/tests/suite.conf b/tests/suite.conf
index f0e3ab9b..4ff454bb 100644
--- a/tests/suite.conf
+++ b/tests/suite.conf
@@ -24,6 +24,7 @@ valgrind:
[paths]
exiv2: ${ENV:exiv2_path}/exiv2
+exifprint: ${ENV:exiv2_path}/exifprint
unit_tests: ${ENV:exiv2_path}/unit_tests
exiv2json: ${ENV:exiv2_path}/exiv2json
metacopy: ${ENV:exiv2_path}/metacopy