|
|
|
// ***************************************************************** -*- C++ -*-
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2004-2015 Andreas Huggel <ahuggel@gmx.net>
|
|
|
|
*
|
|
|
|
* This program is part of the Exiv2 distribution.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
File: version.cpp
|
|
|
|
Version: $Rev$
|
|
|
|
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
|
|
|
|
History: 06-Mar-07, ahu: created
|
|
|
|
|
|
|
|
*/
|
|
|
|
// *****************************************************************************
|
|
|
|
#include "rcsid_int.hpp"
|
|
|
|
EXIV2_RCSID("@(#) $Id$")
|
|
|
|
|
|
|
|
// *****************************************************************************
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#ifndef EXV_USE_SSH
|
|
|
|
#define EXV_USE_SSH 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EXV_USE_CURL
|
|
|
|
#define EXV_USE_CURL 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_USE_CURL == 1
|
|
|
|
#include <curl/curl.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(__CYGWIN__) || defined(__MINGW__)
|
|
|
|
#include <windows.h>
|
|
|
|
# if __LP64__
|
|
|
|
# ifdef _WIN64
|
|
|
|
# undef _WIN64
|
|
|
|
# endif
|
|
|
|
# define _WIN64 1
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EXV_HAVE_XMP_TOOLKIT
|
|
|
|
#define EXV_HAVE_XMP_TOOLKIT 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EXV_HAVE_STRINGS
|
|
|
|
#define EXV_HAVE_STRINGS 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EXV_SYS_TYPES
|
|
|
|
#define EXV_SYS_TYPES 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EXV_HAVE_UNISTD
|
|
|
|
#define EXV_HAVE_UNISTD 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EXV_UNICODE_PATH
|
|
|
|
#define EXV_UNICODE_PATH 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EXV_ENABLE_VIDEO
|
|
|
|
#define EXV_ENABLE_VIDEO 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EXV_ENABLE_WEBREADY
|
|
|
|
#define EXV_ENABLE_WEBREADY 0
|
|
|
|
#endif
|
|
|
|
|
This is mainly a fix for #1206, but also interprets missing Canon Exif
Tags in exiv2 with the help of Phil Harvey's exiftool (see
http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html).
Even with these changes (toward #1204 and #1205), exiv2 lags behind
exiftool in some areas of interpretation of Canon tags. Ideally, a
catch-up effort to bring the code in source: canonmn.cpp in line with
lib/Image/ExifTool/Canon.pm. v10.25 of exiftool was used as reference
for this change.
#1206 seeks to address the fact that when Canon does not have data for
certain tags, they use specific default values in those fields. These
default values need to be ignored and not displayed. This change
brings this feature to exiv2, something that already exiftool does.
With regards to implementation, the struct TagInfo in source: tags.hpp
is extended with four new fields.
The first field is a bool that if set to true (default false), denotes
that this field has ignorable default values.
The second field is the default value that needs to be ignored. This
can be of four types (String, Long, Float, Rational). These four types
were chosen as they had conversion functions in the Value class.
The third field is the comparison type (default equal_to). There are
six comparison types possible (equal_to, not_equal_to, less,
less_equal, greater, greater_equal). This is the comparison applied to
the value stored in the tag's field and the default value specified
above. For e.g. if the value in the tag Exif.CanonCs.RecordMode is -1,
then it needs to be ignored.
The fourth field is the data type (default Long). This could have been
guessed from the type of the second field, but that would necessitate
making this structure into a template calling for changes in multitude
of files.
Usage: In source: canonmn.cpp, several exif tags now have ignorable
default properties. I will list a few examples.
1. Exif.CanonCs.FocusMode: TagInfo(0x0007, "FocusMode", N_("Focus Mode"), N_("Focus mode setting"), canonCsId, makerTags, signedShort, 1, EXV_PRINT_TAG(canonCsFocusMode)),
There are no changes - i.e. this is an example of how the TagInfo
structure was being populated.
2. Exif.CanonCs.RecordMode: TagInfo(0x0009, "RecordMode", N_("Record Mode"), N_("Record mode setting"), canonCsId, makerTags, signedShort, 1, EXV_PRINT_TAG(canonCsRecordMode), true, s_1_),
Take a look at the two new arguments. The first one (true) specifies
that there is a default value that can be ignored. The second one s_1_
specifies the value (-1, in this case) to be ignored.
const UShortValue CanonMakerNote::s_1_(65535, unsignedShort); // Till bug is resolved
Note s_1_ is temporarily having the value 65535 till #1203 that causes
signedShorts to be interpreted as unsignedShorts is resolved.
3. Exif.CanonSi.TargetAperture: TagInfo(0x0004, "TargetAperture", N_("Target Aperture"), N_("Target Aperture"), canonSiId, makerTags, unsignedShort, 1, printSi0x0015, true, us0_, TagInfo::less_equal),
Note the third argument TagInfo::less_equal. This combined with the
second argument us0_ (the number 0) signifies that any values in this
tag that are less than or equal (<=) to 0 should be ignored.
4. TagInfo(0x0028, "ImageUniqueID", N_("Image Unique ID"), N_("Image Unique ID"), canonId, makerTags, asciiString, -1, printValue, true, s0x16_, TagInfo::equal_to, TagInfo::String),
The previous examples have all been of Long type. This shows a case
where the default value is a string.
const AsciiValue CanonMakerNote::s0x16_("0000000000000000");
Once these tag values have been defined, the actual mechanics of
ignoring these default values happens in Image::exifData().
Before the exifData is returned, we loop through the data, ask the
data whether it needs to be ignored (which in turn checks its
underlying tagInfo and compares it with the default value, if
specified) and if so, deletes that element.
A compile-time switch called EXV_DONT_IGNORE_UNDEFINED which when set
to a non-zero value will cause the behavior to revert back to the
original where all values are reported irregardless of the fact that
they need to be ignored.
9 years ago
|
|
|
#ifndef EXV_DONT_IGNORE_UNDEFINED
|
|
|
|
#define EXV_DONT_IGNORE_UNDEFINED 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "http.hpp"
|
|
|
|
#include "svn_version.h"
|
|
|
|
#include "version.hpp"
|
|
|
|
#include "makernote_int.hpp"
|
|
|
|
|
|
|
|
// Adobe XMP Toolkit
|
|
|
|
#if EXV_HAVE_XMP_TOOLKIT
|
|
|
|
#include "xmp.hpp"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// + standard includes
|
|
|
|
#include <iomanip>
|
|
|
|
#include <sstream>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
// #1147
|
|
|
|
#ifndef WIN32
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace Exiv2 {
|
|
|
|
int versionNumber()
|
|
|
|
{
|
|
|
|
return EXIV2_MAKE_VERSION(EXIV2_MAJOR_VERSION, EXIV2_MINOR_VERSION, EXIV2_PATCH_VERSION);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string versionString()
|
|
|
|
{
|
|
|
|
std::ostringstream os;
|
|
|
|
os << EXIV2_MAJOR_VERSION << '.' << EXIV2_MINOR_VERSION << '.' << EXIV2_PATCH_VERSION;
|
|
|
|
return os.str();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string versionNumberHexString()
|
|
|
|
{
|
|
|
|
std::ostringstream os;
|
|
|
|
os << std::hex << std::setw(6) << std::setfill('0') << Exiv2::versionNumber();
|
|
|
|
return os.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* version()
|
|
|
|
{
|
|
|
|
return EXV_PACKAGE_VERSION;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool testVersion(int major, int minor, int patch)
|
|
|
|
{
|
|
|
|
return versionNumber() >= EXIV2_MAKE_VERSION(major,minor,patch);
|
|
|
|
}
|
|
|
|
} // namespace Exiv2
|
|
|
|
|
|
|
|
#ifndef lengthof
|
|
|
|
#define lengthof(x) sizeof(x)/sizeof(x[0])
|
|
|
|
#endif
|
|
|
|
#ifndef _MAX_PATH
|
|
|
|
#define _MAX_PATH 512
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// platform specific support for dumpLibraryInfo
|
|
|
|
#if defined(WIN32)
|
|
|
|
# include <windows.h>
|
|
|
|
# include <psapi.h>
|
|
|
|
|
|
|
|
// tell MSVC to link psapi.
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma comment( lib, "psapi" )
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#elif defined(__APPLE__)
|
|
|
|
# include <mach-o/dyld.h>
|
|
|
|
|
|
|
|
#elif defined(__linux__)
|
|
|
|
# include <unistd.h>
|
|
|
|
// http://syprog.blogspot.com/2011/12/listing-loaded-shared-objects-in-linux.html
|
|
|
|
# include <dlfcn.h>
|
|
|
|
struct something
|
|
|
|
{
|
|
|
|
void* pointers[3];
|
|
|
|
struct something* ptr;
|
|
|
|
};
|
|
|
|
struct lmap
|
|
|
|
{
|
|
|
|
void* base_address; /* Base address of the shared object */
|
|
|
|
char* path; /* Absolute file name (path) of the shared object */
|
|
|
|
void* not_needed1; /* Pointer to the dynamic section of the shared object */
|
|
|
|
struct lmap *next, *prev;/* chain of loaded objects */
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static bool shouldOutput(const exv_grep_keys_t& greps,const char* key,const std::string& value)
|
|
|
|
{
|
|
|
|
bool bPrint = greps.empty();
|
|
|
|
for( exv_grep_keys_t::const_iterator g = greps.begin();
|
|
|
|
!bPrint && g != greps.end() ; ++g
|
|
|
|
) {
|
|
|
|
std::string Key(key);
|
|
|
|
#if __cplusplus >= CPLUSPLUS11
|
|
|
|
std::smatch m;
|
|
|
|
bPrint = std::regex_search(Key,m,*g) || std::regex_search(value,m,*g);
|
|
|
|
#else
|
|
|
|
#if EXV_HAVE_REGEX
|
|
|
|
bPrint = ( 0 == regexec( &(*g), key , 0, NULL, 0)
|
|
|
|
|| 0 == regexec( &(*g), value.c_str(), 0, NULL, 0)
|
|
|
|
);
|
|
|
|
#else
|
|
|
|
std::string Pattern(g->pattern_);
|
|
|
|
std::string Value(value);
|
|
|
|
if ( g->bIgnoreCase_ ) {
|
|
|
|
// https://notfaq.wordpress.com/2007/08/04/cc-convert-string-to-upperlower-case/
|
|
|
|
std::transform(Pattern.begin(), Pattern.end(),Pattern.begin(), ::tolower);
|
|
|
|
std::transform(Key.begin() , Key.end() ,Key.begin() , ::tolower);
|
|
|
|
std::transform(Value.begin() , Value.end() ,Value.begin() , ::tolower);
|
|
|
|
}
|
|
|
|
bPrint = Key.find(Pattern) != std::string::npos || Value.find(Pattern) != std::string::npos;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return bPrint;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output(std::ostream& os,const exv_grep_keys_t& greps,const char* name,const std::string& value)
|
|
|
|
{
|
|
|
|
if ( shouldOutput(greps,name,value) ) os << name << "=" << value << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output(std::ostream& os,const exv_grep_keys_t& greps,const char* name,int value)
|
|
|
|
{
|
|
|
|
std::ostringstream stringStream;
|
|
|
|
stringStream << value;
|
|
|
|
output(os,greps,name,stringStream.str());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Exiv2::dumpLibraryInfo(std::ostream& os,const exv_grep_keys_t& keys)
|
|
|
|
{
|
|
|
|
Exiv2::StringVector libs; // libs[0] == executable
|
|
|
|
|
|
|
|
int bits = 8*sizeof(void*);
|
|
|
|
#if defined(_DEBUG) || defined(DEBUG)
|
|
|
|
int debug=1;
|
|
|
|
#else
|
|
|
|
int debug=0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(DLL_EXPORT) || defined(EXV_HAVE_DLL)
|
|
|
|
int dll=1;
|
|
|
|
#else
|
|
|
|
int dll=0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
const char* compiler =
|
|
|
|
#if defined(_MSC_VER)
|
|
|
|
"MSVC" ;
|
|
|
|
|
|
|
|
#ifndef __VERSION__
|
|
|
|
char version[40];
|
|
|
|
sprintf(version,"%d.%02d",(_MSC_VER-600)/100,_MSC_VER%100);
|
|
|
|
|
|
|
|
// add edition in brackets
|
|
|
|
// 7.10 = 2003 8.00 = 2005 etc 12.00 = 2013 13.00 = 2015 (yet the installer labels it as 14.0!)
|
|
|
|
size_t edition = (_MSC_VER-600)/100;
|
|
|
|
const char* editions[] = { "0","1","2","3","4","5","6","2003", "2005", "2008", "2010", "2012","2013","2015"};
|
|
|
|
if ( edition > lengthof(editions) ) edition = 0 ;
|
|
|
|
if ( edition ) sprintf(version+::strlen(version)," (%s/%s)",editions[edition],bits==64?"x64":"x86");
|
|
|
|
#define __VERSION__ version
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#elif defined(__clang__)
|
|
|
|
"Clang" ;
|
|
|
|
#elif defined(__GNUG__)
|
|
|
|
"G++" ;
|
|
|
|
#elif defined(__GNUC__)
|
|
|
|
"GCC" ;
|
|
|
|
#elif defined(__SUNPRO_CC)
|
|
|
|
"CC (oracle)";
|
|
|
|
#elif defined (__SUNPRO_C)
|
|
|
|
"cc (oracle)";
|
|
|
|
#else
|
|
|
|
"unknown" ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(__SUNPRO_CC) || defined (__SUNPRO_C)
|
|
|
|
#define __oracle__
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef __VERSION__
|
|
|
|
#ifdef __clang__version__
|
|
|
|
#define __VERSION__ __clang__version__
|
|
|
|
#else
|
|
|
|
#define __VERSION__ "unknown"
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
const char* platform =
|
|
|
|
#if defined(__CYGWIN__)
|
|
|
|
"cygwin";
|
|
|
|
#elif defined(_MSC_VER)
|
|
|
|
"windows";
|
|
|
|
#elif defined(__APPLE__)
|
|
|
|
"apple";
|
|
|
|
#elif defined(__MINGW64__)
|
|
|
|
"mingw64";
|
|
|
|
#elif defined(__MINGW32__)
|
|
|
|
"mingw32";
|
|
|
|
#elif defined(__linux__)
|
|
|
|
"linux";
|
|
|
|
#else
|
|
|
|
"unknown";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int have_regex =0;
|
|
|
|
int have_gmtime_r =0;
|
|
|
|
int have_inttypes =0;
|
|
|
|
int have_libintl =0;
|
|
|
|
int have_lensdata =0;
|
|
|
|
int have_iconv =0;
|
|
|
|
int have_memory =0;
|
|
|
|
int have_memset =0;
|
|
|
|
int have_lstat =0;
|
|
|
|
int have_stdbool =0;
|
|
|
|
int have_stdint =0;
|
|
|
|
int have_stdlib =0;
|
|
|
|
int have_strlib =0;
|
|
|
|
int have_strchr =0;
|
|
|
|
int have_strerror =0;
|
|
|
|
int have_strerror_r =0;
|
|
|
|
int have_strings_h =0;
|
|
|
|
int have_strtol =0;
|
|
|
|
int have_mmap =0;
|
|
|
|
int have_munmap =0;
|
|
|
|
int have_sys_stat =0;
|
|
|
|
int have_timegm =0;
|
|
|
|
int have_unistd_h =0;
|
|
|
|
int have_sys_mman =0;
|
|
|
|
int have_libz =0;
|
|
|
|
int have_xmptoolkit =0;
|
|
|
|
int have_bool =0;
|
|
|
|
int have_strings =0;
|
|
|
|
int have_sys_types =0;
|
|
|
|
int have_unistd =0;
|
|
|
|
int have_unicode_path=0;
|
|
|
|
|
|
|
|
int enable_video =0;
|
|
|
|
int enable_webready =0;
|
This is mainly a fix for #1206, but also interprets missing Canon Exif
Tags in exiv2 with the help of Phil Harvey's exiftool (see
http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html).
Even with these changes (toward #1204 and #1205), exiv2 lags behind
exiftool in some areas of interpretation of Canon tags. Ideally, a
catch-up effort to bring the code in source: canonmn.cpp in line with
lib/Image/ExifTool/Canon.pm. v10.25 of exiftool was used as reference
for this change.
#1206 seeks to address the fact that when Canon does not have data for
certain tags, they use specific default values in those fields. These
default values need to be ignored and not displayed. This change
brings this feature to exiv2, something that already exiftool does.
With regards to implementation, the struct TagInfo in source: tags.hpp
is extended with four new fields.
The first field is a bool that if set to true (default false), denotes
that this field has ignorable default values.
The second field is the default value that needs to be ignored. This
can be of four types (String, Long, Float, Rational). These four types
were chosen as they had conversion functions in the Value class.
The third field is the comparison type (default equal_to). There are
six comparison types possible (equal_to, not_equal_to, less,
less_equal, greater, greater_equal). This is the comparison applied to
the value stored in the tag's field and the default value specified
above. For e.g. if the value in the tag Exif.CanonCs.RecordMode is -1,
then it needs to be ignored.
The fourth field is the data type (default Long). This could have been
guessed from the type of the second field, but that would necessitate
making this structure into a template calling for changes in multitude
of files.
Usage: In source: canonmn.cpp, several exif tags now have ignorable
default properties. I will list a few examples.
1. Exif.CanonCs.FocusMode: TagInfo(0x0007, "FocusMode", N_("Focus Mode"), N_("Focus mode setting"), canonCsId, makerTags, signedShort, 1, EXV_PRINT_TAG(canonCsFocusMode)),
There are no changes - i.e. this is an example of how the TagInfo
structure was being populated.
2. Exif.CanonCs.RecordMode: TagInfo(0x0009, "RecordMode", N_("Record Mode"), N_("Record mode setting"), canonCsId, makerTags, signedShort, 1, EXV_PRINT_TAG(canonCsRecordMode), true, s_1_),
Take a look at the two new arguments. The first one (true) specifies
that there is a default value that can be ignored. The second one s_1_
specifies the value (-1, in this case) to be ignored.
const UShortValue CanonMakerNote::s_1_(65535, unsignedShort); // Till bug is resolved
Note s_1_ is temporarily having the value 65535 till #1203 that causes
signedShorts to be interpreted as unsignedShorts is resolved.
3. Exif.CanonSi.TargetAperture: TagInfo(0x0004, "TargetAperture", N_("Target Aperture"), N_("Target Aperture"), canonSiId, makerTags, unsignedShort, 1, printSi0x0015, true, us0_, TagInfo::less_equal),
Note the third argument TagInfo::less_equal. This combined with the
second argument us0_ (the number 0) signifies that any values in this
tag that are less than or equal (<=) to 0 should be ignored.
4. TagInfo(0x0028, "ImageUniqueID", N_("Image Unique ID"), N_("Image Unique ID"), canonId, makerTags, asciiString, -1, printValue, true, s0x16_, TagInfo::equal_to, TagInfo::String),
The previous examples have all been of Long type. This shows a case
where the default value is a string.
const AsciiValue CanonMakerNote::s0x16_("0000000000000000");
Once these tag values have been defined, the actual mechanics of
ignoring these default values happens in Image::exifData().
Before the exifData is returned, we loop through the data, ask the
data whether it needs to be ignored (which in turn checks its
underlying tagInfo and compares it with the default value, if
specified) and if so, deletes that element.
A compile-time switch called EXV_DONT_IGNORE_UNDEFINED which when set
to a non-zero value will cause the behavior to revert back to the
original where all values are reported irregardless of the fact that
they need to be ignored.
9 years ago
|
|
|
int dont_ignore_undef =0;
|
|
|
|
|
|
|
|
#if EXV_HAVE_DECL_STRERROR_R
|
|
|
|
have_strerror_r=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_GMTIME_R
|
|
|
|
have_gmtime_r=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_INTTYPES_H
|
|
|
|
have_inttypes=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_LIBINTL_H
|
|
|
|
have_libintl=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_LENSDATA
|
|
|
|
have_lensdata=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_ICONV
|
|
|
|
have_iconv=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_LIBINTL_H
|
|
|
|
have_libintl=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_REGEX
|
|
|
|
have_regex=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_MEMORY_H
|
|
|
|
have_memory=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_MEMSET
|
|
|
|
have_memset=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_LSTAT
|
|
|
|
have_lstat=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_STDBOOL_H
|
|
|
|
have_stdbool=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_STDINT_H
|
|
|
|
have_stdint=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_STDLIB_H
|
|
|
|
have_stdlib=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_STRCHR
|
|
|
|
have_strchr=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_STRERROR
|
|
|
|
have_strerror=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_STRERROR_R
|
|
|
|
have_strerror_r=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_STRINGS_H
|
|
|
|
have_strings=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_STRTOL
|
|
|
|
have_strtol=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_MMAP
|
|
|
|
have_mmap=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_MUNMAP
|
|
|
|
have_munmap=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_SYS_STAT_H
|
|
|
|
have_sys_stat=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_SYS_TYPES_H
|
|
|
|
have_sys_types=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_TIMEGM
|
|
|
|
have_timegm=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_UNISTD_H
|
|
|
|
have_unistd=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_SYS_MMAN_H
|
|
|
|
have_sys_mman=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_LIBZ
|
|
|
|
have_libz=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_XMP_TOOLKIT
|
|
|
|
have_xmptoolkit=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE__BOOL
|
|
|
|
have_bool=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_STRINGS
|
|
|
|
have_strings=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_SYS_TYPES
|
|
|
|
have_sys_types=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_UNISTD
|
|
|
|
have_unistd=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_UNICODE_PATH
|
|
|
|
have_unicode_path=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_ENABLE_VIDEO
|
|
|
|
enable_video=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_ENABLE_WEBREADY
|
|
|
|
enable_webready=1;
|
|
|
|
#endif
|
|
|
|
|
This is mainly a fix for #1206, but also interprets missing Canon Exif
Tags in exiv2 with the help of Phil Harvey's exiftool (see
http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html).
Even with these changes (toward #1204 and #1205), exiv2 lags behind
exiftool in some areas of interpretation of Canon tags. Ideally, a
catch-up effort to bring the code in source: canonmn.cpp in line with
lib/Image/ExifTool/Canon.pm. v10.25 of exiftool was used as reference
for this change.
#1206 seeks to address the fact that when Canon does not have data for
certain tags, they use specific default values in those fields. These
default values need to be ignored and not displayed. This change
brings this feature to exiv2, something that already exiftool does.
With regards to implementation, the struct TagInfo in source: tags.hpp
is extended with four new fields.
The first field is a bool that if set to true (default false), denotes
that this field has ignorable default values.
The second field is the default value that needs to be ignored. This
can be of four types (String, Long, Float, Rational). These four types
were chosen as they had conversion functions in the Value class.
The third field is the comparison type (default equal_to). There are
six comparison types possible (equal_to, not_equal_to, less,
less_equal, greater, greater_equal). This is the comparison applied to
the value stored in the tag's field and the default value specified
above. For e.g. if the value in the tag Exif.CanonCs.RecordMode is -1,
then it needs to be ignored.
The fourth field is the data type (default Long). This could have been
guessed from the type of the second field, but that would necessitate
making this structure into a template calling for changes in multitude
of files.
Usage: In source: canonmn.cpp, several exif tags now have ignorable
default properties. I will list a few examples.
1. Exif.CanonCs.FocusMode: TagInfo(0x0007, "FocusMode", N_("Focus Mode"), N_("Focus mode setting"), canonCsId, makerTags, signedShort, 1, EXV_PRINT_TAG(canonCsFocusMode)),
There are no changes - i.e. this is an example of how the TagInfo
structure was being populated.
2. Exif.CanonCs.RecordMode: TagInfo(0x0009, "RecordMode", N_("Record Mode"), N_("Record mode setting"), canonCsId, makerTags, signedShort, 1, EXV_PRINT_TAG(canonCsRecordMode), true, s_1_),
Take a look at the two new arguments. The first one (true) specifies
that there is a default value that can be ignored. The second one s_1_
specifies the value (-1, in this case) to be ignored.
const UShortValue CanonMakerNote::s_1_(65535, unsignedShort); // Till bug is resolved
Note s_1_ is temporarily having the value 65535 till #1203 that causes
signedShorts to be interpreted as unsignedShorts is resolved.
3. Exif.CanonSi.TargetAperture: TagInfo(0x0004, "TargetAperture", N_("Target Aperture"), N_("Target Aperture"), canonSiId, makerTags, unsignedShort, 1, printSi0x0015, true, us0_, TagInfo::less_equal),
Note the third argument TagInfo::less_equal. This combined with the
second argument us0_ (the number 0) signifies that any values in this
tag that are less than or equal (<=) to 0 should be ignored.
4. TagInfo(0x0028, "ImageUniqueID", N_("Image Unique ID"), N_("Image Unique ID"), canonId, makerTags, asciiString, -1, printValue, true, s0x16_, TagInfo::equal_to, TagInfo::String),
The previous examples have all been of Long type. This shows a case
where the default value is a string.
const AsciiValue CanonMakerNote::s0x16_("0000000000000000");
Once these tag values have been defined, the actual mechanics of
ignoring these default values happens in Image::exifData().
Before the exifData is returned, we loop through the data, ask the
data whether it needs to be ignored (which in turn checks its
underlying tagInfo and compares it with the default value, if
specified) and if so, deletes that element.
A compile-time switch called EXV_DONT_IGNORE_UNDEFINED which when set
to a non-zero value will cause the behavior to revert back to the
original where all values are reported irregardless of the fact that
they need to be ignored.
9 years ago
|
|
|
#if EXV_DONT_IGNORE_UNDEFINED
|
|
|
|
dont_ignore_undef=1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW__)
|
|
|
|
// enumerate loaded libraries and determine path to executable
|
|
|
|
HMODULE handles[200];
|
|
|
|
DWORD cbNeeded;
|
|
|
|
if ( EnumProcessModules(GetCurrentProcess(),handles,lengthof(handles),&cbNeeded)) {
|
|
|
|
char szFilename[_MAX_PATH];
|
|
|
|
for ( DWORD h = 0 ; h < cbNeeded/sizeof(handles[0]) ; h++ ) {
|
|
|
|
GetModuleFileNameA(handles[h],szFilename,lengthof(szFilename)) ;
|
|
|
|
libs.push_back(szFilename);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#elif defined(__APPLE__)
|
|
|
|
// man 3 dyld
|
|
|
|
uint32_t count = _dyld_image_count();
|
|
|
|
for (uint32_t image = 0 ; image < count ; image++ ) {
|
|
|
|
const char* image_path = _dyld_get_image_name(image);
|
|
|
|
libs.push_back(image_path);
|
|
|
|
}
|
|
|
|
#elif defined(__linux__)
|
|
|
|
// http://stackoverflow.com/questions/606041/how-do-i-get-the-path-of-a-process-in-unix-linux
|
|
|
|
char proc[100];
|
|
|
|
char path[500];
|
|
|
|
sprintf(proc,"/proc/%d/exe", getpid());
|
|
|
|
int l = readlink (proc, path,sizeof(path)-1);
|
|
|
|
if (l>0) {
|
|
|
|
path[l]=0;
|
|
|
|
libs.push_back(path);
|
|
|
|
} else {
|
|
|
|
libs.push_back("unknown");
|
|
|
|
}
|
|
|
|
|
|
|
|
// http://syprog.blogspot.com/2011/12/listing-loaded-shared-objects-in-linux.html
|
|
|
|
struct lmap* pl;
|
|
|
|
void* ph = dlopen(NULL, RTLD_NOW);
|
|
|
|
struct something* p = (struct something*) ph;
|
|
|
|
|
|
|
|
p = p->ptr;
|
|
|
|
pl = (struct lmap*)p->ptr;
|
|
|
|
|
|
|
|
while ( pl )
|
|
|
|
{
|
|
|
|
libs.push_back(pl->path);
|
|
|
|
pl = pl->next;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
output(os,keys,"exiv2",Exiv2::versionString());
|
|
|
|
output(os,keys,"platform" , platform );
|
|
|
|
output(os,keys,"compiler" , compiler );
|
|
|
|
output(os,keys,"bits" , bits );
|
|
|
|
output(os,keys,"dll" , dll );
|
|
|
|
output(os,keys,"debug" , debug );
|
|
|
|
output(os,keys,"cplusplus" , __cplusplus);
|
|
|
|
output(os,keys,"cplusplus11" , __cplusplus >= CPLUSPLUS11 );
|
|
|
|
output(os,keys,"version" , __VERSION__);
|
|
|
|
output(os,keys,"date" , __DATE__ );
|
|
|
|
output(os,keys,"time" , __TIME__ );
|
|
|
|
output(os,keys,"svn" , SVN_VERSION);
|
|
|
|
output(os,keys,"ssh" , EXV_USE_SSH);
|
|
|
|
#if EXV_USE_CURL == 1
|
|
|
|
std::string curl_protocols;
|
|
|
|
curl_version_info_data* vinfo = curl_version_info(CURLVERSION_NOW);
|
|
|
|
for (int i = 0; vinfo->protocols[i]; i++) {
|
|
|
|
curl_protocols += vinfo->protocols[i];
|
|
|
|
curl_protocols += " " ;
|
|
|
|
}
|
|
|
|
output(os,keys,"curlprotocols" ,curl_protocols);
|
|
|
|
#else
|
|
|
|
output(os,keys,"curl" , EXV_USE_CURL);
|
|
|
|
#endif
|
|
|
|
output(os,keys,"id" , "$Id$");
|
|
|
|
if ( libs.begin() != libs.end() ) {
|
|
|
|
output(os,keys,"executable" ,*libs.begin());
|
|
|
|
for ( Exiv2::StringVector_i lib = libs.begin()+1 ; lib != libs.end() ; lib++ )
|
|
|
|
output(os,keys,"library",*lib);
|
|
|
|
}
|
|
|
|
|
|
|
|
output(os,keys,"have_regex" ,have_regex );
|
|
|
|
output(os,keys,"have_strerror_r" ,have_strerror_r );
|
|
|
|
output(os,keys,"have_gmtime_r" ,have_gmtime_r );
|
|
|
|
output(os,keys,"have_inttypes" ,have_inttypes );
|
|
|
|
output(os,keys,"have_libintl" ,have_libintl );
|
|
|
|
output(os,keys,"have_lensdata" ,have_lensdata );
|
|
|
|
output(os,keys,"have_iconv" ,have_iconv );
|
|
|
|
output(os,keys,"have_memory" ,have_memory );
|
|
|
|
output(os,keys,"have_memset" ,have_memset );
|
|
|
|
output(os,keys,"have_lstat" ,have_lstat );
|
|
|
|
output(os,keys,"have_stdbool" ,have_stdbool );
|
|
|
|
output(os,keys,"have_stdint" ,have_stdint );
|
|
|
|
output(os,keys,"have_stdlib" ,have_stdlib );
|
|
|
|
output(os,keys,"have_strlib" ,have_strlib );
|
|
|
|
output(os,keys,"have_strchr" ,have_strchr );
|
|
|
|
output(os,keys,"have_strerror" ,have_strerror );
|
|
|
|
output(os,keys,"have_strerror_r" ,have_strerror_r );
|
|
|
|
output(os,keys,"have_strings_h" ,have_strings_h );
|
|
|
|
output(os,keys,"have_strtol" ,have_strtol );
|
|
|
|
output(os,keys,"have_mmap" ,have_mmap );
|
|
|
|
output(os,keys,"have_munmap" ,have_munmap );
|
|
|
|
output(os,keys,"have_sys_stat" ,have_sys_stat );
|
|
|
|
output(os,keys,"have_timegm" ,have_timegm );
|
|
|
|
output(os,keys,"have_unistd_h" ,have_unistd_h );
|
|
|
|
output(os,keys,"have_sys_mman" ,have_sys_mman );
|
|
|
|
output(os,keys,"have_libz" ,have_libz );
|
|
|
|
output(os,keys,"have_xmptoolkit" ,have_xmptoolkit );
|
|
|
|
output(os,keys,"have_bool" ,have_bool );
|
|
|
|
output(os,keys,"have_strings" ,have_strings );
|
|
|
|
output(os,keys,"have_sys_types" ,have_sys_types );
|
|
|
|
output(os,keys,"have_unistd" ,have_unistd );
|
|
|
|
output(os,keys,"have_unicode_path" ,have_unicode_path);
|
|
|
|
output(os,keys,"enable_video" ,enable_video );
|
|
|
|
output(os,keys,"enable_webready" ,enable_webready );
|
This is mainly a fix for #1206, but also interprets missing Canon Exif
Tags in exiv2 with the help of Phil Harvey's exiftool (see
http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html).
Even with these changes (toward #1204 and #1205), exiv2 lags behind
exiftool in some areas of interpretation of Canon tags. Ideally, a
catch-up effort to bring the code in source: canonmn.cpp in line with
lib/Image/ExifTool/Canon.pm. v10.25 of exiftool was used as reference
for this change.
#1206 seeks to address the fact that when Canon does not have data for
certain tags, they use specific default values in those fields. These
default values need to be ignored and not displayed. This change
brings this feature to exiv2, something that already exiftool does.
With regards to implementation, the struct TagInfo in source: tags.hpp
is extended with four new fields.
The first field is a bool that if set to true (default false), denotes
that this field has ignorable default values.
The second field is the default value that needs to be ignored. This
can be of four types (String, Long, Float, Rational). These four types
were chosen as they had conversion functions in the Value class.
The third field is the comparison type (default equal_to). There are
six comparison types possible (equal_to, not_equal_to, less,
less_equal, greater, greater_equal). This is the comparison applied to
the value stored in the tag's field and the default value specified
above. For e.g. if the value in the tag Exif.CanonCs.RecordMode is -1,
then it needs to be ignored.
The fourth field is the data type (default Long). This could have been
guessed from the type of the second field, but that would necessitate
making this structure into a template calling for changes in multitude
of files.
Usage: In source: canonmn.cpp, several exif tags now have ignorable
default properties. I will list a few examples.
1. Exif.CanonCs.FocusMode: TagInfo(0x0007, "FocusMode", N_("Focus Mode"), N_("Focus mode setting"), canonCsId, makerTags, signedShort, 1, EXV_PRINT_TAG(canonCsFocusMode)),
There are no changes - i.e. this is an example of how the TagInfo
structure was being populated.
2. Exif.CanonCs.RecordMode: TagInfo(0x0009, "RecordMode", N_("Record Mode"), N_("Record mode setting"), canonCsId, makerTags, signedShort, 1, EXV_PRINT_TAG(canonCsRecordMode), true, s_1_),
Take a look at the two new arguments. The first one (true) specifies
that there is a default value that can be ignored. The second one s_1_
specifies the value (-1, in this case) to be ignored.
const UShortValue CanonMakerNote::s_1_(65535, unsignedShort); // Till bug is resolved
Note s_1_ is temporarily having the value 65535 till #1203 that causes
signedShorts to be interpreted as unsignedShorts is resolved.
3. Exif.CanonSi.TargetAperture: TagInfo(0x0004, "TargetAperture", N_("Target Aperture"), N_("Target Aperture"), canonSiId, makerTags, unsignedShort, 1, printSi0x0015, true, us0_, TagInfo::less_equal),
Note the third argument TagInfo::less_equal. This combined with the
second argument us0_ (the number 0) signifies that any values in this
tag that are less than or equal (<=) to 0 should be ignored.
4. TagInfo(0x0028, "ImageUniqueID", N_("Image Unique ID"), N_("Image Unique ID"), canonId, makerTags, asciiString, -1, printValue, true, s0x16_, TagInfo::equal_to, TagInfo::String),
The previous examples have all been of Long type. This shows a case
where the default value is a string.
const AsciiValue CanonMakerNote::s0x16_("0000000000000000");
Once these tag values have been defined, the actual mechanics of
ignoring these default values happens in Image::exifData().
Before the exifData is returned, we loop through the data, ask the
data whether it needs to be ignored (which in turn checks its
underlying tagInfo and compares it with the default value, if
specified) and if so, deletes that element.
A compile-time switch called EXV_DONT_IGNORE_UNDEFINED which when set
to a non-zero value will cause the behavior to revert back to the
original where all values are reported irregardless of the fact that
they need to be ignored.
9 years ago
|
|
|
output(os,keys,"dont_ignore_undef" ,dont_ignore_undef);
|
|
|
|
output(os,keys,"config_path" ,Exiv2::Internal::getExiv2ConfigPath());
|
|
|
|
|
|
|
|
// #1147
|
|
|
|
#ifndef WIN32
|
|
|
|
uid_t uid = getuid() ; output(os,keys,"uid" , uid );
|
|
|
|
uid_t euid = geteuid() ; output(os,keys,"euid", euid );
|
|
|
|
uid_t gid = getgid() ; output(os,keys,"gid" , gid );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EXV_HAVE_XMP_TOOLKIT
|
|
|
|
const char* name = "xmlns";
|
|
|
|
|
|
|
|
Exiv2::Dictionary ns;
|
|
|
|
Exiv2::XmpProperties::registeredNamespaces(ns);
|
|
|
|
for ( Exiv2::Dictionary_i it = ns.begin(); it != ns.end() ; it++ ) {
|
|
|
|
std::string xmlns = (*it).first;
|
|
|
|
std::string uri = (*it).second;
|
|
|
|
output(os,keys,name,xmlns+":"+uri);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(__linux__)
|
|
|
|
dlclose(ph);
|
|
|
|
ph=NULL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|