#618: Added functions for easy access of common metadata, which is not always in the same tag. (Based on a discussion with and initial patch from Carsten Pfeiffer)

This commit is contained in:
Andreas Huggel 2009-03-07 15:26:00 +00:00
parent cde2a54cc5
commit 21ccbfce18
7 changed files with 360 additions and 187 deletions

View File

@ -56,6 +56,7 @@ include $(top_srcdir)/config/config.mk
# Add source files of sample programs to this list
BINSRC = addmoddel.cpp \
convert-test.cpp \
easyaccess-test.cpp \
exifcomment.cpp \
exifdata-test.cpp \
exifprint.cpp \

View File

@ -0,0 +1,58 @@
// ***************************************************************** -*- C++ -*-
// easyaccess-test.cpp, $Rev$
// Sample program using high-level metadata access functions
// included header files
#include <exiv2/image.hpp>
#include <exiv2/exif.hpp>
#include <exiv2/easyaccess.hpp>
#include <iostream>
#include <iomanip>
#include <cassert>
typedef Exiv2::ExifData::const_iterator (*EasyAccessFct)(const Exiv2::ExifData& ed);
struct EasyAccess {
const char* label_;
EasyAccessFct findFct_;
};
static const EasyAccess easyAccess[] = {
{ "Orientation", Exiv2::orientation },
{ "ISO speed", Exiv2::isoSpeed },
{ "Flash bias", Exiv2::flashBias },
{ "Exposure mode", Exiv2::exposureMode },
{ "Scene mode", Exiv2::sceneMode },
{ "Macro mode", Exiv2::macroMode },
{ "Image quality", Exiv2::imageQuality },
{ "White balance", Exiv2::whiteBalance },
{ "Lens name", Exiv2::lensName }
};
int main(int argc, char **argv)
try {
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " file\n";
return 1;
}
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[1]);
assert (image.get() != 0);
image->readMetadata();
Exiv2::ExifData& ed = image->exifData();
for (unsigned int i = 0; i < EXV_COUNTOF(easyAccess); ++i) {
Exiv2::ExifData::const_iterator pos = easyAccess[i].findFct_(ed);
if (pos != ed.end()) {
std::cout << std::setw(13) << std::left << easyAccess[i].label_ << " ("
<< std::setw(30) << pos->key() << ") : "
<< pos->print(&ed) << "\n";
}
}
return 0;
}
catch (Exiv2::AnyError& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -73,6 +73,7 @@ CCSRC = basicio.cpp \
cr2image.cpp \
crwimage.cpp \
datasets.cpp \
easyaccess.cpp \
error.cpp \
exif.cpp \
futils.cpp \

View File

@ -48,6 +48,7 @@ EXIV2_RCSID("@(#) $Id$")
#include "utils.hpp"
#include "types.hpp"
#include "exif.hpp"
#include "easyaccess.hpp"
#include "canonmn.hpp"
#include "iptc.hpp"
#include "xmp.hpp"
@ -324,23 +325,8 @@ namespace Action {
// Flash
printTag(exifData, "Exif.Photo.Flash", _("Flash"));
// Todo: Flash bias, flash energy
// Todo: Implement this for other cameras
done = false;
printLabel(_("Flash bias"));
if (!done) {
done = 0 != printTag(exifData, "Exif.CanonSi.FlashBias");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Panasonic.FlashBias");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Olympus.FlashBias");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.OlympusCs.FlashExposureComp");
}
std::cout << std::endl;
// Flash bias
printTag(exifData, Exiv2::flashBias, _("Flash bias"));
// Actual focal length and 35 mm equivalent
// Todo: Calculate 35 mm equivalent a la jhead
@ -371,139 +357,19 @@ namespace Action {
std::cout << std::endl;
// ISO speed
// from ISOSpeedRatings or the Makernote
printLabel(_("ISO speed"));
done = false;
if (!done) {
done = 0 != printTag(exifData, "Exif.Photo.ISOSpeedRatings");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.CanonSi.ISOSpeed");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Nikon1.ISOSpeed");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Nikon2.ISOSpeed");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Nikon3.ISOSpeed");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCsNew.ISOSpeed");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCsOld.ISOSpeed");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCs5D.ISOSpeed");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCs7D.ISOSpeed");
}
std::cout << std::endl;
printTag(exifData, Exiv2::isoSpeed, _("ISO speed"));
// Exposure mode
// From ExposureProgram or Canon Makernote
printLabel(_("Exposure mode"));
done = false;
if (!done) {
done = 0 != printTag(exifData, "Exif.Photo.ExposureProgram");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.CanonCs.ExposureProgram");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCs7D.ExposureMode");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCs5D.ExposureMode");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCsNew.ExposureMode");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCsOld.ExposureMode");
}
std::cout << std::endl;
printTag(exifData, Exiv2::exposureMode, _("Exposure mode"));
// Metering mode
printTag(exifData, "Exif.Photo.MeteringMode", _("Metering mode"));
// Macro mode
// Todo: Implement this for other cameras
printLabel(_("Macro mode"));
done = false;
if (!done) {
done = 0 != printTag(exifData, "Exif.CanonCs.Macro");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Fujifilm.Macro");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Olympus.Macro");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.OlympusCs.MacroMode");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Panasonic.Macro");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCsNew.MacroMode");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCsOld.MacroMode");
}
std::cout << std::endl;
printTag(exifData, Exiv2::macroMode, _("Macro mode"));
// Image quality setting (compression)
// Todo: Implement this for other cameras
printLabel(_("Image quality"));
done = false;
if (!done) {
done = 0 != printTag(exifData, "Exif.CanonCs.Quality");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Fujifilm.Quality");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Sigma.Quality");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Nikon1.Quality");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Nikon2.Quality");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Nikon3.Quality");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Olympus.Quality");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.OlympusCs.Quality");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Panasonic.Quality");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Minolta.Quality");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCsNew.Quality");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCsOld.Quality");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCs5D.Quality");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCs7D.Quality");
}
std::cout << std::endl;
printTag(exifData, Exiv2::imageQuality, _("Image quality"));
// Exif Resolution
printLabel(_("Exif Resolution"));
@ -529,52 +395,7 @@ namespace Action {
std::cout << std::endl;
// White balance
// Todo: Implement this for other cameras
printLabel(_("White balance"));
done = false;
if (!done) {
done = 0 != printTag(exifData, "Exif.CanonSi.WhiteBalance");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Fujifilm.WhiteBalance");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Sigma.WhiteBalance");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Nikon1.WhiteBalance");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Nikon2.WhiteBalance");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Nikon3.WhiteBalance");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Olympus.WhiteBalance");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.OlympusCs.WhiteBalance");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Panasonic.WhiteBalance");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCs5D.WhiteBalance");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCs7D.WhiteBalance");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCsNew.WhiteBalance");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.MinoltaCsOld.WhiteBalance");
}
if (!done) {
done = 0 != printTag(exifData, "Exif.Photo.WhiteBalance");
}
std::cout << std::endl;
printTag(exifData, Exiv2::whiteBalance, _("White balance"));
// Thumbnail
printLabel(_("Thumbnail"));
@ -633,6 +454,23 @@ namespace Action {
return rc;
} // Print::printTag
int Print::printTag(const Exiv2::ExifData& exifData,
EasyAccessFct easyAccessFct,
const std::string& label) const
{
int rc = 0;
if (!label.empty()) {
printLabel(label);
}
Exiv2::ExifData::const_iterator md = easyAccessFct(exifData);
if (md != exifData.end()) {
md->write(std::cout, &exifData);
rc = 1;
}
if (!label.empty()) std::cout << std::endl;
return rc;
} // Print::printTag
int Print::printList()
{
int rc = 0;

View File

@ -184,6 +184,16 @@ namespace Action {
int printTag(const Exiv2::ExifData& exifData,
const std::string& key,
const std::string& label ="") const;
//! Type for an Exiv2 Easy access function
typedef Exiv2::ExifData::const_iterator (*EasyAccessFct)(const Exiv2::ExifData& ed);
/*!
@brief Print one summary line with a label (if provided) and requested
data. A line break is printed only if a label is provided.
@return 1 if a line was written, 0 if the information was not found.
*/
int printTag(const Exiv2::ExifData& exifData,
EasyAccessFct easyAccessFct,
const std::string& label) const;
private:
virtual Print* clone_() const;

203
src/easyaccess.cpp Normal file
View File

@ -0,0 +1,203 @@
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004-2009 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: easyaccess.cpp
Version: $Rev$
Author(s): Carsten Pfeiffer <pfeiffer@kde.org>
Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 28-Feb-09, gis: created
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Id$")
// *****************************************************************************
// included header files
#include "easyaccess.hpp"
// *****************************************************************************
namespace {
using namespace Exiv2;
/*!
@brief Search \em ed for a Metadatum specified by the \em keys.
The \em keys are searched in the order of their appearance, the
first available Metadatum is returned.
@param ed The %Exif metadata container to search
@param keys Array of keys to look for
@param count Number of elements in the array
*/
ExifData::const_iterator findMetadatum(const ExifData& ed,
const char* keys[],
int count)
{
for (int i = 0; i < count; ++i) {
ExifData::const_iterator pos = ed.findKey(ExifKey(keys[i]));
if (pos != ed.end()) return pos;
}
return ed.end();
} // findMetadatum
} // anonymous namespace
// *****************************************************************************
// class member definitions
namespace Exiv2 {
ExifData::const_iterator orientation(const ExifData& ed)
{
static const char* keys[] = {
"Exif.Image.Orientation",
"Exif.Panasonic.Rotation",
"Exif.MinoltaCs5D.Rotation",
"Exif.MinoltaCs7D.Rotation"
};
return findMetadatum(ed, keys, EXV_COUNTOF(keys));
}
ExifData::const_iterator isoSpeed(const ExifData& ed)
{
static const char* keys[] = {
"Exif.Photo.ISOSpeedRatings",
"Exif.CanonSi.ISOSpeed",
"Exif.CanonCs.ISOSpeed",
"Exif.Nikon1.ISOSpeed",
"Exif.Nikon2.ISOSpeed",
"Exif.Nikon3.ISOSpeed",
"Exif.MinoltaCsNew.ISOSpeed",
"Exif.MinoltaCsOld.ISOSpeed",
"Exif.MinoltaCs5D.ISOSpeed",
"Exif.MinoltaCs7D.ISOSpeed",
"Exif.Pentax.ISO",
"Exif.Olympus.ISOSpeed"
};
return findMetadatum(ed, keys, EXV_COUNTOF(keys));
}
ExifData::const_iterator flashBias(const ExifData& ed)
{
static const char* keys[] = {
"Exif.CanonSi.FlashBias",
"Exif.Panasonic.FlashBias",
"Exif.Olympus.FlashBias",
"Exif.OlympusCs.FlashExposureComp"
};
return findMetadatum(ed, keys, EXV_COUNTOF(keys));
}
ExifData::const_iterator exposureMode(const ExifData& ed)
{
static const char* keys[] = {
"Exif.Photo.ExposureProgram",
"Exif.CanonCs.ExposureProgram",
"Exif.MinoltaCs7D.ExposureMode",
"Exif.MinoltaCs5D.ExposureMode",
"Exif.MinoltaCsNew.ExposureMode",
"Exif.MinoltaCsOld.ExposureMode",
"Exif.Sigma.ExposureMode"
};
return findMetadatum(ed, keys, EXV_COUNTOF(keys));
}
ExifData::const_iterator sceneMode(const ExifData& ed)
{
static const char* keys[] = {
"Exif.CanonCs.EasyMode",
"Exif.Fujifilm.PictureMode",
"Exif.MinoltaCsNew.SubjectProgram",
"Exif.OlympusCs.SceneMode",
"Exif.Panasonic.ShootingMode",
"Exif.Panasonic.SceneMode",
"Exif.Pentax.PictureMode"
};
return findMetadatum(ed, keys, EXV_COUNTOF(keys));
}
ExifData::const_iterator macroMode(const ExifData& ed)
{
static const char* keys[] = {
"Exif.CanonCs.Macro",
"Exif.Fujifilm.Macro",
"Exif.Olympus.Macro",
"Exif.OlympusCs.MacroMode",
"Exif.Panasonic.Macro",
"Exif.MinoltaCsNew.MacroMode",
"Exif.MinoltaCsOld.MacroMode"
};
return findMetadatum(ed, keys, EXV_COUNTOF(keys));
}
ExifData::const_iterator imageQuality(const ExifData& ed)
{
static const char* keys[] = {
"Exif.CanonCs.Quality",
"Exif.Fujifilm.Quality",
"Exif.Sigma.Quality",
"Exif.Nikon1.Quality",
"Exif.Nikon2.Quality",
"Exif.Nikon3.Quality",
"Exif.Olympus.Quality",
"Exif.OlympusCs.Quality",
"Exif.Panasonic.Quality",
"Exif.Minolta.Quality",
"Exif.MinoltaCsNew.Quality",
"Exif.MinoltaCsOld.Quality",
"Exif.MinoltaCs5D.Quality",
"Exif.MinoltaCs7D.Quality"
};
return findMetadatum(ed, keys, EXV_COUNTOF(keys));
}
ExifData::const_iterator whiteBalance(const ExifData& ed)
{
static const char* keys[] = {
"Exif.CanonSi.WhiteBalance",
"Exif.Fujifilm.WhiteBalance",
"Exif.Sigma.WhiteBalance",
"Exif.Nikon1.WhiteBalance",
"Exif.Nikon2.WhiteBalance",
"Exif.Nikon3.WhiteBalance",
"Exif.Olympus.WhiteBalance",
"Exif.OlympusCs.WhiteBalance",
"Exif.Panasonic.WhiteBalance",
"Exif.MinoltaCs5D.WhiteBalance",
"Exif.MinoltaCs7D.WhiteBalance",
"Exif.MinoltaCsNew.WhiteBalance",
"Exif.MinoltaCsOld.WhiteBalance",
"Exif.Photo.WhiteBalance"
};
return findMetadatum(ed, keys, EXV_COUNTOF(keys));
}
ExifData::const_iterator lensName(const ExifData& ed)
{
static const char* keys[] = {
"Exif.CanonCs.LensType",
"Exif.Nikon3.LensData",
"Exif.Minolta.LensID",
"Exif.Pentax.LensType"
};
return findMetadatum(ed, keys, EXV_COUNTOF(keys));
}
} // namespace Exiv2

62
src/easyaccess.hpp Normal file
View File

@ -0,0 +1,62 @@
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004-2009 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 easyaccess.hpp
@brief Provides easy (high-level) access to some Exif meta data.
@version $Rev$
@author Carsten Pfeiffer <pfeiffer@kde.org>
@date 28-Feb-09, gis: created
*/
#ifndef EASYACCESS_HPP_
#define EASYACCESS_HPP_
// *****************************************************************************
// included header files
#include "exif.hpp"
namespace Exiv2 {
// *****************************************************************************
// class declarations
class ExifData;
//! Return the orientation of the image
EXIV2API ExifData::const_iterator orientation(const ExifData& ed);
//! Return the ISO speed used to shoot the image
EXIV2API ExifData::const_iterator isoSpeed(const ExifData& ed);
//! Return the flash bias value
EXIV2API ExifData::const_iterator flashBias(const ExifData& ed);
//! Return the exposure mode setting
EXIV2API ExifData::const_iterator exposureMode(const ExifData& ed);
//! Return the scene mode setting
EXIV2API ExifData::const_iterator sceneMode(const ExifData& ed);
//! Return the macro mode setting
EXIV2API ExifData::const_iterator macroMode(const ExifData& ed);
//! Return the image quality setting
EXIV2API ExifData::const_iterator imageQuality(const ExifData& ed);
//! Return the white balance setting
EXIV2API ExifData::const_iterator whiteBalance(const ExifData& ed);
//! Return the name of the lens used
EXIV2API ExifData::const_iterator lensName(const ExifData& ed);
} // namespace Exiv2
#endif // EASYACCESS_HPP_