Canon CRW read support, first try. Introduces a new approach to parsing metadata. Cluttered by some related additions to the Canon makernote note and a bit of cleanup.
This commit is contained in:
+5
-5
@@ -51,16 +51,16 @@ include $(top_srcdir)/config/config.mk
|
||||
CCHDR = exv_conf.h exv_msvc.h mn.hpp rcsid.hpp
|
||||
|
||||
# Add library C++ source files to this list
|
||||
CCSRC = basicio.cpp canonmn.cpp datasets.cpp error.cpp exif.cpp futils.cpp \
|
||||
fujimn.cpp ifd.cpp image.cpp iptc.cpp jpgimage.cpp makernote.cpp \
|
||||
metadatum.cpp nikonmn.cpp olympusmn.cpp panasonicmn.cpp sigmamn.cpp \
|
||||
sonymn.cpp tags.cpp types.cpp value.cpp
|
||||
CCSRC = basicio.cpp canonmn.cpp crwimage.cpp datasets.cpp error.cpp exif.cpp \
|
||||
futils.cpp fujimn.cpp ifd.cpp image.cpp iptc.cpp jpgimage.cpp \
|
||||
makernote.cpp metadatum.cpp nikonmn.cpp olympusmn.cpp panasonicmn.cpp \
|
||||
sigmamn.cpp sonymn.cpp tags.cpp types.cpp value.cpp
|
||||
|
||||
# Add source files of simple applications to this list
|
||||
BINSRC = addmoddel.cpp dataarea-test.cpp exifcomment.cpp exifdata-test.cpp \
|
||||
exifprint.cpp ifd-test.cpp iotest.cpp iptceasy.cpp iptcprint.cpp \
|
||||
iptctest.cpp key-test.cpp makernote-test.cpp taglist.cpp write-test.cpp \
|
||||
write2-test.cpp
|
||||
write2-test.cpp
|
||||
|
||||
# Main source file of the Exiv2 application
|
||||
EXIV2MAIN = exiv2.cpp
|
||||
|
||||
+11
-11
@@ -229,28 +229,28 @@ namespace Action {
|
||||
md = exifData.findKey(
|
||||
Exiv2::ExifKey("Exif.Photo.ShutterSpeedValue"));
|
||||
if (md != exifData.end()) {
|
||||
double tmp = exp(log(2.0) * md->toFloat()) + 0.5;
|
||||
double tmp = exp(log(2.0) * md->toFloat());
|
||||
if (tmp > 1) {
|
||||
std::cout << "1/" << static_cast<long>(tmp) << " s";
|
||||
std::cout << "1/" << static_cast<long>(tmp + 0.5);
|
||||
}
|
||||
else {
|
||||
std::cout << static_cast<long>(1/tmp) << " s";
|
||||
std::cout << static_cast<long>(1/tmp + 0.5);
|
||||
}
|
||||
std::cout << " s";
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
// Aperture
|
||||
// Get if from FNumber and, failing that, try ApertureValue
|
||||
bool done = false;
|
||||
std::cout << std::setw(align_) << std::setfill(' ') << std::left
|
||||
<< "Aperture" << ": ";
|
||||
if (0 == printTag(exifData, "Exif.Photo.FNumber")) {
|
||||
md = exifData.findKey(
|
||||
Exiv2::ExifKey("Exif.Photo.ApertureValue"));
|
||||
if (md != exifData.end()) {
|
||||
std::cout << std::fixed << std::setprecision(1)
|
||||
<< "F" << exp(log(2.0) * md->toFloat() / 2);
|
||||
}
|
||||
if (!done) {
|
||||
done = 0 != printTag(exifData, "Exif.Photo.FNumber");
|
||||
}
|
||||
if (!done) {
|
||||
done = 0 != printTag(exifData, "Exif.Photo.ApertureValue");
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
@@ -262,7 +262,7 @@ namespace Action {
|
||||
|
||||
// Todo: Flash bias, flash energy
|
||||
// Todo: Implement this for other cameras
|
||||
bool done = false;
|
||||
done = false;
|
||||
std::cout << std::setw(align_) << std::setfill(' ') << std::left
|
||||
<< "Flash bias" << ": ";
|
||||
if (!done) {
|
||||
|
||||
@@ -406,8 +406,6 @@ namespace Exiv2 {
|
||||
/*!
|
||||
@brief Flush any buffered writes and get the current file size
|
||||
in bytes.
|
||||
@note On Win32 systems the file must be closed prior to calling this
|
||||
function.
|
||||
@return Size of the file in bytes;<BR>
|
||||
-1 if failure;
|
||||
*/
|
||||
|
||||
+32
-32
@@ -49,27 +49,6 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
// *****************************************************************************
|
||||
// local declarations
|
||||
namespace {
|
||||
/*
|
||||
@brief Convert Canon hex-based EV (modulo 0x20) to real number
|
||||
Ported from Phil Harvey's Image::ExifTool::Canon::CanonEv
|
||||
by Will Stokes
|
||||
|
||||
0x00 -> 0
|
||||
0x0c -> 0.33333
|
||||
0x10 -> 0.5
|
||||
0x14 -> 0.66666
|
||||
0x20 -> 1
|
||||
..
|
||||
160 -> 5
|
||||
128 -> 4
|
||||
143 -> 4.46875
|
||||
*/
|
||||
float canonEv(long val);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// class member definitions
|
||||
namespace Exiv2 {
|
||||
@@ -163,8 +142,8 @@ namespace Exiv2 {
|
||||
TagInfo(0x0001, "0x0001", "0x0001", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue),
|
||||
TagInfo(0x0002, "ISOSpeed", "ISOSpeed", "ISO speed used", canonCs2IfdId, makerTags, unsignedShort, printCs20x0002),
|
||||
TagInfo(0x0003, "0x0003", "0x0003", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue),
|
||||
TagInfo(0x0004, "0x0004", "0x0004", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue),
|
||||
TagInfo(0x0005, "0x0005", "0x0005", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue),
|
||||
TagInfo(0x0004, "TargetAperture", "TargetAperture", "Target Aperture", canonCs2IfdId, makerTags, unsignedShort, printCs20x0015),
|
||||
TagInfo(0x0005, "TargetShutterSpeed", "TargetShutterSpeed", "Target shutter speed", canonCs2IfdId, makerTags, unsignedShort, printCs20x0016),
|
||||
TagInfo(0x0006, "0x0006", "0x0006", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue),
|
||||
TagInfo(0x0007, "WhiteBalance", "WhiteBalance", "White balance setting", canonCs2IfdId, makerTags, unsignedShort, printCs20x0007),
|
||||
TagInfo(0x0008, "0x0008", "0x0008", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue),
|
||||
@@ -180,8 +159,8 @@ namespace Exiv2 {
|
||||
TagInfo(0x0012, "0x0012", "0x0012", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue),
|
||||
TagInfo(0x0013, "SubjectDistance", "SubjectDistance", "Subject distance (units are not clear)", canonCs2IfdId, makerTags, unsignedShort, printCs20x0013),
|
||||
TagInfo(0x0014, "0x0014", "0x0014", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue),
|
||||
TagInfo(0x0015, "0x0015", "0x0015", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue),
|
||||
TagInfo(0x0016, "0x0016", "0x0016", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue),
|
||||
TagInfo(0x0015, "ApertureValue", "ApertureValue", "Aperture", canonCs2IfdId, makerTags, unsignedShort, printCs20x0015),
|
||||
TagInfo(0x0016, "ShutterSpeedValue", "ShutterSpeedValue", "Shutter speed", canonCs2IfdId, makerTags, unsignedShort, printCs20x0016),
|
||||
TagInfo(0x0017, "0x0017", "0x0017", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue),
|
||||
TagInfo(0x0018, "0x0018", "0x0018", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue),
|
||||
TagInfo(0x0019, "0x0019", "0x0019", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue),
|
||||
@@ -893,6 +872,33 @@ namespace Exiv2 {
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& CanonMakerNote::printCs20x0015(std::ostream& os,
|
||||
const Value& value)
|
||||
{
|
||||
if (value.typeId() != unsignedShort) return os << value;
|
||||
|
||||
std::ostringstream oss;
|
||||
oss.copyfmt(os);
|
||||
os << std::setprecision(2)
|
||||
<< "F" << fnumber(canonEv(value.toLong()));
|
||||
os.copyfmt(oss);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& CanonMakerNote::printCs20x0016(std::ostream& os,
|
||||
const Value& value)
|
||||
{
|
||||
if (value.typeId() != unsignedShort) return os << value;
|
||||
|
||||
URational ur = exposureTime(canonEv(value.toLong()));
|
||||
os << ur.first;
|
||||
if (ur.second > 1) {
|
||||
os << "/" << ur.second;
|
||||
}
|
||||
return os << " s";
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// free functions
|
||||
|
||||
@@ -905,12 +911,6 @@ namespace Exiv2 {
|
||||
return MakerNote::AutoPtr(new CanonMakerNote(alloc));
|
||||
}
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
// *****************************************************************************
|
||||
// local definitions
|
||||
namespace {
|
||||
|
||||
float canonEv(long val)
|
||||
{
|
||||
// temporarily remove sign
|
||||
@@ -932,4 +932,4 @@ namespace {
|
||||
return sign * (val + frac) / 32.0f;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Exiv2
|
||||
|
||||
@@ -188,6 +188,10 @@ namespace Exiv2 {
|
||||
static std::ostream& printCs20x000f(std::ostream& os, const Value& value);
|
||||
//! Subject distance
|
||||
static std::ostream& printCs20x0013(std::ostream& os, const Value& value);
|
||||
//! Aperture
|
||||
static std::ostream& printCs20x0015(std::ostream& os, const Value& value);
|
||||
//! Shutter speed
|
||||
static std::ostream& printCs20x0016(std::ostream& os, const Value& value);
|
||||
//@}
|
||||
|
||||
//! @cond IGNORE
|
||||
@@ -234,6 +238,27 @@ namespace Exiv2 {
|
||||
}; // class CanonMakerNote
|
||||
|
||||
static CanonMakerNote::RegisterMn registerCanonMakerNote;
|
||||
|
||||
// *****************************************************************************
|
||||
// template, inline and free functions
|
||||
|
||||
/*!
|
||||
@brief Convert Canon hex-based EV (modulo 0x20) to real number
|
||||
Ported from Phil Harvey's Image::ExifTool::Canon::CanonEv
|
||||
by Will Stokes
|
||||
|
||||
0x00 -> 0
|
||||
0x0c -> 0.33333
|
||||
0x10 -> 0.5
|
||||
0x14 -> 0.66666
|
||||
0x20 -> 1
|
||||
..
|
||||
160 -> 5
|
||||
128 -> 4
|
||||
143 -> 4.46875
|
||||
*/
|
||||
float canonEv(long val);
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
#endif // #ifndef CANONMN_HPP_
|
||||
|
||||
@@ -0,0 +1,686 @@
|
||||
// ***************************************************************** -*- C++ -*-
|
||||
/*
|
||||
* Copyright (C) 2005 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
/*
|
||||
File: crwimage.cpp
|
||||
Version: $Rev$
|
||||
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
|
||||
History: 28-Aug-05, ahu: created
|
||||
|
||||
*/
|
||||
// *****************************************************************************
|
||||
#include "rcsid.hpp"
|
||||
EXIV2_RCSID("@(#) $Id$");
|
||||
|
||||
// Define DEBUG to output debug information to std::cerr, e.g, by calling make
|
||||
// like this: make DEFS=-DDEBUG crwimage.o
|
||||
//#define DEBUG
|
||||
|
||||
// *****************************************************************************
|
||||
// included header files
|
||||
#ifdef _MSC_VER
|
||||
# include "exv_msvc.h"
|
||||
#else
|
||||
# include "exv_conf.h"
|
||||
#endif
|
||||
|
||||
#include "crwimage.hpp"
|
||||
#include "error.hpp"
|
||||
#include "futils.hpp"
|
||||
#include "value.hpp"
|
||||
#include "tags.hpp"
|
||||
#include "canonmn.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
|
||||
// *****************************************************************************
|
||||
// class member definitions
|
||||
namespace Exiv2 {
|
||||
|
||||
// Local functions. These could be static private functions on Image
|
||||
// subclasses but then ImageFactory needs to be made a friend.
|
||||
/*!
|
||||
@brief Create a new CrwImage instance and return an auto-pointer to it.
|
||||
Caller owns the returned object and the auto-pointer ensures that
|
||||
it will be deleted.
|
||||
*/
|
||||
Image::AutoPtr newCrwInstance(BasicIo::AutoPtr io, bool create);
|
||||
|
||||
//! Check if the file iIo is a CRW image.
|
||||
bool isCrwType(BasicIo& iIo, bool advance);
|
||||
|
||||
const byte CrwImage::blank_[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
CrwImage::CrwImage(BasicIo::AutoPtr io, bool create)
|
||||
: io_(io)
|
||||
{
|
||||
if (create) {
|
||||
initImage(blank_, sizeof(blank_));
|
||||
}
|
||||
} // CrwImage::CrwImage
|
||||
|
||||
int CrwImage::initImage(const byte initData[], size_t dataSize)
|
||||
{
|
||||
if (io_->open() != 0) {
|
||||
return 4;
|
||||
}
|
||||
IoCloser closer(*io_);
|
||||
if (static_cast<size_t>(io_->write(initData, dataSize)) != dataSize) {
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
} // CrwImage::initImage
|
||||
|
||||
bool CrwImage::good() const
|
||||
{
|
||||
if (io_->open() != 0) return false;
|
||||
IoCloser closer(*io_);
|
||||
return isThisType(*io_, false);
|
||||
}
|
||||
|
||||
void CrwImage::clearMetadata()
|
||||
{
|
||||
clearExifData();
|
||||
clearComment();
|
||||
}
|
||||
|
||||
void CrwImage::setMetadata(const Image& image)
|
||||
{
|
||||
setExifData(image.exifData());
|
||||
setComment(image.comment());
|
||||
}
|
||||
|
||||
void CrwImage::clearExifData()
|
||||
{
|
||||
exifData_.clear();
|
||||
}
|
||||
|
||||
void CrwImage::setExifData(const ExifData& exifData)
|
||||
{
|
||||
exifData_ = exifData;
|
||||
}
|
||||
|
||||
void CrwImage::clearIptcData()
|
||||
{
|
||||
throw Error(31, "CrwImage::clearIptcData");
|
||||
}
|
||||
|
||||
void CrwImage::setIptcData(const IptcData& iptcData)
|
||||
{
|
||||
throw Error(31, "CrwImage::setIptcData");
|
||||
}
|
||||
|
||||
void CrwImage::clearComment()
|
||||
{
|
||||
comment_.erase();
|
||||
}
|
||||
|
||||
void CrwImage::setComment(const std::string& comment)
|
||||
{
|
||||
comment_ = comment;
|
||||
}
|
||||
|
||||
void CrwImage::readMetadata()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Reading CRW file " << io_->path() << "\n";
|
||||
#endif
|
||||
if (io_->open() != 0) {
|
||||
throw Error(9, io_->path(), strError());
|
||||
}
|
||||
IoCloser closer(*io_);
|
||||
// Ensure that this is the correct image type
|
||||
if (!isThisType(*io_, false)) {
|
||||
if (io_->error() || io_->eof()) throw Error(14);
|
||||
throw Error(33);
|
||||
}
|
||||
clearMetadata();
|
||||
|
||||
// Read the image into a memory buffer
|
||||
size_t imageSize = io_->size();
|
||||
DataBuf image(imageSize);
|
||||
io_->read(image.pData_, imageSize);
|
||||
if (io_->error() || io_->eof()) throw Error(14);
|
||||
|
||||
// Parse the image
|
||||
RawMetadata::AutoPtr parseTree(new CrwHeader);
|
||||
parseTree->read(image.pData_, image.size_, 0, invalidByteOrder);
|
||||
#ifdef DEBUG
|
||||
parseTree->print(std::cerr, invalidByteOrder);
|
||||
#endif
|
||||
parseTree->extract(*this, invalidByteOrder);
|
||||
|
||||
} // CrwImage::readMetadata
|
||||
|
||||
void CrwImage::writeMetadata()
|
||||
{
|
||||
// Todo: implement me!
|
||||
} // CrwImage::writeMetadata
|
||||
|
||||
//! @cond IGNORE
|
||||
CrwImage::CrwRegister::CrwRegister()
|
||||
{
|
||||
ImageFactory::registerImage(
|
||||
Image::crw, newCrwInstance, isCrwType);
|
||||
}
|
||||
//! @endcond
|
||||
|
||||
bool CrwImage::isThisType(BasicIo& iIo, bool advance) const
|
||||
{
|
||||
return isCrwType(iIo, advance);
|
||||
}
|
||||
|
||||
TypeId CrwEntry::typeId(uint16_t tag)
|
||||
{
|
||||
TypeId ti = invalidTypeId;
|
||||
switch (tag & 0x3800) {
|
||||
case 0x0000: ti = unsignedByte; break;
|
||||
case 0x0800: ti = asciiString; break;
|
||||
case 0x1000: ti = unsignedShort; break;
|
||||
case 0x1800: ti = unsignedLong; break;
|
||||
case 0x2000: ti = undefined; break;
|
||||
case 0x2800: // fallthrough
|
||||
case 0x3000: ti = directory; break;
|
||||
}
|
||||
return ti;
|
||||
} // CrwEntry::typeId
|
||||
|
||||
DataLocId CrwEntry::dataLocation(uint16_t tag)
|
||||
{
|
||||
DataLocId di = invalidDataLocId;
|
||||
switch (tag & 0xc000) {
|
||||
case 0x0000: di = valueData; break;
|
||||
case 0x4000: di = directoryData; break;
|
||||
}
|
||||
return di;
|
||||
} // CrwEntry::dataLocation
|
||||
|
||||
void CrwEntry::add(RawMetadata::AutoPtr component)
|
||||
{
|
||||
throw Error(34, "CrwEntry::add");
|
||||
} // CrwEntry::add
|
||||
|
||||
void CrwEntry::read(const byte* buf,
|
||||
size_t len,
|
||||
size_t start,
|
||||
ByteOrder byteOrder,
|
||||
long /*shift*/)
|
||||
{
|
||||
if (len < 10) throw Error(33);
|
||||
tag_ = getUShort(buf + start, byteOrder);
|
||||
switch (dataLocation()) {
|
||||
case valueData:
|
||||
size_ = getULong(buf + start + 2, byteOrder);
|
||||
offset_ = getULong(buf + start + 6, byteOrder);
|
||||
break;
|
||||
case directoryData:
|
||||
size_ = 8;
|
||||
offset_ = start + 2;
|
||||
break;
|
||||
case invalidDataLocId:
|
||||
case lastDataLocId:
|
||||
// empty
|
||||
break;
|
||||
}
|
||||
pData_ = buf + offset_;
|
||||
} // CrwEntry::read
|
||||
|
||||
void CrwEntry::extract(Image& image, ByteOrder byteOrder) const
|
||||
{
|
||||
CrwMap::extract(*this, image, byteOrder);
|
||||
} // CrwEntry::extract
|
||||
|
||||
void CrwEntry::print(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const
|
||||
{
|
||||
os << prefix
|
||||
<< "tag = 0x" << std::setw(4) << std::setfill('0')
|
||||
<< std::hex << std::right << tagId()
|
||||
<< ", dir = 0x" << std::setw(4) << std::setfill('0')
|
||||
<< std::hex << std::right << dir()
|
||||
<< ", type = " << TypeInfo::typeName(typeId())
|
||||
<< ", size = " << std::dec << size_
|
||||
<< ", offset = " << offset_ << "\n";
|
||||
|
||||
Value::AutoPtr value;
|
||||
if (typeId() != directory) {
|
||||
value = Value::create(typeId());
|
||||
value->read(pData_, size_, byteOrder);
|
||||
if (value->size() < 100) {
|
||||
os << prefix << *value << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
} // CrwEntry::print
|
||||
|
||||
CrwDirectory::~CrwDirectory()
|
||||
{
|
||||
RawMetadata::Components::iterator b = components_.begin();
|
||||
RawMetadata::Components::iterator e = components_.end();
|
||||
for (RawMetadata::Components::iterator i = b; i != e; ++i) {
|
||||
delete *i;
|
||||
}
|
||||
}
|
||||
|
||||
void CrwDirectory::add(RawMetadata::AutoPtr component)
|
||||
{
|
||||
components_.push_back(component.release());
|
||||
} // CrwEntry::add
|
||||
|
||||
void CrwDirectory::read(const byte* buf,
|
||||
size_t len,
|
||||
size_t start,
|
||||
ByteOrder byteOrder,
|
||||
long /*shift*/)
|
||||
{
|
||||
CrwEntry::read(buf, len, start, byteOrder);
|
||||
readDirectory(buf + offset(), size(), 0, byteOrder, 0);
|
||||
} // CrwDirectory::read
|
||||
|
||||
void CrwDirectory::extract(Image& image, ByteOrder byteOrder) const
|
||||
{
|
||||
RawMetadata::Components::const_iterator b = components_.begin();
|
||||
RawMetadata::Components::const_iterator e = components_.end();
|
||||
for (RawMetadata::Components::const_iterator i = b; i != e; ++i) {
|
||||
(*i)->extract(image, byteOrder);
|
||||
}
|
||||
} // CrwDirectory::extract
|
||||
|
||||
void CrwDirectory::print(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const
|
||||
{
|
||||
CrwEntry::print(os, byteOrder, prefix);
|
||||
RawMetadata::Components::const_iterator b = components_.begin();
|
||||
RawMetadata::Components::const_iterator e = components_.end();
|
||||
for (RawMetadata::Components::const_iterator i = b; i != e; ++i) {
|
||||
(*i)->print(os, byteOrder, prefix + " ");
|
||||
}
|
||||
} // CrwDirectory::print
|
||||
|
||||
void CrwDirectory::readDirectory(const byte* buf,
|
||||
size_t len,
|
||||
size_t start,
|
||||
ByteOrder byteOrder,
|
||||
long /*shift*/)
|
||||
{
|
||||
uint32_t dataSize = getULong(buf + len - 4, byteOrder);
|
||||
uint32_t o = start + dataSize;
|
||||
if (o + 2 > len) throw Error(33);
|
||||
uint16_t count = getUShort(buf + o, byteOrder);
|
||||
o += 2;
|
||||
for (uint16_t i = 0; i < count; ++i) {
|
||||
if (o + 10 > len) throw Error(33);
|
||||
uint16_t tag = getUShort(buf + o, byteOrder);
|
||||
CrwEntry* p = 0;
|
||||
switch (CrwEntry::typeId(tag)) {
|
||||
case directory: p = new CrwDirectory; break;
|
||||
default: p = new CrwEntry; break;
|
||||
}
|
||||
p->setDir(this->tag());
|
||||
RawMetadata::AutoPtr m(p);
|
||||
m->read(buf, len, o, byteOrder);
|
||||
add(m);
|
||||
o += 10;
|
||||
}
|
||||
} // CrwDirectory::readDirectory
|
||||
|
||||
const char CrwHeader::signature_[] = "HEAPCCDR";
|
||||
|
||||
CrwHeader::~CrwHeader()
|
||||
{
|
||||
delete rootDirectory_;
|
||||
}
|
||||
|
||||
void CrwHeader::add(RawMetadata::AutoPtr component)
|
||||
{
|
||||
throw Error(34, "CrwHeader::add");
|
||||
} // CrwEntry::add
|
||||
|
||||
void CrwHeader::read(const byte* buf,
|
||||
size_t len,
|
||||
size_t start,
|
||||
ByteOrder byteOrder,
|
||||
long /*shift*/)
|
||||
{
|
||||
if (len < 14) throw Error(33);
|
||||
|
||||
if (buf[0] == 0x49 && buf[1] == 0x49) {
|
||||
byteOrder_ = littleEndian;
|
||||
}
|
||||
else if (buf[0] == 0x4d && buf[1] == 0x4d) {
|
||||
byteOrder_ = bigEndian;
|
||||
}
|
||||
else {
|
||||
throw Error(33);
|
||||
}
|
||||
offset_ = getULong(buf + 2, byteOrder_);
|
||||
if (std::memcmp(buf + 6, signature_, 8) != 0) {
|
||||
throw Error(33);
|
||||
}
|
||||
|
||||
rootDirectory_ = new CrwDirectory;
|
||||
rootDirectory_->readDirectory(buf + offset_, len - offset_, 0, byteOrder_);
|
||||
} // CrwHeader::read
|
||||
|
||||
void CrwHeader::extract(Image& image, ByteOrder byteOrder) const
|
||||
{
|
||||
// Nothing to extract from the header itself, just add correct byte order
|
||||
if (rootDirectory_) rootDirectory_->extract(image, byteOrder_);
|
||||
} // CrwHeader::extract
|
||||
|
||||
void CrwHeader::print(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const
|
||||
{
|
||||
os << prefix
|
||||
<< "Header, offset = 0x" << std::setw(8) << std::setfill('0')
|
||||
<< std::hex << std::right << offset_ << "\n";
|
||||
if (rootDirectory_) rootDirectory_->print(os, byteOrder_, prefix);
|
||||
} // CrwHeader::print
|
||||
|
||||
const CrwMapInfo CrwMap::crwMapInfos_[] = {
|
||||
CrwMapInfo(0x0805, 0x300a, 0, 0x9286, exifIfdId, extract0x0805, 0),
|
||||
CrwMapInfo(0x080a, 0x2807, 0, 0x010f, ifd0Id, extract0x080a, 0),
|
||||
CrwMapInfo(0x080a, 0x2807, 0, 0x0110, ifd0Id, 0, 0),
|
||||
CrwMapInfo(0x080b, 0x3004, 0, 0x0007, canonIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x0810, 0x2807, 0, 0x0009, canonIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x0815, 0x2804, 0, 0x0006, canonIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x1029, 0x300b, 0, 0x0002, canonIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x102a, 0x300b, 0, 0x0004, canonIfdId, extract0x102a, 0),
|
||||
CrwMapInfo(0x102d, 0x300b, 0, 0x0001, canonIfdId, extract0x102d, 0),
|
||||
CrwMapInfo(0x1033, 0x300b, 0, 0x000f, canonIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x1038, 0x300b, 0, 0x0012, canonIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x10a9, 0x300b, 0, 0x00a9, canonIfdId, extractBasic, 0),
|
||||
// CrwMapInfo(0x10b4, 0x300b, 0, 0x00b4, canonIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x10b4, 0x300b, 0, 0xa001, exifIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x10b5, 0x300b, 0, 0x00b5, canonIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x10c0, 0x300b, 0, 0x00c0, canonIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x10c1, 0x300b, 0, 0x00c1, canonIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x1807, 0x3002, 0, 0x9206, exifIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x180b, 0x2807, 0, 0x000c, canonIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x180e, 0x300a, 0, 0x9003, exifIfdId, extract0x180e, 0),
|
||||
CrwMapInfo(0x1810, 0x300a, 0, 0xa002, exifIfdId, extract0x1810, 0),
|
||||
CrwMapInfo(0x1810, 0x300a, 0, 0xa003, exifIfdId, extract0x1810, 0),
|
||||
CrwMapInfo(0x1817, 0x300a, 4, 0x0008, canonIfdId, extractBasic, 0),
|
||||
// CrwMapInfo(0x1818, 0x3002, 0, 0x9204, exifIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x183b, 0x300b, 0, 0x0015, canonIfdId, extractBasic, 0),
|
||||
CrwMapInfo(0x2008, 0x0000, 0, 0x0201, ifd1Id, extract0x2008, 0),
|
||||
CrwMapInfo(0x2008, 0x0000, 0, 0x0202, ifd1Id, 0, 0),
|
||||
CrwMapInfo(0x2008, 0x0000, 0, 0x0103, ifd1Id, 0, 0),
|
||||
CrwMapInfo(0x0000, 0x0000, 0, 0x0000, ifdIdNotSet, extractBasic, 0)
|
||||
}; // CrwMap::crwMapInfos_[]
|
||||
|
||||
void CrwMap::extract(const CrwEntry& crwEntry,
|
||||
Image& image,
|
||||
ByteOrder byteOrder)
|
||||
{
|
||||
const CrwMapInfo* cmi = crwMapInfo(crwEntry.dir(), crwEntry.tagId());
|
||||
if (cmi && cmi->toExif_) {
|
||||
cmi->toExif_(crwEntry, cmi, image, byteOrder);
|
||||
}
|
||||
} // CrwMap::extract
|
||||
|
||||
const CrwMapInfo* CrwMap::crwMapInfo(uint16_t dir, uint16_t tagId)
|
||||
{
|
||||
for (int i = 0; crwMapInfos_[i].ifdId_ != ifdIdNotSet; ++i) {
|
||||
if ( crwMapInfos_[i].crwDir_ == dir
|
||||
&& crwMapInfos_[i].crwTagId_ == tagId) {
|
||||
return &(crwMapInfos_[i]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} // CrwMap::crwMapInfo
|
||||
|
||||
void CrwMap::extract0x0805(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder /*byteOrder*/)
|
||||
{
|
||||
std::string s(reinterpret_cast<const char*>(crwEntry.pData()));
|
||||
image.setComment(s);
|
||||
} // CrwMap::extract0x0805
|
||||
|
||||
void CrwMap::extract0x080a(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder)
|
||||
{
|
||||
if (crwEntry.typeId() != asciiString) {
|
||||
return extractBasic(crwEntry, crwMapInfo, image, byteOrder);
|
||||
}
|
||||
|
||||
// Make
|
||||
ExifKey key1("Exif.Image.Make");
|
||||
Value::AutoPtr value1 = Value::create(crwEntry.typeId());
|
||||
uint32_t i = 0;
|
||||
for (; i < crwEntry.size() && crwEntry.pData()[i] != '\0'; ++i) {
|
||||
// empty
|
||||
}
|
||||
value1->read(crwEntry.pData(), ++i, byteOrder);
|
||||
image.exifData().add(key1, value1.get());
|
||||
|
||||
// Model
|
||||
ExifKey key2("Exif.Image.Model");
|
||||
Value::AutoPtr value2 = Value::create(crwEntry.typeId());
|
||||
uint32_t j = i;
|
||||
for (; i < crwEntry.size() && crwEntry.pData()[i] != '\0'; ++i) {
|
||||
// empty
|
||||
}
|
||||
value2->read(crwEntry.pData() + j, i - j + 1, byteOrder);
|
||||
image.exifData().add(key2, value2.get());
|
||||
} // CrwMap::extract0x080a
|
||||
|
||||
void CrwMap::extract0x102a(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder)
|
||||
{
|
||||
if (crwEntry.typeId() != unsignedShort) {
|
||||
return extractBasic(crwEntry, crwMapInfo, image, byteOrder);
|
||||
}
|
||||
|
||||
long aperture = 0;
|
||||
long shutterSpeed = 0;
|
||||
|
||||
std::string ifdItem(ExifTags::ifdItem(canonCs2IfdId));
|
||||
uint16_t c = 1;
|
||||
while (uint32_t(c)*2 < crwEntry.size()) {
|
||||
uint16_t n = 1;
|
||||
ExifKey key(c, ifdItem);
|
||||
UShortValue value;
|
||||
value.read(crwEntry.pData() + c*2, n*2, byteOrder);
|
||||
image.exifData().add(key, &value);
|
||||
if (c == 21) aperture = value.toLong();
|
||||
if (c == 22) shutterSpeed = value.toLong();
|
||||
c += n;
|
||||
}
|
||||
|
||||
// Exif.Photo.FNumber
|
||||
float f = fnumber(canonEv(aperture));
|
||||
// Beware: primitive conversion algorithm
|
||||
uint32_t den = 1000000;
|
||||
uint32_t nom = static_cast<uint32_t>(f * den);
|
||||
uint32_t g = gcd(nom, den);
|
||||
URational ur(nom/g, den/g);
|
||||
URationalValue fn;
|
||||
fn.value_.push_back(ur);
|
||||
image.exifData().add(ExifKey("Exif.Photo.FNumber"), &fn);
|
||||
|
||||
// Exif.Photo.ExposureTime
|
||||
ur = exposureTime(canonEv(shutterSpeed));
|
||||
URationalValue et;
|
||||
et.value_.push_back(ur);
|
||||
image.exifData().add(ExifKey("Exif.Photo.ExposureTime"), &et);
|
||||
|
||||
} // CrwMap::extract0x102a
|
||||
|
||||
void CrwMap::extract0x102d(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder)
|
||||
{
|
||||
if (crwEntry.typeId() != unsignedShort) {
|
||||
return extractBasic(crwEntry, crwMapInfo, image, byteOrder);
|
||||
}
|
||||
|
||||
std::string ifdItem(ExifTags::ifdItem(canonCs1IfdId));
|
||||
uint16_t c = 1;
|
||||
while (uint32_t(c)*2 < crwEntry.size()) {
|
||||
uint16_t n = 1;
|
||||
ExifKey key(c, ifdItem);
|
||||
UShortValue value;
|
||||
if (c == 23 && crwEntry.size() > 50) n = 3;
|
||||
value.read(crwEntry.pData() + c*2, n*2, byteOrder);
|
||||
image.exifData().add(key, &value);
|
||||
c += n;
|
||||
}
|
||||
} // CrwMap::extract0x102d
|
||||
|
||||
void CrwMap::extract0x180e(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder)
|
||||
{
|
||||
if (crwEntry.size() < 8 || crwEntry.typeId() != unsignedLong) {
|
||||
return extractBasic(crwEntry, crwMapInfo, image, byteOrder);
|
||||
}
|
||||
|
||||
ULongValue v;
|
||||
v.read(crwEntry.pData(), 8, byteOrder);
|
||||
time_t t = v.value_[0];
|
||||
|
||||
// Todo: use _r version
|
||||
struct tm* tm = std::gmtime(&t);
|
||||
size_t m = 20;
|
||||
char s[m];
|
||||
std::strftime(s, m, "%Y:%m:%d %T", tm);
|
||||
|
||||
ExifKey key(crwMapInfo->tag_, ExifTags::ifdItem(crwMapInfo->ifdId_));
|
||||
AsciiValue value;
|
||||
value.read(std::string(s));
|
||||
image.exifData().add(key, &value);
|
||||
} // CrwMap::extract0x180e
|
||||
|
||||
void CrwMap::extract0x1810(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder)
|
||||
{
|
||||
if (crwEntry.typeId() != unsignedLong || crwEntry.size() < 28) {
|
||||
return extractBasic(crwEntry, crwMapInfo, image, byteOrder);
|
||||
}
|
||||
|
||||
ExifKey key1("Exif.Photo.PixelXDimension");
|
||||
ULongValue value1;
|
||||
value1.read(crwEntry.pData(), 4, byteOrder);
|
||||
image.exifData().add(key1, &value1);
|
||||
|
||||
ExifKey key2("Exif.Photo.PixelYDimension");
|
||||
ULongValue value2;
|
||||
value2.read(crwEntry.pData() + 4, 4, byteOrder);
|
||||
image.exifData().add(key2, &value2);
|
||||
|
||||
} // CrwMap::extract0x1810
|
||||
|
||||
void CrwMap::extract0x2008(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* /*crwMapInfo*/,
|
||||
Image& image,
|
||||
ByteOrder /*byteOrder*/)
|
||||
{
|
||||
image.exifData().setJpegThumbnail(crwEntry.pData(), crwEntry.size());
|
||||
} // CrwMap::extract0x2008
|
||||
|
||||
void CrwMap::extractBasic(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder)
|
||||
{
|
||||
// create a key and value pair
|
||||
ExifKey key(crwMapInfo->tag_, ExifTags::ifdItem(crwMapInfo->ifdId_));
|
||||
Value::AutoPtr value;
|
||||
if (crwEntry.typeId() != directory) {
|
||||
value = Value::create(crwEntry.typeId());
|
||||
uint32_t size = 0;
|
||||
if (crwMapInfo->size_ != 0) {
|
||||
// size in the mapping table overrides all
|
||||
size = crwMapInfo->size_;
|
||||
}
|
||||
else if (crwEntry.typeId() == asciiString) {
|
||||
// determine size from the data, by looking for the first 0
|
||||
uint32_t i = 0;
|
||||
for (; i < crwEntry.size() && crwEntry.pData()[i] != '\0'; ++i) {
|
||||
// empty
|
||||
}
|
||||
size = ++i;
|
||||
}
|
||||
else {
|
||||
// by default, use the size from the directory entry
|
||||
size = crwEntry.size();
|
||||
}
|
||||
value->read(crwEntry.pData(), size, byteOrder);
|
||||
}
|
||||
// Add metadatum to exif data
|
||||
image.exifData().add(key, value.get());
|
||||
} // CrwMap::extractBasic
|
||||
|
||||
|
||||
// *************************************************************************
|
||||
// free functions
|
||||
|
||||
Image::AutoPtr newCrwInstance(BasicIo::AutoPtr io, bool create)
|
||||
{
|
||||
Image::AutoPtr image = Image::AutoPtr(new CrwImage(io, create));
|
||||
if (!image->good()) {
|
||||
image.reset();
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
bool isCrwType(BasicIo& iIo, bool advance)
|
||||
{
|
||||
bool result = true;
|
||||
byte tmpBuf[14];
|
||||
iIo.read(tmpBuf, 14);
|
||||
if (iIo.error() || iIo.eof()) {
|
||||
return false;
|
||||
}
|
||||
if (!( ('I' == tmpBuf[0] && 'I' == tmpBuf[1])
|
||||
|| ('M' == tmpBuf[0] && 'M' == tmpBuf[1]))) {
|
||||
result = false;
|
||||
}
|
||||
if ( true == result
|
||||
&& std::memcmp(tmpBuf + 6, CrwHeader::signature_, 8) != 0) {
|
||||
result = false;
|
||||
}
|
||||
if (!advance || !result) iIo.seek(-14, BasicIo::cur);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace Exiv2
|
||||
@@ -0,0 +1,608 @@
|
||||
// ***************************************************************** -*- C++ -*-
|
||||
/*
|
||||
* Copyright (C) 2005 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
/*!
|
||||
@file crwimage.hpp
|
||||
@brief Class CrwImage to access Canon CRW images.<BR>
|
||||
References:<BR>
|
||||
<a href="http://www.sno.phy.queensu.ca/~phil/exiftool/canon_raw.html">The Canon RAW (CRW) File Format</a> by Phil Harvey
|
||||
@version $Rev$
|
||||
@author Andreas Huggel (ahu)
|
||||
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
|
||||
@date 28-Aug-05, ahu: created
|
||||
*/
|
||||
#ifndef CRWIMAGE_HPP_
|
||||
#define CRWIMAGE_HPP_
|
||||
|
||||
// *****************************************************************************
|
||||
// included header files
|
||||
#include "types.hpp"
|
||||
#include "image.hpp"
|
||||
#include "basicio.hpp"
|
||||
#include "exif.hpp"
|
||||
#include "iptc.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// *****************************************************************************
|
||||
// namespace extensions
|
||||
namespace Exiv2 {
|
||||
|
||||
// *****************************************************************************
|
||||
// class declarations
|
||||
class CrwEntry;
|
||||
struct CrwMapInfo;
|
||||
|
||||
// *****************************************************************************
|
||||
// type definitions
|
||||
|
||||
//! Function pointer for functions to extract Exif tags from a CRW entry
|
||||
typedef void (*CrwExtractFct)(const CrwEntry&,
|
||||
const CrwMapInfo*,
|
||||
Image&,
|
||||
ByteOrder);
|
||||
|
||||
//! Function pointer for functions to insert CRW entries from an Exif tag
|
||||
typedef void (*CrwInsertFct)();
|
||||
|
||||
// *****************************************************************************
|
||||
// class definitions
|
||||
|
||||
/*!
|
||||
@brief Class to access Canon CRW images.
|
||||
*/
|
||||
class CrwImage : public Image {
|
||||
friend bool isCrwType(BasicIo& iIo, bool advance);
|
||||
|
||||
// NOT Implemented
|
||||
//! Copy constructor
|
||||
CrwImage(const CrwImage& rhs);
|
||||
//! Assignment operator
|
||||
CrwImage& operator=(const CrwImage& rhs);
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
/*!
|
||||
@brief Constructor that can either open an existing Crw image or create
|
||||
a new image from scratch. If a new image is to be created, any
|
||||
existing data is overwritten. Since the constructor can not return
|
||||
a result, callers should check the good() method after object
|
||||
construction to determine success or failure.
|
||||
@param io An auto-pointer that owns a BasicIo instance used for
|
||||
reading and writing image metadata. \b Important: The constructor
|
||||
takes ownership of the passed in BasicIo instance through the
|
||||
auto-pointer. Callers should not continue to use the BasicIo
|
||||
instance after it is passed to this method. Use the Image::io()
|
||||
method to get a temporary reference.
|
||||
@param create Specifies if an existing image should be read (false)
|
||||
or if a new file should be created (true).
|
||||
*/
|
||||
CrwImage(BasicIo::AutoPtr io, bool create);
|
||||
//! Destructor
|
||||
~CrwImage() {}
|
||||
//@}
|
||||
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
/*!
|
||||
@brief Read all metadata from the image. Before this method
|
||||
is called, the various metadata types (Iptc, Exif) will be empty.
|
||||
|
||||
This method returns success even when no metadata is found in
|
||||
the image. Callers must therefore check the size of individual
|
||||
metadata types before accessing the data.
|
||||
|
||||
@throw Error if opening or reading of the file fails or the image
|
||||
data is not valid (does not look like CRW data).
|
||||
*/
|
||||
void readMetadata();
|
||||
/*!
|
||||
@brief Write metadata back to the image.
|
||||
|
||||
All existing metadata sections in the image are either created,
|
||||
replaced, or erased. If values for a given metadata type have been
|
||||
assigned, a section for that metadata type will either be created or
|
||||
replaced. If no values have been assigned to a given metadata type,
|
||||
any exists section for that metadata type will be removed from the
|
||||
image.
|
||||
|
||||
@throw Error if the operation fails
|
||||
*/
|
||||
void writeMetadata();
|
||||
/*!
|
||||
@brief Assign new exif data. The new exif data is not written
|
||||
to the image until the writeMetadata() method is called.
|
||||
@param exifData An ExifData instance holding exif data to be copied
|
||||
*/
|
||||
void setExifData(const ExifData& exifData);
|
||||
void clearExifData();
|
||||
void setIptcData(const IptcData& iptcData);
|
||||
void clearIptcData();
|
||||
void setComment(const std::string& comment);
|
||||
void clearComment();
|
||||
void setMetadata(const Image& image);
|
||||
void clearMetadata();
|
||||
ExifData& exifData() { return exifData_; }
|
||||
IptcData& iptcData() { return iptcData_; }
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
bool good() const;
|
||||
const ExifData& exifData() const { return exifData_; }
|
||||
const IptcData& iptcData() const { return iptcData_; }
|
||||
std::string comment() const { return comment_; }
|
||||
BasicIo& io() const { return *io_; }
|
||||
//@}
|
||||
|
||||
//! @cond IGNORE
|
||||
// Public only so that we can create a static instance
|
||||
struct CrwRegister{
|
||||
CrwRegister();
|
||||
};
|
||||
//! @endcond
|
||||
|
||||
private:
|
||||
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
|
||||
int initImage(const byte initData[], size_t dataSize);
|
||||
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
/*!
|
||||
@brief Determine if the content of the BasicIo instance is a Crw image.
|
||||
|
||||
The advance flag determines if the read position in the stream is
|
||||
moved (see below). This applies only if the type matches and the
|
||||
function returns true. If the type does not match, the stream
|
||||
position is not changed. However, if reading from the stream fails,
|
||||
the stream position is undefined. Consult the stream state to obtain
|
||||
more information in this case.
|
||||
|
||||
@param iIo BasicIo instance to read from.
|
||||
@param advance Flag indicating whether the position of the io
|
||||
should be advanced by the number of characters read to
|
||||
analyse the data (true) or left at its original
|
||||
position (false). This applies only if the type matches.
|
||||
@return true if the data matches the type of this class;<BR>
|
||||
false if the data does not match
|
||||
*/
|
||||
bool isThisType(BasicIo& iIo, bool advance) const;
|
||||
/*!
|
||||
@brief Writes a Crw header (aka signature) to the BasicIo instance.
|
||||
@param oIo BasicIo instance that the header is written to.
|
||||
@return 0 if successful;<BR>
|
||||
2 if the input image is invalid or can not be read;<BR>
|
||||
4 if the temporary image can not be written to;<BR>
|
||||
-3 other temporary errors;<BR>
|
||||
*/
|
||||
int writeHeader(BasicIo& oIo) const;
|
||||
//@}
|
||||
|
||||
// DATA
|
||||
static const byte blank_[]; //!< Minimal CRW image
|
||||
|
||||
BasicIo::AutoPtr io_; //!< Image data io pointer
|
||||
ExifData exifData_; //!< Exif data container
|
||||
IptcData iptcData_; //!< Iptc data container
|
||||
std::string comment_; //!< User comment
|
||||
|
||||
}; // class CrwImage
|
||||
|
||||
static CrwImage::CrwRegister crwReg;
|
||||
|
||||
/*!
|
||||
Base class for all objects in a raw metadata parse tree.
|
||||
Defines the interface for raw metadata composites.
|
||||
*/
|
||||
class RawMetadata {
|
||||
public:
|
||||
//! RawMetadata auto_ptr type
|
||||
typedef std::auto_ptr<RawMetadata> AutoPtr;
|
||||
//! Container type to hold all metadata
|
||||
typedef std::vector<RawMetadata*> Components;
|
||||
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Virtual Destructor
|
||||
virtual ~RawMetadata() {}
|
||||
//@}
|
||||
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
//! Add a component to the composition
|
||||
virtual void add(AutoPtr component) =0;
|
||||
/*!
|
||||
@brief Read a component from a data buffer
|
||||
|
||||
@param buf Pointer to the data buffer.
|
||||
@param len Number of bytes in the data buffer.
|
||||
@param start Component starts at \em buf + \em start.
|
||||
@param byteOrder Applicable byte order (little or big endian).
|
||||
@param shift offsets in component are relative to \em buf + \em shift.
|
||||
|
||||
@throw Error If the component cannot be parsed.
|
||||
*/
|
||||
virtual void read(const byte* buf,
|
||||
size_t len,
|
||||
size_t start,
|
||||
ByteOrder byteOrder,
|
||||
long shift =0) =0;
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
/*!
|
||||
@brief Extract metadata from the component and add it to
|
||||
\em image.
|
||||
|
||||
@param image Image to add metadata to
|
||||
@param byteOrder Byte order
|
||||
*/
|
||||
virtual void extract(Image& image,
|
||||
ByteOrder byteOrder) const =0;
|
||||
|
||||
/*!
|
||||
@brief Print debug info about a component to \em os.
|
||||
|
||||
@param os Output stream to write to
|
||||
@param byteOrder Byte order
|
||||
@param prefix Prefix to be written before each line of output
|
||||
*/
|
||||
virtual void print(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix ="") const =0;
|
||||
//@}
|
||||
|
||||
}; // class RawMetadata
|
||||
|
||||
/*!
|
||||
@brief This class models one directory entry of a CIFF directory of
|
||||
a CRW (Canon Raw data) image.
|
||||
*/
|
||||
class CrwEntry : public RawMetadata {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
// Default and copy constructors are fine
|
||||
|
||||
//! Virtual destructor.
|
||||
virtual ~CrwEntry() {}
|
||||
//@}
|
||||
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
// Default assignment operator is fine
|
||||
|
||||
// See base class comment
|
||||
virtual void add(RawMetadata::AutoPtr component);
|
||||
|
||||
// See base class comment
|
||||
virtual void read(const byte* buf,
|
||||
size_t len,
|
||||
size_t start,
|
||||
ByteOrder byteOrder,
|
||||
long shift =0);
|
||||
|
||||
//! Set the directory tag for this component.
|
||||
void setDir(uint16_t dir) { dir_ = dir; }
|
||||
//@}
|
||||
|
||||
//! Return the type id for a tag
|
||||
static TypeId typeId(uint16_t tag);
|
||||
//! Return the data location id for a tag
|
||||
static DataLocId dataLocation(uint16_t tag);
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
// See base class comment
|
||||
virtual void extract(Image& image,
|
||||
ByteOrder byteOrder) const;
|
||||
|
||||
// See base class comment
|
||||
virtual void print(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix ="") const;
|
||||
|
||||
//! Return the tag of the directory containing this component
|
||||
uint16_t dir() const { return dir_; }
|
||||
|
||||
//! Return the tag of this component
|
||||
uint16_t tag() const { return tag_; }
|
||||
|
||||
/*!
|
||||
@brief Return the data size of this component
|
||||
|
||||
@note If the data is contained in the directory entry itself,
|
||||
this method returns 8, which is the maximum number
|
||||
of data bytes this component can have. The actual size,
|
||||
i.e., used data bytes, may be less than 8.
|
||||
*/
|
||||
uint32_t size() const { return size_; }
|
||||
|
||||
//! Return the offset to the data from the start of the directory
|
||||
uint32_t offset() const { return offset_; }
|
||||
|
||||
//! Return a pointer to the data area of this component
|
||||
const byte* pData() const { return pData_; }
|
||||
|
||||
//! Return the tag id of this component
|
||||
uint16_t tagId() const { return tag_ & 0x3fff; }
|
||||
|
||||
//! Return the type id of thi component
|
||||
TypeId typeId() const { return typeId(tag_); }
|
||||
|
||||
//! Return the data location for this component
|
||||
DataLocId dataLocation() const { return dataLocation(tag_); }
|
||||
//@}
|
||||
|
||||
private:
|
||||
// DATA
|
||||
uint16_t dir_; //!< Tag of the directory containing this component
|
||||
uint16_t tag_; //!< Tag of the entry
|
||||
uint32_t size_; //!< Size of the data area
|
||||
uint32_t offset_; //!< Offset to the data area from the start of the dir
|
||||
const byte* pData_; //!< Pointer to the data area
|
||||
|
||||
}; // class CrwEntry
|
||||
|
||||
//! This class models a CIFF directory of a CRW (Canon Raw data) image.
|
||||
class CrwDirectory : public CrwEntry {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
// Default and copy constructors are fine
|
||||
|
||||
//! Virtual destructor
|
||||
virtual ~CrwDirectory();
|
||||
//@}
|
||||
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
// Default assignment operator is fine
|
||||
|
||||
// See base class comment
|
||||
virtual void add(RawMetadata::AutoPtr component);
|
||||
|
||||
// See base class comment
|
||||
virtual void read(const byte* buf,
|
||||
size_t len,
|
||||
size_t start,
|
||||
ByteOrder byteOrder,
|
||||
long shift =0);
|
||||
|
||||
/*!
|
||||
@brief Parse a CIFF directory from a memory buffer
|
||||
|
||||
@param buf Pointer to the memory buffer containing the directory
|
||||
@param len Size of the memory buffer
|
||||
@param start Directory starts at buf + start
|
||||
@param byteOrder Applicable byte order (little or big endian)
|
||||
@param shift Not used
|
||||
*/
|
||||
void readDirectory(const byte* buf,
|
||||
size_t len,
|
||||
size_t start,
|
||||
ByteOrder byteOrder,
|
||||
long shift =0);
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
// See base class comment
|
||||
virtual void extract(Image& image,
|
||||
ByteOrder byteOrder) const;
|
||||
|
||||
// See base class comment
|
||||
virtual void print(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix ="") const;
|
||||
//@}
|
||||
|
||||
private:
|
||||
// DATA
|
||||
RawMetadata::Components components_; //!< List of components in this dir
|
||||
|
||||
}; // class CrwDirectory
|
||||
|
||||
//! This class models the header of a CRW (Canon Raw data) image.
|
||||
class CrwHeader : public RawMetadata {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Default constructor
|
||||
CrwHeader()
|
||||
: rootDirectory_ (0),
|
||||
byteOrder_ (littleEndian),
|
||||
offset_ (0x0000001a)
|
||||
{}
|
||||
//! Virtual destructor
|
||||
virtual ~CrwHeader();
|
||||
//@}
|
||||
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
// See base class comment
|
||||
virtual void add(RawMetadata::AutoPtr component);
|
||||
|
||||
// See base class comment
|
||||
virtual void read(const byte* buf,
|
||||
size_t len,
|
||||
size_t start,
|
||||
ByteOrder byteOrder,
|
||||
long shift =0);
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
// See base class comment
|
||||
virtual void extract(Image& image,
|
||||
ByteOrder byteOrder) const;
|
||||
|
||||
// See base class comment
|
||||
virtual void print(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix ="") const;
|
||||
//@}
|
||||
|
||||
// DATA
|
||||
static const char signature_[]; //!< Canon CRW signature "HEAPCCDR"
|
||||
|
||||
private:
|
||||
// DATA
|
||||
CrwDirectory* rootDirectory_; //!< Pointer to the root directory
|
||||
ByteOrder byteOrder_; //!< Applicable byte order
|
||||
uint32_t offset_; //!< Offset to the start of the root dir
|
||||
|
||||
}; // class CrwHeader
|
||||
|
||||
//! Structure for conversion info for CIFF entries
|
||||
struct CrwMapInfo {
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Default constructor
|
||||
CrwMapInfo(
|
||||
uint16_t crwTagId,
|
||||
uint16_t crwDir,
|
||||
uint32_t size,
|
||||
uint16_t tag,
|
||||
IfdId ifdId,
|
||||
CrwExtractFct toExif,
|
||||
CrwInsertFct fromExif)
|
||||
: crwTagId_ (crwTagId),
|
||||
crwDir_ (crwDir),
|
||||
size_ (size),
|
||||
tag_ (tag),
|
||||
ifdId_ (ifdId),
|
||||
toExif_ (toExif),
|
||||
fromExif_ (fromExif)
|
||||
{}
|
||||
//@}
|
||||
|
||||
// DATA
|
||||
uint16_t crwTagId_; //!< CRW tag id
|
||||
uint16_t crwDir_; //!< CRW directory tag
|
||||
uint32_t size_; //!< Data size (overwrites the size from the entry)
|
||||
uint16_t tag_; //!< Exif tag to map to
|
||||
IfdId ifdId_; //!< Exif Ifd id to map to
|
||||
CrwExtractFct toExif_; //!< Conversion function
|
||||
CrwInsertFct fromExif_; //!< Reverse conversion function
|
||||
|
||||
}; // struct CrwMapInfo
|
||||
|
||||
/*!
|
||||
@brief Static class providing mapping functionality from CRW entries
|
||||
to image metadata and vice versa
|
||||
*/
|
||||
class CrwMap {
|
||||
//! @name Not implemented
|
||||
//@{
|
||||
//! Default constructor
|
||||
CrwMap();
|
||||
//@}
|
||||
|
||||
public:
|
||||
/*!
|
||||
@brief Extract image metadata from a CRW entry convert and add it
|
||||
to the image metadata.
|
||||
|
||||
@param crwEntry Source CRW entry
|
||||
@param image Destination image for the metadata
|
||||
@param byteOrder Byte order in which the data of the entry is encoded
|
||||
*/
|
||||
static void extract(const CrwEntry& crwEntry,
|
||||
Image& image,
|
||||
ByteOrder byteOrder);
|
||||
|
||||
private:
|
||||
//! Return conversion information for one CRW \em dir and \em tagId
|
||||
static const CrwMapInfo* crwMapInfo(uint16_t dir, uint16_t tagId);
|
||||
|
||||
/*!
|
||||
@brief Standard extraction function to convert CRW entries to
|
||||
Exif metadata.
|
||||
|
||||
Uses the mapping defined in the conversion structure \em crwMapInfo
|
||||
to convert the data. If the \em size field in the conversion structure
|
||||
is not 0, then it is used instead of the \em size provided by the
|
||||
entry itself.
|
||||
*/
|
||||
static void extractBasic(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder);
|
||||
|
||||
//! Extract the user comment
|
||||
static void extract0x0805(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder);
|
||||
|
||||
//! Extract camera Make and Model information
|
||||
static void extract0x080a(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder);
|
||||
|
||||
//! Extract Canon Camera Settings 2
|
||||
static void extract0x102a(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder);
|
||||
|
||||
//! Extract Canon Camera Settings 1
|
||||
static void extract0x102d(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder);
|
||||
|
||||
//! Extract the date when the picture was taken
|
||||
static void extract0x180e(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder);
|
||||
|
||||
//! Extract image width and height
|
||||
static void extract0x1810(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder);
|
||||
|
||||
//! Extract the thumbnail image
|
||||
static void extract0x2008(const CrwEntry& crwEntry,
|
||||
const CrwMapInfo* crwMapInfo,
|
||||
Image& image,
|
||||
ByteOrder byteOrder);
|
||||
|
||||
// DATA
|
||||
static const CrwMapInfo crwMapInfos_[]; //!< Metadata conversion table
|
||||
|
||||
}; // class CrwMap
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
#endif // #ifndef CRWIMAGE_HPP_
|
||||
@@ -74,6 +74,10 @@ namespace Exiv2 {
|
||||
ErrMsg( 28, "Invalid charset: `%1'"), // %1=charset name
|
||||
ErrMsg( 29, "Unsupported date format"),
|
||||
ErrMsg( 30, "Unsupported time format"),
|
||||
ErrMsg( 31, "%1: CRW images don't support IPTC metadata"), // %1=function
|
||||
ErrMsg( 32, "%1: CRW images don't support JPEG comments"), // %1=function
|
||||
ErrMsg( 33, "This does not look like a CRW image"),
|
||||
ErrMsg( 34, "%1: Not supported"), // %1=function
|
||||
|
||||
// Last error message (message is not used)
|
||||
ErrMsg( -2, "(Unknown Error)")
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
#include "value.hpp"
|
||||
#include "ifd.hpp"
|
||||
#include "tags.hpp"
|
||||
#include "jpgimage.hpp"
|
||||
#include "image.hpp"
|
||||
#include "makernote.hpp"
|
||||
#include "futils.hpp"
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
|
||||
// Ensure registration with factory
|
||||
#include "jpgimage.hpp"
|
||||
#include "crwimage.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <cerrno>
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ namespace Exiv2 {
|
||||
class Image {
|
||||
public:
|
||||
//! Supported image formats
|
||||
enum Type { none, jpeg, exv };
|
||||
enum Type { none, jpeg, exv, crw };
|
||||
|
||||
//! Image auto_ptr type
|
||||
typedef std::auto_ptr<Image> AutoPtr;
|
||||
|
||||
+8
-3
@@ -579,11 +579,16 @@ namespace Exiv2 {
|
||||
if (len2 != len1) {
|
||||
os << "-" << len2;
|
||||
}
|
||||
os << "mm "
|
||||
<< "F" << (float)fno1.first / fno1.second;
|
||||
os << "mm ";
|
||||
std::ostringstream oss;
|
||||
oss.copyfmt(os);
|
||||
os << "F" << std::setprecision(2)
|
||||
<< static_cast<float>(fno1.first) / fno1.second;
|
||||
if (fno2 != fno1) {
|
||||
os << "-" << (float)fno2.first / fno2.second;
|
||||
os << "-" << std::setprecision(2)
|
||||
<< static_cast<float>(fno2.first) / fno2.second;
|
||||
}
|
||||
os.copyfmt(oss);
|
||||
}
|
||||
else {
|
||||
os << "(" << value << ")";
|
||||
|
||||
+5
-1
@@ -265,7 +265,11 @@ namespace Exiv2 {
|
||||
{
|
||||
float f = value.toFloat();
|
||||
if (f == 0.0 || f == 1.0) return os << "None";
|
||||
return os << std::fixed << std::setprecision(1) << f << "x";
|
||||
std::ostringstream oss;
|
||||
oss.copyfmt(os);
|
||||
os << std::fixed << std::setprecision(1) << f << "x";
|
||||
os.copyfmt(oss);
|
||||
return os;
|
||||
} // OlympusMakerNote::print0x0204
|
||||
|
||||
//! OneTouchWB
|
||||
|
||||
+8
-2
@@ -289,8 +289,14 @@ namespace Exiv2 {
|
||||
std::ostream& PanasonicMakerNote::print0x0023(std::ostream& os,
|
||||
const Value& value)
|
||||
{
|
||||
return os << std::fixed << std::setprecision(1)
|
||||
<< value.toLong() / 3 << " EV";
|
||||
std::ostringstream oss;
|
||||
oss.copyfmt(os);
|
||||
os << std::fixed << std::setprecision(1)
|
||||
<< value.toLong() / 3 << " EV";
|
||||
os.copyfmt(oss);
|
||||
|
||||
return os;
|
||||
|
||||
} // PanasonicMakerNote::print0x0023
|
||||
|
||||
//! ColorEffect
|
||||
|
||||
+49
-6
@@ -45,6 +45,7 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
#include <utility>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
// *****************************************************************************
|
||||
// class member definitions
|
||||
@@ -187,8 +188,8 @@ namespace Exiv2 {
|
||||
TagInfo(0x9004, "DateTimeDigitized", "Date and Time (digitized)", "Date and time image was made digital data", exifIfdId, dateTime, asciiString, printValue),
|
||||
TagInfo(0x9101, "ComponentsConfiguration", "ComponentsConfiguration", "Meaning of each component", exifIfdId, imgConfig, undefined, print0x9101),
|
||||
TagInfo(0x9102, "CompressedBitsPerPixel", "Compressed Bits per Pixel", "Image compression mode", exifIfdId, imgConfig, unsignedRational, printFloat),
|
||||
TagInfo(0x9201, "ShutterSpeedValue", "Shutter speed", "Shutter speed", exifIfdId, captureCond, signedRational, printFloat),
|
||||
TagInfo(0x9202, "ApertureValue", "Aperture", "Aperture", exifIfdId, captureCond, unsignedRational, printFloat),
|
||||
TagInfo(0x9201, "ShutterSpeedValue", "Shutter speed", "Shutter speed", exifIfdId, captureCond, signedRational, print0x9201),
|
||||
TagInfo(0x9202, "ApertureValue", "Aperture", "Aperture", exifIfdId, captureCond, unsignedRational, print0x9202),
|
||||
TagInfo(0x9203, "BrightnessValue", "Brightness", "Brightness", exifIfdId, captureCond, signedRational, printFloat),
|
||||
TagInfo(0x9204, "ExposureBiasValue", "Exposure Bias", "Exposure bias", exifIfdId, captureCond, signedRational, print0x9204),
|
||||
TagInfo(0x9205, "MaxApertureValue", "MaxApertureValue", "Maximum lens aperture", exifIfdId, captureCond, unsignedRational, printFloat),
|
||||
@@ -883,7 +884,11 @@ namespace Exiv2 {
|
||||
{
|
||||
Rational fnumber = value.toRational();
|
||||
if (fnumber.second != 0) {
|
||||
os << "F" << (float)fnumber.first / fnumber.second;
|
||||
std::ostringstream oss;
|
||||
oss.copyfmt(os);
|
||||
os << "F" << std::setprecision(2)
|
||||
<< static_cast<float>(fnumber.first) / fnumber.second;
|
||||
os.copyfmt(oss);
|
||||
}
|
||||
else {
|
||||
os << "(" << value << ")";
|
||||
@@ -932,6 +937,26 @@ namespace Exiv2 {
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& print0x9201(std::ostream& os, const Value& value)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss.copyfmt(os);
|
||||
os << "F" << std::setprecision(2) << fnumber(value.toFloat());
|
||||
os.copyfmt(oss);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& print0x9202(std::ostream& os, const Value& value)
|
||||
{
|
||||
URational ur = exposureTime(value.toFloat());
|
||||
os << ur.first;
|
||||
if (ur.second > 1) {
|
||||
os << "/" << ur.second;
|
||||
}
|
||||
return os << " s";
|
||||
}
|
||||
|
||||
std::ostream& print0x9204(std::ostream& os, const Value& value)
|
||||
{
|
||||
Rational bias = value.toRational();
|
||||
@@ -942,9 +967,9 @@ namespace Exiv2 {
|
||||
os << "0";
|
||||
}
|
||||
else {
|
||||
long d = lgcd(labs(bias.first), bias.second);
|
||||
long num = labs(bias.first) / d;
|
||||
long den = bias.second / d;
|
||||
int32_t d = gcd(bias.first, bias.second);
|
||||
int32_t num = std::abs(bias.first) / d;
|
||||
int32_t den = bias.second / d;
|
||||
os << (bias.first < 0 ? "-" : "+") << num;
|
||||
if (den != 1) {
|
||||
os << "/" << den;
|
||||
@@ -1259,4 +1284,22 @@ namespace Exiv2 {
|
||||
return os;
|
||||
}
|
||||
|
||||
float fnumber(float apertureValue)
|
||||
{
|
||||
return std::exp(std::log(2.0) * apertureValue / 2);
|
||||
}
|
||||
|
||||
URational exposureTime(float shutterSpeedValue)
|
||||
{
|
||||
URational ur(1, 1);
|
||||
double tmp = std::exp(std::log(2.0) * shutterSpeedValue);
|
||||
if (tmp > 1) {
|
||||
ur.second = static_cast<long>(tmp + 0.5);
|
||||
}
|
||||
else {
|
||||
ur.first = static_cast<long>(1/tmp + 0.5);
|
||||
}
|
||||
return ur;
|
||||
}
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
+16
-5
@@ -146,7 +146,7 @@ namespace Exiv2 {
|
||||
//! Container for Exif tag information. Implemented as a static class.
|
||||
class ExifTags {
|
||||
//! Prevent construction: not implemented.
|
||||
ExifTags() {}
|
||||
ExifTags();
|
||||
//! Prevent copy-construction: not implemented.
|
||||
ExifTags(const ExifTags& rhs);
|
||||
//! Prevent assignment: not implemented.
|
||||
@@ -394,18 +394,22 @@ namespace Exiv2 {
|
||||
std::ostream& print0x0112(std::ostream& os, const Value& value);
|
||||
//! Print the YCbCrPositioning
|
||||
std::ostream& print0x0213(std::ostream& os, const Value& value);
|
||||
//! Print the Copyright
|
||||
//! Print the copyright
|
||||
std::ostream& print0x8298(std::ostream& os, const Value& value);
|
||||
//! Print the Exposure time
|
||||
//! Print the exposure time
|
||||
std::ostream& print0x829a(std::ostream& os, const Value& value);
|
||||
//! Print the F number
|
||||
//! Print the f-number
|
||||
std::ostream& print0x829d(std::ostream& os, const Value& value);
|
||||
//! Print the Exposure mode
|
||||
//! Print the exposure mode
|
||||
std::ostream& print0x8822(std::ostream& os, const Value& value);
|
||||
//! Print ISO speed ratings
|
||||
std::ostream& print0x8827(std::ostream& os, const Value& value);
|
||||
//! Print components configuration specific to compressed data
|
||||
std::ostream& print0x9101(std::ostream& os, const Value& value);
|
||||
//! Print exposure time converted from APEX shutter speed value
|
||||
std::ostream& print0x9201(std::ostream& os, const Value& value);
|
||||
//! Print f-number converted from APEX aperture value
|
||||
std::ostream& print0x9202(std::ostream& os, const Value& value);
|
||||
//! Print the exposure bias value
|
||||
std::ostream& print0x9204(std::ostream& os, const Value& value);
|
||||
//! Print the subject distance
|
||||
@@ -449,6 +453,13 @@ namespace Exiv2 {
|
||||
//! Print subject distance range
|
||||
std::ostream& print0xa40c(std::ostream& os, const Value& value);
|
||||
//@}
|
||||
|
||||
//! Calculate F number from an APEX aperture value
|
||||
float fnumber(float apertureValue);
|
||||
|
||||
//! Calculate the exposure time from an APEX shutter speed value
|
||||
URational exposureTime(float shutterSpeedValue);
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
#endif // #ifndef TAGS_HPP_
|
||||
|
||||
+1
-30
@@ -67,6 +67,7 @@ namespace Exiv2 {
|
||||
TypeInfoTable(date, "Date", 8),
|
||||
TypeInfoTable(time, "Time", 11),
|
||||
TypeInfoTable(comment, "Comment", 1),
|
||||
TypeInfoTable(directory, "Directory", 1),
|
||||
// End of list marker
|
||||
TypeInfoTable(lastTypeId, "(Unknown)", 0)
|
||||
};
|
||||
@@ -297,36 +298,6 @@ namespace Exiv2 {
|
||||
os << std::dec << std::setfill(' ');
|
||||
} // hexdump
|
||||
|
||||
int gcd(int a, int b)
|
||||
{
|
||||
int temp;
|
||||
if (a < b) {
|
||||
temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
while ((temp = a % b) != 0) {
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
return b;
|
||||
} // gcd
|
||||
|
||||
long lgcd(long a, long b)
|
||||
{
|
||||
long temp;
|
||||
if (a < b) {
|
||||
temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
while ((temp = a % b) != 0) {
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
return b;
|
||||
} // lgcd
|
||||
|
||||
bool isHex(const std::string& str, size_t size, const std::string& prefix)
|
||||
{
|
||||
if ( str.size() <= prefix.size()
|
||||
|
||||
+42
-13
@@ -81,7 +81,8 @@ namespace Exiv2 {
|
||||
unsignedLong, unsignedRational, invalid6, undefined,
|
||||
signedShort, signedLong, signedRational,
|
||||
string, date, time,
|
||||
comment,
|
||||
comment,
|
||||
directory,
|
||||
lastTypeId };
|
||||
|
||||
// Todo: decentralize IfdId, so that new ids can be defined elsewhere
|
||||
@@ -93,6 +94,11 @@ namespace Exiv2 {
|
||||
olympusIfdId, panasonicIfdId, sigmaIfdId, sonyIfdId,
|
||||
lastIfdId };
|
||||
|
||||
//! Type to identify where the data is stored in a directory
|
||||
enum DataLocId { invalidDataLocId,
|
||||
valueData, directoryData,
|
||||
lastDataLocId };
|
||||
|
||||
// *****************************************************************************
|
||||
// class definitions
|
||||
|
||||
@@ -269,18 +275,6 @@ namespace Exiv2 {
|
||||
*/
|
||||
void hexdump(std::ostream& os, const byte* buf, long len, long offset =0);
|
||||
|
||||
/*!
|
||||
@brief Return the greatest common denominator of integers a and b.
|
||||
Both parameters must be greater than 0.
|
||||
*/
|
||||
int gcd(int a, int b);
|
||||
|
||||
/*!
|
||||
@brief Return the greatest common denominator of long values a and b.
|
||||
Both parameters must be greater than 0.
|
||||
*/
|
||||
long lgcd(long a, long b);
|
||||
|
||||
/*!
|
||||
@brief Return true if str is a hex number starting with prefix followed
|
||||
by size hex digits, false otherwise. If size is 0, any number of
|
||||
@@ -302,6 +296,41 @@ namespace Exiv2 {
|
||||
return os.str();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Return the greatest common denominator of n and m.
|
||||
(implementation from Boost rational.hpp)
|
||||
|
||||
@note We use n and m as temporaries in this function, so there is no
|
||||
value in using const IntType& as we would only need to make a copy
|
||||
anyway...
|
||||
*/
|
||||
template <typename IntType>
|
||||
IntType gcd(IntType n, IntType m)
|
||||
{
|
||||
// Avoid repeated construction
|
||||
IntType zero(0);
|
||||
|
||||
// This is abs() - given the existence of broken compilers with Koenig
|
||||
// lookup issues and other problems, I code this explicitly. (Remember,
|
||||
// IntType may be a user-defined type).
|
||||
if (n < zero)
|
||||
n = -n;
|
||||
if (m < zero)
|
||||
m = -m;
|
||||
|
||||
// As n and m are now positive, we can be sure that %= returns a
|
||||
// positive value (the standard guarantees this for built-in types,
|
||||
// and we require it of user-defined types).
|
||||
for(;;) {
|
||||
if(m == zero)
|
||||
return n;
|
||||
n %= m;
|
||||
if(n == zero)
|
||||
return m;
|
||||
m %= n;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
#endif // #ifndef TYPES_HPP_
|
||||
|
||||
+16
-16
@@ -255,8 +255,8 @@ Exif.CanonCs1.0x0027 0x0027 Makernote Short 1
|
||||
Exif.CanonCs2.0x0001 0x0001 Makernote Short 1 0
|
||||
Exif.CanonCs2.ISOSpeed 0x0002 Makernote Short 1 160
|
||||
Exif.CanonCs2.0x0003 0x0003 Makernote Short 1 276
|
||||
Exif.CanonCs2.0x0004 0x0004 Makernote Short 1 149
|
||||
Exif.CanonCs2.0x0005 0x0005 Makernote Short 1 287
|
||||
Exif.CanonCs2.TargetAperture 0x0004 Makernote Short 1 149
|
||||
Exif.CanonCs2.TargetShutterSpeed 0x0005 Makernote Short 1 287
|
||||
Exif.CanonCs2.0x0006 0x0006 Makernote Short 1 0
|
||||
Exif.CanonCs2.WhiteBalance 0x0007 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0008 0x0008 Makernote Short 1 0
|
||||
@@ -272,8 +272,8 @@ Exif.CanonCs2.0x0011 0x0011 Makernote Short 1
|
||||
Exif.CanonCs2.0x0012 0x0012 Makernote Short 1 1
|
||||
Exif.CanonCs2.SubjectDistance 0x0013 Makernote Short 1 782
|
||||
Exif.CanonCs2.0x0014 0x0014 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0015 0x0015 Makernote Short 1 149
|
||||
Exif.CanonCs2.0x0016 0x0016 Makernote Short 1 289
|
||||
Exif.CanonCs2.ApertureValue 0x0015 Makernote Short 1 149
|
||||
Exif.CanonCs2.ShutterSpeedValue 0x0016 Makernote Short 1 289
|
||||
Exif.CanonCs2.0x0017 0x0017 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0018 0x0018 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0019 0x0019 Makernote Short 1 0
|
||||
@@ -379,8 +379,8 @@ Exif.CanonCs1.0x0027 0x0027 Makernote Short 1
|
||||
Exif.CanonCs2.0x0001 0x0001 Makernote Short 1 0
|
||||
Exif.CanonCs2.ISOSpeed 0x0002 Makernote Short 1 160
|
||||
Exif.CanonCs2.0x0003 0x0003 Makernote Short 1 276
|
||||
Exif.CanonCs2.0x0004 0x0004 Makernote Short 1 149
|
||||
Exif.CanonCs2.0x0005 0x0005 Makernote Short 1 287
|
||||
Exif.CanonCs2.TargetAperture 0x0004 Makernote Short 1 149
|
||||
Exif.CanonCs2.TargetShutterSpeed 0x0005 Makernote Short 1 287
|
||||
Exif.CanonCs2.0x0006 0x0006 Makernote Short 1 0
|
||||
Exif.CanonCs2.WhiteBalance 0x0007 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0008 0x0008 Makernote Short 1 0
|
||||
@@ -396,8 +396,8 @@ Exif.CanonCs2.0x0011 0x0011 Makernote Short 1
|
||||
Exif.CanonCs2.0x0012 0x0012 Makernote Short 1 1
|
||||
Exif.CanonCs2.SubjectDistance 0x0013 Makernote Short 1 782
|
||||
Exif.CanonCs2.0x0014 0x0014 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0015 0x0015 Makernote Short 1 149
|
||||
Exif.CanonCs2.0x0016 0x0016 Makernote Short 1 289
|
||||
Exif.CanonCs2.ApertureValue 0x0015 Makernote Short 1 149
|
||||
Exif.CanonCs2.ShutterSpeedValue 0x0016 Makernote Short 1 289
|
||||
Exif.CanonCs2.0x0017 0x0017 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0018 0x0018 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0019 0x0019 Makernote Short 1 0
|
||||
@@ -504,8 +504,8 @@ Exif.CanonCs1.0x0027 0x0027 Makernote Short 1
|
||||
Exif.CanonCs2.0x0001 0x0001 Makernote Short 1 0
|
||||
Exif.CanonCs2.ISOSpeed 0x0002 Makernote Short 1 160
|
||||
Exif.CanonCs2.0x0003 0x0003 Makernote Short 1 276
|
||||
Exif.CanonCs2.0x0004 0x0004 Makernote Short 1 149
|
||||
Exif.CanonCs2.0x0005 0x0005 Makernote Short 1 287
|
||||
Exif.CanonCs2.TargetAperture 0x0004 Makernote Short 1 149
|
||||
Exif.CanonCs2.TargetShutterSpeed 0x0005 Makernote Short 1 287
|
||||
Exif.CanonCs2.0x0006 0x0006 Makernote Short 1 0
|
||||
Exif.CanonCs2.WhiteBalance 0x0007 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0008 0x0008 Makernote Short 1 0
|
||||
@@ -521,8 +521,8 @@ Exif.CanonCs2.0x0011 0x0011 Makernote Short 1
|
||||
Exif.CanonCs2.0x0012 0x0012 Makernote Short 1 1
|
||||
Exif.CanonCs2.SubjectDistance 0x0013 Makernote Short 1 782
|
||||
Exif.CanonCs2.0x0014 0x0014 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0015 0x0015 Makernote Short 1 149
|
||||
Exif.CanonCs2.0x0016 0x0016 Makernote Short 1 289
|
||||
Exif.CanonCs2.ApertureValue 0x0015 Makernote Short 1 149
|
||||
Exif.CanonCs2.ShutterSpeedValue 0x0016 Makernote Short 1 289
|
||||
Exif.CanonCs2.0x0017 0x0017 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0018 0x0018 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0019 0x0019 Makernote Short 1 0
|
||||
@@ -628,8 +628,8 @@ Exif.CanonCs1.0x0027 0x0027 Makernote Short 1
|
||||
Exif.CanonCs2.0x0001 0x0001 Makernote Short 1 0
|
||||
Exif.CanonCs2.ISOSpeed 0x0002 Makernote Short 1 160
|
||||
Exif.CanonCs2.0x0003 0x0003 Makernote Short 1 276
|
||||
Exif.CanonCs2.0x0004 0x0004 Makernote Short 1 149
|
||||
Exif.CanonCs2.0x0005 0x0005 Makernote Short 1 287
|
||||
Exif.CanonCs2.TargetAperture 0x0004 Makernote Short 1 149
|
||||
Exif.CanonCs2.TargetShutterSpeed 0x0005 Makernote Short 1 287
|
||||
Exif.CanonCs2.0x0006 0x0006 Makernote Short 1 0
|
||||
Exif.CanonCs2.WhiteBalance 0x0007 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0008 0x0008 Makernote Short 1 0
|
||||
@@ -645,8 +645,8 @@ Exif.CanonCs2.0x0011 0x0011 Makernote Short 1
|
||||
Exif.CanonCs2.0x0012 0x0012 Makernote Short 1 1
|
||||
Exif.CanonCs2.SubjectDistance 0x0013 Makernote Short 1 782
|
||||
Exif.CanonCs2.0x0014 0x0014 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0015 0x0015 Makernote Short 1 149
|
||||
Exif.CanonCs2.0x0016 0x0016 Makernote Short 1 289
|
||||
Exif.CanonCs2.ApertureValue 0x0015 Makernote Short 1 149
|
||||
Exif.CanonCs2.ShutterSpeedValue 0x0016 Makernote Short 1 289
|
||||
Exif.CanonCs2.0x0017 0x0017 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0018 0x0018 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0019 0x0019 Makernote Short 1 0
|
||||
|
||||
+21
-21
@@ -9,7 +9,7 @@ This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
Exiv2 help ---------------------------------------------------------------
|
||||
Usage: exiv2 [ options ] [ action ] file ...
|
||||
Usage: lt-exiv2 [ options ] [ action ] file ...
|
||||
|
||||
Manipulate the Exif metadata of images.
|
||||
|
||||
@@ -429,8 +429,8 @@ Exif.Photo.DateTimeOriginal Ascii 20 2003:12:14 00:00:43
|
||||
Exif.Photo.DateTimeDigitized Ascii 20 2003:12:14 00:00:43
|
||||
Exif.Photo.ComponentsConfiguration Undefined 4 YCbCr
|
||||
Exif.Photo.CompressedBitsPerPixel Rational 1 5
|
||||
Exif.Photo.ShutterSpeedValue SRational 1 8.96875
|
||||
Exif.Photo.ApertureValue Rational 1 4.65625
|
||||
Exif.Photo.ShutterSpeedValue SRational 1 F22
|
||||
Exif.Photo.ApertureValue Rational 1 1/25 s
|
||||
Exif.Photo.ExposureBiasValue SRational 1 0
|
||||
Exif.Photo.MaxApertureValue Rational 1 2.97086
|
||||
Exif.Photo.MeteringMode Short 1 Center weighted
|
||||
@@ -502,8 +502,8 @@ Exif.CanonCs1.0x0027 Short 1 1
|
||||
Exif.CanonCs2.0x0001 Short 1 0
|
||||
Exif.CanonCs2.ISOSpeed Short 1 100
|
||||
Exif.CanonCs2.0x0003 Short 1 276
|
||||
Exif.CanonCs2.0x0004 Short 1 149
|
||||
Exif.CanonCs2.0x0005 Short 1 287
|
||||
Exif.CanonCs2.TargetAperture Short 1 F5
|
||||
Exif.CanonCs2.TargetShutterSpeed Short 1 1/501 s
|
||||
Exif.CanonCs2.0x0006 Short 1 0
|
||||
Exif.CanonCs2.WhiteBalance Short 1 Auto
|
||||
Exif.CanonCs2.0x0008 Short 1 0
|
||||
@@ -519,8 +519,8 @@ Exif.CanonCs2.0x0011 Short 1 0
|
||||
Exif.CanonCs2.0x0012 Short 1 1
|
||||
Exif.CanonCs2.SubjectDistance Short 1 782
|
||||
Exif.CanonCs2.0x0014 Short 1 0
|
||||
Exif.CanonCs2.0x0015 Short 1 149
|
||||
Exif.CanonCs2.0x0016 Short 1 289
|
||||
Exif.CanonCs2.ApertureValue Short 1 F5
|
||||
Exif.CanonCs2.ShutterSpeedValue Short 1 1/523 s
|
||||
Exif.CanonCs2.0x0017 Short 1 0
|
||||
Exif.CanonCs2.0x0018 Short 1 0
|
||||
Exif.CanonCs2.0x0019 Short 1 0
|
||||
@@ -770,8 +770,8 @@ Exif.Photo.DateTimeOriginal Ascii 20 2003:09:25 20:18:50
|
||||
Exif.Photo.DateTimeDigitized Ascii 20 2003:09:25 20:18:50
|
||||
Exif.Photo.ComponentsConfiguration Undefined 4 YCbCr
|
||||
Exif.Photo.CompressedBitsPerPixel Rational 1 3
|
||||
Exif.Photo.ShutterSpeedValue SRational 1 6.32193
|
||||
Exif.Photo.ApertureValue Rational 1 4.97086
|
||||
Exif.Photo.ShutterSpeedValue SRational 1 F8.9
|
||||
Exif.Photo.ApertureValue Rational 1 1/31 s
|
||||
Exif.Photo.ExposureBiasValue SRational 1 0
|
||||
Exif.Photo.MaxApertureValue Rational 1 3.61472
|
||||
Exif.Photo.MeteringMode Short 1 Matrix
|
||||
@@ -862,8 +862,8 @@ Exif.CanonCs1.0x002d Short 1 65535
|
||||
Exif.CanonCs2.0x0001 Short 1 0
|
||||
Exif.CanonCs2.ISOSpeed Short 1 100
|
||||
Exif.CanonCs2.0x0003 Short 1 200
|
||||
Exif.CanonCs2.0x0004 Short 1 159
|
||||
Exif.CanonCs2.0x0005 Short 1 202
|
||||
Exif.CanonCs2.TargetAperture Short 1 F5.6
|
||||
Exif.CanonCs2.TargetShutterSpeed Short 1 1/79 s
|
||||
Exif.CanonCs2.0x0006 Short 1 0
|
||||
Exif.CanonCs2.WhiteBalance Short 1 Auto
|
||||
Exif.CanonCs2.0x0008 Short 1 3
|
||||
@@ -879,8 +879,8 @@ Exif.CanonCs2.0x0011 Short 1 0
|
||||
Exif.CanonCs2.0x0012 Short 1 1
|
||||
Exif.CanonCs2.SubjectDistance Short 1 Infinite
|
||||
Exif.CanonCs2.0x0014 Short 1 546
|
||||
Exif.CanonCs2.0x0015 Short 1 156
|
||||
Exif.CanonCs2.0x0016 Short 1 204
|
||||
Exif.CanonCs2.ApertureValue Short 1 F5.4
|
||||
Exif.CanonCs2.ShutterSpeedValue Short 1 1/81 s
|
||||
Exif.CanonCs2.0x0017 Short 1 140
|
||||
Exif.CanonCs2.0x0018 Short 1 0
|
||||
Exif.CanonCs2.0x0019 Short 1 0
|
||||
@@ -918,8 +918,8 @@ Exif.Photo.ExifVersion Undefined 4 48 49 49 48
|
||||
Exif.Photo.DateTimeOriginal Ascii 20 2000:10:26 04:45:50
|
||||
Exif.Photo.ComponentsConfiguration Undefined 4 YCbCr
|
||||
Exif.Photo.CompressedBitsPerPixel Rational 1 (0/0)
|
||||
Exif.Photo.ShutterSpeedValue SRational 1 5
|
||||
Exif.Photo.ApertureValue Rational 1 4
|
||||
Exif.Photo.ShutterSpeedValue SRational 1 F5.7
|
||||
Exif.Photo.ApertureValue Rational 1 1/16 s
|
||||
Exif.Photo.BrightnessValue SRational 1 1.5
|
||||
Exif.Photo.ExposureBiasValue SRational 1 0
|
||||
Exif.Photo.MaxApertureValue Rational 1 4
|
||||
@@ -962,8 +962,8 @@ Exif.Photo.DateTimeOriginal Ascii 20 2003:09:26 11:15:35
|
||||
Exif.Photo.DateTimeDigitized Ascii 20 2003:09:26 11:15:35
|
||||
Exif.Photo.ComponentsConfiguration Undefined 4 YCbCr
|
||||
Exif.Photo.CompressedBitsPerPixel Rational 1 1.5
|
||||
Exif.Photo.ShutterSpeedValue SRational 1 6
|
||||
Exif.Photo.ApertureValue Rational 1 4
|
||||
Exif.Photo.ShutterSpeedValue SRational 1 F8
|
||||
Exif.Photo.ApertureValue Rational 1 1/16 s
|
||||
Exif.Photo.BrightnessValue SRational 1 -1.83
|
||||
Exif.Photo.ExposureBiasValue SRational 1 +1/2
|
||||
Exif.Photo.MeteringMode Short 1 Center weighted
|
||||
@@ -1171,9 +1171,9 @@ Exif.Photo.ExifVersion Undefined 4 48 50 50 48
|
||||
Exif.Photo.DateTimeOriginal Ascii 20 2005:02:18 21:20:16
|
||||
Exif.Photo.DateTimeDigitized Ascii 20 2005:02:18 21:20:16
|
||||
Exif.Photo.ComponentsConfiguration Undefined 4 YCbCr
|
||||
Exif.Photo.CompressedBitsPerPixel Rational 1 4.0
|
||||
Exif.Photo.CompressedBitsPerPixel Rational 1 4
|
||||
Exif.Photo.ExposureBiasValue SRational 1 0
|
||||
Exif.Photo.MaxApertureValue Rational 1 3.0
|
||||
Exif.Photo.MaxApertureValue Rational 1 3
|
||||
Exif.Photo.MeteringMode Short 1 Matrix
|
||||
Exif.Photo.LightSource Short 1 Unknown
|
||||
Exif.Photo.Flash Short 1 No, compulsory
|
||||
@@ -1253,9 +1253,9 @@ Exif.Photo.ExifVersion Undefined 4 48 50 50 48
|
||||
Exif.Photo.DateTimeOriginal Ascii 20 2005:05:27 05:18:33
|
||||
Exif.Photo.DateTimeDigitized Ascii 20 2005:05:27 05:18:33
|
||||
Exif.Photo.ComponentsConfiguration Undefined 4 YCbCr
|
||||
Exif.Photo.CompressedBitsPerPixel Rational 1 8.0
|
||||
Exif.Photo.CompressedBitsPerPixel Rational 1 8
|
||||
Exif.Photo.ExposureBiasValue SRational 1 0
|
||||
Exif.Photo.MaxApertureValue Rational 1 3.0
|
||||
Exif.Photo.MaxApertureValue Rational 1 3
|
||||
Exif.Photo.MeteringMode Short 1 Matrix
|
||||
Exif.Photo.LightSource Short 1 Unknown
|
||||
Exif.Photo.Flash Short 1 Yes, auto, return light detected
|
||||
|
||||
@@ -39,8 +39,8 @@ Exif.Photo.ExifVersion Undefined 4 48 50 49 48
|
||||
Exif.Photo.DateTimeOriginal Ascii 20 2004:06:08 16:04:50
|
||||
Exif.Photo.DateTimeDigitized Ascii 20 2004:06:08 16:04:50
|
||||
Exif.Photo.ComponentsConfiguration Undefined 4 YCbCr
|
||||
Exif.Photo.ShutterSpeedValue SRational 1 6.6
|
||||
Exif.Photo.ApertureValue Rational 1 6.4
|
||||
Exif.Photo.ShutterSpeedValue SRational 1 F9.8
|
||||
Exif.Photo.ApertureValue Rational 1 1/84 s
|
||||
Exif.Photo.ExposureBiasValue SRational 1 0
|
||||
Exif.Photo.MaxApertureValue Rational 1 3.1
|
||||
Exif.Photo.MeteringMode Short 1 Matrix
|
||||
|
||||
+32
-32
@@ -95,8 +95,8 @@ Case 1: Non-intrusive change to the standard Exif metadata
|
||||
< Exif.CanonCs2.0x0001 0x0001 Short 1 0
|
||||
< Exif.CanonCs2.ISOSpeed 0x0002 Short 1 160
|
||||
< Exif.CanonCs2.0x0003 0x0003 Short 1 276
|
||||
< Exif.CanonCs2.0x0004 0x0004 Short 1 149
|
||||
< Exif.CanonCs2.0x0005 0x0005 Short 1 287
|
||||
< Exif.CanonCs2.TargetAperture 0x0004 Short 1 149
|
||||
< Exif.CanonCs2.TargetShutterSpeed 0x0005 Short 1 287
|
||||
< Exif.CanonCs2.0x0006 0x0006 Short 1 0
|
||||
< Exif.CanonCs2.WhiteBalance 0x0007 Short 1 0
|
||||
< Exif.CanonCs2.0x0008 0x0008 Short 1 0
|
||||
@@ -112,8 +112,8 @@ Case 1: Non-intrusive change to the standard Exif metadata
|
||||
< Exif.CanonCs2.0x0012 0x0012 Short 1 1
|
||||
< Exif.CanonCs2.SubjectDistance 0x0013 Short 1 782
|
||||
< Exif.CanonCs2.0x0014 0x0014 Short 1 0
|
||||
< Exif.CanonCs2.0x0015 0x0015 Short 1 149
|
||||
< Exif.CanonCs2.0x0016 0x0016 Short 1 289
|
||||
< Exif.CanonCs2.ApertureValue 0x0015 Short 1 149
|
||||
< Exif.CanonCs2.ShutterSpeedValue 0x0016 Short 1 289
|
||||
< Exif.CanonCs2.0x0017 0x0017 Short 1 0
|
||||
< Exif.CanonCs2.0x0018 0x0018 Short 1 0
|
||||
< Exif.CanonCs2.0x0019 0x0019 Short 1 0
|
||||
@@ -218,8 +218,8 @@ Case 1: Non-intrusive change to the standard Exif metadata
|
||||
> Exif.CanonCs2.0x0001 0x0001 0
|
||||
> Exif.CanonCs2.ISOSpeed 0x0002 160
|
||||
> Exif.CanonCs2.0x0003 0x0003 276
|
||||
> Exif.CanonCs2.0x0004 0x0004 149
|
||||
> Exif.CanonCs2.0x0005 0x0005 287
|
||||
> Exif.CanonCs2.TargetAperture 0x0004 149
|
||||
> Exif.CanonCs2.TargetShutterSpeed 0x0005 287
|
||||
> Exif.CanonCs2.0x0006 0x0006 0
|
||||
> Exif.CanonCs2.WhiteBalance 0x0007 0
|
||||
> Exif.CanonCs2.0x0008 0x0008 0
|
||||
@@ -235,8 +235,8 @@ Case 1: Non-intrusive change to the standard Exif metadata
|
||||
> Exif.CanonCs2.0x0012 0x0012 1
|
||||
> Exif.CanonCs2.SubjectDistance 0x0013 782
|
||||
> Exif.CanonCs2.0x0014 0x0014 0
|
||||
> Exif.CanonCs2.0x0015 0x0015 149
|
||||
> Exif.CanonCs2.0x0016 0x0016 289
|
||||
> Exif.CanonCs2.ApertureValue 0x0015 149
|
||||
> Exif.CanonCs2.ShutterSpeedValue 0x0016 289
|
||||
> Exif.CanonCs2.0x0017 0x0017 0
|
||||
> Exif.CanonCs2.0x0018 0x0018 0
|
||||
> Exif.CanonCs2.0x0019 0x0019 0
|
||||
@@ -348,8 +348,8 @@ Case 2: Non-intrusive change to the makernote metadata
|
||||
< Exif.CanonCs2.0x0001 0x0001 Short 1 0
|
||||
< Exif.CanonCs2.ISOSpeed 0x0002 Short 1 160
|
||||
< Exif.CanonCs2.0x0003 0x0003 Short 1 276
|
||||
< Exif.CanonCs2.0x0004 0x0004 Short 1 149
|
||||
< Exif.CanonCs2.0x0005 0x0005 Short 1 287
|
||||
< Exif.CanonCs2.TargetAperture 0x0004 Short 1 149
|
||||
< Exif.CanonCs2.TargetShutterSpeed 0x0005 Short 1 287
|
||||
< Exif.CanonCs2.0x0006 0x0006 Short 1 0
|
||||
< Exif.CanonCs2.WhiteBalance 0x0007 Short 1 0
|
||||
< Exif.CanonCs2.0x0008 0x0008 Short 1 0
|
||||
@@ -365,8 +365,8 @@ Case 2: Non-intrusive change to the makernote metadata
|
||||
< Exif.CanonCs2.0x0012 0x0012 Short 1 1
|
||||
< Exif.CanonCs2.SubjectDistance 0x0013 Short 1 782
|
||||
< Exif.CanonCs2.0x0014 0x0014 Short 1 0
|
||||
< Exif.CanonCs2.0x0015 0x0015 Short 1 149
|
||||
< Exif.CanonCs2.0x0016 0x0016 Short 1 289
|
||||
< Exif.CanonCs2.ApertureValue 0x0015 Short 1 149
|
||||
< Exif.CanonCs2.ShutterSpeedValue 0x0016 Short 1 289
|
||||
< Exif.CanonCs2.0x0017 0x0017 Short 1 0
|
||||
< Exif.CanonCs2.0x0018 0x0018 Short 1 0
|
||||
< Exif.CanonCs2.0x0019 0x0019 Short 1 0
|
||||
@@ -471,8 +471,8 @@ Case 2: Non-intrusive change to the makernote metadata
|
||||
> Exif.CanonCs2.0x0001 0x0001 0
|
||||
> Exif.CanonCs2.ISOSpeed 0x0002 160
|
||||
> Exif.CanonCs2.0x0003 0x0003 276
|
||||
> Exif.CanonCs2.0x0004 0x0004 149
|
||||
> Exif.CanonCs2.0x0005 0x0005 287
|
||||
> Exif.CanonCs2.TargetAperture 0x0004 149
|
||||
> Exif.CanonCs2.TargetShutterSpeed 0x0005 287
|
||||
> Exif.CanonCs2.0x0006 0x0006 0
|
||||
> Exif.CanonCs2.WhiteBalance 0x0007 0
|
||||
> Exif.CanonCs2.0x0008 0x0008 0
|
||||
@@ -488,8 +488,8 @@ Case 2: Non-intrusive change to the makernote metadata
|
||||
> Exif.CanonCs2.0x0012 0x0012 1
|
||||
> Exif.CanonCs2.SubjectDistance 0x0013 782
|
||||
> Exif.CanonCs2.0x0014 0x0014 0
|
||||
> Exif.CanonCs2.0x0015 0x0015 149
|
||||
> Exif.CanonCs2.0x0016 0x0016 289
|
||||
> Exif.CanonCs2.ApertureValue 0x0015 149
|
||||
> Exif.CanonCs2.ShutterSpeedValue 0x0016 289
|
||||
> Exif.CanonCs2.0x0017 0x0017 0
|
||||
> Exif.CanonCs2.0x0018 0x0018 0
|
||||
> Exif.CanonCs2.0x0019 0x0019 0
|
||||
@@ -688,8 +688,8 @@ Case 4: Intrusive change to the standard Exif metadata
|
||||
< Exif.CanonCs2.0x0001 0x0001 Short 1 0
|
||||
< Exif.CanonCs2.ISOSpeed 0x0002 Short 1 160
|
||||
< Exif.CanonCs2.0x0003 0x0003 Short 1 276
|
||||
< Exif.CanonCs2.0x0004 0x0004 Short 1 149
|
||||
< Exif.CanonCs2.0x0005 0x0005 Short 1 287
|
||||
< Exif.CanonCs2.TargetAperture 0x0004 Short 1 149
|
||||
< Exif.CanonCs2.TargetShutterSpeed 0x0005 Short 1 287
|
||||
< Exif.CanonCs2.0x0006 0x0006 Short 1 0
|
||||
< Exif.CanonCs2.WhiteBalance 0x0007 Short 1 0
|
||||
< Exif.CanonCs2.0x0008 0x0008 Short 1 0
|
||||
@@ -705,8 +705,8 @@ Case 4: Intrusive change to the standard Exif metadata
|
||||
< Exif.CanonCs2.0x0012 0x0012 Short 1 1
|
||||
< Exif.CanonCs2.SubjectDistance 0x0013 Short 1 782
|
||||
< Exif.CanonCs2.0x0014 0x0014 Short 1 0
|
||||
< Exif.CanonCs2.0x0015 0x0015 Short 1 149
|
||||
< Exif.CanonCs2.0x0016 0x0016 Short 1 289
|
||||
< Exif.CanonCs2.ApertureValue 0x0015 Short 1 149
|
||||
< Exif.CanonCs2.ShutterSpeedValue 0x0016 Short 1 289
|
||||
< Exif.CanonCs2.0x0017 0x0017 Short 1 0
|
||||
< Exif.CanonCs2.0x0018 0x0018 Short 1 0
|
||||
< Exif.CanonCs2.0x0019 0x0019 Short 1 0
|
||||
@@ -811,8 +811,8 @@ Case 4: Intrusive change to the standard Exif metadata
|
||||
> Exif.CanonCs2.0x0001 0x0001 0
|
||||
> Exif.CanonCs2.ISOSpeed 0x0002 160
|
||||
> Exif.CanonCs2.0x0003 0x0003 276
|
||||
> Exif.CanonCs2.0x0004 0x0004 149
|
||||
> Exif.CanonCs2.0x0005 0x0005 287
|
||||
> Exif.CanonCs2.TargetAperture 0x0004 149
|
||||
> Exif.CanonCs2.TargetShutterSpeed 0x0005 287
|
||||
> Exif.CanonCs2.0x0006 0x0006 0
|
||||
> Exif.CanonCs2.WhiteBalance 0x0007 0
|
||||
> Exif.CanonCs2.0x0008 0x0008 0
|
||||
@@ -828,8 +828,8 @@ Case 4: Intrusive change to the standard Exif metadata
|
||||
> Exif.CanonCs2.0x0012 0x0012 1
|
||||
> Exif.CanonCs2.SubjectDistance 0x0013 782
|
||||
> Exif.CanonCs2.0x0014 0x0014 0
|
||||
> Exif.CanonCs2.0x0015 0x0015 149
|
||||
> Exif.CanonCs2.0x0016 0x0016 289
|
||||
> Exif.CanonCs2.ApertureValue 0x0015 149
|
||||
> Exif.CanonCs2.ShutterSpeedValue 0x0016 289
|
||||
> Exif.CanonCs2.0x0017 0x0017 0
|
||||
> Exif.CanonCs2.0x0018 0x0018 0
|
||||
> Exif.CanonCs2.0x0019 0x0019 0
|
||||
@@ -941,8 +941,8 @@ Case 5: Intrusive change to the Canon makernote metadata
|
||||
< Exif.CanonCs2.0x0001 0x0001 Short 1 0
|
||||
< Exif.CanonCs2.ISOSpeed 0x0002 Short 1 160
|
||||
< Exif.CanonCs2.0x0003 0x0003 Short 1 276
|
||||
< Exif.CanonCs2.0x0004 0x0004 Short 1 149
|
||||
< Exif.CanonCs2.0x0005 0x0005 Short 1 287
|
||||
< Exif.CanonCs2.TargetAperture 0x0004 Short 1 149
|
||||
< Exif.CanonCs2.TargetShutterSpeed 0x0005 Short 1 287
|
||||
< Exif.CanonCs2.0x0006 0x0006 Short 1 0
|
||||
< Exif.CanonCs2.WhiteBalance 0x0007 Short 1 0
|
||||
< Exif.CanonCs2.0x0008 0x0008 Short 1 0
|
||||
@@ -958,8 +958,8 @@ Case 5: Intrusive change to the Canon makernote metadata
|
||||
< Exif.CanonCs2.0x0012 0x0012 Short 1 1
|
||||
< Exif.CanonCs2.SubjectDistance 0x0013 Short 1 782
|
||||
< Exif.CanonCs2.0x0014 0x0014 Short 1 0
|
||||
< Exif.CanonCs2.0x0015 0x0015 Short 1 149
|
||||
< Exif.CanonCs2.0x0016 0x0016 Short 1 289
|
||||
< Exif.CanonCs2.ApertureValue 0x0015 Short 1 149
|
||||
< Exif.CanonCs2.ShutterSpeedValue 0x0016 Short 1 289
|
||||
< Exif.CanonCs2.0x0017 0x0017 Short 1 0
|
||||
< Exif.CanonCs2.0x0018 0x0018 Short 1 0
|
||||
< Exif.CanonCs2.0x0019 0x0019 Short 1 0
|
||||
@@ -1064,8 +1064,8 @@ Case 5: Intrusive change to the Canon makernote metadata
|
||||
> Exif.CanonCs2.0x0001 0x0001 0
|
||||
> Exif.CanonCs2.ISOSpeed 0x0002 160
|
||||
> Exif.CanonCs2.0x0003 0x0003 276
|
||||
> Exif.CanonCs2.0x0004 0x0004 149
|
||||
> Exif.CanonCs2.0x0005 0x0005 287
|
||||
> Exif.CanonCs2.TargetAperture 0x0004 149
|
||||
> Exif.CanonCs2.TargetShutterSpeed 0x0005 287
|
||||
> Exif.CanonCs2.0x0006 0x0006 0
|
||||
> Exif.CanonCs2.WhiteBalance 0x0007 0
|
||||
> Exif.CanonCs2.0x0008 0x0008 0
|
||||
@@ -1081,8 +1081,8 @@ Case 5: Intrusive change to the Canon makernote metadata
|
||||
> Exif.CanonCs2.0x0012 0x0012 1
|
||||
> Exif.CanonCs2.SubjectDistance 0x0013 782
|
||||
> Exif.CanonCs2.0x0014 0x0014 0
|
||||
> Exif.CanonCs2.0x0015 0x0015 149
|
||||
> Exif.CanonCs2.0x0016 0x0016 289
|
||||
> Exif.CanonCs2.ApertureValue 0x0015 149
|
||||
> Exif.CanonCs2.ShutterSpeedValue 0x0016 289
|
||||
> Exif.CanonCs2.0x0017 0x0017 0
|
||||
> Exif.CanonCs2.0x0018 0x0018 0
|
||||
> Exif.CanonCs2.0x0019 0x0019 0
|
||||
|
||||
@@ -19,8 +19,8 @@ Exif.CanonCs1.Selftimer 0x0002 Makernote Short 1
|
||||
Exif.CanonCs2.0x0001 0x0001 Makernote Short 1 0
|
||||
Exif.CanonCs2.ISOSpeed 0x0002 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0003 0x0003 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0004 0x0004 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0005 0x0005 Makernote Short 1 42
|
||||
Exif.CanonCs2.TargetAperture 0x0004 Makernote Short 1 0
|
||||
Exif.CanonCs2.TargetShutterSpeed 0x0005 Makernote Short 1 42
|
||||
Exif.CanonCf.NoiseReduction 0x0001 Makernote Short 1 43
|
||||
|
||||
----- Non-intrusive writing of special Canon MakerNote tags
|
||||
@@ -33,8 +33,8 @@ Exif.CanonCs1.Selftimer 0x0002 Makernote Short 1
|
||||
Exif.CanonCs2.0x0001 0x0001 Makernote Short 1 0
|
||||
Exif.CanonCs2.ISOSpeed 0x0002 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0003 0x0003 Makernote Short 1 0
|
||||
Exif.CanonCs2.0x0004 0x0004 Makernote Short 1 99
|
||||
Exif.CanonCs2.0x0005 0x0005 Makernote Short 1 42
|
||||
Exif.CanonCs2.TargetAperture 0x0004 Makernote Short 1 99
|
||||
Exif.CanonCs2.TargetShutterSpeed 0x0005 Makernote Short 1 42
|
||||
Exif.CanonCf.NoiseReduction 0x0001 Makernote Short 1 43
|
||||
|
||||
----- One Fujifilm MakerNote tag
|
||||
|
||||
Reference in New Issue
Block a user